void *getExportedSymbol(HMODULE module, int index) { IMAGE_EXPORT_DIRECTORY* export_dir = getExportDir(module); if (!export_dir) { error("getExportedSymbol(%p,%d): module has no exports", module, index); return NULL; } uint32_t *addressOfFunctions = rva_to_addr(export_dir->AddressOfFunctions, module); return rva_to_addr(addressOfFunctions[index], module); }
// retrieve the export directory structure for a given module, // using information from the various headers IMAGE_EXPORT_DIRECTORY *getExportDir(HMODULE module) { if (!module && CACHED_EXPORT_DIR) return CACHED_EXPORT_DIR; IMAGE_NT_HEADERS *nt_header = getNtHeader(module); IMAGE_DATA_DIRECTORY *datadir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (datadir->Size == 0) return NULL; // no export directory void *result = rva_to_addr(datadir->VirtualAddress, module); if (!module) /* i.e. "self" */ CACHED_EXPORT_DIR = result; return result; }
//------------------------------------------------------------------------------ void* get_export(void* base, const char* func_name) { IMAGE_DOS_HEADER* dos_header; IMAGE_NT_HEADERS* nt_header; IMAGE_DATA_DIRECTORY* data_dir; IMAGE_EXPORT_DIRECTORY* ied; int i; DWORD* names; WORD* ordinals; DWORD* addresses; dos_header = base; nt_header = (IMAGE_NT_HEADERS*)((char*)base + dos_header->e_lfanew); data_dir = nt_header->OptionalHeader.DataDirectory; if (data_dir == NULL) { LOG_INFO("Failed to find export table for base %p", base); return NULL; } if (data_dir->VirtualAddress == 0) { LOG_INFO("No export directory found at base %p", base); return NULL; } ied = rva_to_addr(base, data_dir->VirtualAddress); names = rva_to_addr(base, ied->AddressOfNames); ordinals = rva_to_addr(base, ied->AddressOfNameOrdinals); addresses = rva_to_addr(base, ied->AddressOfFunctions); for (i = 0; i < (int)(ied->NumberOfNames); ++i) { const char* export_name; WORD ordinal; export_name = rva_to_addr(base, names[i]); if (_stricmp(export_name, func_name)) { continue; } ordinal = ordinals[i]; return rva_to_addr(base, addresses[ordinal]); } return NULL; }
//------------------------------------------------------------------------------ void* get_data_directory(void* base, int index, int* size) { IMAGE_NT_HEADERS* nt_headers; IMAGE_DATA_DIRECTORY* data_dir; nt_headers = get_nt_headers(base); data_dir = nt_headers->OptionalHeader.DataDirectory + index; if (data_dir == NULL) { return NULL; } if (data_dir->VirtualAddress == 0) { return NULL; } if (size != NULL) { *size = data_dir->Size; } return rva_to_addr(base, data_dir->VirtualAddress); }
// get pointer to the NT header of a given module inline IMAGE_NT_HEADERS *getNtHeader(HMODULE module) { IMAGE_DOS_HEADER *dos_header = rva_to_addr(0, module); // DOS header at offset 0 return rva_to_addr(dos_header->e_lfanew, module); }