ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Simplest way for get KERNEL32 base address ³ Billy Belceb£/DDT ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Heh, you realized in this magazine that i love to write little and effective tutorials (besides huge beasts like my VWGs), and here you have one more. It is, under my viempoint the simplest (in concept and bytes) way for get the KERNEL32.DLL base address. I tested in my computer, on Win98 and WinNT4-SP3, and it worked as good as my import-table search routine. As always, and as all my knowledge, i owe my idea to Super (perdon por llamarte tanto, ya se ke soy un puto pesao ;). Ehrm... Ok, ok, i'm going :) As you know, when we execute an application, the code is "called" from a part of the code of KERNEL32 (i.e., is like KERNEL makes a CALL to our code) and, if you remember, when a call is made, the return address is in the stack (that is, in the memory address told by ESP). Let's see a practic example of this: ;ÄÄÄ[ CUT HERE ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .586p ; Bah... simply for phun. .model flat ; Hehehe i love 32 bit stuph ;) .data ; Some data (needed by TASM32/TLINK32) db 00h .code start: mov eax,[esp] ; Now EAX would be BFF8XXXXh (if w9X) ret ; Way for terminate process ;) end start ;ÄÄÄ[ CUT HERE ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Well, simple. We have in EAX a value approximately as BFF8XXXX (XXXX is an unimportant value, it's put as this because it's not required to know it exactly, don't annoy me with silly things like that ones ;). As Win32 platf- orms ussually round up to a page all, we can search for the beginning of any page, and as the KERNEL32 header is just in the beginning of a page, we can check easily for it. And when we found this PE header i am talking about, we know KERNEL32 base address. Hrmm, as limit we could establish 50h pages. Hehe, don't worry. Some code follows ;) ;ÄÄÄ[ CUT HERE ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .586p .model flat .data extrn ExitProcess:PROC db 0 kernel equ 0BFF70000h imagebase equ 000400000h limit equ (50000h/1000h) ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; ; Unuseful and non-substance data :) ; ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; .code test: call delta delta: pop ebp sub ebp,offset delta mov esi,[esp] and esi,0FFFFF000h ; AND ESI,-1000 call GetK32 push 00000000h call ExitProcess ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; ; Ehrm, i consider you at least a normal ASM coder, so i consider you know ; ; that the first block of instructions is for get delta offset (well, not ; ; needed in particular in this example, anyway i like to make this to be ; ; as the likeness of virus code). Well, the second block is what is inte- ; ; resting for us. We put in ESI the address from our application is called ; ; that is in the address shown by ESP (if we don't touch the stack after ; ; program loading, of course). The second instruction, that AND, is for ; ; get the beginning of the page from our code is being called. We call our ; ; routine, and after that we terminate process ;) ; ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; GetK32: __1: cmp byte ptr [ebp+K32_Limit],00h jz WeFailed cmp word ptr [esi],"ZM" jz CheckPE __2: sub esi,1000h dec byte ptr [ebp+K32_Limit] jmp __1 ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; ; Firstly we check if we passed our limit (of 50h pages). After that we ; ; check if in the beginning of the page (as it should be) is the MZ sign, ; ; and if found we go for check for PE header. If not, we substract 1 page ; ; (1000h bytes, 4096d bytes), we decrease the limit variable, and search ; ; again... ; ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; CheckPE: mov edi,[esi+3Ch] add edi,esi cmp dword ptr [edi],"EP" jz WeGotK32 jmp __2 WeFailed: stc WeGotK32: xchg eax,esi ret K32_Limit dw limit ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; ; We get the value from offset 3Ch from MZ header (handles the address RVA ; ; of where begins the PE header), we normalize this value with the address ; ; of the page, and if the memory address marked by this offset is the PE ; ; mark, we assume that we found that... and indeed we did!) ;) ; ;-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú-ú; end test ;ÄÄÄ[ CUT HERE ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ A recommendation: i tested it and it didn't gave me any kind of problem in Win98 and WinNT4 with SP3, anyway, as i don't know what could happen every- where, i recommend you to use SEH in order to avoid possible Page Faults (and their correpsondent blue screen). I won't waste more my time in this silly tutorial. See ya. Billy Belceb£, mass killer and ass kicker.