4,6 The Native API
If some of the options in this batch file are foreign to you, don't worry. I'll
discuss Windows debuggers in more detail later on. Now that we've cranked
up our debugger, let's disassemble the Wn'teFile(J function to see where it
leads us.
> uf Wn'tePi 1 e
kernel 32!WriteFi1e+OxlfO
7655dcfa ff75e4
push
dword ptr [ebp-lCh]
7655dcfd e88ae80300
cal 1
kernel 32!BaseSetLastNTError {7659c58c)
7655dd02 33c0
xor
eax,eax
7655dd42 ffl5f8115576
cal 1
dword ptr [kernel32! imp NtWriteFile
(765511f8)]
Looking at this listing (which I've truncated for the sake of brevity), the first
thing you can see is that the WriteFile(} API function has been implennented
in the Kernel32.dl 1. The last line of this listing is also important. It calls a
routine located at an address (0x765511f8) that's stored in a lookup table.
> dps 765511f8 L3
765511f8 77bb9278 ntdl1INtWriteFi 1 e
765511fc 77becc6d ntdl1IZwCancelloFi1eEx
76551200 77b78908 ntdl1IZwReadPi1eScatter
Hence, the WriteFi!e() code in kennel32.dll ends up calling a funcdon that
has been exported by ntdll .dll. Now we're getting somewhere.
> uf ntdl1!NtWriteFi 1 e
ntdl1INtWriteFile:
77bb9278 b863010000
mov
eax,18Ch
77bb927d ba0003fe7f
mov
edx.offset SharedUserData!SystemCal1 Stub
{7ffe0300)
77bb9282 ffl2
cal 1
dword ptr [edx]
77bb9284 c22400
ret
24h
As you can see, this isn't really the implementation of the NtWritePi 1 e() Na¬
tive API call. Instead, it's just a stub routine residing in ntdll .dl1 that ends up
calling the gateway in ntdll .dl1 that executes the SYSENTER instrucdon. Notice
how the system service number for the NtWriteFi 1 e() Native call (i.e., 0xl8C)
is loaded into the EAX register in the stub code, well in advance of the SYSENTER
instruction.
> dps 7ffe0300
7ffe0300 77da0f30 ntdl 1 ! Ki FastSysteinCal 1
7ffe0304 77da0f34 ntdl1!KiFastSystemCal1 Ret
7ffG0308 00000000
> uf ntdl1jKiFastSystemCal 1_
Parti I 167