TheWover / donut

Generates x86, x64, or AMD64+x86 position-independent shellcode that loads .NET Assemblies, PE files, and other Windows payloads from memory and runs them with parameters
BSD 3-Clause "New" or "Revised" License
3.61k stars 638 forks source link

[Feature] Add ETW Bypass #47

Closed TheWover closed 1 year ago

TheWover commented 4 years ago

ETW Bypass

Feature addition for v0.9.3.

Event Tracing for Windows can be used to monitor the CLR for events related to the loading of .NET Assemblies from memory. As Adam Chester (xpn) recently demonstrated in his blog, it can be bypassed in-process like with AMSI: https://blog.xpnsec.com/hiding-your-dotnet-etw/

For v0.9.3, we should add ETW bypasses to the modular bypass system like we have for AMSI and WLDP. I propose the following techniques for bypassing ETW:

1) Patching ntdll!EtwEventWrite to return rather than that send an ETW message. Same as in xpn's blog post. 2) Hook ntdll!EtwEventWrite, filter for events related to the CLR, and drop all of them. 3) Hook ntdll!EtwEventWrite, filter for events related to the loading of Assemblies from memory, and swap their information so that it appears that mscorlib.dll is being loaded instead.

These bypasses demonstrate three different types of ways to attack ETW and should be a sufficient starting point for anybody wanting to add more sophisticated implementations.

For 2 and 3, we would need to add a simple hooking mechanism into Donut. We had discussed this in the past. I think this is finally a use case worth adding it into Donut. An open question then, is how do we want to add the hooking functionality? I propose adding loader/hook.c and using a very simple implementation of EAT Hooking. I welcome input on this.

This will be the last significant feature addition for v0.9.3 final release.

odzhan commented 4 years ago

1 would be easy to implement. 2 and 3 would be a little more difficult because it requires data as well as code. I'm not familiar with how ETW works, what messages to look for and what to filter from being passed on to the real function. If you can implement 2 and 3 using some managed/unmanaged demo code, I can translate that to a PIC in C.

TheWover commented 4 years ago

Cool, I'll try to do that. I know b33f got something similar working using Fermion: https://twitter.com/FuzzySec/status/1240659417219170304 . I'll try to reproduce it on my own

TheWover commented 4 years ago

Lol, OutflankNL just published an example of how to do this in C. Great timing! https://github.com/outflanknl/TamperETW

TheWover commented 4 years ago

If we end up using ETW to monitor for the conditions necessary for unloading the new ApplicationDomain, then we will need to be careful with the ETW bypasses. Using xpn's technique of patching out EtwEventWrite prevents any ETW messages from being sent... which prevents us from using ETW to monitor our own process. Fortunately, the most sohisticated bypasses of filtering ETW events would not prevent using ETW for monitoring.

TheWover commented 4 years ago

Added initial ETW bypass (bypass A) that is based on Adam's bypass that he described in his blog post. Added the code and updated the makefiles. Tested the bypass, checking the process's list of loaded Assemblies with Process Hacker. It did not see the ones that were loaded, demonstrating the bypass.

In testing, the bypass and the loader worked fine when run inside of loader in debug mode. But when injected into notepad, the shellcode loaded the CLR but did not execute the Assembly successfully. Not sure why yet, will need to debug some more.

This initial version will need to be expanded on and probably cleaned a little, but is a good starting point.

image

TheWover commented 4 years ago

After playing around with NtQuerySystemInformation recently to enumerate handles, I think you may be able to close / unregister EtwRegistration handles in order to disable ETW registrations in a local/remote process. This is a note to self to investigate this. Would be much safer and covert than code patching.

TheWover commented 4 years ago

If I can, I'll try this out over the next couple days if I can.

TheWover commented 4 years ago

https://docs.microsoft.com/en-us/windows/win32/api/evntprov/nf-evntprov-eventunregister

TheWover commented 4 years ago

From a bit of Ghidra, looks like Advapi32.dll!EventWrite is just a forward to ntdll.dll!EtwEventWrite. Should be able to use either one.

TheWover commented 4 years ago

As an update, this other bypass is in progress. It is more stable than patching.

TheWover commented 1 year ago

As another update, the patching bypass is completed and works. Others may be added later, but this is the simplest version and is what will be in v1.0