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?
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: