----------------------- getting the kernel32 image base in C++ - written by malfunction ----------------------- This article is about getting the kernel32 image base in C++ without using any API or inline asm. My code is more or less just a proof of concept, only useful for those weirdos who want to code a real virus in 100% C++. The method used here is the very well known attempt to get the return address of CreateProcess from the stack. Of course, there are many other values on the stack when my function is called. Thus, I trace back through the whole stack. Everything must be SEH guarded, of course. To be sure to have the right image base I compare the name of the export table. I do that for both upper and lower case because I'm unsure if there might be differences between some Windows versions. I tested it successfully on WinXP SP2. I don't if __try / __except make the code VC++ specific, but I don't care anyway. The code is rather self-explanatory if you know some C/C++. Have fun. ------------------------------------------------------- #include <windows.h> #include <stdio.h> #include <conio.h> #include <winnt.h> PIMAGE_DOS_HEADER getKernel32ImageBase(int dummy) { DWORD **stackAddress = (DWORD **)(&dummy - 2); DWORD *address; while(true) { address = (DWORD *)((DWORD)*stackAddress & 0xFFFF0000); bool found = false; while(true) { __try { PIMAGE_DOS_HEADER image=(PIMAGE_DOS_HEADER)address; if(image->e_magic == IMAGE_DOS_SIGNATURE) { DWORD *magic=(DWORD *)((BYTE *)image + image->e_lfanew); if(*magic == IMAGE_NT_SIGNATURE) { PIMAGE_OPTIONAL_HEADER32 optHeader=(PIMAGE_OPTIONAL_HEADER32) ((BYTE *)magic + IMAGE_SIZEOF_FILE_HEADER + 4); DWORD expRVA=optHeader->DataDirectory[0].VirtualAddress; if(expRVA) { PIMAGE_EXPORT_DIRECTORY expDir=(PIMAGE_EXPORT_DIRECTORY) (optHeader->ImageBase + expRVA); DWORD *dllName=(DWORD *)(optHeader->ImageBase + expDir->Name); if(*dllName==0x4E52454B && *(dllName+1)==0x32334C45) // KERNEL32 return (PIMAGE_DOS_HEADER)address; if(*dllName==0x6E72656B && *(dllName+1)==0x32336C65) // kernel32 return (PIMAGE_DOS_HEADER)address; } } } } __except(1) { break; } address = (DWORD *)((DWORD)address - 0x00010000); } stackAddress--; } } int main(int argc, char *argv[]) { PIMAGE_DOS_HEADER address=getKernel32ImageBase(0); printf("Kernel32.dll's ImageBase is: \t%08X\n", (DWORD)address); getch(); return 0; }