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;
}
我正在编写一个用 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;
}