我正在分析32位和64位DLL。我想找出导出函数的地址是什么。我已经处理过32位DLL,但相同的代码不适用于64位模块。
DWORD address = (*module)->getImageBaseAddress();
DWORD headerAddress = address + ((PIMAGE_DOS_HEADER)address)->e_lfanew;
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS)headerAddress;
PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)(address + header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PVOID names = (BYTE *)address + exports->AddressOfNames;
PVOID moduleFunctions = (BYTE *)address + exports->AddressOfFunctions;
std::cout << "Characteristics: " << exports->Characteristics << endl;
std::cout << "TimeDateStamp: " << exports->TimeDateStamp << endl;
std::cout << "Major version: " << exports->MajorVersion << endl;
std::cout << "Minor version: " << exports->MinorVersion << endl;
std::cout << "Name: " << exports->Name << endl;
std::cout << "Base: " << exports->Base << endl;
std::cout << "Number of fun: " << exports->NumberOfFunctions << endl;
std::cout << "Number of names: " << exports->NumberOfNames << endl;
for (int i = 0; i < exports->NumberOfFunctions; i++) {
std::cout << std::string((char*)((BYTE *)address + ((DWORD *)names)[i])) << " @ " << ((DWORD *)moduleFunctions)[i] << endl;
}
第一个输出行看起来很好(TimeDateStamp
具有正确的值,函数名称已正确解析等)。不幸的是,当我将函数的图像基础偏移与IDA在DLL文件分析后给出的偏移进行比较后,结果会有所不同。例如。对于第一个模块,我得到的偏移量等于11d0b
,因为IDA没有有效的指令从这个地址开始(imageBase + 0x11d0b)。
我在64位DLL中获取函数地址的方法是否正确?为什么我会得到不同的结果?为什么32位模块的一切正常?
答案 0 :(得分:5)
如果您使用64位二进制文件,则optional header
结构的大小不同。请查看PE COFF spec以获取官方参考资料。
您需要在可选标题(第一个字段)中键入“Magic Number”,以确定要使用的结构格式。
编辑:添加显示选择正确标题格式的代码段:
char* address = (*module)->getImageBaseAddress();
char* headerAddress = address + ((PIMAGE_DOS_HEADER)address)->e_lfanew;
PIMAGE_NT_HEADERS32 header32 = (PIMAGE_NT_HEADERS32)headerAddress;
PIMAGE_NT_HEADERS64 header64 = (PIMAGE_NT_HEADERS64)headerAddress;
PIMAGE_EXPORT_DIRECTORY exports = NULL;
if (header32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
exports = (PIMAGE_EXPORT_DIRECTORY)(address + header32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
else if (header32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) // PE32+
exports = (PIMAGE_EXPORT_DIRECTORY)(address + header64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
else
return 0;
另请注意,如果您尝试从文件手动加载的图像(例如文件的原始映射)执行此操作,则需要通过查找内存中的内存地址将RVA转换为文件偏移量。部分列表以标识文件指针位置。