#include<iostream> #include<fstream> #include<Windows.h> #include<cstring> #include"RVAToFOA.h" using namespace std; //函数声明 unsigned int GetFunctionAddressByName(char *functionName); long GetFileSize(char *fileName); unsigned int GetFunctionAddressByOrdinals(int n); void PrintExportTable(); char* buffer; long fileSize = GetFileSize("D:\\Notepad++\\plugins\\mimeTools.dll"); //获取各结构的地址 IMAGE_DOS_HEADER* pDOSHeader = (IMAGE_DOS_HEADER*)(buffer); IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(&buffer[0] + pDOSHeader->e_lfanew); IMAGE_FILE_HEADER* pFileHeader = (IMAGE_FILE_HEADER*)((int)(pNTHeaders)+4); IMAGE_OPTIONAL_HEADER* pOptionalHeader = (IMAGE_OPTIONAL_HEADER*)((int)(pFileHeader)+sizeof(IMAGE_FILE_HEADER)); IMAGE_SECTION_HEADER* pSectionHeader[10]; IMAGE_EXPORT_DIRECTORY* pExportTable = (IMAGE_EXPORT_DIRECTORY*) (&buffer[0] + RVAToFOA(buffer, pOptionalHeader->DataDirectory[0].VirtualAddress)); //导出函数名称表 unsigned char* addressOfNames[1000]; unsigned char** pAddressOfNames;//定义unsigned char** pAddressOfNames,利用pAddressOfNames来存贮导入函数名称表的地址 //导出函数地址表 unsigned int* addressOfFunctions[1000]; unsigned int** pAddressOfFunctions;//学会用二级指针 //导出函数序号表 unsigned short nameOrdinals[1000]; unsigned short* pNameOrdinals; int main() { //先获取第一个节区头的地址 pSectionHeader[0] = (IMAGE_SECTION_HEADER*)((unsigned int)(pOptionalHeader)+sizeof(IMAGE_OPTIONAL_HEADER)); for (int i = 0;i < pFileHeader->NumberOfSections - 1;i++) pSectionHeader[i + 1] = (IMAGE_SECTION_HEADER*)((unsigned int)(pSectionHeader[i]) + sizeof(IMAGE_SECTION_HEADER)); //给导出函数地址表赋值 for (int i = 0;i < pExportTable->NumberOfFunctions;i++) { pAddressOfFunctions = (unsigned int**)(buffer + RVAToFOA(buffer, pExportTable->AddressOfFunctions)); addressOfFunctions[i] = *(pAddressOfFunctions + i); } //给导出函数名称表赋值 for (int i = 0;i < pExportTable->NumberOfNames;i++) { pAddressOfNames = (unsigned char**)(buffer + RVAToFOA(buffer, pExportTable->AddressOfNames)); addressOfNames[i] = *(pAddressOfNames+i); } //给导出函数序号表赋值 for (int i = 0;i < pExportTable->NumberOfNames;i++) { pNameOrdinals = (unsigned short*)(buffer + RVAToFOA(buffer, pExportTable->AddressOfNameOrdinals)); nameOrdinals[i] = *(pNameOrdinals + i); } PrintExportTable(); } unsigned int GetFunctionAddressByName(char *functionName) { int i; for (i = 0;i < pExportTable->NumberOfNames;i++)//两字符串相等返回0 if (strcmp(functionName, (const char*)(buffer + RVAToFOA(buffer, (unsigned int)addressOfNames[i])))==0) return (unsigned int)addressOfFunctions[nameOrdinals[i]]+pOptionalHeader->ImageBase; if (i == pExportTable->NumberOfNames) { cout << "找不到此函数" << endl; return 0; } } unsigned int GetFunctionAddressByOrdinals(int n) { if(n<= pExportTable->Base+ pExportTable->NumberOfFunctions) return (unsigned int)addressOfFunctions[n-pExportTable->Base] + pOptionalHeader->ImageBase; else { cout << "无此函数" << endl; return 0; } } //获取文件大小 long GetFileSize(char *fileName) { filebuf *pbuf; ifstream fileStr; long size; //采用二进制模式打开 fileStr.open(fileName, ios::binary); //获取fileStr对应buffer对象的指针 pbuf = fileStr.rdbuf(); // 调用buffer对象方法获取文件大小 size = pbuf->pubseekoff(0, ios::end, ios::in); pbuf->pubseekpos(0, ios::in); // 分配内存空间 buffer = new char[size]; // 获取文件内容 pbuf->sgetn(buffer, size); fileStr.close(); return size; } //打印导出表 void PrintExportTable() { cout << "Name:" << (char*)(buffer + RVAToFOA(buffer, pExportTable->Name)) << endl; cout << "Base:" << hex << pExportTable->Base << endl; cout << "NumberOfFunctions:" << hex << pExportTable->NumberOfFunctions << "<所有导出的函数的个数>" << endl; cout << "NumberOfFunctions:" << hex << pExportTable->NumberOfFunctions << "<所有导出的函数的个数>" << endl; cout << "NumberOfFunctions:" << hex << pExportTable->NumberOfNames << "<以函数名导出的函数的个数>" << endl; cout << "AddressOfFunctions:" << hex << pExportTable->AddressOfFunctions << "<导出函数地址表偏移>" << endl; cout << "AddressOfNameOrdinals:" << hex << pExportTable->AddressOfNameOrdinals << "<导出函数序号表偏移>" << endl; cout << "****函数地址表****" << endl; for (int i = 0;i < pExportTable->NumberOfFunctions;i++) cout << "函数地址:" << hex << (unsigned int)(pAddressOfFunctions[i]) << endl; cout << "****函数名称表****" << endl; for (int i = 0;i < pExportTable->NumberOfNames;i++) cout << "函数--" << hex << (unsigned int)(addressOfNames[i]) << endl << "函数名称:" << (char*)(buffer+RVAToFOA(buffer,(unsigned int)(addressOfNames[i]))) << endl; cout << "****函数序号表****" << endl; for (int i = 0;i < pExportTable->NumberOfNames;i++) cout << "函数序号:" << hex << nameOrdinals[i] << endl;</span> } //RVAToFOA.cpp的内容 #include<Windows.h> #include"RVAToFOA.h" unsigned int RVAToFOA(char* buffer, unsigned int address) { IMAGE_DOS_HEADER* pDOSHeader = (IMAGE_DOS_HEADER*)(buffer); IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(&buffer[0] + pDOSHeader->e_lfanew); IMAGE_FILE_HEADER* pFileHeader = (IMAGE_FILE_HEADER*)((int)(pNTHeaders)+4); IMAGE_OPTIONAL_HEADER* pOptionalHeader = (IMAGE_OPTIONAL_HEADER*)((int)(pFileHeader)+sizeof(IMAGE_FILE_HEADER)); IMAGE_SECTION_HEADER* pSectionHeader[10]; pSectionHeader[0] = (IMAGE_SECTION_HEADER*)((int)(pOptionalHeader)+sizeof(IMAGE_OPTIONAL_HEADER)); for (int i = 0;i < pFileHeader->NumberOfSections - 1;i++) { pSectionHeader[i + 1] = (IMAGE_SECTION_HEADER*)((int)(pSectionHeader[i]) + sizeof(IMAGE_SECTION_HEADER)); } //if(address<pSectionHeader[0]->VirtualAddress) return for (int i = 0;i < pFileHeader->NumberOfSections - 1;i++) { if (address >= pSectionHeader[i]->VirtualAddress&&address <= pSectionHeader[i + 1]->VirtualAddress) return address - pSectionHeader[i]->VirtualAddress + pSectionHeader[i]->PointerToRawData; } }
以任意dll文件为例
解析结果与DIE分析出的相同
过程中主要学会的指针的灵活运用,其他表的解析后续学习中再贴上,欢迎私信交流,指导不足