#include<iostream>
#include<malloc.h>
#include<Windows.h>
#include<tchar.h>
#include<string.h>
//#pragma comment(lib,"Dll3.lib")
#pragma warning(disable:4996)
//extern "C" _declspec(dllimport) int sum(int x, int y);
typedef int (*lpsum)(int, int);
using namespace std;
int filelen(FILE* pfile)
{
fseek(pfile, 0, SEEK_END);
int result = ftell(pfile);
rewind(pfile);
return result;
}
int Align(int x, int y)
{
if (x % y == 0)
{
return int(x / y)*y;
}
else
{
return int(x / y)*y + y;
}
}
int rvaTofoa(int rva, char* buffer)
{
PIMAGE_DOS_HEADER pDosH = (PIMAGE_DOS_HEADER)(buffer);
PIMAGE_NT_HEADERS pNTH = (PIMAGE_NT_HEADERS)(buffer + pDosH->e_lfanew);
PIMAGE_FILE_HEADER pFH = (PIMAGE_FILE_HEADER)((char*)pNTH + 0x4);
PIMAGE_OPTIONAL_HEADER pOH = (PIMAGE_OPTIONAL_HEADER)((char*)pFH + 0x14);
int opHeaderLen = int(pFH->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER pSecH = (PIMAGE_SECTION_HEADER)((char*)pOH + opHeaderLen);
if (rva <= pOH->SizeOfHeaders)
{
return rva;
}
else
{
for (int i = 0; i < pFH->NumberOfSections; i++)
{
if ((rva > pSecH[i].VirtualAddress) &&( rva < pSecH[i].VirtualAddress + pSecH[i].Misc.VirtualSize))
{
return rva - pSecH[i].VirtualAddress + pSecH[i].PointerToRawData;
}
}
}
printf(" rvaTofoa error\r\n");
return 0;
}
/*
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics; // 未使用
DWORD TimeDateStamp; // 时间戳
WORD MajorVersion; // 未使用
WORD MinorVersion; // 未使用
DWORD Name; // 指向该导出表文件名字符串
DWORD Base; // 导出函数起始序号
DWORD NumberOfFunctions; // 所有导出函数的个数
DWORD NumberOfNames; // 以函数名字导出的函数个数
DWORD AddressOfFunctions; // 导出函数地址表RVA
DWORD AddressOfNames; // 导出函数名称表RVA
DWORD AddressOfNameOrdinals; // 导出函数序号表RVA
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
*/
void printExportDir(PIMAGE_EXPORT_DIRECTORY pED,char* buffer)
{
int nameFAddress = rvaTofoa(pED->Name, buffer);
char* name = buffer + nameFAddress;
printf("导出表文件名字为:%s\r\n", name);
printf("Characteristics: %08x\r\n", pED->Characteristics);
printf("TimeDateStamp: %08x\r\n", pED->TimeDateStamp);
printf("MajorVersion: %04x\r\n", pED->MajorVersion);
printf("MinorVersion: %04x\r\n", pED->MinorVersion);
printf("Name: %08x\r\n", pED->Name);
printf("Base: %08x\r\n", pED->Base);
printf("NumberOfFunctions: %08x\r\n", pED->NumberOfFunctions);
printf("NumberOfNames: %08x\r\n", pED->NumberOfNames);
printf("AddressOfFunctions: %08x\r\n", pED->AddressOfFunctions);
printf("AddressOfNames: %08x\r\n", pED->AddressOfNames);
printf("AddressOfNameOrdinals: %08x\r\n", pED->AddressOfNameOrdinals);
}
int GetFunctionAddrByName(char* buffer, char* name)
{
PIMAGE_DOS_HEADER pDosH = (PIMAGE_DOS_HEADER)(buffer);
PIMAGE_NT_HEADERS pNTH = (PIMAGE_NT_HEADERS)(buffer + pDosH->e_lfanew);
PIMAGE_FILE_HEADER pFH = (PIMAGE_FILE_HEADER)((char*)pNTH + 0x4);
PIMAGE_OPTIONAL_HEADER pOH = (PIMAGE_OPTIONAL_HEADER)((char*)pFH + 0x14);
int opHeaderLen = int(pFH->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER pSecH = (PIMAGE_SECTION_HEADER)((char*)pOH + opHeaderLen);
PIMAGE_DATA_DIRECTORY pDD = (PIMAGE_DATA_DIRECTORY)(pOH->DataDirectory);
int exportVAddress = pDD->VirtualAddress;
//printf("%08x\r\n", exportAddress);
int exportFAddress = rvaTofoa(exportVAddress, buffer);
PIMAGE_EXPORT_DIRECTORY pED = (PIMAGE_EXPORT_DIRECTORY)(buffer + exportFAddress);
//先在DWORD AddressOfNames; // 导出函数名称表RVA中寻找
int* FAddressOfNames = (int*)(rvaTofoa(pED->AddressOfNames,buffer)+buffer);//先得到函数名表在文件中的地址
printf("函数名表在文件中的地址%08x\r\n", rvaTofoa(pED->AddressOfNames, buffer));
int num = -1;
for (int i = 0; i < pED->NumberOfNames; i++)
{
//从中取出函数名的rva地址
int rvaOfname = (int) * (FAddressOfNames + i);
//转化为函数名在文件中地址
char* fileOfname = (char*)(buffer + rvaTofoa(rvaOfname, buffer));
printf("%s\r\n", fileOfname);
if (strcmp(fileOfname, name) == 0)
{
num = i;
break;
}
}
printf("%d\r\n", num);
//用获得的索引从序号表中找函数的序号 此处易错类型为word
WORD ord = *((WORD*)(rvaTofoa(pED->AddressOfNameOrdinals,buffer) + buffer) + num);
printf("%d\r\n", ord);
//用查到的序号查函数地址
int add = *((int*)(rvaTofoa(pED->AddressOfFunctions,buffer) + buffer) + ord);
return add;
}
int GetFunctionAddrByOrdinals(char* buffer, int num)
{
PIMAGE_DOS_HEADER pDosH = (PIMAGE_DOS_HEADER)(buffer);
PIMAGE_NT_HEADERS pNTH = (PIMAGE_NT_HEADERS)(buffer + pDosH->e_lfanew);
PIMAGE_FILE_HEADER pFH = (PIMAGE_FILE_HEADER)((char*)pNTH + 0x4);
PIMAGE_OPTIONAL_HEADER pOH = (PIMAGE_OPTIONAL_HEADER)((char*)pFH + 0x14);
int opHeaderLen = int(pFH->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER pSecH = (PIMAGE_SECTION_HEADER)((char*)pOH + opHeaderLen);
PIMAGE_DATA_DIRECTORY pDD = (PIMAGE_DATA_DIRECTORY)(pOH->DataDirectory);
int exportVAddress = pDD->VirtualAddress;
int exportFAddress = rvaTofoa(exportVAddress, buffer);
PIMAGE_EXPORT_DIRECTORY pED = (PIMAGE_EXPORT_DIRECTORY)(buffer + exportFAddress);
int ordbase = pED->Base;
int ord = num - ordbase;
int add = *((int*)(rvaTofoa(pED->AddressOfFunctions, buffer) + buffer) + ord);
return add;
}
int main()
{
FILE* pfile = fopen("C://Users//52511//Desktop//Dll3.dll","rb");
char* buffer = NULL;
int len = filelen(pfile);
buffer = (char*)malloc(len * sizeof(char));
memset(buffer, 0, len);
fread(buffer, 1, len, pfile);
PIMAGE_DOS_HEADER pDosH = (PIMAGE_DOS_HEADER)(buffer);
PIMAGE_NT_HEADERS pNTH = (PIMAGE_NT_HEADERS)(buffer + pDosH->e_lfanew);
PIMAGE_FILE_HEADER pFH = (PIMAGE_FILE_HEADER)((char*)pNTH + 0x4);
PIMAGE_OPTIONAL_HEADER pOH = (PIMAGE_OPTIONAL_HEADER)((char*)pFH + 0x14);
int opHeaderLen = int(pFH->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER pSecH = (PIMAGE_SECTION_HEADER)((char*)pOH + opHeaderLen);
PIMAGE_DATA_DIRECTORY pDD = (PIMAGE_DATA_DIRECTORY)(pOH->DataDirectory);
int exportVAddress = pDD->VirtualAddress;
//printf("%08x\r\n", exportAddress);
int exportFAddress = rvaTofoa(exportVAddress, buffer);
PIMAGE_EXPORT_DIRECTORY pED = (PIMAGE_EXPORT_DIRECTORY)(buffer+exportFAddress);
printExportDir(pED,buffer);
char* name =(char*) "Plus";
int address1 = GetFunctionAddrByName(buffer, name);
printf("Plus函数rva为:%08x\r\n", address1);
//int fileaddress1 = rvaTofoa(address, buffer);
//printf("Plus函数foa为%08x\r\n", fileaddress1);
int address2=GetFunctionAddrByOrdinals(buffer, 15);
printf("15函数rva为:%08x\r\n", address2);
int fileaddress2 = rvaTofoa(address2, buffer);
printf("15函数foa为:%08x\r\n", fileaddress2);
return 0;
}
滴水导出表
最新推荐文章于 2024-09-18 22:56:15 发布
这篇文章详细介绍了如何解析PE文件,包括计算文件偏移地址(FOA)从相对虚拟地址(RVA),以及查找和获取DLL导出函数地址的方法。主要涉及了IMAGE_DOS_HEADER,IMAGE_NT_HEADERS等结构体,以及rvaTofoa函数的实现。
摘要由CSDN通过智能技术生成