Team82 Logo Claroty
Return to Team82 Research

Delving Into Windows CE: Let’s Build an Embedded Windows Application, Part 1

/

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.

An HMI panel running on the Windows CE OS.

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.

A vending machine running on the Windows CE OS.

An example of a vehicle infotainment center on Windows CE.

Setting up Windows CE Application Development

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.

Creating A New Project

Starting by creating the new project in Visual Studio 2005, Select File→New→Project.

Creating a new project in Visual Studio 2005.

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.

The Visual Studio 2005 new project template.

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.

Wizard window to configure our project settings, Click Next >
Application Setting view: Set our application target to be executable.

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.

Solution Explorer of our application project.

Opening the T82.cpp C++ module file we find that most of the boilerplate code has been lifted for us by our trusty IDE.

Initial state of our main C++ application module.

As we can see, we have our main routine exported as a global symbol for our program to invoke at runtime.


Windows CE Application Implementation

Creating an Application Window

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.

T82.cpp module implementation yielding a raw window in our application.

Now let us break down each component in the image so we can better understand how to interpret this module's code.

Window Processing Function - WinProc(...)

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.

Registering A Window Class - RegisterClass(&cls)

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.”

Creating A Window: 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.

Pocket PC 2003 emulator with our deployed application up and running.

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.

Adding Graphical Elements to our CE App

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)

Loading a bitmap resource, and error prompting upon loading failure.

Painting An Image

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.

Code block handling the painting of an image and text on the application window

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.

Explanation for the term Device-Context according to the MSDN specification.

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

Painting Text

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.

Our simple graphical application.

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.

Running T82 application on a Windows Embedded device

Wrapping Up

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.

Stay in the know Get the Team82 Newsletter
Recent Vulnerability Disclosures
Claroty
LinkedIn Twitter YouTube Facebook