You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

修正说明

  1. 移除了有问题的readFirst4函数,直接在main中读取魔数,避免野指针问题。
  2. 使用uint8_t类型存储魔数,确保字节操作的准确性。
  3. 校验完整的ELF魔数(4字节),而不是仅第一个字节。
  4. 正确处理read的返回值,确保读取到完整的4字节。
  5. 避免内存泄漏,不再做不必要的malloc,用完文件描述符及时关闭。

内容的提问来源于stack exchange,提问作者nezeadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 13:52:52