七、获取输出表信息
1、获取数据目录中元素的入口
LPVOID GetDirectoryEntryToData(LPVOID ImageBase, USHORT DirectoryEntry)
{
DWORD dwDataStartRVA;
PIMAGE_NT_HEADERS pNtH = nullptr;
PIMAGE_OPTIONAL_HEADER pOH = nullptr;
LPVOID pData = nullptr;
pNtH = GetNtHeaders(ImageBase);
if (!pNtH)
{
return nullptr;
}
pOH = GetOptionalHeader(ImageBase);
if (!pOH)
{
return nullptr;
}
dwDataStartRVA = pOH->DataDirectory[DirectoryEntry].VirtualAddress;
pData = ImageRvaToVa(pNtH, ImageBase, dwDataStartRVA, NULL);
if (!pData)
{
return nullptr;
}
return pData;
}
其中, ImageRvaToVa()用于从相对虚拟地址向磁盘地址的转换,返回一个指向磁盘地址的指针。这个函数定义在imagehlp.h中,使用时需要手动引用imagehlp.lib:
#include <imagehlp.h>
#pragma comment ( lib, "imagehlp.lib" )
2、获取输出表在磁盘文件中的位置
PIMAGE_EXPORT_DIRECTORY GetExportDirectory(LPVOID ImageBase)
{
if (!ImageBase)
{
return nullptr;
}
PIMAGE_EXPORT_DIRECTORY pED = (PIMAGE_EXPORT_DIRECTORY)GetDirectoryEntryToData(ImageBase, IMAGE_DIRECTORY_ENTRY_EXPORT);
if (!pED)
{
return nullptr;
}
return pED;
}
3、获取输出表信息
void ShowExportDirectory(PMAP_FILE_STRUCT stMapFile){
char data[9][48] = {
"Characteristics: ",
"TimeDateStamp: ",
"Name: ",
"Base: ",
"NumberOfFunctions: ",
"NumberOfNames: ",
"AddressOfFunctions: ",
"AddressOfNames: ",
"AddressOfNameOrdinals: "
};
PIMAGE_EXPORT_DIRECTORY pED = GetExportDirectory(stMapFile->ImageBase);
if (!pED)
{
printf("Can't get Export Table\n");
return;
}
char *szName = nullptr;
szName = (char *)ImageRvaToVa(GetNtHeaders(stMapFile->ImageBase), stMapFile->ImageBase, pED->Name, NULL);
//时间转换
time_t t = pED->TimeDateStamp;
char strTime[26] = { 0 };
tm* ptmBegin = localtime(&t);
strftime(strTime, 26, "%Y/%m/%d %H:%M:%S", ptmBegin);
printf("\n\n[Export Table]\n");
printf("%s %08lX\n", data[0], pED->Characteristics);
printf("%s %08lX (%s)\n", data[1], pED->TimeDateStamp, strTime);
printf("%s %08lX (%s)\n", data[2], pED->Name, szName);
printf("%s %08lX\n", data[3], pED->Base);
printf("%s %08lX\n", data[4], pED->NumberOfFunctions);
printf("%s %08lX\n", data[5], pED->NumberOfNames);
printf("%s %08lX\n", data[6], pED->AddressOfFunctions);
printf("%s %08lX\n", data[7], pED->AddressOfNames);
printf("%s %08lX\n", data[8], pED->AddressOfNameOrdinals);
}
结果如图所示:
4、获取输出函数:
void ShowExportFuncsInfo(LPVOID ImageBase)
{
if (!ImageBase)
{
return;
}
UINT iNumOfName = 0;
PDWORD pdwFuncs = nullptr;
PDWORD pdwNames = nullptr;
PWORD pwOrds = nullptr;
bool bIsByName = false;
PIMAGE_NT_HEADERS pNtH = nullptr;
PIMAGE_EXPORT_DIRECTORY pED = nullptr;
char cBuff[10] = { 0 };
char *szFuncName = nullptr;
pNtH = GetNtHeaders(ImageBase);
if (!pNtH)
{
return;
}
pED = GetExportDirectory(ImageBase);
if (!pED)
{
return;
}
iNumOfName = pED->NumberOfNames;
pwOrds = (PWORD)ImageRvaToVa(pNtH, ImageBase, pED->AddressOfNameOrdinals, NULL);
pdwFuncs = (PDWORD)ImageRvaToVa(pNtH, ImageBase, pED->AddressOfFunctions, NULL);
pdwNames = (PDWORD)ImageRvaToVa(pNtH, ImageBase, pED->AddressOfNames, NULL);
if (!pdwFuncs)
{
return;
}
printf("\n\nOrdinal RVA Function Name\n");
for (UINT i = 0; i < pED->NumberOfFunctions; i++)
{
if (pdwFuncs[i])
{
for (UINT j = 0; j < iNumOfName; j++)
{
if (i == pwOrds[j])
{
bIsByName = true;
szFuncName = (char *)ImageRvaToVa(pNtH, ImageBase, pdwNames[i], NULL);
break;
}
bIsByName = false;
}
printf("%04lX %08lX %s\n", (UINT)(pED->Base + i), pdwFuncs[i], szFuncName);
}
}
}
结果如图所示: