I learned something new today.
For some time I have tried to understand Skapes paper on Windows shellcode with some success. I had trouble with the finding kernel32.dll using PEB technique and here is why.
The code is this (without Windows 9x version):
push esi xor eax, eax mov eax, fs:[eax + 0x30] ;Get address of TIB mov eax, [eax + 0x0c] ;Get address of LDR mov esi, [eax + 0x1c] ;Get address of first loaded module descriptor lodsd ;Get address of next loaded module descriptor mov eax, [eax + 0x8] ;Get base address of module (kernel32.dll) pop esi ret
Easy, right ? Wrong…not if you follow MSDN documentation.
If you google 'PEB_LDR_DATA' the first link you get is http://msdn.microsoft.com/en-us/library/windows/desktop/aa813708(v=vs.85).aspx
So according to Skapes shellcode the addres of the first module descriptor is 0x1c (28) bytes into that structure. But according to MSDN the structure is exactly 28 bytes long…which is a damn lie!
I asked on a SecurtyFocus mailing list called security-basics and got a reply that the MSDN information was wrong!
An accurate definition can be found at undocumented.ntinternals.net.
I drew an illustration (I like visualizing data structures) which helps when following the code:
The FS register points to the Thread Information Block and from there on you can follow the pointer at offset 0x30 to the PEB. Then at offset 0x0c you find a pointer to the PEB loader data. At offset 0x1c you find the linked list of loaded modules in initialization order. Note that the forward link points INSIDE the LDR module structure and NOT to the base address of the structure. This means that at address zero relative to that forward link you find the next forward link to the kernel32 module structure…still an address inside the structure. Eight bytes past that you find a pointer to the base address of kernel32.dll.