emVersion);
printf("从子系统版本: 0x%08X \t %08d \n", NtHeader->OptionalHeader.MinorSubsystemVersion, NtHeader->OptionalHeader.MinorSubsystemVersion);
printf("Win32版本: 0x%08X \t %08d \n", NtHeader->OptionalHeader.Win32VersionValue, NtHeader->OptionalHeader.Win32VersionValue);
printf("DLL标识: 0x%08X \t %08d \n", NtHeader->OptionalHeader.DllCharacteristics, NtHeader->OptionalHeader.DllCharacteristics);
printf("SizeOfStackReserve: 0x%08X \t %08d \n", NtHeader->OptionalHeader.SizeOfStackReserve, NtHeader->OptionalHeader.SizeOfStackReserve);
printf("SizeOfStackCommit: 0x%08X \t %08d \n", NtHeader->OptionalHeader.SizeOfStackCommit, NtHeader->OptionalHeader.SizeOfStackCommit);
printf("SizeOfHeapReserve: 0x%08X \t %08d \n", NtHeader->OptionalHeader.SizeOfHeapReserve, NtHeader->OptionalHeader.SizeOfHeapReserve);
printf("SizeOfHeapCommit: 0x%08X \t %08d \n", NtHeader->OptionalHeader.SizeOfHeapCommit, NtHeader->OptionalHeader.SizeOfHeapCommit);
printf("LoaderFlags: 0x%08X \t %08d \n", NtHeader->OptionalHeader.LoaderFlags, NtHeader->OptionalHeader.LoaderFlags);
}
else
{
printf("非标准程序 \n");
}
system("pause");
return 0;
}
当程序被运行后,则可输出NT头中针对FileHeader
及OptionalHeader
表中的所有内容,输出效果图如下图所示;
此外针对数据目录表的枚举,也将变得很容易实现,一般而言通过NtHeader->OptionalHeader.NumberOfRvaAndSizes
读者可得到数据目录表的数量,当得到了数据目录表的数量后则可通过循环的方式依次输出DataDirectory[x]
数组中每一个变量的参数信息,根据每次循环的不同则输出不同的参数;
// --------------------------------------------------
// 临时将RVA转换为FOA的函数
// --------------------------------------------------
DWORD RVAtoFOA(DWORD rva)
{
auto SectionTables = IMAGE_FIRST_SECTION(NtHeader); // 获取区段表
WORD Count = NtHeader->FileHeader.NumberOfSections; // 获取区段数量
for (int i = 0; i < Count; ++i)
{
// 判断是否存在于区段中
DWORD Section_Start = SectionTables[i].VirtualAddress;
DWORD Section_Ends = SectionTables[i].VirtualAddress + SectionTables[i].SizeOfRawData;
if (rva >= Section_Start && rva < Section_Ends)
{
// 找到之后计算位置并返回值
return rva - SectionTables[i].VirtualAddress + SectionTables[i].PointerToRawData;
}
}
return -1;
}
int main(int argc, char * argv[])
{
BOOL PE = IsPeFile(OpenPeFile("c://pe/x86.exe"), 0);
if (PE == TRUE)
{
int Data_Size = NtHeader->OptionalHeader.NumberOfRvaAndSizes;
printf("编号 \t 目录RVA \t 目录FOA \t Size长度(十进制) \t Size长度(十六进制) \t 功能描述 \n");
for (int x = 0; x < Data_Size; x++)
{
printf("%03d \t 0x%08X \t 0x%08X \t %08d \t\t 0x%08X \t\t", x + 1, NtHeader->OptionalHeader.DataDirectory[x].VirtualAddress,
RVAtoFOA(NtHeader->OptionalHeader.DataDirectory[x].VirtualAddress),
NtHeader->OptionalHeader.DataDirectory[x].Size, NtHeader->OptionalHeader.DataDirectory[x].Size);
switch (x)
{
case 0: printf("Export symbols \n"); break;
case 1: printf("Import symbols \n"); break;
case 2: printf("Resources \n"); break;
case 3: printf("Exception \n"); break;
case 4: printf("Security \n"); break;
case 5: printf("Base relocation \n"); break;
case 6: printf("Debug \n"); break;
case 7: printf("Copyright string