Yet another one…
This time, smaller, more correct, and still null-free.
I looked a bit at some shellcodes at exploit-db and googled too, to see whether anyone got a smaller way to no avail.
I based my code on:
AFAIK, who based his post on:
And this is my version:
00000002 (01) 5e POP ESI
; Use DB 0×64; LODSD
00000003 (02) 64ad LODS EAX, [FS:ESI]
00000005 (03) 8b700c MOV ESI, [EAX+0xc]
00000008 (03) 8b761c MOV ESI, [ESI+0x1c]
0000000b (03) 8b5608 MOV EDX, [ESI+0×8]
0000000e (04) 807e1c18 CMP BYTE [ESI+0x1c], 0×18
00000012 (02) 8b36 MOV ESI, [ESI]
00000014 (02) 75f5 JNZ 0xb
The tricky part was how to read from FS:0×30, and the way I use is the smallest one, at least from what I checked.
Another issue that was fixed is the check for kernel32.dll, usually the variation of this shellcode checks for a null byte, but it turned out to be bogous on W2k machines, so it was changed to check for a null word. Getting the shellcode by a byte or two longer.
This way, it’s only 22 bytes, it doesn’t assume that kernel32.dll is the second/third entry in the list, it actually loops till it finds the correct module length (len of ‘kernel32.dll’ * 2 bytes). Also since kernelbase.dll can come first and that renders lots of implementations of this technique unusable.
And obviously the resulting base address of kernel32.dll is in EDX.
[Update July 9th:]
Here’s a link to an explanation about PEB/LDR lists.
See first comment for a better version which is only 17 bytes.