#include<iostream>
#include<Windows.h>
DWORD RvaToFoa(DWORD dwRva, const char* buffer)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(buffer + pDos->e_lfanew);
PIMAGE_SECTION_HEADER pSh = IMAGE_FIRST_SECTION(pNt);
if (dwRva < pSh[0].VirtualAddress)
{
return dwRva;//因为Dos头+PE头+节表,在文件和在内存中展开都是一样的
}
for (size_t i = 0; i < pNt->FileHeader.NumberOfSections; i++)
{
if (dwRva >= pSh[i].VirtualAddress && dwRva <= pSh[i].VirtualAddress + pSh[i].Misc.VirtualSize)//判断是否落在了某一个区段内
{
return dwRva - pSh[i].VirtualAddress + pSh[i].PointerToRawData; //返回文件中的偏移
}
}
return NULL;
}
char* Loadfile(const char* szbuffer)
{
HANDLE fRet = CreateFileA(szbuffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fRet == INVALID_HANDLE_VALUE)
{
std::cout << "打开文件失败:" << std::endl;
return NULL;
}
DWORD H_size = 0;
DWORD L_size = GetFileSize(fRet, &H_size);
if (L_size == INVALID_FILE_SIZE)
{
std::cout << "获取文件大小失败:" << GetLastError() << std::endl;
return NULL;
}
char* tempbuff = new char[L_size];
memset(tempbuff, 0, L_size);
DWORD readszie = 0;
if (ReadFile(fRet, tempbuff, L_size, &readszie, NULL))
{
return tempbuff;
}
std::cout << "读取文件失败!" << std::endl;
return NULL;
}
BOOL ImportTable(const char* szbuffer, DWORD index)
{
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)szbuffer;
PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(szbuffer + pDos->e_lfanew);
//通过数据目录表获取了Import的结构体
PIMAGE_DATA_DIRECTORY pData = &(pNt->OptionalHeader).DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
//获取了导入表数组的首地址
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToFoa(pData->VirtualAddress, szbuffer) + szbuffer);
pImport += index;
//获取了Thunk数组的首地址
PIMAGE_THUNK_DATA pTd = (PIMAGE_THUNK_DATA)(RvaToFoa(pImport->OriginalFirstThunk, szbuffer) + szbuffer);
DWORD dwIndex = 0;
while (pTd->u1.Ordinal != NULL)
{
PIMAGE_IMPORT_BY_NAME pIbn = (PIMAGE_IMPORT_BY_NAME)(RvaToFoa(pTd->u1.AddressOfData, szbuffer) + szbuffer);
//因为PIMAGE_THUNK_DATA每一个都是4字节,pImport->OriginalFirstThunk指向PIMAGE_THUNK_DATA类型的数组
printf("ThunkRVA:%08X\n", pImport->OriginalFirstThunk + dwIndex);
printf("ThunkOffset:%08X\n", (RvaToFoa(pImport->OriginalFirstThunk, szbuffer) + dwIndex));
printf("Thunk值:%08X\n", pTd->u1.Ordinal);
try
{
printf("提示:%04X\n", pIbn->Hint);
printf("函数名:%s\n\n", pIbn->Name);
}
catch (...)
{
DWORD temp = pTd->u1.Ordinal - 0x80000000;
char tempbuff[MAX_PATH] = { 0 };
sprintf_s(tempbuff, "序号:%Xh %dd", temp, temp);
printf("——\n");
printf("函数名:%s\n\n", tempbuff);
}
pTd++;
dwIndex += 4;
}
return TRUE;
}
int main()
{
char* szbuffer = Loadfile("E:\\VS_2019\\ConsoleApplication2\\Debug/ConsoleApplication2.exe");
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)szbuffer;
PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(szbuffer + pDos->e_lfanew);
PIMAGE_DATA_DIRECTORY pData = &(pNt->OptionalHeader).DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToFoa(pData->VirtualAddress, szbuffer) + szbuffer);
DWORD nDll = 0;//导入表的数量
DWORD index = 0;//导入表的次数标志
while (pImport->Name != 0)
{
nDll++;
pImport++;
}
pImport -= nDll;
for (size_t i = 0; i < nDll; i++)
{
char* MoudleName = (char*)(RvaToFoa(pImport->Name, szbuffer) + szbuffer);
printf("%s\n", MoudleName);
printf("名称Rva:0x%x\n", pImport->Name);
printf("时间戳:0x%x\n", pImport->TimeDateStamp);
printf("导入名称表的RVA:0x%x\n", pImport->OriginalFirstThunk);
printf("ForwarderChain:0x%x\n", pImport->ForwarderChain);
printf("导入地址表的RVA:0x%x\n", pImport->FirstThunk);
printf("Characteristics:0x%x\n\n", pImport->Characteristics);
ImportTable(szbuffer, index);
index++;
pImport++;
}
system("pause");
return 0;
}
PE文件结构—导入表解析
于 2024-05-09 15:18:38 首次发布