gpt4 book ai didi

c - 如何在 C 中以二进制形式从 PE_file 导入信息

转载 作者:行者123 更新时间:2023-11-30 21:06:14 24 4
gpt4 key购买 nike

我正在用C语言制作PE文件格式分析器。当我使用 Visual Studio 时,我可以让它变得更容易。但是,我已经厌倦了不使用 Visual Studio 来改进我的 C 编程。它是由GCC制作的(我的笔记本电脑是macbook)。

要分析PE文件格式,如你所知,我必须使用文件指针并将文件读取为'rb'类型。我做到了,看起来效果很好......我想打印第一个和第二个单词(“MZ”),但它打印了未知的(对我来说)数字。

P.S 我写的代码与之前的代码略有不同,比之前的要小。但它打印 NULL。这意味着我写的代码真的错了...请告诉我哪些部分是错误的

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

// struct to save info of PE_File format
typedef struct _IMAGE_DOS_HEADER
{
unsigned short e_magic;
unsigned short e_cblp;
unsigned short e_cp;
unsigned short e_crlc;
unsigned short e_cparhdr;
unsigned short e_minalloc;
unsigned short e_maxalloc;
unsigned short e_ss;
unsigned short e_sp;
unsigned short e_csum;
unsigned short e_ip;
unsigned short e_cs;
unsigned short e_lfarlc;
unsigned short e_ovno;
unsigned short e_res[4];
unsigned short e_oemid;
unsigned short e_oeminfo;
unsigned short e_res2[10];
unsigned long e_lfanew;

} DOS_HEADER;

// I use two different functions.
// First one was made to import PE File format info from file that I used.
// Another was made to print some imformation. I use some comment because I didn't realize those.
DOS_HEADER get_dos_header(FILE *fp, char* fp_buffer);
void print_data_of_structures(DOS_HEADER/*, NT_HEADER, FILE_HEADER, OPTIONAL_HEADER, DATA_DIRECTORY*/);

int main(void)
{
DOS_HEADER dos_header;

char file_path[1000];
printf("Please input your file path : ");
scanf("%[^\n]s", file_path);

FILE* fp = NULL;
fp = fopen(file_path, "rb");
if(fp == NULL)
printf("Unalbe to open file :/\n");

// To calculate file size.
long fp_size = 0;
fseek(fp, 0, SEEK_END);
fp_size = ftell(fp);
rewind(fp);

// Declare to use as buffer
char* fp_buffer = malloc(sizeof(char) * (fp_size + 1));

// Use function to save analyzed information.
DOS_HEADER info_dos_header = get_dos_header(fp, fp_buffer);

// Print information.
print_data_of_structures(info_dos_header);

fclose(fp);
free(fp_buffer);

return 0;
}

DOS_HEADER get_dos_header(FILE* fp, char* fp_buffer)
{
DOS_HEADER raw_info_dos_header = {0, };

// Read hex info from fp 2 byte 1 time and save at fp_buffer.
fseek(fp, 0, SEEK_SET);
fread(fp_buffer, 2, 1, fp);
raw_info_dos_header.e_magic = fp_buffer;

return raw_info_dos_header;
}

void print_data_of_structures(DOS_HEADER info_dos_header/*, NT_HEADER info_nt_header, FILE_HEADER info_file_header, OPTIONAL_HEADER info_optional_header, DATA_DIRECTORY info_data_directory*/)
{
// print info_dos_header
printf("Print DOS_HEADER\n");
// I tried several print format(for example %hu, %x, %d) But I coudn't "MZ" or any numbers has realation with "MZ".
printf("%s", info_dos_header.e_magic);
}

最佳答案

您的代码有两个大问题:混合类型。

DOS_HEADER中,所有成员(除了最后一个)都是unsigned Short类型。这很重要。

get_dos_header中你正在做

fread(fp_buffer, 2, 1, fp);
raw_info_dos_header.e_magic = fp_buffer;

这是错误的。

  1. 不要使用魔数(Magic Number),使用 sizeof 来获取正确的大小
  2. 检查 fread 的返回值,特别是在分析二进制文件时格式,您必须确保您已经阅读了您所期望的内容。
  3. size 参数为 1 时,处理 fread 会容易得多,因为仅当 size 参数为 1 时,fread 的返回值才与读取的字节数。
  4. e_magic 是一个无符号短整型fp_buffer 是一个char*。这个作业是不复制 fp_buffer 指向的内容,您正在存储一个地址就好像它是一个无符号短值。您需要复制指向的内存通过fp_buffer

而且我不明白你分配文件大小的缓冲区有什么意义当你逐 block 阅读时。如果不分配的话会更容易完全缓冲并使用大小大于您要读取的数组。

int get_dos_header(FILE* fp, DOS_HEADER *dos)
{
unsigned char buffer[8];

size_t ret = fread(buffer, 1, sizeof(dos->e_magic), fp);

if(ret != sizeof(dos->e_magic))
{
fprintf(stderr, "Invalid file size\n");
return 0;
}

memcpy(&dos->e_magic, buffer, sizeof(dos->e_magic));

// DO the others fread operation

...

return 1;
}

然后在main中你可以这样做:

DOS_HEADER raw_info_dos_header = {0, };
if(get_dos_header(fp, &raw_info_dos_header) == 0)
{
fprintf(stderr, "failed to get the DOS header\n");
return 1;
}
...

第二个问题在print_data_of_structs中:

printf("%s", info_dos_header.e_magic);

e_magic 是一个 unsigned Short%s 需要一个指向 char 的指针,它需要一个字符串。 e_magic 绝对不是字符串。这会产生未定义的行为。printf 应该如下所示:

printf("e_magic: %hu\n", info_dos_header.e_magic);

printf("e_magic: 0x%04hx\n", info_dos_header.e_magic);

以十六进制格式打印它。

我还建议您改用指针。你的结构很大并且传递了一个指向函数的指针比将大型结构的副本传递给函数要便宜得多功能。所以而不是

void print_data_of_structures(DOS_HEADER info_dos_header);

将其声明为

void print_data_of_structures(DOS_HEADER *info_dos_header);

并且也不要将可能失败的函数(例如 get_dos_header)声明为void,否则如何告诉调用函数它失败了?它是此类函数最好返回 int (1 表示成功,0 表示失败)并且期望一个指向存储信息的结构的指针(看看我如何更改了上面的 get_dos_header

关于c - 如何在 C 中以二进制形式从 PE_file 导入信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50072154/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com