This is the first in a four-part series of research blogs that will examine the Windows CE operating system, a legacy OS still prevalent in OT environments. In part 1, we describe our development of a simple Windows CE app that helped us better understand the OS and further our research.
Our team constantly establishes research goals that help us make industrial and medical infrastructure safer against cyberattacks. In doing so, we tackle a wide variety of systems and try to uncover issues that may lie hidden and risk the stability of their infrastructure. In one specific case, our target was a special HMI panel that ran on the Windows CE operating system.
This prompted us to delve into the world of Windows CE operating systems in ICS and SCADA environments. As it turns out, the more we explored, the more we wanted to share. Therefore, we’ll be publishing a series of blogs on this environment that will include our vulnerability research methodology and a number of CVEs we uncovered along the way.
In this first part of this blog series we will do a simple introduction to native application development on a Windows CE system. We believe that doing so could help in having more familiarity with this OS and speed up further research.
This operating system is commonly found in industrial settings because of its ease of access. It’s most often used in critical factory machinery, and is easily configurable and customizable, making it a great fit for HMI systems deployments.
Windows CE is also suitable in many other scenarios. For example, it is commonly under the hood of devices such as vending machines, public kiosks that display easy-to-use interfaces, and also some vehicle infotainment systems.
To develop our application we need to have a functional workspace—Visual Studio 2005 IDE in this case— that allows us to build and deploy it. This utility will be important in order to compile and deploy our application with ease and a minimum amount of issues.
Starting by creating the new project in Visual Studio 2005, Select File→New→Project
.
Then a “New Project” window will pop up where we choose the template for our application project. In our case we want to create a GUI application for a smart device system.
Then we will continue to the configuration step of our project using a helpful wizard window. In our case, we would like our target to be an executable for the Pocket PC 2003 Platform. So we need to click the “Next >
” button to set these settings accordingly.
Finishing this configuration part, we get to the real deal. If we have done everything correctly, we should be getting the following Solution Explorer prompt in the IDE.
Opening the T82.cpp
C++ module file we find that most of the boilerplate code has been lifted for us by our trusty IDE.
As we can see, we have our main routine exported as a global symbol for our program to invoke at runtime.
To create an application window we will be using Microsoft MSDN API documentation as our guiding document. In order to achieve a visual window effect we will use the following library methods:
PostQuitMessage
(winuser.h, coredll.dll)
DefWindowProc
(winuser.h, coredll.dll)
RegisterClass
(winuser.h, coredll.dll)
CreateWindow
(winuser.h, coredll.dll)
ShowWindow
(winuser.h, coredll.dll)
GetMessage
(winuser.h, coredll.dll)
DispatchMessage
(winuser.h, coredll.dll)
We will also need to implement a callback function that handles accepted messages to our applications window.
Now let us break down each component in the image so we can better understand how to interpret this module's code.
The callback function we implemented called WinProc(...)
is in charge of handling the different messages our window might be notified with. As we can see, this method implements a switch-case construct to handle each specific window message type.
The main program routine executes a loop on the main thread of the application to receive different operating system messages, such as interacting with the running process of the application and dispatching them forward to the application’s managed window.
These messages then propagate and get caught and handled by this window processing function. For example, in case a message is posted to the window indicating the destruction of it, we invoke the PostQuitMessage(0)
method to close our application and terminate its process.
The WNDCLASS
structure defines our applications window object class unique attributes. The definition of this class according to MSDN is as follows:
typedef struct _WNDCLASS {
UINTstyle; // style used for the class [CS_DBLCLKS,...]
WNDPROClpfnWndProc; // callback func - window msgs processing
intcbClsExtra; // structure extra data bytes size - 0x0
intcbWndExtra; // window instance extra data bytes size - 0x0
HANDLEhInstance; // handle to the containing procedure instance
HICONhIcon; // Unsupported
HCURSORhCursor; // handle to mouse cursor class
HBRUSHhbrBackground; // winodw background color brush class handle
LPCTSTRlpszMenuName; // long string pointer to winodw menu name
LPCTSTRlpszClassName; // long string point to window class name
} WNDCLASS;
Meanwhile, the specification clarifies that by using the method RegisterClass(&cls), we are registering a new window class named “Team82.”
CreateWindow(...), ShowWindow(...)
As the name of the method CreateWindow(...)
suggests, this is the method in charge of creating an instance of the window class we previously defined and registered.
We supply specific arguments to this method according to the MSDN specification. The following is the argument list for the method and a concise description for each entry:
lpClassName
: The window class name we instantiate
lpWindowName
: The name of our window (present in the title bar)
dwStyle
: The style used for the window we create [WS_BORDER, WS_CAPTION, ...]
X
: X coordinate value for the window location upper-left corner
Y
: Y coordinate value for the window location upper-left corner
nWidth
: The width of our window
nHeight
: The height of our window
hWndParent
: Handle to the owner of this window - could be a parent window handle or NULL
hMenu
: Handle to the window menu object
hInstance
: Handle to the module associated with this window object
lpParam
: Long pointer to parameter value passed to the window object upon creation, retrievable on handling of the WM_CREATE message
To reveal our window on the PocketPC 2003 screen we invoke the ShowWindow(...)
method with our HWND
window handle of the one we just created.
Visual Studio 2005 has a built-in emulator for the PocketPC 2003 device system and is available for application testing before shipping our brand new application to production. If we did everything correctly, we should be able to get our application to build and deploy on that emulator.
Great! Our application is up and running and we can see our “Team82” title in the top bar. But maybe we need to add some graphics and style it better.
To add graphical elements and make them included and rendered during the application’s window life-cycle we incorporate a few new code lines in the WinProc
painting state.
In that case we will be using the following Windows library functions:
LoadBitmap
(winuser.h, coredll.dll)
MessageBox
(winuser.h, coredll.dll)
BeginPaint
(winuser.h, coredll.dll)
CreateCompatibleDC
(windows.h, coredll.dll)
SelectObject
(winuser.h, coredll.dll)
GetObject
(winuser.h, coredll.dll)
BitBlt
(winuser.h, coredll.dll)
DeleteDC
(winuser.h, coredll.dll)
CreateSolidBrush
(winuser.h, coredll.dll)
DrawText
(winuser.h, coredll.dll)
EndPaint
(winuser.h, coredll.dll)
We start the graphical styling of our application by choosing an asset bitmap and loading it into our project resources.
* Note: The supported format for Bitmaps for this platform seems to be limited to BMP3, which can be easily retrieved using a tool such as mogrify
by imagemagick.
$ mogrify -format BMP3 <SRC-IMG-File>
$ mogrify -resize 200 <SRC-IMG-File-Name>.BMP3
We define our resource ID value as a constant definition and declare a HBITMAP variable to hold our loaded bitmap asset.
The significant part of this subject code is contained inside the window processing callback function, specifically the WM_PAINT
segment.
This segment begins with retrieving a handle to the window device context which will be repainted by invoking the library method BeginPaint
. Additionally we create a compatible copy for the device context which we use later.
We then select the object containing the asset, we loaded earlier, using the handle variable hBitmap
and fetch its content data into a BITMAP
variable also declared earlier. Following these statements, we use the library method BitBlt
to pipe our BITMAP
variable pixels to our compatible device-context hDcMem
.
In order to paint text on the application window, we create a solid color brush and define a rectangle to border the prompted text. After defining the relevant components hBrush
and txtRect
, we invoke the library method DrawText
with the string “Demo
”. Finishing our graphical styling we invoke the method EndPaint
.
We save our progress. Then we build the application and deploy it on our Pocket PC 2003 emulator to see our results.
Now that we implemented our application, we may as well deploy on another device to be cross-platform. We reiterate our steps once again with a different deployment target device. This time our application target device will be a Windows CE device.
In this blog post, we introduced native application development on the Windows CE operating system. Having the capability to build and debug applications on this system will become very useful and important later when researching other applications deployed on devices running with Windows CE operating systems.
CWE-547 USE OF HARD-CODED, SECURITY-RELEVANT CONSTANTS:
Optigo Networks Visual BACnet Capture Tool and Optigo Visual Networks Capture Tool version 3.1.2rc11 are vulnerable to an attacker impersonating the web application service and mislead victim clients.
Optigo Networks recommends users to upgrade to the following:
CVSS v3: 7.5
CWE-288 AUTHENTICATION BYPASS USING AN ALTERNATE PATH OR CHANNEL:
Optigo Networks Visual BACnet Capture Tool and Optigo Visual Networks Capture Tool version 3.1.2rc11 contain an exposed web management service that could allow an attacker to bypass authentication measures and gain controls over utilities within the products.
Optigo Networks recommends users to upgrade to the following:
CVSS v3: 9.8
CWE-547 USE OF HARD-CODED, SECURITY-RELEVANT CONSTANTS:
Optigo Networks Visual BACnet Capture Tool and Optigo Visual Networks Capture Tool version 3.1.2rc11 contain a hard coded secret key. This could allow an attacker to generate valid JWT (JSON Web Token) sessions.
Optigo Networks recommends users to upgrade to the following:
CVSS v3: 7.5
CWE-912 HIDDEN FUNCTIONALITY:
The "update" binary in the firmware of the affected product sends attempts to mount to a hard-coded, routable IP address, bypassing existing device network settings to do so. The function triggers if the 'C' button is pressed at a specific time during the boot process. If an attacker is able to control or impersonate this IP address, they could upload and overwrite files on the device.
Per FDA recommendation, CISA recommends users remove any Contec CMS8000 devices from their networks.
If asset owners cannot remove the devices from their networks, users should block 202.114.4.0/24 from their networks, or block 202.114.4.119 and 202.114.4.120.
Please note that this device may be re-labeled and sold by resellers.
Read more here: Do the CONTEC CMS8000 Patient Monitors Contain a Chinese Backdoor? The Reality is More Complicated….
CVSS v3: 7.5
CWE-295 IMPROPER CERTIFICATE VALIDATION:
The affected product is vulnerable due to failure of the update mechanism to verify the update server's certificate which could allow an attacker to alter network traffic and carry out a machine-in-the-middle attack (MITM). An attacker could modify the server's response and deliver a malicious update to the user.
Medixant recommends users download the v2025.1 or later version of their software.
CVSS v3: 5.7