Найти текстовый раздел эльфа в C - PullRequest
2 голосов
/ 07 апреля 2020

Как правильно получить текстовый раздел файла Elf и отобразить его содержимое? Я пытался сделать это сам, но он показывает только 250 бит данных, но когда я пытаюсь с помощью команды readelf, это показывает мне гораздо больше. Я думаю, что только что сделал неправильное смещение, чтобы получить раздел. Каков правильный подход?

Обновление: я дополнил код. Теперь это дает мне ошибку сегментации, когда я хочу напечатать имена символов.

Код:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <elf.h>

int main(int argc, char *argv[]) {


    int fd;
    int val;

    Elf32_Ehdr elfHdr;
    Elf32_Shdr sectHdr;
    Elf32_Shdr textSection;
    Elf32_Shdr *symtab = NULL;
    Elf32_Shdr *strtab = NULL;
    FILE* ElfFile = NULL;
    char* SectNames = NULL;

    if(argc != 2) {
        perror("Chose file!");
        return -1;
    }   



    ElfFile = fopen(argv[1],"r");
    if(ElfFile == NULL) {
        printf("Error opening file");
        return -1;
    }


    fread(&elfHdr, 1, sizeof(Elf32_Ehdr), ElfFile);




    fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * elfHdr.e_shentsize, SEEK_SET);
    fread(&sectHdr, 1, sizeof(sectHdr), ElfFile);
    SectNames = malloc(sectHdr.sh_size);
    fseek(ElfFile, sectHdr.sh_offset, SEEK_SET);
    fread(SectNames, 1, sectHdr.sh_size, ElfFile);

    printf("\nSECTION HEADERS:\n\n");



    for (int idx = 0; idx < elfHdr.e_shnum; idx++){
        char* name = "";

        fseek(ElfFile, elfHdr.e_shoff + idx * sizeof(sectHdr), SEEK_SET);
        fread(&sectHdr, 1, sizeof(sectHdr), ElfFile);

        // print section name
        if (sectHdr.sh_name);
        name = SectNames + sectHdr.sh_name;

        if(strcmp(name,".text") == 0) {
            textSection = sectHdr;
        }

        if(strcmp(name, ".symtab") == 0) {
            //symbolTable = (Elf32_Sym*)sectHdr.sh_addr;
            symtab = (Elf32_Shdr*) &sectHdr;
        }
        if(strcmp(name, ".strtab") == 0) {
            strtab = (Elf32_Shdr *) &sectHdr;
        }

        printf("%s\n", name);
    }

    printf("\nTEXT SECTION (zacetek: 0x%lx):\n\n", textSection.sh_addr);
    printf("Section size: %i\n\n", textSection.sh_size);

    fseek(ElfFile, textSection.sh_addr, SEEK_SET);

    for(int i=0; i < textSection.sh_size; i = i+32) {
        int value;
        fseek(ElfFile, textSection.sh_addr + i, SEEK_SET);
        fread(&value, 1, sizeof(value), ElfFile);
        printf("0x%x\n", value);
    }

    fclose(ElfFile);

    //read file content to the buffer

    char* source = NULL;
    FILE *fp = fopen(argv[1],"r");
    if(fp != NULL) {
        if(fseek(fp, 0L, SEEK_END) == 0) {
            long bufsize = ftell(fp);
            if(bufsize == -1) {
                printf("Error setting buffer size!");
                return -1;
            }
            source = malloc(sizeof(char) * (bufsize + 1));

            if(fseek(fp, 0L, SEEK_SET) != 0) {
                printf("Error line 120");
                return -1;
            }
            size_t newLen = fread(source, sizeof(char), bufsize, fp);
            if(ferror(fp) != 0) {
                fputs("Error reading file", stderr);
            }
            else {
                source[newLen++] = '\0';
            }
        }
        fclose(fp);
    }

    char* data = &source;


    printf("\nSymbol table names:\n\n");
    printf("\nSize of symbolTableHeader: %i\n", symtab->sh_size);

    printf("\nSymbol table names:\n\n");


    Elf32_Sym *sym = (Elf32_Sym*)(data + symtab->sh_offset);
    char *str = (char*) (data + strtab->sh_offset);

    for(size_t i = 0; i < symtab->sh_size / sizeof(Elf32_Sym); i++) {
        printf("%s\n", str + sym[i].st_name); //this is where it throws me segmentation fault (core dumped)
    }





    return 0;
}

1 Ответ

1 голос
/ 07 апреля 2020

Я думаю, что только что сделал неправильное смещение, чтобы получить раздел.

Ваша программа выполняет итерации по всем разделам, поэтому в конце первого l oop, sectHdr содержит заголовок раздела last , что маловероятно для раздела .text.

Так что во втором l oop вы печатаете содержимое любого раздела, который оказался последним .

Чтобы распечатать раздел .text, вам нужно сохранить заголовок раздела при его обнаружении.

Обновление:

Так что, если я делаю для l oop по всем разделам, а затем strcmp с каждым именем, и когда я нахожу совпадение с .text, я сохраняю адрес этого заголовка.

Вы не сохраняете адрес этого заголовка - вы сохраняете содержимое .

А если я хочу получить доступ к таблице символов, которая не является секцией (имеет свой собственный тип: Elf32_Sym) Как мне добраться до этой таблицы?

Таблица символов имеет свой собственный раздел (содержит набор Elf32_Sym записей). См. ответ .

Обновление 2:

Этот код:

    if(strcmp(name, ".symtab") == 0) {
        //symbolTable = (Elf32_Sym*)sectHdr.sh_addr;
        symtab = (Elf32_Shdr*) &sectHdr;
    }
    if(strcmp(name, ".strtab") == 0) {
        strtab = (Elf32_Shdr *) &sectHdr;
    }

равен очевидно broken: вы сохраняете указатель на память, которую вы перезаписываете на каждой итерации l oop. Вы должны сохранить копию из .symtab и .strtab заголовка раздела (так же, как вы делаете для .text).

Еще лучшее решение - mmap весь файл в память. Затем вы можете сохранять указатели на различные его части (это то, что делает другой ответ - data указывает на начало mmap ed области).

...