A touch of WoW64

Windows has long moved to 64-bit, and the kernel is 64-bit. However, we also notice that 64-bit Windows can run 32-bit code with seemingly no issues at all. The reason for this is that Microsoft implemented a translation layer between the 32-bit code and the 64-bit OS, and this is (largely) implemented in wow64cpu.dll and wow64.dll.

Put very simply, the core task of wow64cpu.dll is to save the 32-bit state, convert everything to 64-bit, and call Wow64SystemServiceEx(), which is found in wow64.dll. Wow64SystemServiceEx() then re-packages the call into a 64-bit version (converting the parameters to 64-bit), making the actual system call into the kernel, grabs the 64-bit returned results, re-packages them back to 32-bit, and passes it back to the 32-bit program.

This is made more obvious by comparing how system calls are made in a native x86 code (32-bit Windows), versus a Wow64 piece of code.

Native x86 (e.g. ntdll.dll in 32-bit Windows):

mov eax, 30h        ; Some system call number
mov edx, offset SharedUserData!SystemCallStub
call dword ptr [edx]

Wow64 (e.g. ntdll.dll in 64-bit Windows):

mov eax, 0A5h       ; I used ntdll!NtCreateThreadEx
xor ecx, ecx        ; It's a 64-bit register
lea edx, [esp+4]
call dword ptr fs:[0C0h]

The key difference is the call, where in Wow64, it’s call fs:[0C0h]. Since fs:[0] points to the TEB, examining the TEB reveals the following:

0:001> dt ntdll!_TEB
   +0x000 NtTib                        : _NT_TIB
   +0x01c EnvironmentPointer           : Ptr32 Void
   +0x020 ClientId                     : _CLIENT_ID
   +0x028 ActiveRpcHandle              : Ptr32 Void
   +0x02c ThreadLocalStoragePointer    : Ptr32 Void
   +0x030 ProcessEnvironmentBlock      : Ptr32 _PEB
   +0x034 LastErrorValue               : Uint4B
   +0x038 CountOfOwnedCriticalSections : Uint4B
   +0x03c CsrClientThread              : Ptr32 Void
   +0x040 Win32ThreadInfo              : Ptr32 Void
   +0x044 User32Reserved               : [26] Uint4B
   +0x0ac UserReserved                 : [5] Uint4B
   +0x0c0 WOW32Reserved                : Ptr32 Void   <-----
   +0x0c4 CurrentLocale                : Uint4B
   +0x0c8 FpSoftwareStatusRegister     : Uint4B
   +0x0cc SystemReserved1              : [54] Ptr32 Void
   ...

The name is WOW32Reserved, and its the piece of code that was described above (re-packaging, kernel call, re-packaging).

System calls are but one reason where Wow64 code differs from the 32-bit native code. There are others, including code that communicate with 64-bit drivers, and so on.