// PE导出表.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
int main(void)
{
PVOID64 ulModuleBase;
ulModuleBase = GetModuleHandleW(TEXT("kernel32.dll")); //得到"kernel32.dll"的基地址
PIMAGE_DOS_HEADER pDosHeader; //dos头结构体
PIMAGE_NT_HEADERS64 NtDllHeader; //nt结构头
IMAGE_OPTIONAL_HEADER64 opthdr; //可选镜像头部
IMAGE_EXPORT_DIRECTORY *pExportTable;
ULONG_PTR* arrayOfFunctionAddresses;
ULONG_PTR* arrayOfFunctionNames;
WORD* arrayOfFunctionOrdinals;
ULONG_PTR Base, x, functionAddress;
ULONG_PTR functionOrdinal;
char *functionName;
__try
{
//得到dos头 PE内存映像从DOS头开始,也就是从IMAGE_DOS_HEADER结构体开始,文件在内存中的开始地址,也就是IMAGE_DOS_HEADER结构体开始的位置
/*把这个值强制类型转换后,赋值给PIMAGE_DOS_HEADER类型指针,作为指向IMAGE_DOS_HEADER结构体的指针*/
pDosHeader = (PIMAGE_DOS_HEADER)ulModuleBase; //强制类型转换,将一个“PVOID64”转换为“PIMAGE_DOS_HEADER”
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) //校验IMAGE_DOS_HEADER结构体的e_magic 是否符合预定义的数值5A4D
{
printf("IMAGE_DOS_SIGNATURE failed\r\n");
return FALSE;
}
//得到NT文件头 NT结构体
NtDllHeader = (PIMAGE_NT_HEADERS64)(ULONG_PTR)((ULONG_PTR)pDosHeader + pDosHeader->e_lfanew);
if (NtDllHeader->Signature != IMAGE_NT_SIGNATURE) //校验是否找到PE文件头,IMAGE_NT_SIGNATURE预定义为PE文件头,值为4550,DWORD型
{
printf("IMAGE_NT_SIGNATURE failed\r\n");
return FALSE;
}
//得到可选镜像结构体
opthdr = NtDllHeader->OptionalHeader;
//得到内存的导出表结构
pExportTable = (IMAGE_EXPORT_DIRECTORY*)((ULONG_PTR)ulModuleBase + opthdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); //得到导出表
//地址
arrayOfFunctionAddresses = (ULONG_PTR*)((ULONG_PTR)ulModuleBase + pExportTable->AddressOfFunctions); //地址表
/*NumberOfNames:被定义函数名称的导出函数的总数,显然只有这个数量的函数既可以用函数名方式导出。也可以用序号方式导出,剩*/
/*下的NumberOfFunctions 减去NumberOfNames 数量的函数只能用序号方式导出。该字段的值只会小于或者等于NumberOfFunctions 字段*/
/*的值,如果这个值是0,表示所有的函数都是以序号方式导出的。*/
arrayOfFunctionNames = (ULONG_PTR*)((BYTE*)ulModuleBase + pExportTable->AddressOfNames); //函数名表
if (IsBadReadPtr(arrayOfFunctionNames, pExportTable->NumberOfFunctions))
{
printf("内存不可访问\n");
system("Pause");
return false;
}
arrayOfFunctionOrdinals = (WORD*)((BYTE*)ulModuleBase + pExportTable->AddressOfNameOrdinals);
//得到导出表的起始地址
Base = pExportTable->Base;
//然后我们开始搜索整个导出表
for (x = 0; x < pExportTable->NumberOfFunctions; x++) //在整个导出表里扫描
{
functionName = (char*)((BYTE*)ulModuleBase + arrayOfFunctionNames[x]);
functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1;
functionAddress = (ULONG_PTR)((BYTE*)ulModuleBase + arrayOfFunctionAddresses[functionOrdinal]);
printf("%s:0x%08X\r\n", functionName, functionAddress);
}
}
_except(EXCEPTION_EXECUTE_HANDLER){
}
system("Pause");
return 0;
}
这段代码问题到底出在那里,AddressOfNameOrdinals,AddressOfNames导出表结构体的这两个成员都是0,按照这个程序给出的代码导出表函数名的数组起始地址直接和DOS头文件重合,这绝对有问题,可是错在那里,如何改?求大牛指教
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!