// 导出表2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdlib.h>
DWORD RVA2OffSet(DWORD dwRVA, PIMAGE_NT_HEADERS32 pNt)
{
DWORD dwOffset = 0;
//获取区段头表
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
//获取区段的数量
DWORD dwSize = pNt->FileHeader.NumberOfSections;
//遍历找到dwRVA所在的区段
for (DWORD i = 0; i < dwSize; i++)
{
if (dwRVA>=pSection[i].VirtualAddress &&
dwRVA < (pSection[i].Misc.VirtualSize + pSection[i].VirtualAddress))
{
dwOffset = dwRVA - pSection[i].VirtualAddress + pSection[i].PointerToRawData;
return dwOffset;
}
}
return dwOffset;
}
void ShowExport(PVOID lpImage, DWORD dwSize)
{
//获取Dos头
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImage;
if (IMAGE_DOS_SIGNATURE != pDos->e_magic )
{
return;
}
//获取nt头
PIMAGE_NT_HEADERS32 pNt = (PIMAGE_NT_HEADERS32)((DWORD)lpImage + pDos->e_lfanew);
if (IMAGE_NT_SIGNATURE != pNt->Signature)
{
return;
}
//获取目录表
PIMAGE_DATA_DIRECTORY pData = pNt->OptionalHeader.DataDirectory;
//获取导出表RVA
pData = &(pData[IMAGE_DIRECTORY_ENTRY_EXPORT]);
//获取导出表在文件中的偏移
DWORD dwExtOffset = RVA2OffSet(pData->VirtualAddress, pNt);
PIMAGE_EXPORT_DIRECTORY pExpt = (PIMAGE_EXPORT_DIRECTORY)((DWORD)lpImage + dwExtOffset);
//获取数量
DWORD dwFunCount = pExpt->NumberOfFunctions;
DWORD dwNameCount = pExpt->NumberOfNames;
DWORD dwModName = pExpt->Name;
//获取地址表
PDWORD pEAT = (PDWORD)((DWORD)lpImage + RVA2OffSet(pExpt->AddressOfFunctions, pNt));
//获取名称表
PDWORD pENT = (PDWORD)((DWORD)lpImage +RVA2OffSet(pExpt->AddressOfNames, pNt));
//获取索引表-----这里要使用WORD
PWORD pEIT = (PWORD)((DWORD)lpImage + RVA2OffSet(pExpt->AddressOfNameOrdinals, pNt));
for (DWORD dwOrd = 0; dwOrd < dwFunCount; dwOrd++)
{ //这里如果没有的话是个NULL
if (!pEAT[dwOrd])
{
continue;
}
//获取函数的实际序号
DWORD dwID = pExpt->Base + dwOrd;
//获取导出函数地址值
DWORD dwFunOffset = RVA2OffSet(pEAT[dwOrd], pNt);
printf("函数序号: %08d RVA:%p 函数偏移:%p ",
dwID,
pEAT[dwOrd],
dwFunOffset);
//获取函数名
// 根据序号索引到函数名称表中的名字
for (DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++)
{
// 在序号表中查找函数的序号<span style="font-family: Arial, Helvetica, sans-serif;">------------序号表的值 对应着 地址表的下标</span>
if (pEIT[dwIndex] == dwOrd)
{
// 根据序号索引到函数名称表中的名字
DWORD dwNameOffset = RVA2OffSet(pENT[dwIndex], pNt);
char* pFunName = (char*)((DWORD)lpImage + dwNameOffset);
printf("函数名称: %s\n",
pFunName);
continue;
}
}
printf("\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
LPCTSTR path = L"C:\\Users\\Denny\\Desktop\\(手动查找导入导出表)\\(手动查找导入导出表)\\MFCLibrary1Dll.dll";
HANDLE hFile = nullptr;
if ( INVALID_HANDLE_VALUE == (hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ))
{
return 0;
}
DWORD dwSize = 0;
if ( INVALID_FILE_SIZE == (dwSize = GetFileSize(hFile, NULL)))
{
CloseHandle(hFile);
return 0;
}
PVOID lpFileImage = nullptr;
if (!(lpFileImage = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE)))
{
CloseHandle(hFile);
return 0;
}
DWORD dwRet = 0;
//将文件内容读取到内容空间
if (! ReadFile(hFile, lpFileImage, dwSize, &dwRet, NULL))
{
CloseHandle(hFile);
VirtualFree(lpFileImage, dwSize, MEM_RELEASE);
return 0;
}
ShowExport(lpFileImage, dwSize);
system("pause");
return 0;
}
PE总结9 --PE文件结构之 解析导出表
最新推荐文章于 2024-07-10 17:42:39 发布