Nytro Posted April 6, 2011 Report Posted April 6, 2011 Get kernel ImageBaseThis is a small example of how to get the ImageBase ofKernel32.dll and how to get addresses of the kernel'sLoadLibrary and GetProcAddress functions without any APIs !I tested this code on Win98SE and Win2k.For any comments or bugreports trop a line to yoda_f2f@gmx.net.HAppy New Year !yoda.386.model flat,stdcalloption casemap:noneINCLUDE \masm32\include\windows.incINCLUDE \masm32\include\comdlg32.incINCLUDELIB \masm32\lib\comdlg32.lib; ------ STRUCTS ------sSEH STRUCT OrgEsp DD ? OrgEbp DD ? SaveEip DD ?sSEH ENDS; ------ EQU'S ------MIN_KERNEL_SEARCH_BASE EQU 070000000hMAX_API_STRING_LENGTH EQU 150; ------ CONST ------.CONSTszLoadLibrary DB "LoadLibraryA",0szGetProcAddress DB "GetProcAddress",0szExitProcess DB "ExitProcess",0szUser32 DB "user32",0szMessageBox DB "MessageBoxA",0szwsprintf DB "wsprintfA",0szInfoCap DB "- Kernel -",0szInfoText DB "The following information were obtained",13,10 DB "without the help of an Import Table !",13,10 DB 13,10 DB "Kernel32.dll ImageBase: 0x%08lX",13,10 DB "User32.dll ImageBase: 0x%08lX",13,10 DB 13,10 DB "API Addresses:",13,10 DB "LoadLibraryA: 0x%08lX",13,10 DB "GetProcAddress: 0x%08lX",13,10 DB "ExitProcess: 0x%08lX",13,10 DB 13,10 DB "MessageBoxA: 0x%08lX",13,10 DB "wsprintfA: 0x%08lX",0; ------ DATA ------.DATA_LoadLibrary DD 0_GetProcAddress DD 0_ExitProcess DD 0_MessageBox DD 0_wsprintf DD 0cBuff DB 200 DUP (0)SEH sSEH <0>dwKernelBase DD 0dwUserBase DD 0; ------ CODE ------.CODEmain: ASSUME FS : NOTHING ;INT 3 ;---- GET ImageBase of kernel32.dll ---- PUSH [ESP] CALL GetKernelBase OR EAX, EAX JZ QUIT MOV dwKernelBase, EAX ;---- GET SOME KERNEL API ADDRESSES ---- ;-> LoadLibraryA PUSH OFFSET szLoadLibrary PUSH dwKernelBase CALL GetProcAddr OR EAX, EAX JZ QUIT MOV _LoadLibrary, EAX ;-> GetProcAddress PUSH OFFSET szGetProcAddress PUSH dwKernelBase CALL GetProcAddr OR EAX, EAX JZ QUIT MOV _GetProcAddress, EAX ;-> ExitProcess PUSH OFFSET szExitProcess PUSH dwKernelBase CALL GetProcAddr OR EAX, EAX JZ QUIT MOV _ExitProcess, EAX ;---- LOAD USER32.DLL ---- PUSH OFFSET szUser32 CALL _LoadLibrary OR EAX, EAX JZ QUIT MOV dwUserBase, EAX ;---- GET SOME USER API ADDRESSES ---- ;-> MessageBoxA PUSH OFFSET szMessageBox PUSH dwUserBase CALL GetProcAddr OR EAX, EAX JZ QUIT MOV _MessageBox, EAX ;-> wsprintfA PUSH OFFSET szwsprintf PUSH dwUserBase CALL GetProcAddr OR EAX, EAX JZ QUIT MOV _wsprintf, EAX ;---- BUILD AND SHOW THE INFORMATION MSG ---- PUSH _wsprintf PUSH _MessageBox PUSH _ExitProcess PUSH _GetProcAddress PUSH _LoadLibrary PUSH dwUserBase PUSH dwKernelBase PUSH OFFSET szInfoText PUSH OFFSET cBuff CALL _wsprintf ADD ESP, (9 * SIZEOF(DWORD)) PUSH MB_ICONINFORMATION OR MB_SYSTEMMODAL PUSH OFFSET szInfoCap PUSH OFFSET cBuff PUSH 0 CALL _MessageBox ;---- EXIT ---- CALL _ExitProcess QUIT: RET ; exit to OS;---- AN UNUSED IMPORT ----; The Win32 Loader of Win2k (maybe also of WinNT) won't call the EntryPoint of files which don't; have an Import Table ; So here's an unused Import to make MASM compile an Import Table. PUSH NULL CALL GetOpenFileName; ------ ROUTINES ------; returns NULL in the case of an errorGetKernelBase PROC USES EDI ESI, dwTopStack : DWORD ; install SEH frame PUSH OFFSET SehHandler PUSH FS:[0] MOV SEH.OrgEsp, ESP MOV SEH.OrgEbp, EBP MOV SEH.SaveEip, OFFSET ExceptCont MOV FS:[0], ESP ; start the search MOV EDI, dwTopStack AND EDI, 0FFFF0000h ; wipe the LOWORD ! .WHILE TRUE .IF WORD PTR [EDI] == IMAGE_DOS_SIGNATURE MOV ESI, EDI ADD ESI, [ESI+03Ch] .IF DWORD PTR [ESI] == IMAGE_NT_SIGNATURE .BREAK .ENDIF .ENDIF ExceptCont: SUB EDI, 010000h .IF EDI < MIN_KERNEL_SEARCH_BASE MOV EDI, 0BFF70000h .BREAK .ENDIF .ENDW XCHG EAX, EDI ; shutdown SEH frame POP FS:[0] ADD ESP, 4 RETGetKernelBase ENDP; returns address or NULL in the case of an errorGetProcAddr PROC USES ESI EDI ECX EBX EDX, dwDllBase : DWORD, szApi : LPSTR ; install SEH frame PUSH OFFSET SehHandler PUSH FS:[0] MOV SEH.OrgEsp, ESP MOV SEH.OrgEbp, EBP MOV SEH.SaveEip, OFFSET @@BadExit MOV FS:[0], ESP ; check PE Signarue MOV ESI, dwDllBase CMP WORD PTR [ESI], IMAGE_DOS_SIGNATURE JNZ @@BadExit ADD ESI, [ESI+03Ch] CMP DWORD PTR [ESI], IMAGE_NT_SIGNATURE JNZ @@BadExit ; get the string length of the target Api MOV EDI, szApi MOV ECX, MAX_API_STRING_LENGTH XOR AL, AL REPNZ SCASB MOV ECX, EDI SUB ECX, szApi ; ECX -> Api string length ; trace the export table MOV EDX, [ESI+078h] ; EDX -> Export table ADD EDX, dwDllBase ASSUME EDX : PTR IMAGE_EXPORT_DIRECTORY MOV EBX, [EDX].AddressOfNames ; EBX -> AddressOfNames array pointer ADD EBX, dwDllBase XOR EAX, EAX ; EAX AddressOfNames Index .REPEAT MOV EDI, [EBX] ADD EDI, dwDllBase MOV ESI, szApi PUSH ECX ; save the api string length REPZ CMPSB .IF ZERO? ADD ESP, 4 .BREAK .ENDIF POP ECX ADD EBX, 4 INC EAX .UNTIL EAX == [EDX].NumberOfNames ; did we found sth ? .IF EAX == [EDX].NumberOfNames JMP @@BadExit .ENDIF ; find the corresponding Ordinal MOV ESI, [EDX].AddressOfNameOrdinals ADD ESI, dwDllBase PUSH EDX ; save the export table pointer MOV EBX, 2 XOR EDX, EDX MUL EBX POP EDX ADD EAX, ESI XOR ECX, ECX MOV WORD PTR CX, [EAX] ; ECX -> Api Ordinal ; get the address of the api MOV EDI, [EDX].AddressOfFunctions XOR EDX, EDX MOV EBX, 4 MOV EAX, ECX MUL EBX ADD EAX, dwDllBase ADD EAX, EDI MOV EAX, [EAX] ADD EAX, dwDllBase JMP @@ExitProc ASSUME EDX : NOTHING @@BadExit: XOR EAX, EAX @@ExitProc: ; shutdown SEH frame POP FS:[0] ADD ESP, 4 RETGetProcAddr ENDPSehHandler PROC C pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD MOV EAX, pContext ASSUME EAX : PTR CONTEXT PUSH SEH.SaveEip POP [EAX].regEip PUSH SEH.OrgEsp POP [EAX].regEsp PUSH SEH.OrgEbp POP [EAX].regEbp MOV EAX, ExceptionContinueExecution RETSehHandler ENDPend mainDemonstrate how to search for and obtain the module base address of kernel32.dll and the addresses of the functions in it without using any API function. Tested on both Win98 and Win2kDownload:http://win32assembly.online.fr/files/kernel.zip Quote