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

PE Loader: No RWX Memory #38

Closed wumb0 closed 3 years ago

wumb0 commented 4 years ago

Small change to avoid RWX memory in the PE loader. This change sets section permissions appropriately. Maybe there was a reason you didn't include this; in that case just decline the pull!

Cool tool! Thanks!

odzhan commented 4 years ago

Hello, thanks for the patch and glad you like the tool. While it makes sense to set the appropriate permissions for each section of the PE file mapped into memory, unfortunately this additional step doesn't prevent detection of the loader. Hence, the reason it was never implemented by us.

The type of pages allocated for the PE file via VirtualAlloc are of type MEM_COMMIT. So, If someone wants to find suspicious pages with shellcode or the Donut loader, the simple way is to check the State field of MEMORY_BASIC_INFORMATION returned by VirtualQueryEx for MEM_COMMIT.

@TheWover has been researching stealthier injection techniques lately, so there may be a way to hide Donut from memory scanners in the future. For now I'll leave this open as a reminder of what needs to be done for v1.0.

TheWover commented 4 years ago

@wumb0 Thanks for the PR! As @odzhan said, for now we'll leave this open as a reminder for v1.0. If we make any changes to the PE loader, we'll add them to that release. As he mentioned, I have been researching ways to covertly store PEs in memory for execution using Module Overloading. Eventually, I would like to add Module Overloading to Donut. If/when we do, we'll use your logic to make sure that the PE sections are the correct permissions inside of the shared memory section that the PE is stored in.

wumb0 commented 4 years ago

thanks for the quick responses. makes sense to me. looking forward to reading through your module overloading implementation. wondering how you'll pick a "safe" DLL to load and hollow out :)

TheWover commented 4 years ago

@wumb0 In the meantime, if you're curious, you can check out how we did it for SharpSploit. ;-)

https://github.com/cobbr/SharpSploit/blob/52ad861d98d75bb0a7f6cd9d421dc8a8463adc08/SharpSploit/Execution/DynamicInvoke/Generic.cs#L1096-L1236

TheWover commented 3 years ago

While it may still be detectable, this is an improvement. My intention in the short term is to merge this, then separately switch to using NtCreate/Map/UnmapViewOfSection instead of VirtualAlloc/VirtualFree. This accomplishes the following:

1) Uses alternative API calls that are slightly less likely to be hooked 2) Makes it easier to later switch to use Module Overloading 3) The PE sections, protected as the PE specifies, sitting in a memory Section is slightly less anomalous than it sitting in memory allocated by VirtualAlloc.

Again, this does not in any way prevent detection, but it is a slight improvement and will enable future features.