By:刺刀 发表于 2016-9-27 16:58

自己打造一个 PeView 工具 C语言实现(基本上可以了)

本帖最后由 By:刺刀 于 2018-9-12 14:45 编辑

在还还没有写完的时候 放出来 主要是想和大家交流下 代码的写法什么的感觉我自己写的好烂看看大家还有没有更好的办法 .感谢 _stdcall 的帮助终于对齐了
刚刚我还写了一个自动对其的函数喃
果然好蠢 代码已经更新 ~ 16/09/29
现在是这样的了
下面就是输入输出表这些东东了吧~
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <conio.h>
#include <Windows.h>


// 计算数组长度
#define GET_ARRAY_LEN(array) (sizeof(array) / sizeof(array))
/*
      打印 IMAGE_DOS_HEADER 信息
      PIMAGE_DOS_HEADER pDosHeader: IMAGE_DOS_HEADER 结构体指针
*/
void printImageDosHeader (IN PIMAGE_DOS_HEADER pDosHeader) {
      printf ("IMAGE_DOS_HEADER:\n");
      char *DOS_HEADER_Name[] = {"e_magic", "e_cblp", "e_cp", "e_crlc", "e_cparhdr",
                "e_minalloc", "e_maxalloc", "e_ss", "e_sp",
                "e_csum", "e_ip", "e_cs", "e_lfarlc", "e_ovno",
                "e_res", "e_oemid", "e_oeminfo",
                "e_res2",
                "e_lfanew", //指向IMAGE_NT_HEADERS的所在
      };
      int temp = 0;
      for (int i = 0; i < 31; i++) {

                if (i == 14) { // 打印 e_res 的内容
                        for (int j = 0; j < 4; j++) {
                              printf ("\t%-20s:%04X\n", DOS_HEADER_Name,
                                        *(&(pDosHeader->e_magic) + i++));
                        }
                        temp++;
                }
                else if (i == 20) { // 打印 e_res2 的内容
                        for (int j = 0; j < 10; j++) {
                              printf ("\t%-20s:%04X\n", DOS_HEADER_Name,
                                        *(&(pDosHeader->e_magic) + i++));
                        }
                        temp++;
                }
                printf ("\t%-20s:%04X\n", DOS_HEADER_Name, *(&(pDosHeader->e_magic) + i));
      }
}

/*
      打印 IMAGE_OPTIONAL_HEADER32 结构体信息
      IMAGE_NT_HEADERS* pPeHeader: IMAGE_NT_HEADERS 结构体指针
*/
void printOptionalHead32 (IN IMAGE_NT_HEADERS* pPeHeader) {
      char *OptionalHeadName[] = {
                // Standard fields.
                "Magic", "MajorLinkerVersion", "MinorLinkerVersion", "SizeOfCode",
                "SizeOfInitializedData", "SizeOfUninitializedData", "AddressOfEntryPoint", "BaseOfCode", "BaseOfData",
                // NT additional fields.
                "ImageBase", "SectionAlignment", "FileAlignment", "MajorOperatingSystemVersion",
                "MinorOperatingSystemVersion", "MajorImageVersion", "MinorImageVersion", "MajorSubsystemVersion",
                "MinorSubsystemVersion", "Win32VersionValue", "SizeOfImage", "SizeOfHeaders", "CheckSum",
                "Subsystem", "DllCharacteristics", "SizeOfStackReserve", "SizeOfStackCommit", "SizeOfHeapReserve",
                "SizeOfHeapCommit", "LoaderFlags", "NumberOfRvaAndSizes", "IMAGE_DATA_DIRECTORY"};
      char *DataDirectory[] = {"VirtualAddress", "Size"};
      char *VirtualAddressp[] = {"IMAGE_DIRECTORY_ENTRY_EXPORT", "IMAGE_DIRECTORY_ENTRY_IMPORT",
                "IMAGE_DIRECTORY_ENTRY_RESOURCE", "IMAGE_DIRECTORY_ENTRY_EXCEPTION", "IMAGE_DIRECTORY_ENTRY_SECURITY",
                "IMAGE_DIRECTORY_ENTRY_DEBUG", "IMAGE_DIRECTORY_ENTRY_COPYRIGHT", "IMAGE_DIRECTORY_ENTRY_GLOBALPTR",
                "IMAGE_DIRECTORY_ENTRY_TLS", "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
                "IMAGE_DIRECTORY_ENTRY_IAT", "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
                "IMAGE_NUMBEROF_DIRECTORY_ENTRIES"
      };
      size_t structOffset = 0;
      DWORD* addr;
      printf ("IMAGE_OPTIONAL_HEADER32\n");
      for (size_t i = 0; i < GET_ARRAY_LEN (OptionalHeadName); i++) {
                if (i == 1) {
                        structOffset++;;
                        printf ("\t%-40s:%02X\n", OptionalHeadName, pPeHeader->OptionalHeader.MajorLinkerVersion);
                        printf ("\t%-40s:%02X\n", OptionalHeadName, pPeHeader->OptionalHeader.MinorLinkerVersion);
                }
                if (i == 3) {
                        for (size_t j = 0; j < 9; j++) {
                              addr = &(pPeHeader->OptionalHeader.Magic) + structOffset;
                              structOffset += 2;
                              printf ("\t%-40s:%08X\n", OptionalHeadName, *addr);
                        }
                }
                if (i == 18) {
                        for (size_t j = 0; j < 4; j++) {
                              addr = &(pPeHeader->OptionalHeader.Magic) + structOffset;
                              structOffset += 2;
                              printf ("\t%-40s:%08X\n", OptionalHeadName, *addr);
                        }
                }
                if (i == 24) {
                        for (size_t j = 0; j < 6; j++) {
                              addr = &(pPeHeader->OptionalHeader.Magic) + structOffset;
                              structOffset += 2;
                              printf ("\t%-40s:%08X\n", OptionalHeadName, *addr);
                        }
                }
                printf ("\t%-40s:%04X\n", OptionalHeadName, *(&(pPeHeader->OptionalHeader.Magic) + structOffset));
                structOffset++;
      }
}

/*
      打印 IMAGE_NT_HEADERS 结构体信息
      IMAGE_NT_HEADERS *pPeHeader: IMAGE_NT_HEADERS 结构体指针
*/
void printImageNtHeaders (IN IMAGE_NT_HEADERS* pPeHeader) {

      char *PeHeaderName[] = {"Signature", "IMAGE_FILE_HEADER", "IMAGE_OPTIONAL_HEADER32"};

      char *FileHeaderName[] = {"Machine", "NumberOfSections", "TimeDateStamp", "PointerToSymbolTable",
                "NumberOfSymbols", "SizeOfOptionalHeader", "Characteristics"};

      printf ("IMAGE_NT_HEADERS:\n");
      printf ("\t%-20s:%08X\n", PeHeaderName, pPeHeader->Signature);
      printf ("IMAGE_FILE_HEADER:\n");
      int temp = 0;
      size_t structOffset = 0;
      DWORD *addr;
      for (int i = 0; i < 7; i++) {
                if (i == 2) {
                        for (int j = 0; j < 3; j++) {
                              /*
                              printf ("\t%-20s:%04X%04X\n", FileHeaderName,
                                        // 这里实在是想不到什么好方法来处理了 求指导下
                                        *(&(pPeHeader->FileHeader.Machine) + structOffset++),
                                        *(&(pPeHeader->FileHeader.Machine) + structOffset++));
                              这里完全被自己带沟里去了......
                              果然对指针还是不了解啊
                              addr = (DOWRD *)&(pPeHeader->FileHeader.Machine) + structOffset; // 这个就偏移飞了.
                              */
                              addr = &(pPeHeader->FileHeader.Machine) + structOffset;
                              structOffset += 2;
                              printf ("\t%-40s:%08X\n", FileHeaderName, *addr);
                              i++;
                        }
                }
                printf ("\t%-40s:%04X\n", FileHeaderName, *(&(pPeHeader->FileHeader.Machine) + structOffset++));
      }
}

int main (int argc, char *argv[])
{
      if (argc < 2) {
                printf ("Help: %s FileName\n", argv);
                exit (EXIT_FAILURE);
      }

      IMAGE_DOS_HEADER DosHeader; // Dos 头 结构体
      IMAGE_NT_HEADERS PeHeader; // PE 头 结构体
      FILE *fpPeFile = fopen (argv, "rb"); // 以二进制方式打开文件

      if (!fpPeFile) {
                fprintf (stderr, "打开文件失败\n");
                exit (EXIT_FAILURE);
      }

      fread (&DosHeader.e_magic, 1, sizeof(DosHeader), fpPeFile);
      if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { // e_magic --> DOS可执行文件标记
                fprintf (stderr, "请确定该文件是PE文件\n");
                exit (EXIT_FAILURE);
      }

      /*
      这里我想多了 其实可以一次性读取出来的
      fseek (fpPeFile, 0, SEEK_SET);
      for (int i = 0; i < 30; i++) {
                // 取 DosHeader.e_magic 首地址
                // 根据这个地址来计算 结构体偏移
                fread (&DosHeader.e_magic + i, 1, sizeof(WORD), fpPeFile);
      }
      fread (&DosHeader.e_lfanew, 1, sizeof(LONG), fpPeFile); // 获取 指向PE文件头的文件偏移
      */
      
      printImageDosHeader (&DosHeader);

      // 直接跳过了 Dos Stub
      fseek (fpPeFile, DosHeader.e_lfanew, 0); // 移动文件偏移到PE头
      // 获取PeHeader 信息
      fread (&PeHeader, 1, sizeof(PeHeader), fpPeFile);

      printImageNtHeaders (&PeHeader);
      printOptionalHead32 (&PeHeader);
      return 0;
}



有时候想太多 真不好!





Raohz520 发表于 2016-9-27 17:19

那你都可以发原创区了{:301_999:}   加油楼主

By:刺刀 发表于 2016-9-27 17:29

Raohz520 发表于 2016-9-27 17:19
那你都可以发原创区了   加油楼主

我在想怎么对齐字符串喃
现在这样输出出来好丑

levelangel 发表于 2016-9-27 17:38

不要使用空格,使用\t,就能保证对齐

哈喽灬沐沐 发表于 2016-9-27 17:55

感谢分享

_stdcall 发表于 2016-9-27 17:57

By:刺刀 发表于 2016-9-27 17:29
我在想怎么对齐字符串喃
现在这样输出出来好丑

printf( "%-20s" , ....);   就对齐了

lbmtl 发表于 2016-9-27 17:59

加油加油 支持技术流

艺海小田 发表于 2016-9-27 18:05

喜欢这样的交流,中国未来程序因你们无私交流而大放光彩!

营州都督 发表于 2016-9-27 19:14

小白支持一下,感谢楼主!!!!

sumile 发表于 2016-9-27 22:20

Process Hacker附带一个Peview工具,而且是开源的,可以参考一下。
页: [1] 2
查看完整版本: 自己打造一个 PeView 工具 C语言实现(基本上可以了)