用C语言读取二进制PE文件
我正在尝试用C阅读一个PE文件。在阅读了相关的Microsoft文档和其他关于OSDev的文章之后,我仍然对如何处理文件中的偏移量感到困惑 文件头的MS-DOS存根包含0x3c处的标志,该标志提供实际PE头开始的偏移量(PE签名,字面上是一个4字节的“PE\0\0”) 我试着用指针算法来解释PE文件中给出的地址——一个地址,但恐怕我不太知道怎么做 此外,我知道这是通过Win32 API实现的;然而,我想从中学习,并学会如何做自己 非常感谢您事先提供的任何帮助用C语言读取二进制PE文件,c,file,io,binary,portable-executable,C,File,Io,Binary,Portable Executable,我正在尝试用C阅读一个PE文件。在阅读了相关的Microsoft文档和其他关于OSDev的文章之后,我仍然对如何处理文件中的偏移量感到困惑 文件头的MS-DOS存根包含0x3c处的标志,该标志提供实际PE头开始的偏移量(PE签名,字面上是一个4字节的“PE\0\0”) 我试着用指针算法来解释PE文件中给出的地址——一个地址,但恐怕我不太知道怎么做 此外,我知道这是通过Win32 API实现的;然而,我想从中学习,并学会如何做自己 非常感谢您事先提供的任何帮助 #include <stdio
#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感谢您的快速回复。我正在研究我的解决方案的结构打包,但问题是MS-DOS存根可能大小不一,因为它本身就是一个MS-DOS程序。我所知道的是,在
0x3c
中,它告诉我实际PE签名的地址(这是实际PE文件的开始)。看看我如何实际解释指针?我如何告诉C取什么在代码> EyLFANEW ,把它当作一个地址,然后指向它?简单的方法是将一个字符数组的大小与头结构结合起来。使用c99,您可以用一个可变长度的数组结束结构,但是由于需要考虑头的大小,计算会变得更加复杂。
#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;
}
}