Introducing Aladdin, a new tool and technique for red teamers to bypass misconfigured Windows Defender Application Control (WDAC) and AppLocker. Aladdin exploits a deserialisation issue over .NET remoting in order to execute code inside addinprocess.exe
, bypassing a 2019 patch released by Microsoft in .NET Framework version 4.8.
Download Aladdin
GitHub: https://github.com/nettitude/Aladdin
A travel to the magic land of .NET deserialization
Once upon a time, in the mysterious land of cybersecurity, there was a red teamer named Aladdin. Aladdin was frustrated, since most of the payloads that he was using at the time were not able to run on a system with application control lists enabled, and those powerful EDR creatures that the evil Blue Lord had created were killing all his beacons.
One day, while out on a mission, Aladdin stumbled upon a strange magic lantern. As he picked it up, a genie appeared before him and granted him three wishes. Without hesitation, Aladdin thought of his first wish.
“I wish I could find a payload that would be able to execute on a WDAC enabled Windows 10 system”.
The genie granted his wish and disappeared, leaving Aladdin with the magic lantern at hand. Excited to test out his new power, Aladdin set to research existing techniques for bypassing WDAC / AppLocker. While consulting the majestic oracle named Google, he came across an article from the magician James Forshaw named “DG on Windows 10 S: Executing Arbitrary Code”. The article was written in 2017 and went into great detail about the Microsoft .NET process addinprocess.exe
, residing in every Windows workstation (with Microsoft .NET installed). Add-ins are effectively a form of plugin model that the .NET Framework provides, enabling developers to create plugins for their applications. The model achieves this by constructing a communication pipeline between the host and the add-in.
As discovered by the magician, the process once launched would use the method ChannelServices.RegisterChannel to register a .NET remoting channel, a topic he was quite familiar with exploiting. The topic was also covered by other magicians more recently. Besides creating a .NET remoting channel, the magician identified that the process would use the BinaryFormatter Class to deserialize input in binary format, while setting the TypeFilterLevel to Full.
Microsoft clearly state that BinaryFormatter cannot be made secure.
According to Microsoft, “.NET Framework remoting provides two levels of automatic deserialization, Low and Full. The Full deserialization level supports automatic deserialization of all types that remoting supports in all situations”. When decompiled, addinprocess.exe
uses TypeFilterLevel.Full
.
This effectively meant that any data passed to the .NET Remoting channel would be deserialized, without worrying about any security controls that the Low
deserialization level for .NET Framework remoting would enforce.
Aladdin, following the magician’s steps, identified that in order to launch the addinprocess.exe
, the argument of /guid:[GUID] and the argument of /pid:[existing PID] should be provided.
The /guid argument was user controlled and was being used as the IPC channel name. The /pid argument referred to the process identifier of an already running process, that addinprocess.exe
would wait until exit.
After reading through the article multiple times, Aladdin set out to create a new WDAC enabled Windows 10 system in order to test the original proof of concept. Useful resources for creating such a policy were that of WDACTools from Matt Graeber and Building a windows defender application control lab from FortyNorth.
The POC effectively was creating a correctly formatted set of bytes, based on the .NET remoting protocol, followed by the serialized provided assembly and the IPC endpoint
The output of the POC was a binary array being placed in a template JScript SCT payload.
Aladdin went ahead and tried out the generated SCT payload, but to no avail.
Unfulfilled, he sought further consultation from the great oracle Google, which revealed that the giant Microsoft had already put out some magic defences that stopped this powerful attack.
As he began poking and prodding at the patch, the magic lantern glowed brightly, reminding him that he had two additional wishes.
Aladdin decided to use his second wish.
“I wish I could find a bypass for the patch applied by the great giant”
The genie again granted his wish and disappeared, leaving Aladdin with the magic lantern at hand and a blog post from the mage Nick Landers – Re-Animating ActivitySurrogateSelector.
Reading the article initially, Aladdin was feeling that he was reading some arcane powerful knowledge that he could not understand, but with every additional read, it became increasingly evident that the patch, besides adding a type check in the GetObjectData function looking for object types of ActivityBind
or DependencyObject
, also introduced a new function named DisableActivitySurrogateSelectorTypeCheck.
The function was effectively responsible for checking a flag via ConfigurationManager.AppSettings, which in turn was a property that allowed the programmatic reading / writing of the AppSettingsSection
of an application.
One of the great things that the mage Nick Landers discovered was the following C# code that disabled the type check:
And a new commit was made to the powerful project YSoSerial.Net.
Aladdin immediately started thinking on how to incorporate this bypass into the original POC, and after a few moments / hours / days (time is relative) of tinkering, managed to:
- Create a gadget that disables the
ActivitySurrogateSelector
using the ysoserial.net project (payload1.bin
). - Modify the original POC of James Forshaw by first setting
DisableActivitySurrogateSelectorTypeCheck
to true. - Generate a simple payload that would pop a message box using the POC of James Forshaw (
payload2.bin
). - Spawn Addinprocess in his test VM with the correct arguments. Once spawned, the
addinprocess.exe
created a new named pipe under\\.\pipe\32a91b0f-30cd-4c75-be79-ccbd6345de11
, where .NET remoting was listening. - Send the first binary payload to the newly created pipe from cmd, to disable
ActivitySurrogateSelector
(type payload1.bin > \\.\pipe\32a91b0f-30cd-4c75-be79-ccbd6345de11
) - Send the second binary payload to the named pipe, to trigger the deserialization code execution (
type payload2.bin > \\.\pipe\32a91b0f-30cd-4c75-be79-ccbd6345de11
). - Stare at his screen.
The genie had granted his wish, and he was able to execute an arbitrary C# assembly via deserialization inside the Microsoft signed process addinprocess.exe
.
The original POC also provided an SCT template that executes the attack via JScript, using Scripting.FileSystemObject
. This object is useful since it allows writing to a named pipe although the scriptlet hosting environment is severely limited to which COM objects can be created, in a WDAC enabled system.
Without losing any time, Aladdin proceeded to create a tool that given a C# assembly DLL, would generate a BinaryFormatter
serialized payload incorporating the bypass and the .NET Remoting bytes needed to communicate over the named pipe. Using the provided SCT template as a base, Aladdin also created templates for HTA / VBS / CHM / VBA allowing the execution of the payload from these old trusty vectors.
Happy that everything was working, and his payloads were not being caught, Aladdin became immediately worried that this technique could be abused for evil purposes and as such he went ahead and researched what could be done in order to prevent it.
The big giant Microsoft goes into great lengths detailing the risks of BinaryFormatter
deserialization vulnerabilities and includes advice on blocking the addinprocess.exe
executable via their recommended block rules. These rules could also be applied via a supplemental WDAC policy or via a third-party application control software.
If prevention controls cannot be applied, then process creation visibility could help detecting the execution of process (which in most environments should not be that common).
While finalizing the code, Aladdin saw the magic lantern glowing again, reminding him that he had a third and final wish. Without much hesitation Aladdin decided to use his last wish:
“I wish I could write an article about this tool”