Introduction

Using the SetParent function to own other application windows is quite outdated and might not be surprising. This technique is widely adopted in modern web browser
applications such as Google Chrome and Internet Explorer 9. In these applications, one process acts as a container which manages other windows, and other processes work
as if they are child processes or threads. This is the most famous legitimate usage of the technique. However, this article explains how it could be a catastrophe
and suggests protection techniques against attacks presented here.

Why do I bring this old technique up?

Although there are many articles about this topic on the Internet, they focus on manipulating this technique in order to extend the functionality of applications.
For example, many of them introduce and explain how to host other applications in your dialog. However, nowadays in my mind, I am hooked on possible security threats
of the usage of this function.

Briefly, this article explains and demonstrates how the technique can be used to deceive users in order to leak sensitive information. Since it can be deployed
easily in lots of commercial and noncommercial applications, it can be a great security risk.

Level of threats: There is no protection against it

Basically, all things and issues covered by this article can also be implemented by various techniques. A well known approach is injecting code to a process.
Since there is no restriction for code in the same process, everything is possible by injecting a malicious module. However, since it is quite famous, there are many
protection solutions which prevent that. Therefore, although the method presented in here is not powerful as much as the injection method, it is more dangerous than
the previously proposed techniques in that most security solutions such as anti-virus solutions do not alarm and inform the users.

Moreover, as I will explain in a later section of this article, it also allows you to extend a target application to deceive users enter additional data that
was originally not required by the original software. For example, you may add new payment windows in order to obtain users' payment information.

Background I: Windows System

This section covers how a Windows system works in a brief way. The most interesting and surprising thing about the Windows system is that it does not have strict
links between processes and windows. Since the process creates windows, it seems to be obvious that windows must be linked to the creator, a certain process.
However, in reality, there is no specific restriction on the issue.

Therefore, you can create and access any control in the Windows Operating Systems unless these accesses are related to memory accesses. Specifically, some accesses
require memory space in order to store the requested information. For instance, the WM_GETTEXT message returns text which a control owns. To receive data, you must assign
lParam to the memory address. However, since each process has totally isolated memory space, if you want to obtain information by using the
WM_GETTEXT message, you should allocate and access other processes' memory area by using WriteProcessMemory and ReadProcessMemory.
In summary, there is no explicit bar which thwarts the inter-process control access.

Background II: Windows Messages

In this section, I summarize the Windows messaging system in a very concise manner. Basically, most controls have event handlers to response users' requests.
As you might know, each window has a WindowProc function to process their messages. In addition to this, child controls rely on their parent window's message handler.
For example, when users click the button, an event handler, WindowProc, of the parent window receives a WM_COMMAND message with an ID
of the button control (wParam). Since it cannot be changed unless you subclass the control, which usually incurs many problems in runtime when you use it to control
windows in other processes, you should have a control of the parent window of control in order to interact with the user requests. Therefore, it is hard to receive messages
like WM_COMMAND without injecting your code which can be detected by many protection solutions. In short, if you put your control, not a window, on
another application, you should monitor to read the data in your control repeatedly.

The following picture is CuteFTP 8 Lite's login window and I will demonstrate how to replace our control to steal sensitive data in this application.

First of all, I inspected a CuteFTP 8 Lite's login window by using Spy++ to extract the control ID and its window hierarchy. The control ID of the username editbox
is 0xBBB and that of the password control is 0xBBC. By using this information, you can find a CuteFTP login window like the below code.

To obtain data a user typed, a timer is used to periodically call the GetWindowText function. As you might know, using GetWindowText in order to get password text
from out of a process is not possible. Therefore, some articles inject their module to a target process in order to do it. However, as you seen here, it is very
simple to obtain passwords! No injection and extra module!

Moreover, replacing a password window with your own window is also possible. Additionally, you can apply this technique payment application in order to steal
information such as your card number and security number such as your password. (Note that I do not demonstrate it in here due to its impact.)

Demo II: Inserting an editbox control for payment information

Now I am trying to add a new feature to an existing application to make a user enter additional data.

I added new labels and an editbox in order to obtain the card number and its security number. To make it more convincing, I also wrote a description above
the controls. However, if you change a static control's parent into UltraEdit's window, the static control's background color becomes white. This is because the background color
of the control is determined by the WM_CTLCOLOR message which is sent to the parent window's event handler. Since the parent window, About window, does not know
the injected control's existence, the control has a NULL background color, white.

One option to figure out this problem is to subclass the control and process the WM_PAINT message.
In the MFC application, you can subclass windows by creating derived classes and inheriting it.

Now, you can see more convincing windows as shown in the below picture.

It is very difficult to be identified by users since there is no indication whether or not it is from UltraEdit. In other words, it is much more dangerous
than phishing web sites since it doesn't have any URL which informs users that they are currently in the wrong place.

The CHiJackDlg::Hijack_UltraEdit_1() function does what I've explained in this section. Since there is no difference in techniques except what I stated above,
I have not posted the source code in here. If you want to see the code, please download the sample project.

Demo III: Adding new feature to deceive a user to enter additional data

In this section, I will demonstrate new features. Since lots of previous techniques focus on monitoring sensitive user information, they depend on what
applications request. For example, if an application does not have any payment window, monitoring applications are not able to have payment information. However,
in here, I present a tricky method to obtain payment information in an application which does not have any payment function.

For the demonstration, UltraEdit's About window is also used. The first process replaces the 'Buy Now!' button with your own button. However, as I mentioned
above, just inserting a button into the other process is not working since WM_COMMAND is sent to its parent window. Therefore, I try to insert a child dialog with the button.
Let's see the following steps.

Create a dialog in the resource editor. (IDD_CHILD)

Change the dialog style to Child and the border option to None.

Add a button (IDC_BUTTON1) on IDD_CHILD.

Change the button name to '&Buy Now!'

Add the AttachWithSize function to the dialog class.

Add an event handler on the button (OnButton1).

Create a dialog in the resource editor. (IDD_PAYMENT)

Check the 'Center' option in the More Styles tab.

Place controls and code whatever you want, as shown in the below picture.

In this case, WM_COMMAND messages of the button are sent to the IDD_CHILD window. Although IDD_CHILD will not receive messages since the parent
window does not know the existence of IDD_CHILD, we can achieve most of our goal in this way.

By using this method, you can add full featured dialogs including resources and embedded web browsers. In addition, all processes are just same
as what you implement for normal applications.

Protections: Protect against above attacks

The easiest way to prevent the above techniques is to run a thread that monitors windows from other processes. By using
EnumChildWindows() and GetWindowThreadProcessId(), you can identify all windows which are shown in your dialog.

In addition, you may check your control's visibility and position periodically. If there is any change, it should be prevented. After identifying injected controls,
the best way to protect applications is to destroy them. However, since they belong to another process, the DestroyWindow API cannot destroy it. Therefore, the second solution
is to disable and hide injected controls to prevent a user from entering sensitive information.

The below code shows the first possible protection solution I discussed in this section.

More aggressive protection can be implemented by using API hooks and filtering the SetParent and CreateWindow API which can specify a control's parent.
Although it is not a difficult task, I do not include the code since it could take quite a long time to test it.

What can be and cannot be

Since Windows Vista and 7 have introduced UAC which blocks all message exchanging activities among different UAC levels, it is not able to use
the SetParent function to replace controls with windows from processes that have a lower UAC level.

Additional note on target applications

In this article, I chose CuteFTP and UltraEdit to demonstrate how the technique works. As you might know, the content of this article can be applied
for any kind of application. Therefore, the reason why I demonstrate the method on these applications is just for convenience, not trying to show that they are vulnerable.

If anyone feels this is improper, please let me know of another way to present this idea. Thanks!

Comments and Discussions

You are right, process memory is isolated and each process has their own address space. Your conclusion that you cannot successfully send WM_GETTEXT to a control in another process is wrong, though. Standard Windows messages (WM_NULL through WM_USER - 1) are automatically marshaled across process boundaries.