#include "stdafx.h"
#include <windows.h>
#include "stdlib.h"
#define FILEPATH_IN "C:/testdll.dll"
DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer )
{
FILE *pFile = NULL;
DWORD fileSize = 0; //文件大小
LPVOID pTempFileBuffer = NULL; //缓冲区首地址
pFile = fopen(lpszFile,"rb"); //打开文件
if(!pFile)
{
printf("打开文件失败");
return NULL;
}
//读取文件大小
fseek(pFile,0,SEEK_END); //将指针从开始的位置移动到末尾
fileSize = ftell(pFile); //获取数据大小
//分配缓冲区(申请内存)
pTempFileBuffer = malloc(fileSize);
if(!pTempFileBuffer)
{
printf("分配空间失败");
fclose(pFile);
return NULL;
}
//将文件数据读取到缓冲区
fseek(pFile,0,SEEK_SET); //将指针指向开始
size_t n = fread(pTempFileBuffer,fileSize,1,pFile); //将数据读取到缓冲区中
if(!n)
{
printf("读取数据失败");
free(pTempFileBuffer); //释放内存
fclose(pFile); //关闭文件
return NULL;
}
//关闭文件
*pFileBuffer = pTempFileBuffer;
pTempFileBuffer = NULL;
fclose(pFile); //关闭文件
return fileSize;
}
//**********************************************************************
DWORD RvaToFoa(IN LPVOID pFileBuffer, IN DWORD dwRva)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
//DOS头
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
//NT头地址
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//标准PE头地址
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4);
//可选PE头地址
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个节表地址
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
for(int i=0 ; i < pPEHeader->NumberOfSections ; i++)
{
//节在内存中的位置RVA
DWORD dwSectionBeginRva = pSectionHeader[i].VirtualAddress;
//节在内存中相对于文件中结束的位置RVA
DWORD dwSectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData;
//判断RVA是否在当前节中
if(dwRva >= dwSectionBeginRva && dwRva <= dwSectionEndRva)
{
//FOA = RVA - 节在内存中的位置 + 节在文件中的偏移
DWORD dwFoa = dwRva - dwSectionBeginRva + pSectionHeader[i].PointerToRawData;
return dwFoa;
}
}
}
//**********************************************************************
VOID TestPrintExPort()
{
LPVOID pFileBuffer = NULL;
DWORD Size = 0;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
//File-> FileBuffer
Size = ReadPEFile(FILEPATH_IN,&pFileBuffer); //调用函数读取文件数据
if(!pFileBuffer || !Size)
{
printf("File-> FileBuffer失败");
return;
}
//获取头信息
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuffer + pDosHeader->e_lfanew + 0x4 + IMAGE_SIZEOF_FILE_HEADER);
//指向数组
PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionHeader->DataDirectory;
//导出表的地址Rva
DWORD dwExProtTableRva = pDataDirectory[0].VirtualAddress;
//导出表的地址Foa
DWORD dwExProtTableFoa = RvaToFoa(pFileBuffer,dwExProtTableRva);
//导出表在文件中的地址
PIMAGE_EXPORT_DIRECTORY PExProtTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + dwExProtTableFoa);
printf("导出表name:0x%08X\n",PExProtTable->Name);
printf("导出表Base:0x%08X\n",PExProtTable->Base);
printf("导出表NumberOfFunctions:0x%08X\n",PExProtTable->NumberOfFunctions);
printf("导出表NumberOfNames:0x%08X\n",PExProtTable->NumberOfNames);
printf("导出表AddressOfFunctions:0x%08X\n",PExProtTable->AddressOfFunctions);
printf("导出表AddressOfNames:0x%08X\n",PExProtTable->AddressOfNames);
printf("导出表AddressOfNameOrdinals:0x%08X\n",PExProtTable->AddressOfNameOrdinals);
//将导出表Name、AddressOfNames、AddressOfFunctions、AddressOfNameOrdinals的Rva转换成Foa
DWORD dwNameFoa = RvaToFoa(pFileBuffer,PExProtTable->Name);
DWORD dwAddressOfNamesFoa = RvaToFoa(pFileBuffer,PExProtTable->AddressOfNames);
DWORD dwAddressOfFunctionsFoa = RvaToFoa(pFileBuffer,PExProtTable->AddressOfFunctions);
DWORD dwAddressOfNameOrdinalsFoa = RvaToFoa(pFileBuffer,PExProtTable->AddressOfNameOrdinals);
//导出表的名字
PBYTE pDllName = (PBYTE)((DWORD)pFileBuffer + dwNameFoa);
printf("导出表名%s\n",pDllName);
//导出函数地址表文件中的位置
PDWORD pAddressTable = (PDWORD)((DWORD)pFileBuffer + dwAddressOfFunctionsFoa);
//导出函数序号表文件中的位置
PWORD pOrdinaTable = (PWORD)((DWORD)pFileBuffer + dwAddressOfNameOrdinalsFoa);
//导出函数名称表文件中的位置
PDWORD pNameTable = (PDWORD)((DWORD)pFileBuffer + dwAddressOfNamesFoa);
//判断是以序号导出还是以名字导出
BOOL bIndexIsExIst = FALSE;
for(DWORD i=0 ; i<PExProtTable->NumberOfFunctions ; i++)
{
//获取导出函数地址
printf("RVA的地址:%08X",pAddressTable[i]);
bIndexIsExIst = FALSE;
//以导出函数名称表的个数的数量循环
for(DWORD nNameIndex = 0 ; nNameIndex < PExProtTable->NumberOfNames ; ++nNameIndex)
{
//根据导出函数地址的下标,去序号表中找是否存在
if(i == pOrdinaTable[nNameIndex])
{
bIndexIsExIst = TRUE;
break;
}
}
if(bIndexIsExIst == TRUE)
{
//序号表中存在,根据序号表的索引,去名称表中找函数名称,获得函数名称表RVA
DWORD dwNameRva = pNameTable[nNameIndex];
//将函数名称表RVA转换成存有真实函数名称的文件偏移
PBYTE pFunName = (PBYTE)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer,dwNameRva));
printf(" 函数名[%s]\t",pFunName);
//获取导出序号
printf(" 序号[%d]",i + PExProtTable->Base);
}
else
{
//序号表中不存在,判断是否存在这个函数
if(pAddressTable[i] != 0)
{
//隐藏函数名
printf(" 函数名:[-]\t");
printf(" 序号[%d]",i + PExProtTable->Base);
}
}
printf("\n");
}
return;
}
//**********************************************************************
int main(int argc, char* argv[])
{
TestPrintExPort();
getchar();
return 0;
}
|