在C中读取二进制PE文件

时间:2015-02-22 06:02:38

标签: c file io binary portable-executable

我试图在C中读取PE文件。在阅读相关的Microsoft文档和OSDev上的其他文章以及SO之后,我仍然对如何处理文件中的偏移感到困惑。

文件头部的MS-DOS存根包含一个0x3c的标志,它提供实际PE头的起始偏移量(PE签名,字面意思是4字节" PE \ 0 \ 0"。)

我尝试做的是使用指针算法将PE文件中给出的地址解释为 - 一个地址,但我担心我不知道如何做到这一点。

另外,我知道这可以通过Win32 API实现;但是,我想从中学习并学习如何自己动手。

非常感谢您提前提供任何帮助。

#include <stdio.h>
#include <stdlib.h>

#define PE_SIG_OFFSET_LOCATION 0x3c

int main(void)
{
  const char* filepath = "sample.exe";
  FILE* file = fopen(filepath, "rb");
  int i, n = 0;

  if(!file)
  {
    perror("Failed to open file");
    return EXIT_FAILURE;
  }

  fpos_t start = fgetpos(file, &start);

  int c;

  while((c = fgetc(file)) != EOF)
  {
    n++;
    // putchar(c);
  }

  if(ferror(file))
  {
    puts("I/O error when reading.");
  }
  else if(feof(file))
  {
    fsetpos(file, &start);
    int c = 0;

    char* contents = (char*)malloc(n * sizeof(char));

    for(i=0;i<=n;i++)
    {
      if(c == EOF)
      {
        break;
      }

      c = fgetc(file);
      contents[i] = c;
    }

    fclose(file);

    i = 0;

    char offset[4 * sizeof(char)] = {contents[PE_SIG_OFFSET_LOCATION * sizeof(char)], contents[(PE_SIG_OFFSET_LOCATION * sizeof(char))+ (1 * sizeof(char))], contents[(PE_SIG_OFFSET_LOCATION * sizeof(char))+ (2 * sizeof(char))], contents[(PE_SIG_OFFSET_LOCATION * sizeof(char))+ (3 * sizeof(char))]}; 

    char* sig = &contents[PE_SIG_OFFSET_LOCATION * sizeof(char)];

    printf("sig = %c \n", sig);

    // somehow interpret the character the sig currently points to as a hex memory and get sig to point to that (i.e. the start of the PE header)

    free(contents);

    return EXIT_SUCCESS;
  }
}

编辑:在technosaurus建议我联合一个表示DOS标题的打包结构与实际内容的char数组后,代码仍然没有正常运行(它读取和打印文件没关系,但是当它需要打印签名时,它会打印出垃圾而不是MZ)。

#include <stdio.h>
#include <stdlib.h>

#define PE_SIG_OFFSET_LOCATION 0x3c

int main(void)
{
  const char* filepath = "sample.exe";
  FILE* file = fopen(filepath, "rb");
  int i, n = 0;

  if(!file)
  {
    perror("Failed to open file");
    return EXIT_FAILURE;
  }

  fpos_t start = fgetpos(file, &start);

  int c;

  while((c = fgetc(file)) != EOF)
  {
    n++;
    // putchar(c);
  }

  if(ferror(file))
  {
    puts("I/O error when reading.");
  }
  else if(feof(file))
  {
    fsetpos(file, &start);
    int c = 0;

    typedef struct DOS_Header
    {
      char signature[2];
      short lastsize;
      short nblocks;
      short nreloc;
      short hdrsize;
      short minalloc;
      short maxalloc;
      void *ss;
      void *sp;
      short checksum;
      void *ip;
      void *cs;
      short relocpos;
      short noverlay;
      short reserved1[4];
      short oem_id;
      short oem_info;
      short reserved2[10];
      long e_lfanew;
    }DOS_Header;

  union
  {
      DOS_Header header;
      char* contents;
    }u;

  u.contents = (char*)malloc(n * sizeof(char));

    for(i=0;i<=n;i++)
    {
      if(c == EOF)
      {
        break;
      }

      c = fgetc(file);
      u.contents[i] = c;
    }

    fclose(file);

  i = 0;

  for(i=0;i<=n;i++)
  {
    printf("%c", u.contents[i]);
  }

  printf("\n DOS sig: %c%c \n", u.header.signature[0], u.header.signature[1]);


    free(u.contents);

    return EXIT_SUCCESS;
  }
}

0 个答案:

没有答案