C语言读取文件时,使用"rb" 属性读取文件的数据类型是什么?

When reading a file in C Lang, what is the data type of the file you read using the "rb" property?

我正在编写一个用 C 解析 PE 结构的程序。我将把它放入二进制文件中并按长度解析它。示例)DOS header 的长度为 0x40(64) 字节,因此我尝试从 binary_buf[0]binary_buf[39] 处理它。 我应该读取什么数据类型的文件?

我不知道该写什么,因为我用int还是char都一样。如果您能告诉我为什么要使用该数据类型,我将不胜感激。

unsigned char *binary_buf = NULL; 

fp = fopen(filename, "rb"); 
if (fp == NULL) {
    printf("이 파일은 열 수 없습니다.\n");
    return 0;
}

fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);

binary_buf = malloc(size+1);
fread(binary_buf, 1, size, fp);
fclose(fp);

printf("%d", binary_buf[0]); //77 = 0x4D == 'M'

感谢您阅读我的问题。祝你有美好的一天!

您正在读取二进制文件,unsigned char 数组似乎正是您所需要的。

请注意,分配一个额外的字节对于这项工作似乎没有必要,因为您不是从文件内容创建 C 字符串。

将 PE 头的内容作为单个字节读取是最好的可移植方法:header 数据具有特定的布局,由于对齐和字节顺序问题,该布局可能无法与 C 结构正确匹配。

检查签名后,您应该从 header 中的已知偏移量中提取相关值,并使用适当的整数算法构造文件偏移量。

DOS Header 为 64 字节长,布局如下:

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

其中 WORD 是 16 位小端整数,LONG 是 32 位小端整数。

这是修改后的版本:

#include <limits.h>
#include <stdio.h>

int read_PE_file(const char *filename) {
    unsigned char *binary_buf = NULL; 
    FILE *fp = fopen(filename, "rb"); 
    if (fp == NULL) {
        fprintf(stderr, "Error opening file %s\n", filename);
        return -1;
    }

    fseek(fp, 0, SEEK_END);
    long length = ftell(fp);
    unsigned long size;
    fseek(fp, 0, SEEK_SET);

    if (length < 0) {
        fprintf(stderr, "Error seeking file %s\n", filename);
        fclose(fp);
        return -1;
    }
    size = length;
    if (size < 64) {
        fprintf(stderr, "file %s too short, size=%lu\n", filename, size);
        fclose(fp);
        return -1;
    }
#if LONG_MAX > SIZE_MAX
    if (size > SIZE_MAX) {
        fprintf(stderr, "file %s too large, size=%lu\n", filename, size);
        fclose(fp);
        return -1;
    }
#endif
    if ((binary_buf = malloc(size)) == NULL) {
        fprintf(stderr, "Error allocating %lu byte buffer for file %s\n", size, filename);
        fclose(fp);
        return -1;
    }
    if (fread(binary_buf, 1, size, fp) != size) {
        fprintf(stderr, "Error reading file %s\n", filename);
        free(binary_buf);
        fclose(fp);
        return -1;
    }
    fclose(fp);
    if (binary_buf[0] != 0x4D || binary_buf[1] != 0x5A) {
        fprintf(stderr, "File %s does not have MZ signature\n", filename);
        free(binary_buf);
        fclose(fp);
        return -1;
    }
    unsigned long offset = binary_buf[60] +
                           (binary_buf[61] << 8) + 
                           ((unsigned long)binary_buf[62] << 16) + 
                           ((unsigned long)binary_buf[63] << 24);
      
    if (offset > size) {
        fprintf(stderr, "new executable offset %lu greater than file size %lu for file %s\n", offset, size, filename);
        free(binary_buf);
        fclose(fp);
        return -1;
    }
    printf("new executable offset: %lu\n", offset);
    [...]
    free(binary_buf);
    return 0;
}