代码很简单,只是需要对PE文件头的理解,在这段代码中,我遇到的问题是结构体指针的问题,目前已经理解,具体请看代码中注释。
BOOL EnumEATTable(PVOID pModuleBase)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_EXPORT_DIRECTORY pExportTable = NULL;
ULONG_PTR *arrayOfFunctionAddress = NULL;
ULONG_PTR *arrayOfFunctionName = NULL;
WORD *arrayOfFunctionOrdinals = NULL;
char *functionName = NULL;
ULONG_PTR functionOrdinal, functionAddress;
pDosHeader = (PIMAGE_DOS_HEADER)pModuleBase;
if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
printf("Dos Header Error.\r\n");
return FALSE;
}
//下面的操作会使pDosHeader->e_lfanew的值乘以64,再进行相加,
//由于pDosHeader为指针类型,因此在进行相加时,会乘以结构体的大小
//pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader + pDosHeader->e_lfanew);
//这种方式是将指针直接转为ULONG类型,排除指针的影响,进行地址计算。
pNtHeader = (PIMAGE_NT_HEADERS)((ULONG)pDosHeader + pDosHeader->e_lfanew);
//这种方式是将结构体的指针,转为字节指针,由于字节指针长度为1,乘以字节指针长度也无影响。
pNtHeader = (PIMAGE_NT_HEADERS)((BYTE *)pDosHeader + pDosHeader->e_lfanew);
if(pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
printf("PE Header Error.\r\n");
return FALSE;
}
pExportTable = (PIMAGE_EXPORT_DIRECTORY)((ULONG)pModuleBase + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
arrayOfFunctionAddress = (ULONG_PTR *)((ULONG)pModuleBase + pExportTable->AddressOfFunctions);
arrayOfFunctionName = (ULONG_PTR *)((ULONG)pModuleBase + pExportTable->AddressOfNames);
arrayOfFunctionOrdinals = (WORD *)((ULONG)pModuleBase + pExportTable->AddressOfNameOrdinals);
for(int i = 0; i < pExportTable->NumberOfFunctions; i++)
{
functionName = (char *)((ULONG)pModuleBase + arrayOfFunctionName[i]);
functionOrdinal = arrayOfFunctionOrdinals[i] + pExportTable->Base - 1;
functionAddress = (ULONG_PTR)((ULONG)pModuleBase + arrayOfFunctionAddress[functionOrdinal]);
printf("%s:0x%0X\r\n", functionName, functionAddress);
}
}