自学了C语言,自己实现LordPE, PeViewer等工具的控制台版本
程序主界面
打印DOS头信息
打印NT头信息
数据目录
打印节区头信息
以下是实现功能的代码,由于是自学,所以可能有些代码对大佬来说会非常奇怪,还请大家多指教。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <conio.h> //提供getch(),用于无回显输入
void Print_Hex_Data(FILE* fp, unsigned char des[], int n); //截取二进制数据,会将小端序转换成正常序
void Print_Hex_Char(FILE* fp, unsigned char des[], int n); //截取二进制数据,不会将小端序转换成正常序
void Print_Dos_Header(FILE* fp); //打印DOS头
void Print_Nt_Header(FILE* fp); //打印NT头
void Print_Sec_Header(FILE* fp); //打印节区头
int HtoD(char* str); //将16进制的字符串数字转换成10进制的整型数字
int main(int argc, char* argv[]) {
int opt = 0;
char pe_name[FILENAME_MAX] = { 0 };
next: puts("请输入PE名:");
scanf("%s", pe_name);
getchar();
FILE* fp = fopen(pe_name, "rb");
if (fp == NULL)
{
perror("打开文件失败");
exit(0);
}
puts("******输入数字选择******");
puts("*1.DOS头 *");
puts("*2.NT头 *");
puts("*3.节区头 *");
puts("*4.打开另一个PE文件 *");
puts("*按其他键退出 *");
puts("************************");
while (1)
{
opt=getch()-48; //getch()获取的是字符的ASCII码值
switch (opt)
{
case 1:
Print_Dos_Header(fp);
break;
case 2:
Print_Nt_Header(fp);
break;
case 3:
Print_Sec_Header(fp);
break;
case 4:
goto next;
default:
return 0;
}
}
fclose(fp);
return 0;
}
int HtoD(char* str) //将16进制的字符串数字转换成10进制的整形数字
{
int i = 0;
int exp = 0;
int res = 0;
int temp = 0;
while (str[i] != '\0') {
++i;
}
exp = i - 1;
i = 0;
while (str[i] != '\0') {
if (str[i] >= '0' && str[i] <= '9') //'0'-'9'时应刚减去48, '0'的ASCII码值为48(0x30)
{
temp = str[i] - 48;
}
else //'A'-'F'时应减去55, 'A'的ASCII码为65(0x41)
{
temp = str[i] - 55;
}
res += temp * pow(16, exp);
exp--;
i++;
}
return res;
}
//将二进制数据转换成可显示的十六进制值, 会将小端序转换成正常顺序
/*
参数说明:fp-文件指针
des-缓冲区
n-读取字节数
*/
void Print_Hex_Data(FILE* fp, unsigned char des[], int n) {
char str[20] = { 0 };
fread(str, sizeof(char), n, fp);
int j = 0;
for (int i = n - 1; i >= 0; i--) //这里从读取的缓冲最后一个字符开始取,倒序
{
unsigned char ch = str[i];
unsigned char high_ch = ch >> 4; //取高4位,转换时类型要统一
unsigned char low_ch = ch & 15; //取低4位,15的二进制数是00001111
//将数字转成对应的ASCII码值
if (high_ch < 10) {
high_ch += 0x30;
}
else {
high_ch += 0x37;
}
if (low_ch < 10) {
low_ch += 0x30;
}
else {
low_ch += 0x37;
}
des[j] = high_ch;
++j;
des[j] = low_ch;
++j;
}
des[j] = '\0';
}
//将二进制数据转换成可显示的十六进制值, 不会转换字节顺序
void Print_Hex_Char(FILE* fp, unsigned char des[], int n)
{
char str[20] = { 0 };
fread(str, sizeof(char), n, fp);
int j = 0;
for (int i = 0; i < n; i++) //顺序读取,不会调整顺序
{
unsigned char ch = str[i];
unsigned char high_ch = ch >> 4; //取高4位,转换时类型要统一
unsigned char low_ch = ch & 15; //取低4位,15的二进制数是00001111
//将数字转成对应的ASCII码值
if (high_ch < 10) {
high_ch += 0x30;
}
else {
high_ch += 0x37;
}
if (low_ch < 10) {
low_ch += 0x30;
}
else {
low_ch += 0x37;
}
des[j] = high_ch;
++j;
des[j] = low_ch;
++j;
}
des[j] = '\0';
}
//打印DOS头信息
void Print_Dos_Header(FILE* fp)
{
rewind(fp);
char str[100];
printf("--DOS头\n");
puts(" | ");
Print_Hex_Char(fp, str, 2);
printf(" |----0x%.8X---->e_magic(魔数)-->%s\n", 0, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_cblp(文件最后一页字节数)-->%s\n", 2, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_cp(文件页数)-->%s\n", 4, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_crlc(重定位)-->%s\n", 6, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_cparhdr(段中头的大小)-->%s\n", 8, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_minalloc(需要的最少额外段)-->%s\n", 10, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_maxalloc(需要的最多额外段)-->%s\n", 12, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_ss(初始的SS寄存器的值)-->%s\n", 14, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_sp(初始的SP寄存器的值)-->%s\n", 16, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_csum(校验和)-->%s\n", 18, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_ip(初始的IP寄存器的值)-->%s\n", 20, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_cs(初始的CS寄存器的值)-->%s\n", 22, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_lfarlc(重定位表在文件中的地址)-->%s\n", 24, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_ovno(交叠数)-->%s\n", 26, str);
Print_Hex_Data(fp, str, 8);
printf(" |----0x%.8X---->e_res[4](保留字)-->%s\n", 28, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_oemid(OEM识别符)-->%s\n", 36, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->e_oeminfo(OEM信息)-->%s\n", 38, str);
Print_Hex_Data(fp, str, 20);
printf(" |----0x%.8X---->e_res2[10](O保留字)-->%s\n", 40, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->e_lfanew(NT头起始地址)-->%s\n", 60, str);
puts(" | ");
}
//打印NT头
void Print_Nt_Header(FILE* fp)
{
rewind(fp);
fseek(fp, 60, SEEK_SET);
char str[20] = { 0 };
Print_Hex_Data(fp, str, 4);
long int nt_begin_offset = 0;
//将字符串地址,转换成十进制的地址
nt_begin_offset = HtoD(str);
fseek(fp, nt_begin_offset, SEEK_SET);
printf("--NT头\n");
puts(" | ");
Print_Hex_Char(fp, str, 4);
printf(" |----0x%.8X---->Magic(魔数)-->%s\n", nt_begin_offset, str);
//文件头
{
puts(" |----文件头 ");
Print_Hex_Char(fp, str, 2);
printf(" | |----0x%.8X---->Machine(处理器型号)-->%s\n", nt_begin_offset + 4, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->NumberOfSections(节区数)-->%s\n", nt_begin_offset + 6, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->TimeDateStamp(时间戳)-->%s\n", nt_begin_offset + 10, str);
Print_Hex_Char(fp, str, 4);
printf(" | |----0x%.8X---->PointerToSymbolTable(符号表指针,调试用,一般为0)-->%s\n", nt_begin_offset + 14, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->NumberOfSymbols(符号数,调试用,一般为0)-->%s\n", nt_begin_offset + 18, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->SizeOfOptionalHeader(可选头大小)-->%s\n", nt_begin_offset + 20, str);
Print_Hex_Char(fp, str, 2);
printf(" | |----0x%.8X---->Characteristics(文件属性)-->%s\n", nt_begin_offset + 22, str);
puts(" | ");
}
//可选头
puts(" |----可选头 ");
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->Magic(魔数,判断32或64位)-->%s\n", nt_begin_offset + 24, str);
if (!strcmp(str, "010B")) //打印32位PE文件可选头
{
Print_Hex_Data(fp, str, 1);
printf(" | |----0x%.8X---->MajorLinkerVersion(链接器主版本号)-->%s\n", nt_begin_offset + 26, str);
Print_Hex_Data(fp, str, 1);
printf(" | |----0x%.8X---->MinorLinkerVersion(链接器次版本号)-->%s\n", nt_begin_offset + 27, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfCode(代码段大小)-->%s\n", nt_begin_offset + 28, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfInitializedData(已初始化的数据大小)-->%s\n", nt_begin_offset + 32, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfUninitializedData(未初始化的数据大小)-->%s\n", nt_begin_offset + 36, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->AddressOfEntryPoint(程序入口点)-->%s\n", nt_begin_offset + 40, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->BaseOfCode(代码地址)-->%s\n", nt_begin_offset + 44, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->BaseOfData(数据地址)-->%s\n", nt_begin_offset + 48, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->ImageBase(映像基址)-->%s\n", nt_begin_offset + 52, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SectionAlignment(内存中单元块的大小)-->%s\n", nt_begin_offset + 56, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->FileAlignment(文件中单元块的大小)-->%s\n", nt_begin_offset + 60, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MajorOperatingSystemVersion(操作系统主版本号)-->%s\n", nt_begin_offset + 64, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MinorOperatingSystemVersion(操作系统次版本号)-->%s\n", nt_begin_offset + 66, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MajorImageVersion(映像文件主版本号)-->%s\n", nt_begin_offset + 68, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MinorImageVersion(映像文件次版本号)-->%s\n", nt_begin_offset + 70, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MajorSubsystemVersion(子系统主版本号)-->%s\n", nt_begin_offset + 72, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MinorSubsystemVersion(子系统次版本号)-->%s\n", nt_begin_offset + 74, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->Win32VersionValue(保留项)-->%s\n", nt_begin_offset + 76, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfImage(映像文件大小)-->%s\n", nt_begin_offset + 80, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfHeaders(所有头大小)-->%s\n", nt_begin_offset + 84, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->CheckSum(校验和)-->%s\n", nt_begin_offset + 88, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->Subsystem(子系统,区分文件类别,1-系统驱动 2-GUI程序 3-CGI程序)-->%s\n", nt_begin_offset + 92, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->DllCharacteristics(DLL特性,已废弃)-->%s\n", nt_begin_offset + 94, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfStackReserves(保留的栈大小)-->%s\n", nt_begin_offset + 96, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfStackCommit(交付使用的栈大小)-->%s\n", nt_begin_offset + 100, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfHeapReserve(保留的堆大小)-->%s\n", nt_begin_offset + 104, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfHeapCommit(交付使用的堆大小)-->%s\n", nt_begin_offset + 108, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->LoaderFlags(加载器标志,已废弃)-->%s\n", nt_begin_offset + 112, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->NumberOfRvaAndSizes(数据目录个数)-->%s\n", nt_begin_offset + 116, str);
}
else //打印64位PE文件可选头
{
Print_Hex_Data(fp, str, 1);
printf(" | |----0x%.8X---->MajorLinkerVersion(链接器主版本号)-->%s\n", nt_begin_offset + 26, str);
Print_Hex_Data(fp, str, 1);
printf(" | |----0x%.8X---->MinorLinkerVersion(链接器次版本号)-->%s\n", nt_begin_offset + 27, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfCode(代码段大小)-->%s\n", nt_begin_offset + 28, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfInitializedData(已初始化的数据大小)-->%s\n", nt_begin_offset + 32, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfUninitializedData(未初始化的数据大小)-->%s\n", nt_begin_offset + 36, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->AddressOfEntryPoint(程序入口点)-->%s\n", nt_begin_offset + 40, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->BaseOfCode(代码地址)-->%s\n", nt_begin_offset + 44, str);
Print_Hex_Data(fp, str, 8);
printf(" | |----0x%.8X---->ImageBase(映像基址)-->%s\n", nt_begin_offset + 48, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SectionAlignment(内存中单元块的大小)-->%s\n", nt_begin_offset + 56, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->FileAlignment(文件中单元块的大小)-->%s\n", nt_begin_offset + 60, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MajorOperatingSystemVersion(操作系统主版本号)-->%s\n", nt_begin_offset + 64, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MinorOperatingSystemVersion(操作系统次版本号)-->%s\n", nt_begin_offset + 66, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MajorImageVersion(映像文件主版本号)-->%s\n", nt_begin_offset + 68, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MinorImageVersion(映像文件次版本号)-->%s\n", nt_begin_offset + 70, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MajorSubsystemVersion(子系统主版本号)-->%s\n", nt_begin_offset + 72, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->MinorSubsystemVersion(子系统次版本号)-->%s\n", nt_begin_offset + 74, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->Win32VersionValue(保留项)-->%s\n", nt_begin_offset + 76, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfImage(映像文件大小)-->%s\n", nt_begin_offset + 80, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->SizeOfHeaders(所有头大小)-->%s\n", nt_begin_offset + 84, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->CheckSum(校验和)-->%s\n", nt_begin_offset + 88, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->Subsystem(子系统,区分文件类别,1-系统驱动 2-GUI程序 3-CGI程序)-->%s\n", nt_begin_offset + 92, str);
Print_Hex_Data(fp, str, 2);
printf(" | |----0x%.8X---->DllCharacteristics(DLL特性,已废弃)-->%s\n", nt_begin_offset + 94, str);
Print_Hex_Data(fp, str, 8);
printf(" | |----0x%.8X---->SizeOfStackReserves(保留的栈大小)-->%s\n", nt_begin_offset + 96, str);
Print_Hex_Data(fp, str, 8);
printf(" | |----0x%.8X---->SizeOfStackCommit(交付使用的栈大小)-->%s\n", nt_begin_offset + 104, str);
Print_Hex_Data(fp, str, 8);
printf(" | |----0x%.8X---->SizeOfHeapReserve(保留的堆大小)-->%s\n", nt_begin_offset + 112, str);
Print_Hex_Data(fp, str, 8);
printf(" | |----0x%.8X---->SizeOfHeapCommit(交付使用的堆大小)-->%s\n", nt_begin_offset + 120, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->LoaderFlags(加载器标志,已废弃)-->%s\n", nt_begin_offset + 128, str);
Print_Hex_Data(fp, str, 4);
printf(" | |----0x%.8X---->NumberOfRvaAndSizes(数据目录个数)-->%s\n", nt_begin_offset + 132, str);
}
//数据目录
{
int datadirectory_offset = 0;
fseek(fp, nt_begin_offset + 24, SEEK_SET);
Print_Hex_Data(fp, str, 2);
if (!strcmp(str, "010B"))
{
datadirectory_offset = nt_begin_offset + 120; //32位程序数据目录较nt头起始地址偏移120字节
}
else {
datadirectory_offset = nt_begin_offset + 136; //64位程序数据目录较nt头起始地址偏移136字节
}
fseek(fp, datadirectory_offset, SEEK_SET); //将文件流置于数据目录起始处
char str_add[20] = { 0 };
printf(" | |\n");
printf(" | |----数据目录\n");
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->输出表(Export Table) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->输入表(Import Table) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 8, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->资源(Resource) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 16, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->异常数据(Exception) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 24, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->安全数据(Security) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 32, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->重定位表(Relocation) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 40, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->调试数据(Debug) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 48, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->版权数据(Copyright) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 56, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->全局指针Globalptr) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 64, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->TLS表 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 72, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->载入配置(Load Config) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 80, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->绑定输入(Bound Import) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 88, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->输入地址表(Import Address Table) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 96, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->延迟装入表(Delay Import) 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 104, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->COM 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 112, str, str_add);
Print_Hex_Data(fp, str, 4);
Print_Hex_Data(fp, str_add, 4);
printf(" | |---->0x%.8X---->保留字段 地址: 0x%s 大小: 0x%s\n", datadirectory_offset + 120, str, str_add);
}
}
//打印节区头
void Print_Sec_Header(FILE* fp)
{
//确定节区头的偏移量
int sec_header_offset = 0;
char str[20] = { 0 }; //先获取NT头偏移量
fseek(fp, 60, SEEK_SET);
Print_Hex_Data(fp, str, 4);
int nt_begin_offset = HtoD(str);
fseek(fp, nt_begin_offset + 24, SEEK_SET); //获取可选头magic数
Print_Hex_Data(fp, str, 2);
if (!strcmp(str, "010B"))
{
sec_header_offset = nt_begin_offset + 248; //32位NT头大小为248
}
else
{
sec_header_offset = nt_begin_offset + 264; //64位NT头大小为264
}
//获取节区个数
fseek(fp, nt_begin_offset + 6, SEEK_SET); //文件头的第二个最字段(word型)
Print_Hex_Data(fp, str, 2);
int section_num = HtoD(str);
fseek(fp, sec_header_offset, SEEK_SET); //将文件流置于节区头起始位置
printf("--节区头\n");
for (int i = 0; i < section_num; i++)
{
puts(" | ");
fread(str, sizeof(char), 8, fp);
printf(" |----0x%.8X---->Name[8](节名): %s\n", sec_header_offset * (i + 1), str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->VirtualSize(在内存中的大小): %s\n", sec_header_offset * (i + 1) + 8, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->VirtualAddress(在内存中的地址): %s\n", sec_header_offset * (i + 1) + 12, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->SizeOfRawData(在文件中的大小): %s\n", sec_header_offset * (i + 1) + 16, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->PointerToRawData(在文件中的地址):%s\n", sec_header_offset * (i + 1) + 20, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->PointerToRelocations(重定位指针):%s\n", sec_header_offset * (i + 1) + 24, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->PointerToLinenumbers(行数指针): %s\n", sec_header_offset * (i + 1) + 28, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->NumberOfRelocations(重定位数目): %s\n", sec_header_offset * (i + 1) + 32, str);
Print_Hex_Data(fp, str, 2);
printf(" |----0x%.8X---->NumberOfLinenumbers(行数数目): %s\n", sec_header_offset * (i + 1) + 34, str);
Print_Hex_Data(fp, str, 4);
printf(" |----0x%.8X---->Characteristics(节区属性): %s\n", sec_header_offset * (i + 1) + 36, str);
}
}