自学了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); } }
更多【PE学习笔记-利用C语言实现PE头解析】相关视频教程:www.yxfzedu.com