c - 打开 ELF 文件并检查

标签 c elf

我需要编写 C 程序来检查 ELF 链接 View 格式的目标文件并将其转换为可执行 View 格式,将其加载到内存中。

第一个问题:如何打开文件并读取它?

最佳答案

我尝试编写一些代码来读取 elf 文件,请参见下面:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#include <sys/mman.h>
#include <stddef.h>

static void shdr_parse(void *ptr)
{
    Elf32_Shdr *shdr_ptr = NULL;
    Elf32_Ehdr *Elf32_ptr = (Elf32_Ehdr *)ptr;


    int n = Elf32_ptr->e_shnum;
    char *shstrtab = NULL;

    printf("e_shstrndx: 0x%x\n", Elf32_ptr->e_shstrndx);
    printf("e_shnum: 0x%x\n", Elf32_ptr->e_shnum);
    /*
     * first of all, let's get the shstrtab, we'll get 
     * the name of each section with it
     */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    while (n--) {
        if (shdr_ptr->sh_type == SHT_STRTAB) {
            shstrtab = (char *)(ptr + shdr_ptr->sh_offset);
            if (!strcmp(&shstrtab[shdr_ptr->sh_name], ".shstrtab"))
                break;
        }
        shdr_ptr++;
    }

    /* list all of sections */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    n = Elf32_ptr->e_shnum;
    int i = 0;
    while (n--) {
        printf("[%02d]%s type: 0x%x, offset: 0x%x, size: 0x%x\n", i++, 
                &shstrtab[shdr_ptr->sh_name], shdr_ptr->sh_type, 
                shdr_ptr->sh_offset, shdr_ptr->sh_size);
        shdr_ptr++;
    }

    printf("=== sizeof(Elf32_Sym): 0x%x\n", sizeof(Elf32_Sym));

    /* list .gnu.hash */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    n = Elf32_ptr->e_shnum;
    i = 0;
    while (n--) {
        if (!strcmp(&shstrtab[shdr_ptr->sh_name], ".gnu.hash")) {
        Elf32_Dyn *dyn_ptr = (Elf32_Dyn *)(ptr + shdr_ptr->sh_offset);
        printf("GNU_HASH 0x%x\n", dyn_ptr->d_un.d_ptr);
            break;
        }
        shdr_ptr++;
    }

}

static void phdr_parse(void *ptr)
{
    Elf32_Ehdr *Elf32_ptr = NULL;

    Elf32_ptr = (Elf32_Ehdr *)ptr;
    Elf32_Phdr *elf32_phdr = NULL;
    int n, found = 0;

    n = Elf32_ptr->e_phnum;
    elf32_phdr = ptr + Elf32_ptr->e_phoff;
    while (n--) {
        if (elf32_phdr->p_type == PT_DYNAMIC) {
            found = 1;
            break;
        }
        elf32_phdr++;
    }

    if (found) {
        printf("=== PT_DYNAMIC: offset: 0x%x, size: 0x%x\n", 
                elf32_phdr->p_offset, elf32_phdr->p_filesz);
        printf("sizeof(Elf32_Dyn): %d\n", sizeof(Elf32_Dyn));
    }

    /* list all of dynamic sections */
    Elf32_Dyn *dyn_entry = ptr + elf32_phdr->p_offset;
    while (dyn_entry->d_tag != DT_NULL) {
        if (dyn_entry->d_tag == 0x6ffffef5) {
            printf("DT_HASH: addr: 0x%x\n", dyn_entry->d_un.d_ptr);
            break;
        }
        printf("tag: 0x%x, value: 0x%x\n", dyn_entry->d_tag, dyn_entry->d_un.d_ptr);

        dyn_entry++;
    }

}

static void relocs_parse(void *ptr)
{
    Elf32_Shdr *shdr_ptr = NULL;
    Elf32_Ehdr *Elf32_ptr = (Elf32_Ehdr *)ptr;


    int n = Elf32_ptr->e_shnum;
    char *shstrtab = NULL;

    /*
     * first of all, let's get the shstrtab, we'll get 
     * the name of each section with it
     */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    while (n--) {
        if (shdr_ptr->sh_type == SHT_STRTAB) {
            shstrtab = (char *)(ptr + shdr_ptr->sh_offset);
            if (!strcmp(&shstrtab[shdr_ptr->sh_name], ".shstrtab"))
                break;
        }
        shdr_ptr++;
    }

    /* list all of sections */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    n = Elf32_ptr->e_shnum;
    int i = 0;
    while (n--) {
        if (shdr_ptr->sh_type == SHT_REL || shdr_ptr->sh_type == SHT_RELA) {
            printf("[%02d]%s type: 0x%x, offset: 0x%x, size: 0x%x\n", i++, 
                    &shstrtab[shdr_ptr->sh_name], shdr_ptr->sh_type, 
                    shdr_ptr->sh_offset, shdr_ptr->sh_size);

            int n2 = (shdr_ptr->sh_size / sizeof(Elf32_Rel)); 
            Elf32_Rel *rel = (Elf32_Rel *)(ptr + shdr_ptr->sh_offset);
            while (n2--) {
            printf("==== offset: 0x%x, sizeof(Elf32_Rel): 0x%x\n", 
                    rel->r_offset, sizeof(Elf32_Rel));
            }
        }
        shdr_ptr++;
    }
}

static void symtab_parse(void *ptr)
{
    Elf32_Shdr *shdr_ptr = NULL;
    Elf32_Ehdr *Elf32_ptr = (Elf32_Ehdr *)ptr;


    int n = Elf32_ptr->e_shnum;
    char *shstrtab = NULL;

    /*
     * first of all, let's get the shstrtab, we'll get 
     * the name of each section with it
     */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    while (n--) {
        if (shdr_ptr->sh_type == SHT_STRTAB) {
            shstrtab = (char *)(ptr + shdr_ptr->sh_offset);
            if (!strcmp(&shstrtab[shdr_ptr->sh_name], ".shstrtab"))
                break;
        }
        shdr_ptr++;
    }

    /* list all of sections */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    n = Elf32_ptr->e_shnum;
    int i = 0;
    while (n--) {
        if (shdr_ptr->sh_type == SHT_SYMTAB) {
            printf("[%02d]%s type: 0x%x, offset: 0x%x, size: 0x%x\n", i++, 
                    &shstrtab[shdr_ptr->sh_name], shdr_ptr->sh_type, 
                    shdr_ptr->sh_offset, shdr_ptr->sh_size);

            int n2 = (shdr_ptr->sh_size / sizeof(Elf32_Sym)); 
            Elf32_Sym *sym = (Elf32_Sym *)(ptr + shdr_ptr->sh_offset);
            while (n2--) {
                printf("== value: 0x%x\n", sym->st_value);
                sym++;
            }
        }
        shdr_ptr++;
    }
}

static void dynsym_parse(void *ptr)
{
    Elf32_Shdr *shdr_ptr = NULL;
    Elf32_Ehdr *Elf32_ptr = (Elf32_Ehdr *)ptr;


    int n = Elf32_ptr->e_shnum;
    char *shstrtab = NULL;

    /*
     * first of all, let's get the shstrtab, we'll get 
     * the name of each section with it
     */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    while (n--) {
        if (shdr_ptr->sh_type == SHT_STRTAB) {
            shstrtab = (char *)(ptr + shdr_ptr->sh_offset);
            if (!strcmp(&shstrtab[shdr_ptr->sh_name], ".shstrtab"))
                break;
        }
        shdr_ptr++;
    }

    /* list all of sections */
    shdr_ptr = (Elf32_Shdr *)(ptr + Elf32_ptr->e_shoff);
    n = Elf32_ptr->e_shnum;
    int i = 0;
    while (n--) {
        if (shdr_ptr->sh_type == SHT_SYMTAB) {
            printf("[%02d]%s type: 0x%x, offset: 0x%x, size: 0x%x\n", i++, 
                    &shstrtab[shdr_ptr->sh_name], shdr_ptr->sh_type, 
                    shdr_ptr->sh_offset, shdr_ptr->sh_size);

            int n2 = (shdr_ptr->sh_size / sizeof(Elf32_Sym)); 
            Elf32_Sym *sym = (Elf32_Sym *)(ptr + shdr_ptr->sh_offset);
            while (n2--) {
                printf("== value: 0x%x\n", sym->st_value);
                sym++;
            }
        }
        shdr_ptr++;
    }
}

/*
 * display the memory postion of members of hedr struct
 */
static void ehdr_show_addr(void *ptr)
{
    Elf32_Ehdr *Elf32_ptr = (Elf32_Ehdr *)ptr;

    printf("&e_ident: %p\n", &Elf32_ptr->e_ident);
    printf("&e_entry: %p\n", &Elf32_ptr->e_entry);
    printf("&e_flags: %p\n", &Elf32_ptr->e_flags);

}

static void ehdr_parse(void *ptr)
{
    Elf32_Ehdr *Elf32_ptr = NULL;

    Elf32_ptr = (Elf32_Ehdr *)ptr;
    Elf32_Phdr *elf32_phdr = NULL;
    int n;


    printf("==================== EHDR ==================================\n");
    printf("e_ident: %s\n", Elf32_ptr->e_ident);
    printf("e_entry: %p\n", (void *)Elf32_ptr->e_entry);
    printf("e_phoff: %ld\n", (unsigned long)Elf32_ptr->e_phoff);
    printf("e_shoff: %ld\n", (unsigned long)Elf32_ptr->e_shoff);
    printf("e_ehsize: %d\n", Elf32_ptr->e_ehsize & 0xffff);
    printf("sizeof(Elf32_Ehdr): %d\n", sizeof(Elf32_Ehdr));
    printf("e_phentsize: %d\n", Elf32_ptr->e_phentsize);
    printf("e_phnum: %d\n", Elf32_ptr->e_phnum);
    printf("e_shentsize: %d\n", Elf32_ptr->e_shentsize);
    printf("e_shnum: %d\n", Elf32_ptr->e_shnum);
    printf("e_shstrndx: %d\n", Elf32_ptr->e_shstrndx);
    printf("==================== EHDR ==================================\n");

    /* next, parse shdr */
    shdr_parse(ptr + Elf32_ptr->e_shoff);
    /* pdhr */
    n = Elf32_ptr->e_phnum;
    elf32_phdr = ptr + Elf32_ptr->e_phoff;
    while (n--)
        phdr_parse(elf32_phdr++);


}


int main(int argc, char *argv[])
{
    int fd_src;
    //size_t len = 0;
    size_t filesize = 0;
    void *ptr = NULL;   /* ptr to binary file which mapped in memory */
    if (argc != 2) {
        printf("Usage: %s [ src bin ] ...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /*
     * we'll calculate the file size then map to memory
     */
    fd_src = open(argv[1], O_RDONLY);

    if (fd_src < 0) {
        printf("Failed to open %s!\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    /* get file size with lseek SEEK_END */
    filesize = lseek(fd_src, 0, SEEK_END);
    if (filesize < 0) {
        perror("lseek failed!");
        close(fd_src);
        exit(EXIT_FAILURE);
    }

    ptr = mmap(0, filesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_src, 0);
    if (ptr < 0) {
        perror("mmap failed!");
        close(fd_src);
        exit(EXIT_FAILURE);
    }

//    ehdr_parse(ptr);
//    ehdr_show_addr(ptr);
//    shdr_parse(ptr);
    /* phdr_parse(ptr); */
    /* relocs_parse(ptr); */
    dynsym_parse(ptr);

    /* do the clean work */
    munmap(ptr, filesize);
    close(fd_src);

    return EXIT_SUCCESS;
}

在开始旅程之前,最好阅读一些有关 elf 格式的内容,以便您更好地理解它,希望对您有所帮助。

关于c - 打开 ELF 文件并检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16176031/

相关文章:

linux - 在 Ubuntu 64 上运行 ELF 64 位 LSB 可执行文件

c - GCC 将所有字符串存储在 .rodata 中

c - 替代 C 中的许多 case switch 语句

c - 通过管道的 perror scanf 引起的无限循环

c - 位操作谜题

c - 理解啤酒瓶示例中的递归

linux - 在 PT_GNU_STACK 程序头上设置执行位时,为什么进程的所有段都变为可执行

c - 如何检查程序是否在c中静态编译

linux - Linux 上的 PEiD 替代方案

c++ - 如何使用 "time.h"库(仅)以毫秒为单位获取当前时间?