SharpSploit
SharpSploit copied to clipboard
WOW64 Stub for D/Invoke
Abstract
Two days ago I discussed with @TheWover and @FuzzySecurity about contributing to this project, and they both mentioned that D/Invoke wasn't supporting Windows on Windows x64 (hereby as "WOW64"). I therefore made a custom stub to implement this feature.
WOW64 is a feature that was introduced with Windows XP and that allow the execution of x86 applications on x64 systems. This is done via three main DLLs (hereby as "module"):
-
wow64.dll
for non-GUI-related API calls translation; -
wow64win.dll
for GUI-related API translation; and -
wow64cpu.dll
for x86 emulation.
I don't know the inner mechanisms and how all of that work; however I know that there is an insane number of things that happen for each system calls and re-implementing everything would be a huge piece of work.
Implementation
A normal WOW64 stub from NTDLL is as follows:
0:000> u NtCreateMutant
ntdll!NtCreateMutant:
773b1be0 b8b3000000 mov eax,0B3h
773b1be5 bad0603c77 mov edx,offset ntdll!Wow64SystemServiceCall (773c60d0)
773b1bea ffd2 call edx
773b1bec c21000 ret 10h
773b1bef 90 nop
As shown, there is no system call executed from here, instead the stub call ntdll!Wow64SystemServiceCall
. The problem is that this is a private (i.e. not exported) function and I still did not find a reliable way to retrieve the address of the function.
But this is not a big deal because this is only pointing to a JMP
instruction to an exported function: Wow64Transition
. This function is responsible for switching the segment register (i.e. CPU long mode) to transition from x86 to x64 and therefore to the whNt*
functions.
0:000> u ntdll!Wow64SystemServiceCall L 1
ntdll!Wow64SystemServiceCall:
773c60d0 ff2528824677 jmp dword ptr [ntdll!Wow64Transition (77468228)]
The address of the Wow64Transition
exported function can be easily found by using GetExportAddress()
from SharpSploit.Execution.DynamicInvoke
class. With the address, a custom stub can be created:
0:006> u 04d90000
04d90000 b8b3000000 mov eax,0B3h
04d90005 ff1528824677 call dword ptr [ntdll!Wow64Transition (77468228)]
04d9000b c21000 ret 10h
04d9000e 90 nop
04d9000f 90 nop
If you are executig NtAllocateVirtualMemory
, this should look like that:
- .NET delegate from function pointer (x86)
- Custom stub (x86)
- ntdll!Wow64Transition (x86)
- wow64!whNNtAllocateVirtualMemory (x64)
- ntdll!NtAllocateVirtualMemory (x64)
- syscall (x64)
Final Notes
Target Framework: .NET Framework 4.7.1 Build and Run: Dubug, Release, Release with optimisation Test Program: https://gist.github.com/am0nsec/dc81efa478b7d6c8d948177bcb5a276d
As a solution on Win10 currently this probably works (I haven't tested yet), my issue is compat. One of the reasons to copy the callstub is because they change across Windows versions. See for example WOW64 on Win7:
On 7 neither Wow64SystemServiceCall or Wow64Transition are exported functions. Let me check this out over the weekend and add my comments below 👍
@FuzzySecurity A manual reimplementation shouldn't be as complicated as mentioned above. If you follow Wow64SystemServiceCall
you will notice it's just a chain of calls into an eventual transition back into x64 mode (in wow64cpu.dll) after which a normal x64 syscall is performed before the switch back to WOW64 mode. Furthermore, x64 mode is held in cs:33h
and WOW64 mode is held in cs:23h
which I believe remains static throughout all Windows versions.
Unfortunately lost my C# code to do this (otherwise would offer it as reference) but maybe this could help?
Re-implementing the whole process would be indeed an insane amount of work.
You can transition between x64 and x86 by switching the execution context, this is actually what the Heaven's Gate technique do. However, this is now mitigated by CFG.