,, MMP""MM""YMM `7MM P' MM `7 MM MM MMpMMMb. .gP"Ya MM MM MM ,M' Yb MM MM MM 8M"""""" MM MM MM YM. , .JMML. .JMML JMML.`Mbmmd' `7MMF' `7MF' `7MMF' `7MMF' `MA ,V MM MM VM: ,V `7M' `MF' MM MM .gP"Ya ,6"Yb.`7M' `MF'.gP"Ya `7MMpMMMb. MM. M' `VA ,V' MMmmmmmmMM ,M' Yb 8) MM VA ,V ,M' Yb MM MM `MM A' XMX MM MM 8M"""""" ,pm9MM VA ,V 8M"""""" MM MM :MM; ,V' VA. MM MM YM. , 8M MM VVV YM. , MM MM VF .AM. .MA..JMML. .JMML.`Mbmmd' `Moo9^Yo. W `Mbmmd'.JMML JMML. ,, ,, ,, .g8"""bgd `7MM `7MM mm db .dP' `M MM MM MM dM' ` ,pW"Wq. MM MM .gP"Ya ,p6"bo mmMMmm `7MM ,pW"Wq.`7MMpMMMb. MM 6W' `Wb MM MM ,M' Yb 6M' OO MM MM 6W' `Wb MM MM MM. 8M M8 MM MM 8M"""""" 8M MM MM 8M M8 MM MM `Mb. ,'YA. ,A9 MM MM YM. , YM. , MM MM YA. ,A9 MM MM `"bmmmd' `Ybmd9'.JMML..JMML.`Mbmmd' YMbmd' `Mbmo.JMML.`Ybmd9'.JMML JMML. -- Contact -- https://twitter.com/vxunderground email@example.com
On 64-bit platform, there is only one ntoskrnl.exe, and it is 64-bit code. It also uses a different calling convention (registers, so called "fastcall") compared to 32-bit code (stack, so called "stdcall", old name was "pascal"). So how can 32-bit code run on 64-bit platform? There is "thunking" layer in wow64cpu.dll, which saves 32-bit state, converts parameters to 64-bit form, then runs "Wow64SystemServiceEx" in wow64.dll. But 64-bit registers are visible only in 64-bit mode, so how does wow64cpu.dll work? Here is what I call Heaven's Gate, but first we must go back to ntdll.dll.
When an important function is called from a DLL like kernel32.dll, it calls into the native interface in ntdll.dll. The native interface powerful but mostly undocumented layer between user-mode and kernel-mode. For some detail, see my Chthon code in 29A#6. It used to be that to call into kernel mode, the code would do this:
In Windows XP, it became possible to use sysenter instead of int 2eh, for better performance. In 64-bit Windows, a "xor ecx, ecx" was added because of 64-bit pointer size, and the int 2eh was replaced by:
and now we are one step closer to Heaven's Gate. The field at fs:[0c0h] is called WOW32Reserved, and holds an address in wow64cpu.dll. If we follow the call, we reach a jump. A far jump. A special far jump. Heaven's Gate.
The jump in wow64cpu.dll is a 64-bit gate. We can jump through it into the world of 64-bit code: 64-bit address space, 64-bit registers, 64-bit calls. We might think that jumping into wow64cpu.dll is useless because we cannot control where it goes after that, but of course we can change the address ourself to anywhere we like. We can alter the address inside wow64cpu.dll, we can alter the address at fs:[0c0h], or we can just call through the gate on our own. The gate maps the entire 4Gb of memory, and the selector value is always 33h. We can switch between the modes easily, too. All we need is the return address on the stack. We can switch modes in this long way:
To switch back to 32-bit code can be done this way:
Once in 64-bit mode, we can only use the native interface in ntdll.dll The 0eah-style jmp not supported in 64-bit mode, and there are no absolute memory addressing in 64-bit mode. All addressing is rip-relative, which is why the jmp is relative to the fr64 label.
Of course there's a simpler way, which looks like this:
To switch back to 32-bit code, just use a 32-bit retf. That's much easier.
Once in 64-bit mode, we can only use the native interface in ntdll.dll because the kernel32.dll in our process memory is 32-bit, and won't run in 64-bit mode. We can get the base address of ntdll.dll this way:
Best of all, Yasm now allows mixing 32-bit and 64-bit code in the same file. When I was writing Shrug48 (because half-way between 32-bit and 64-bit), this was not possible, so I had two source files that had to be built separately and then concatenated afterwards. Now with Yasm, we can use "bits 32" before the 32-bit code, and "bits 64" before the 64-bit code, anywhere in the file, and we can swap between them as much as we want, like this:
Using the gate is another way to check for 64-bit support, without using the obvious IsWow64Process API call. Just place a SEH around the call, and if an exception occurs, then you are on a 32-bit platform.
64-bit code in 32-bit files. The ultimate emulator killer. ;)
Active - Benny - izee - Malum - Obleak - Prototype - Ratter - Ronin - RT Fishel - sars - SPTH - The Gingerbread Man - Ultras - uNdErX - Vallez - Vecna - VirusBuster - Whitehead