Search code examples
windowsassemblyreverse-engineeringx86-64ntdll

Implement x86 to x64 assembly code switch


I was looking how NtDll works for x86 processes, and i debugged the function NtCreateFile using IDA PRO. The code for it is following:

mov     eax, 55h        ; NtCreateFile
mov     edx, offset _Wow64SystemServiceCall@0 ; 
call    edx ; Wow64SystemServiceCall() ; 
retn    2Ch

And the Wow64SystemServiceCall():

mov     edx, large fs:30h
mov     edx, [edx+464h]
test    edx, 2
jz      short loc_7738B5C8
int     2Eh             ; DOS 2+ internal - EXECUTE COMMAND
                        ; DS:SI -> counted CR-terminated command string
retn
loc_7738B5C8:                           ; CODE XREF: 
jmp     far ptr byte_7738B8FF

I looked up the command code for jmp far ptr byte_7738B8FF and it was EA CF B5 38 77 33 00 which is a jump to another segment, 0x33 jmp 0x33:0x7738b5cf . So from what i read in internet, this is the x64 segment base for processes on 64-bit systems, right? Unfortunately i cannot debug further, because, ida doesnt follow the jump. But i made another simple C application compiled for x64, and called CreateFile, attached x64 IDA PRO Remote debugger, and looked up disassembly, and NtCreateFile was looking like so:

x64_NtCreateFile proc near  
mov     r10, rcx
mov     eax, 55h
test    byte ptr ds:7FFE0308h, 1
jnz     short loc_7FFED6695B85
syscall
retn
loc_7FFED6695B85:                     
int     2Eh             ; DOS 2+ internal - EXECUTE COMMAND
                        ; DS:SI -> counted CR-terminated command string
retn

So i have a few question, how does the jump from x86 process attached ntdll far jump jmp 0x33:0x7738b5cf just lands into x64_NtCreateFile first instruction? How does the switching from x86 to x64 happens in this case exactly? Basically i can just make x86 application, and switch segment with jump, and just execute the x64 code in there, which i can create by just doing something like db (0x00) ; x64 machine code commands, is this right?


Solution

  • If you look at the bytes at address 0x7738b5cf, you would see something like

    41 FF A7 F8 00 00 00 (at least if you're on Windows 8.1 or newer)

    which corresponds to a single x86_64 instruction jmp QWORD PTR [r15+0xf8].

    Right after switching from 32-bit to 64-bit code execution via the far jump, the R15 register will always point to a special jump table within wow64cpu.dll (the R15 register is setup to point to this table from 64-bit code that executes before the 32-bit entry point of your application).

    [r15+0xf8] just happens to point to the CpupReturnFromSimulatedCode method within wow64cpu.dll, which will setup the right context and perform the actual system call (in your case for NtCreateFile) using the syscall instruction.

    For some information that elaborates upon this, see: