Closed TheWover closed 1 year 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.
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
Lol, OutflankNL just published an example of how to do this in C. Great timing! https://github.com/outflanknl/TamperETW
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.
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.
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.
If I can, I'll try this out over the next couple days if I can.
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.
As an update, this other bypass is in progress. It is more stable than patching.
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
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) Hookntdll!EtwEventWrite
, filter for events related to the CLR, and drop all of them. 3) Hookntdll!EtwEventWrite
, filter for events related to the loading of Assemblies from memory, and swap their information so that it appears thatmscorlib.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.