I experimented with the following code to simulate GetProcAddress.
// Retrieve NT header from base address. IMAGE_NT_HEADERS *GetNtHeaderFromBase( void *pBaseAddr ) { IMAGE_DOS_HEADER *pDosHeader; IMAGE_NT_HEADERS *pNtHeaders; pDosHeader = ((IMAGE_DOS_HEADER *)pBaseAddr); if(pDosHeader->e_magic != 0x5A4D) return NULL; pNtHeaders = ((IMAGE_NT_HEADERS *)((DWORD)pBaseAddr + pDosHeader->e_lfanew)); if(pNtHeaders->Signature != 0x4550) return NULL; return ((pNtHeaders == NULL) ? NULL : pNtHeaders); } // This emulates GetProcAddress. void *GetFuncAddr( DWORD pBaseAddr, char *lpszFuncName ) { IMAGE_NT_HEADERS *pNtHeaders; IMAGE_DATA_DIRECTORY *pDataDir; IMAGE_EXPORT_DIRECTORY *pExportDir; const char **lpszNames; DWORD *lpdwFuncs, dwIndex; pNtHeaders = GetNtHeaderFromBase((void *)pBaseAddr); if(pNtHeaders == NULL) return NULL; pDataDir = ((IMAGE_DATA_DIRECTORY *)(pNtHeaders->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT)); if(pDataDir == NULL) return NULL; pExportDir = ((IMAGE_EXPORT_DIRECTORY *)(pBaseAddr + pDataDir->VirtualAddress)); if(pExportDir == NULL) return NULL; lpdwFuncs = ((DWORD *)(pBaseAddr + pExportDir->AddressOfFunctions)); lpszNames = ((const char **)(pBaseAddr + pExportDir->AddressOfNames)); if(lpdwFuncs == NULL || lpszNames == NULL) return NULL; for(dwIndex = 0; dwIndex < pExportDir->NumberOfFunctions; dwIndex++) { // decrypt funcname and get the address if(!cmpstr(((char *)(pBaseAddr + lpszNames[dwIndex])), lpszFuncName)) return (void*)(pBaseAddr + lpdwFuncs[dwIndex]); } return NULL; }
But when I run the program on Windows Vista x64, I get an access violation. I thought these were numbers in GetNtHeaderFromBase (numbers transmitted by IMAGE_DOS_HEADER and IMAGE_NET_HEADER), but I can not find any link anywhere regarding that it could be in x64 binary bit.
Does anyone know what changes I need to make to this code to make it work under 64-bit Windows? Or, the best way to get getprocaddress function that works on both x32 and x64?
Thanks for the help and code.
Jess.
source share