C语言读取ELF文件魔数异常:比对0x7F失败且字节显示异常
问题:ELF文件魔数校验代码无法正常工作
我编写了一段C代码,尝试读取ELF文件的前4字节并与魔数0x7F进行比对,以此判断文件是否为ELF文件,但代码无法正常运行。我在错误提示前添加printf语句查看读取的字节,结果显示为方框问号,且始终触发“不是ELF文件”的错误提示,请问我哪里出错了?
代码如下:
#include "main.h" /** * readFirst4 - function to read first eight bytes * @filename: filename of file to be read * Return: string of bytes to be checked */ char *readFirst4(int fd_elf) { unsigned int _read1; char *test_string; _read1 = read(fd_elf, test_string, sizeof(int)); if (_read1 != 0 && _read1 != -1) return (test_string); else return ("Error unable to read file\n"); } /** * closeFile - function that closes a file * @fd_elf: file descriptor */ void closeFile(int fd_elf, char *filename) { if((close(fd_elf) == -1)) { dprintf(STDERR_FILENO, "Error: unable to close file %s\n", filename); exit(98); } } /** * main - execute program * @argc: number of arguments * @args: array of arguments * Return: 0 */ int main(int argc,char **argv) { int fd_ELF, reader; char *first_four; first_four = malloc(sizeof(int)); if (first_four == NULL) exit(98); if (argc != 2) { dprintf(STDERR_FILENO, "Usage: elf_header filename\n"); exit(98); } fd_ELF = open(argv[1], O_RDONLY); if (fd_ELF == -1) { dprintf(STDERR_FILENO, "Error unable to read file %s\n", argv[1]); exit(98); } if ((first_four = readFirst4(fd_ELF)) != (char *)0x7F) { printf("%s\n", first_four); dprintf(STDERR_FILENO, "Error: Not an ELF file - it has the wrong magic bytes at the start\n"); exit(98); } printf("file %s is an ELF file", argv[1]); closeFile(fd_ELF, argv[1]); return (0); }
注:错误提示仅应在文件非ELF文件时触发,但当前即使是ELF文件也会报错。
错误分析与修正
核心错误点
- 野指针与内存泄漏:
readFirst4函数中的test_string是未初始化的野指针,直接调用read写入会触发未定义行为。同时main函数中已经malloc了first_four,但后续又将其重新赋值为readFirst4的返回值,导致原malloc的内存丢失,造成泄漏。 - 魔数比对逻辑错误:ELF的完整魔数是前4字节:
0x7F, 'E', 'L', 'F',你仅尝试比对第一个字节,且比对方式错误——你在比较指针地址(first_four的地址和(char*)0x7F),而不是字节内容。 - 二进制字节打印错误:读取的是二进制数据,不是C风格字符串,用
printf("%s")打印会把非ASCII字符(如0x7F)显示为方框问号,且如果没有\0终止符会导致越界访问。
修正后的代码
#include "main.h" #include <stdint.h> /** * closeFile - function that closes a file * @fd_elf: file descriptor */ void closeFile(int fd_elf, char *filename) { if(close(fd_elf) == -1) { dprintf(STDERR_FILENO, "Error: unable to close file %s\n", filename); exit(98); } } /** * main - execute program * @argc: number of arguments * @argv: array of arguments * Return: 0 */ int main(int argc, char **argv) { int fd_ELF; uint8_t elf_magic[4]; // 用无符号字节存储魔数,避免符号扩展问题 if (argc != 2) { dprintf(STDERR_FILENO, "Usage: elf_header filename\n"); exit(98); } fd_ELF = open(argv[1], O_RDONLY); if (fd_ELF == -1) { dprintf(STDERR_FILENO, "Error unable to read file %s\n", argv[1]); exit(98); } // 读取前4字节魔数 ssize_t bytes_read = read(fd_ELF, elf_magic, sizeof(elf_magic)); if (bytes_read != sizeof(elf_magic)) { dprintf(STDERR_FILENO, "Error: Failed to read ELF magic bytes\n"); closeFile(fd_ELF, argv[1]); exit(98); } // 校验完整ELF魔数 if (!(elf_magic[0] == 0x7F && elf_magic[1] == 'E' && elf_magic[2] == 'L' && elf_magic[3] == 'F')) { dprintf(STDERR_FILENO, "Error: Not an ELF file - it has the wrong magic bytes at the start\n"); closeFile(fd_ELF, argv[1]); exit(98); } printf("file %s is an ELF file\n", argv[1]); closeFile(fd_ELF, argv[1]); return (0); }
修正说明
- 移除了有问题的
readFirst4函数,直接在main中读取魔数,避免野指针问题。 - 使用
uint8_t类型存储魔数,确保字节操作的准确性。 - 校验完整的ELF魔数(4字节),而不是仅第一个字节。
- 正确处理
read的返回值,确保读取到完整的4字节。 - 避免内存泄漏,不再做不必要的malloc,用完文件描述符及时关闭。
内容的提问来源于stack exchange,提问作者nezeadi
相关产品推荐
相关产品推荐

