鱼C论坛

 找回密码
 立即注册
查看: 2020|回复: 5

[已解决]考验C语言编程能力的题

[复制链接]
发表于 2019-3-11 16:48:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大家好,我又来了,今天遇到一个比较考验C语言编程的问题,大家听说过pe吧,这是可执行程序最重要的一个文件了,现在有一个要求就是,用C语言  编写一个程序用来显示任意exe程序的pe头,包括(dos头,NT头(标准pe头,可选pe头)),以及里面的内容打印出来
虽然网上有些编程例子,但是那些并不是很好,有一些错误,所以就考考大家了,(ps:本人菜鸟,自然不会做,丢人了 ),顺便也想试试小甲鱼,你会不会做呢??@小甲鱼
附上pe结构文件表
其实只要输出这些内容就可以了。
最佳答案
2019-3-11 20:37:18
PE头都是有结构的。用C写也很简单吧,先把所需要的结构声明出来,然后用二进制读文件,读入结构体中。
  1. #include <stdio.h>
  2. #include <stdlib.h>


  3. typedef unsigned short WORD; // 声明 WORD 类型
  4. typedef unsigned int DWORD; // 声明 DWORD 类型

  5. // 声明 IMAGE_DOS_HEADER 结构体
  6. typedef struct IDosHeader
  7. {
  8.         WORD e_magic;
  9.         WORD e_cblp;
  10.         WORD e_cp;
  11.         WORD e_crlc;
  12.         WORD e_cparhdr;
  13.         WORD e_minalloc;
  14.         WORD e_maxalloc;
  15.         WORD e_ss;
  16.         WORD e_sp;
  17.         WORD e_csum;
  18.         WORD e_ip;
  19.         WORD e_cs;
  20.         WORD e_lfarlc;
  21.         WORD e_ovno;
  22.         WORD e_res[4];
  23.         WORD e_oemid;
  24.         WORD e_oeminfo;
  25.         WORD e_res2[10];
  26.         DWORD e_lfanew;
  27. } IDosHeader;

  28. int main()
  29. {
  30.         IDosHeader DosHeader;
  31.         FILE *fp = NULL;
  32.         char szFileName[100];

  33.         // 获取文件名(如:c:\2.exe)
  34.         printf("请输入文件名:");
  35.         gets(szFileName);

  36.         // 打开文件
  37.         if ( (fp=fopen(szFileName, "rb"))==NULL )
  38.         {
  39.                 printf("文件打开失败!\n");
  40.                 exit(EXIT_FAILURE);
  41.         }
  42.        
  43.         // 读取内容
  44.         if (fread(&DosHeader, sizeof(IDosHeader),1 , fp) != 1)
  45.         {
  46.                 printf("文件读取失败!\n");
  47.                 exit(EXIT_FAILURE);
  48.         }

  49.         printf("e_magic:%#x\n", DosHeader.e_magic); // 以16进制输出
  50.         printf("e_cblp:%#x\n", DosHeader.e_cblp); // 以16进制输出

  51.         return 0;
  52. }
复制代码
1.png

PE结构.rar

304.49 KB, 阅读权限: 10, 下载次数: 0

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-3-11 20:37:18 | 显示全部楼层    本楼为最佳答案   
PE头都是有结构的。用C写也很简单吧,先把所需要的结构声明出来,然后用二进制读文件,读入结构体中。
  1. #include <stdio.h>
  2. #include <stdlib.h>


  3. typedef unsigned short WORD; // 声明 WORD 类型
  4. typedef unsigned int DWORD; // 声明 DWORD 类型

  5. // 声明 IMAGE_DOS_HEADER 结构体
  6. typedef struct IDosHeader
  7. {
  8.         WORD e_magic;
  9.         WORD e_cblp;
  10.         WORD e_cp;
  11.         WORD e_crlc;
  12.         WORD e_cparhdr;
  13.         WORD e_minalloc;
  14.         WORD e_maxalloc;
  15.         WORD e_ss;
  16.         WORD e_sp;
  17.         WORD e_csum;
  18.         WORD e_ip;
  19.         WORD e_cs;
  20.         WORD e_lfarlc;
  21.         WORD e_ovno;
  22.         WORD e_res[4];
  23.         WORD e_oemid;
  24.         WORD e_oeminfo;
  25.         WORD e_res2[10];
  26.         DWORD e_lfanew;
  27. } IDosHeader;

  28. int main()
  29. {
  30.         IDosHeader DosHeader;
  31.         FILE *fp = NULL;
  32.         char szFileName[100];

  33.         // 获取文件名(如:c:\2.exe)
  34.         printf("请输入文件名:");
  35.         gets(szFileName);

  36.         // 打开文件
  37.         if ( (fp=fopen(szFileName, "rb"))==NULL )
  38.         {
  39.                 printf("文件打开失败!\n");
  40.                 exit(EXIT_FAILURE);
  41.         }
  42.        
  43.         // 读取内容
  44.         if (fread(&DosHeader, sizeof(IDosHeader),1 , fp) != 1)
  45.         {
  46.                 printf("文件读取失败!\n");
  47.                 exit(EXIT_FAILURE);
  48.         }

  49.         printf("e_magic:%#x\n", DosHeader.e_magic); // 以16进制输出
  50.         printf("e_cblp:%#x\n", DosHeader.e_cblp); // 以16进制输出

  51.         return 0;
  52. }
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
A小小鸟 + 5 + 5 + 3 大哥,膜拜

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-11 23:16:36 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <stdint.h>
  5. #include <windows.h>

  6. size_t get_file_size(const char *filename)
  7. {
  8.         FILE *file = fopen(filename, "r");
  9.         if(!file)
  10.                 return -1;

  11.         fseek(file, 0, SEEK_END);
  12.         size_t size = ftell(file);
  13.         fclose(file);
  14.         return size;
  15. }

  16. bool read_file(const char *filename, uint8_t *buff, size_t size)
  17. {
  18.         FILE *file = fopen(filename, "rb");
  19.         if(!file)
  20.                 return false;

  21.         fread(buff, 1, size, file);
  22.         fclose(file);
  23.         return true;
  24. }

  25. void print_image_dos_header(IMAGE_DOS_HEADER *idh)
  26. {
  27.         printf("IMAGE_DOS_HEADER\n");
  28.         printf("e_magic: %.4x\n", idh->e_magic);
  29.         printf("e_cblp: %.4x\n", idh->e_cblp);
  30.         printf("e_cp: %.4x\n", idh->e_cp);
  31.         printf("e_crlc: %.4x\n", idh->e_crlc);
  32.         printf("e_cparhdr: %.4x\n", idh->e_cparhdr);
  33.         printf("e_minalloc: %.4x\n", idh->e_minalloc);
  34.         printf("e_maxalloc: %.4x\n", idh->e_maxalloc);
  35.         printf("e_ss: %.4x\n", idh->e_ss);
  36.         printf("e_sp: %.4x\n", idh->e_sp);
  37.         printf("e_csum: %.4x\n", idh->e_csum);
  38.         printf("e_ip: %.4x\n", idh->e_ip);
  39.         printf("e_cs: %.4x\n", idh->e_cs);
  40.         printf("e_lfarlc: %.4x\n", idh->e_lfarlc);
  41.         printf("e_ovno: %.4x\n", idh->e_ovno);
  42.         printf("e_res[0]: %.2x\n", idh->e_res[0]);
  43.         printf("e_res[1]: %.2x\n", idh->e_res[1]);
  44.         printf("e_res[2]: %.2x\n", idh->e_res[2]);
  45.         printf("e_res[3]: %.2x\n", idh->e_res[3]);
  46.         printf("e_oemid: %.4x\n", idh->e_oemid);
  47.         printf("e_oeminfo: %.4x\n", idh->e_oeminfo);
  48.         printf("e_res2[0]: %.2x\n", idh->e_res2[0]);
  49.         printf("e_res2[1]: %.2x\n", idh->e_res2[1]);
  50.         printf("e_res2[2]: %.2x\n", idh->e_res2[2]);
  51.         printf("e_res2[3]: %.2x\n", idh->e_res2[3]);
  52.         printf("e_res2[4]: %.2x\n", idh->e_res2[4]);
  53.         printf("e_res2[5]: %.2x\n", idh->e_res2[5]);
  54.         printf("e_res2[6]: %.2x\n", idh->e_res2[6]);
  55.         printf("e_res2[7]: %.2x\n", idh->e_res2[7]);
  56.         printf("e_res2[8]: %.2x\n", idh->e_res2[8]);
  57.         printf("e_res2[9]: %.2x\n", idh->e_res2[9]);
  58.         printf("e_lfanew: %.8x\n", idh->e_lfanew);
  59. }

  60. void print_image_nt_headers(IMAGE_NT_HEADERS *inh, uint8_t *base)
  61. {
  62.         printf("IMAGE_NT_HEADERS\n");
  63.         printf("Signature: %.8x\n", inh->Signature);
  64.        
  65.         // 下面这两个结构,这里只打印出在文件中的偏移
  66.         printf("FileHeader: %.8x\n", (uint8_t *)&inh->FileHeader - base);
  67.         printf("OptionalHeader: %.8x\n", (uint8_t *)&inh->OptionalHeader - base);
  68. }

  69. void print_image_file_header(IMAGE_FILE_HEADER *ifh)
  70. {
  71.         printf("IMAGE_FILE_HEADER\n");
  72.         printf("Machine: %.4x\n", ifh->Machine);
  73.         printf("NumberOfSections: %.4x\n", ifh->NumberOfSections);
  74.         printf("TimeDateStamp: %.8x\n", ifh->TimeDateStamp);
  75.         printf("PointerToSymbolTable: %.8x\n", ifh->PointerToSymbolTable);
  76.         printf("NumberOfSymbols: %.8x\n", ifh->NumberOfSymbols);
  77.         printf("SizeOfOptionalHeader: %.4x\n", ifh->SizeOfOptionalHeader);
  78.         printf("Characteristics: %.4x\n", ifh->Characteristics);
  79. }

  80. void print_image_optional_header(IMAGE_OPTIONAL_HEADER *ioh, uint8_t *base)
  81. {
  82.         printf("IMAGE_OPTIONAL_HEADER\n");
  83.         printf("Magic: %.4x\n", ioh->Magic);
  84.         printf("MajorLinkerVersion: %.2x\n", ioh->MajorLinkerVersion);
  85.         printf("MinorLinkerVersion: %.2x\n", ioh->MinorLinkerVersion);
  86.         printf("SizeOfCode: %.8x\n", ioh->SizeOfCode);
  87.         printf("SizeOfInitializedData: %.8x\n", ioh->SizeOfInitializedData);
  88.         printf("SizeOfUninitializedData: %.8x\n", ioh->SizeOfUninitializedData);
  89.         printf("AddressOfEntryPoint: %.8x\n", ioh->AddressOfEntryPoint);
  90.         printf("BaseOfCode: %.8x\n", ioh->BaseOfCode);
  91.         printf("BaseOfData: %.8x\n", ioh->BaseOfData);
  92.         printf("ImageBase: %.8x\n", ioh->ImageBase);
  93.         printf("SectionAlignment: %.8x\n", ioh->SectionAlignment);
  94.         printf("FileAlignment: %.8x\n", ioh->FileAlignment);
  95.         printf("MajorOperatingSystemVersion: %.4x\n", ioh->MajorOperatingSystemVersion);
  96.         printf("MinorOperatingSystemVersion: %.4x\n", ioh->MinorOperatingSystemVersion);
  97.         printf("MajorImageVersion: %.4x\n", ioh->MajorImageVersion);
  98.         printf("MinorImageVersion: %.4x\n", ioh->MinorImageVersion);
  99.         printf("MajorSubsystemVersion: %.4x\n", ioh->MajorSubsystemVersion);
  100.         printf("MinorSubsystemVersion: %.4x\n", ioh->MinorSubsystemVersion);
  101.         printf("Win32VersionValue: %.8x\n", ioh->Win32VersionValue);
  102.         printf("SizeOfImage: %.8x\n", ioh->SizeOfImage);
  103.         printf("SizeOfHeaders: %.8x\n", ioh->SizeOfHeaders);
  104.         printf("CheckSum: %.8x\n", ioh->CheckSum);
  105.         printf("Subsystem: %.4x\n", ioh->Subsystem);
  106.         printf("DllCharacteristics: %.4x\n", ioh->DllCharacteristics);
  107.         printf("SizeOfStackReserve: %.8x\n", ioh->SizeOfStackReserve);
  108.         printf("SizeOfStackCommit: %.8x\n", ioh->SizeOfStackCommit);
  109.         printf("SizeOfHeapReserve: %.8x\n", ioh->SizeOfHeapReserve);
  110.         printf("SizeOfHeapCommit: %.8x\n", ioh->SizeOfHeapCommit);
  111.         printf("LoaderFlags: %.8x\n", ioh->LoaderFlags);
  112.         printf("NumberOfRvaAndSizes: %.8x\n", ioh->NumberOfRvaAndSizes);

  113.         // 下面这个数组,我还没有想好要以什么样的形式展开,如何展开,现在只是打印文件偏移
  114.         printf("DataDirectory: %.8x\n", (uint8_t *)&ioh->DataDirectory - base);
  115. }

  116. int main(void)
  117. {
  118.         const char *filename = "print_pe.exe";
  119.         size_t size = get_file_size(filename);
  120.         uint8_t *buff = malloc(size);
  121.         read_file(filename, buff, size);
  122.        
  123.         IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)buff;
  124.         IMAGE_NT_HEADERS *inh = (IMAGE_NT_HEADERS *)(buff + idh->e_lfanew);

  125.         print_image_dos_header(idh); printf("\n");
  126.         print_image_nt_headers(inh, buff); printf("\n");
  127.         print_image_file_header(&inh->FileHeader); printf("\n");
  128.         print_image_optional_header(&inh->OptionalHeader, buff); printf("\n");

  129.         free(buff);
  130.         return 0;
  131. }
复制代码

  1. IMAGE_DOS_HEADER
  2. e_magic: 5a4d
  3. e_cblp: 0090
  4. e_cp: 0003
  5. e_crlc: 0000
  6. e_cparhdr: 0004
  7. e_minalloc: 0000
  8. e_maxalloc: ffff
  9. e_ss: 0000
  10. e_sp: 00b8
  11. e_csum: 0000
  12. e_ip: 0000
  13. e_cs: 0000
  14. e_lfarlc: 0040
  15. e_ovno: 0000
  16. e_res[0]: 00
  17. e_res[1]: 00
  18. e_res[2]: 00
  19. e_res[3]: 00
  20. e_oemid: 0000
  21. e_oeminfo: 0000
  22. e_res2[0]: 00
  23. e_res2[1]: 00
  24. e_res2[2]: 00
  25. e_res2[3]: 00
  26. e_res2[4]: 00
  27. e_res2[5]: 00
  28. e_res2[6]: 00
  29. e_res2[7]: 00
  30. e_res2[8]: 00
  31. e_res2[9]: 00
  32. e_lfanew: 000000f0

  33. IMAGE_NT_HEADERS
  34. Signature: 00004550
  35. FileHeader: 000000f4
  36. OptionalHeader: 00000108

  37. IMAGE_FILE_HEADER
  38. Machine: 014c
  39. NumberOfSections: 0009
  40. TimeDateStamp: 5c86674e
  41. PointerToSymbolTable: 00000000
  42. NumberOfSymbols: 00000000
  43. SizeOfOptionalHeader: 00e0
  44. Characteristics: 0102

  45. IMAGE_OPTIONAL_HEADER
  46. Magic: 010b
  47. MajorLinkerVersion: 0e
  48. MinorLinkerVersion: 10
  49. SizeOfCode: 00005200
  50. SizeOfInitializedData: 00004400
  51. SizeOfUninitializedData: 00000000
  52. AddressOfEntryPoint: 00011343
  53. BaseOfCode: 00001000
  54. BaseOfData: 00001000
  55. ImageBase: 00400000
  56. SectionAlignment: 00001000
  57. FileAlignment: 00000200
  58. MajorOperatingSystemVersion: 0006
  59. MinorOperatingSystemVersion: 0000
  60. MajorImageVersion: 0000
  61. MinorImageVersion: 0000
  62. MajorSubsystemVersion: 0006
  63. MinorSubsystemVersion: 0000
  64. Win32VersionValue: 00000000
  65. SizeOfImage: 00020000
  66. SizeOfHeaders: 00000400
  67. CheckSum: 00000000
  68. Subsystem: 0003
  69. DllCharacteristics: 8140
  70. SizeOfStackReserve: 00100000
  71. SizeOfStackCommit: 00001000
  72. SizeOfHeapReserve: 00100000
  73. SizeOfHeapCommit: 00001000
  74. LoaderFlags: 00000000
  75. NumberOfRvaAndSizes: 00000010
  76. DataDirectory: 00000168

  77. 请按任意键继续. . .
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
A小小鸟 + 5 + 5 + 3 大哥好厉害,还是我太菜了

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-11 23:24:57 | 显示全部楼层
仅仅解析出值是不够的,如果这个程序还要继续写下去,那就要去解析值所对应的含义
例如
e_magic: 5a4d
应该解析为
e_magic: IMAGE_DOS_SIGNATURE

IMAGE_DOS_SIGNATURE这个宏定义的值就是 0x5a4d

  1. #include "pshpack4.h"                   // 4 byte packing is the default

  2. #define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ
  3. #define IMAGE_OS2_SIGNATURE                 0x454E      // NE
  4. #define IMAGE_OS2_SIGNATURE_LE              0x454C      // LE
  5. #define IMAGE_VXD_SIGNATURE                 0x454C      // LE
  6. #define IMAGE_NT_SIGNATURE                  0x00004550  // PE00
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-12 14:31:19 | 显示全部楼层
ba21 发表于 2019-3-11 20:37
PE头都是有结构的。用C写也很简单吧,先把所需要的结构声明出来,然后用二进制读文件,读入结构体中。

哇,大哥好厉害,我只能膜拜了,我还以为是很高大上的呢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-12 14:34:11 | 显示全部楼层

我什么时候,能达到你的一半啊,感觉你的编程能力好厉害啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-13 10:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表