Teaching an Old Framework New Tricks: The Dangers of Windows UI Automation
Editorial and additional commentary by Tricia Howard
Executive summary
Akamai security researcher Tomer Peled explored new ways to use and abuse Microsoft's UI Automation framework and discovered an attack technique that evades endpoint detection and response (EDR).
To exploit this technique, a user must be convinced to run a program that uses UI Automation. This can lead to stealthy command execution, which can harvest sensitive data, redirect browsers to phishing websites, and more.
Detection of this technique is challenging in several ways, including for EDR. All EDR technologies we have tested against this technique were unable to find any malicious activity.
This technique can be used on every Windows endpoint with operating system XP and above.
In this blog post, we provide a full write-up on how to (ab)use the UI Automation framework (including possible attacks that could leverage it) and we present a proof of concept (PoC) for each abuse vector we discuss. We also provide detection and mitigation options.
Introduction
Those of us who write for a living love dictation and grammar-checking software. Those of us who do security research for a living like to break stuff and write about it. So, after months of seeing ads for these writing assistants, we decided to tinker around and see what we could find.
Specifically, we wanted to understand how an application can manipulate another application’s user interface (UI) remotely. What we discovered was just as shocking as learning that people still run XP: It is processed by a very old framework called the UI Automation framework.
This framework was conceived in the days of Windows XP as a way to help people with disabilities use the computer more easily. It was given elevated permissions to help with things like enlarging text, reading text out loud, and even simulating clicks (in some situations). To do this UI Automation needs permission to manipulate almost any UI element that is present on the screen, which makes sense considering the intended purpose: The technology will only do what it’s told it can and can’t do.
This is where we began our research journey to figure out the impact attackers can have if they abuse UI Automation.
We found that attackers can abuse UI Automation to exfiltrate data, manipulate internet browsing, execute commands, and even read and write(😱) messages from chat applications like WhatsApp or Slack. And all of this went undetected by every EDR vendor we tested.
This blog post will give you everything you need to know about this framework from how it works to how its features can be abused. We will conclude with detection and mitigation options for blue teamers.
Interacting with UI Automation via COM
To interact with elements in other applications, the UI Automation framework (UIA) leverages the Component Object Model (COM) as its interprocess communication (IPC) mechanism.
COM is a framework that was designed by Microsoft to allow different programs to communicate with one another regardless of the language they are written in or compiled with. The COM framework allows developers to create components called COM objects. These objects are registered on a Windows endpoint with their name, a universally unique identifier (UUID), and a binary that contains their logic and other configurable values.
To interact with UIA users create its COM object by calling the function “CoCreateInstance” with the CUIAutomation class UUID and UIAutomation interface UUID as seen in the table.
CUIAutomation UUID |
ff48dba4-60ef-4201-aa87-54103eef594e |
UIAutomation interface UUID |
30cbe57d-d9d0-452a-ab13-7ac5ac4825ee |
During the creation of the COM object, the system will load the DLL that is specified in the registry, which in this case is “UIAutomationCore.dll.”
Does any of this sound familiar? The eagle-eyed reader may have noticed that this all sounds similar to our extensive examination of MS-RPC. COM uses RPC as a foundation, hence their similarities.
UI Automation — Hello World
Before jumping into how attackers might abuse this framework, you may want to review how to interact with UIA in general (with C++). This will give you the background to see where things went wrong with the implementation of this framework. You can review how to interact with UIA on our GitHub.
Once the UIA object is created, its DLL will be loaded into the user’s application, as well as every other process that has any UI elements.
Nothing else will occur until we add event handlers for remote process UI changes. The example below shows how to set up a handler for any changes in the tooltip that is currently opened for a user.
ppAutomation->AddAutomationEventHandler(UIA_ToolTipOpenedEventId, pTargetElement, TreeScope_Subtree, NULL, (IUIAutomationEventHandler*)whatsappEventHandler);
Once this is done, UIA will open up a “server” on the remote process that communicates with our application (Figure 1). The data that is transferred between them is information on all UI elements of the remote process.
According to the Microsoft’s documentation, the following handler prototype is the standard handler that UIA expects:
HRESULT HandleAutomationEvent(
[in] IUIAutomationElement *sender,
[in] EVENTID eventId
);
We can identify the exact application that was brought to the front of the UI (by opening it or by any other means) by invoking the function “sender.get_CurrentName” from inside the handler. Now that we can pinpoint which application is in focus, we can try to read/write to it.
To do so, we need to find an element that we want to read/write from by iterating through all the elements (which are descendants of sender element) and either reading their UI value, changing their text value, or retrieving their invokable element and calling its “Invoke” function (Figure 2).
Abusing UI Automation for malicious activities
In the last section we talked about how to abuse UIA, now we’re going to talk about the possible malicious activities afforded by the abuse. The best way to show these is through examples, and we’ve got three:
- Reading and writing messages
- Stealing sensitive data
- Executing commands
Reading and writing messages
Every messaging application has a graphical user interface (GUI) that contains different types of UI elements that we can access using the UIA. Figure 3 is an example of Slack's GUI, which likely looks familiar to you.
The available actions within a GUI span from selecting conversations (which are implemented as buttons behind the scenes) to reading messages (text blocks), so we have a plethora of things we can interact with.
Once an attacker is able to “connect” to the UI window of such an application, they can simulate a click on the conversation they want (through the UI button element) and enter it. From there they can choose to either read the conversation and exfiltrate the data and/or find the UI element that is responsible for writing a message, change the value of the text in its TextArea element, and simulate a click the send button.
Of course, this type of manipulation would be reflected on the screen as well, leaving a lot up to chance on the attacker’s side. A stealthier approach would be to read-only from the currently open conversation and collect data over a longer period (Figure 4).
Another option to maintain stealth without taking a passive approach is to use the caching mechanism of UIA. In addition to the UI elements currently shown on the screen that we can interact with, more elements are loaded in advance and placed in a cache. We can also interact with those elements, such as reading messages not shown on the screen, or even set the text box and send messages without it being reflected on the screen.
Although we could not verify it before this blog post went live, the caching mechanism might also allow us to interact with those elements while the computer is locked, allowing us to go wild with our interactions and remain completely unknown to the user.
Stealing sensitive data
One of the more damaging ways we thought of to (ab)use UIA is to steal credit card information.
After a user enters an online merchant, an attacker can programmatically listen to changes in the UI elements by setting up a handler. Once a change has been made (that is, credit card information has been entered), the attacker can retrieve the text from the UI elements for later exfiltration (Figure 5).
Executing commands
Another common attack path on browsers is via phishing and browser redirections.
By filtering out firefox/chrome/edge UI windows, attackers can simply search for their search bar UI element and set its value to what they want and simulate a click (Figure 6). To make it more stealthy, they can wait for the moment the currently shown web page refreshes or changes, so that the change to a different website is less noticeable.
This would allow attackers to redirect users to malicious sites in their control. From there, the possibilities are effectively endless: browser exploitation (e.g., using the Browser Exploitation Framework [BeEF]), drive-by attacks, legitimate site masquerade for phishing or credential harvesting, and more.
Potential impact of UI Automation
The attacks we discussed in the previous sections have been around for decades with different implementations, and most defense tools know how to detect and respond to them.
However, everything we discussed above is considered a feature of UI Automation. This goes back to the intended purpose of the application: Those permissions levels have to exist in order to use it. This is why UIA is able to bypass Defender — the application finds nothing out of the ordinary. In fact, no EDR we tested was able to see these actions as malicious — likely for the same reason. If something is seen as a feature rather than a bug, the machine’s logic will follow the feature.
This makes this framework potentially very lucrative for attackers and it’s why we believe higher awareness is key for dealing with this attack vector.
Further research
UIA over DCOM
Distributed COM (DCOM) is a way to call COM objects remotely between machines. Theoretically, it should be possible to remotely access the UIA over DCOM, thereby allowing all the attacks we’ve discussed to be executed without the phishing/local access requirement.
As part of our analysis, we realized that UIA’s COM object isn’t configured to allow DCOM by default. This significantly decreases the attack potential, barring misconfiguration.
Although UIA itself isn’t available through DCOM, we did find something related: theUIAutomationCrossBitnessHook COM/DCOM object. This object does not require a privilege for remote activation and execution.
By reversing its DLL we found its interface contains two functions: one to set the UI manager and the other to unset it. It seems that it doesn’t have any other remote functionality, so we couldn’t use it to read or write data, but it could be a nice research target for the future.
UIA named pipes
Earlier in the post we mentioned that UIA opens up a “server” on a remote process. Behind the scenes these servers and clients are implemented using named pipes. The naming convention consists of the constant string UIA_PIPE followed by the process ID and some other identifier (Figure 7).
Now, this is where it gets scary: Named pipes can accept remote connections. This is very dangerous in this case because it means that an attacker might be able to manipulate UI elements over the network. When we tried to connect from a remote server, however, we ran into an ACCESS_DENIED error.
This is because Microsoft set the flag PIPE_REJECT_REMOTE_CLIENTS when creating the named pipe. This means that we can’t access the UIA remotely via those pipes, but they are still available locally. It is possible to enumerate those pipes (without guessing the process ID or identifier) and access them,which might pave the way to some sort of privilege elevation attacks or impersonation, though that was not a part of this analysis.
Detection/mitigation
Microsoft recognized that this framework should not interact with higher privilege applications. Therefore, by default, applications that use the UI Automation framework run at medium trust level and are not allowed to access higher privilege processes. This can be bypassed using a signed application with a manifest file containing the key requestedExecutionLevel.uiAccess set to true:
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="highestAvailable"
uiAccess="true" />
</requestedPrivileges>
</security>
</trustInfo>
As for detection, administrators can monitor the use of the UIAutomationCore.dll. If it is loaded to a previously unknown process, it should raise legitimate cause for concern.
Similarly, network administrators can monitor the named pipes that are opened on an endpoint by the UIA, as another indicator of its use, which you can do using the following osqueries:
SELECT DISTINCT pid, name, proc.path FROM process_memory_map AS pmm JOIN processes AS proc USING(pid) WHERE pmm.path LIKE '%uiautomationcore.dll'
Processes that load UIAutomationCore.dll
WITH uia_pipes AS (SELECT name AS pipe_name, SUBSTR(name, 10, INSTR(SUBSTR(name, 10), '_')-1) AS pid FROM pipes WHERE name LIKE 'UIA_PIPE_%' ) SELECT DISTINCT pid, name AS process_name, path, pipe_name FROM uia_pipes JOIN processes USING(pid)
Processes that opened the UI Automation named pipe
Conclusion
This analysis is an unfortunate example of how technology created for good can be hijacked for malicious purposes. Although the UI Automation framework can be helpful for people with disabilities, it also provides opportunities for attackers to mimic spyware.
While the exploitation of UIA may be more difficult than some other attacks, the fact that EDR cannot detect it may make UIA a highly attractive attack surface. In an effort to reduce its attractiveness to threat actors, Microsoft has placed some restrictions on UIA, but attackers can still take advantage of it with the proper amount of skill. Our hope is that this blog post will raise awareness about this attack technique and help blue teamers defend themselves against such an attack vector.