“ELF for dummies” ( parte 3 de muitas )

Veremos como obter informações sobre alguma seção do ELF e exibi-la


Primeira parte em:
http://oscaraleeto.wordpress.com/2007/01/14/elf-for-dummies-parte-1-de-muitas/

Segunda parte em:
http://oscaraleeto.wordpress.com/2007/01/16/%e2%80%9celf-for-dummies%e2%80%9d-parte-2-de-muitas/

elflib.c (adicionar)
************************************

/*

    Exibe infomacoes da secao informada    
    int fd:             File Descriptor do ELF
    char *name:         Nome da secao
    Retorna:            1 em caso de erro,
                        0 caso consiga exibir a secao com sucesso
    Veja Também:        get_section
                        get_section_idx

*/
int dump_section(int fd, char *name)
{
    Elf32_Shdr *shdr;

    if ( (shdr = get_section(fd, name)) == NULL) {
        printf ("[-] Section %s not found.n", name);
        return 1;
    }

    printf ("[=] Section %s:n"
        "   Name:      %sn"
        "   Type:      0x%xn"
        "   Flags:     0x%xn"
        "   Addr:      0x%xn"
        "   Offset:    0x%xn"
        "   Size:      0x%xn"
        "   Link:      0x%xn"
        "   Info:      0x%xn"
        "   Align:     0x%xn"
        "   Ent. Size: 0x%xn",
            name,
            get_section_name(fd, shdr->sh_name),
            shdr->sh_type,
            shdr->sh_flags,
            shdr->sh_addr,
            shdr->sh_offset,
            shdr->sh_size,
            shdr->sh_link,
            shdr->sh_info,
            shdr->sh_addralign,
            shdr->sh_entsize );
    return 0;
}


/*
    Obtem uma secao do ELF atraves do nome

    int fd:             File Descriptor do ELF
    char *name:         Nome da secao
    Retorna:            NULL em caso de erro,
                        Um ponteiro para um Elf32_Shdr, caso consiga obter
    Veja Também:        get_section_name
                        get_section_idx
                        dump_section
*/
Elf32_Shdr * get_section(int fd, char *name)
{
    Elf32_Ehdr ehdr;
    Elf32_Shdr *shdr;
    char *sections, *symbols, *sym;
    int sections_len, symbols_len, cont;
    if ( lseek (fd, 0, SEEK_SET) < 0 ) {
        perror("lseek");
        return NULL;
    }

    if ( read(fd, &ehdr, sizeof(ehdr)) < 0 ) {
        perror("read");
        return NULL;
    }
    if ( lseek (fd, ehdr.e_shoff, SEEK_SET) < 0 ) {
        perror("lseek");
        return NULL;
    }

    sections = (char *) malloc(sections_len = sizeof(*shdr)*ehdr.e_shnum);
    if (sections == NULL) {
        perror("malloc");
        return NULL;
    }

    if ( read(fd, sections, sections_len) < sections_len) {
        perror("read");
        return NULL;
    }

    shdr = (Elf32_Shdr *) sections;
    for ( cont = 0; cont < ehdr.e_shnum; cont++) {
        if (strncmp(name, get_section_name(fd, shdr->sh_name), sizeof(name)) == 0)
            return shdr;
        shdr++;
    }

    return NULL;
}

/*
    Obtem o nome de uma secao do ELF, atraves do index
    int fd:             File Descriptor do ELF
    int idx:            Index da secao
    Retorna:            NULL em caso de erro,
                        Um ponteiro para o nome da secao, caso consiga obter
    Veja Também:        get_section
                        get_section_idx
                        dump_section
*/
char * get_section_name(int fd,  int idx)
{
    Elf32_Ehdr ehdr;
    Elf32_Shdr *shdr;
    char *sections, *symbols, *sym;
    int sections_len, symbols_len, cont;

    if ( lseek (fd, 0, SEEK_SET) < 0 ) {
        perror("lseek");
        return NULL;
    }

    if ( read(fd, &ehdr, sizeof(ehdr)) < 0 ) {
        perror("read");
        return NULL;
    }

    if ( lseek (fd, ehdr.e_shoff, SEEK_SET) < 0 ) {
        perror("lseek");
        return NULL;
    }

    sections = (char *) malloc(sections_len = sizeof(*shdr)*ehdr.e_shnum);
    if (sections == NULL) {
        perror("malloc");
        return NULL;
    }

    if ( read(fd, sections, sections_len) < sections_len) {
        perror("read");
        return NULL;
    }

    shdr = (Elf32_Shdr *) sections;
    shdr += ehdr.e_shstrndx;

    symbols = (char *) malloc(shdr->sh_size);
    lseek(fd, shdr->sh_offset, SEEK_SET);
    read(fd, symbols, shdr->sh_size);

    sym = (char *) symbols;
    sym += idx;

    free(sections);
    free(symbols);

    if ( lseek (fd, 0, SEEK_SET) < 0 ) {
        perror("lseek");
        return NULL;
    }

    return sym;
}

************************************

Um exemplo de uso:

dumpsection.c
************************************

#include "elflib.h"
int usage(char **args)
{
    printf ( "usage: %s <filename> <section name>n", args[0] );
    exit (0);
}

int main (int argc, char **argv)
{
    int fd;    if (argc != 3) {
        usage(argv);
        exit (1);
    }

    if ( (fd = open(argv[1], O_RDWR)) < 0 ) {
        perror("open");
        exit(1);
    }

    dump_section (fd, argv[2]);
}

************************************

Compilando o dumpsection.c e o sample.c,
do exemplo passado:

$ gcc -o dumpsection dumpsection.c
$ gcc -o sample sample.c

Agora para verificar o funcionamento, executamos o dumpsection passando
como parâmetro o nome de um binário em formato ELF e o nome de alguma seção do ELF, como por exemplo .text, .bss, .data:

$ ./dumpsection sample .text
[=] Section .text:
Name: .text
Type: 0×1
Flags: 0×6
Addr: 0×80482d0
Offset: 0×2d0
Size: 0×210
Link: 0×0
Info: 0×0
Align: 0×10
Ent. Size: 0×0

$ ./dumpsection sample .bss
[=] Section .bss:
Name: .bss
Type: 0×8
Flags: 0×3
Addr: 0×8049624
Offset: 0×624
Size: 0×4
Link: 0×0
Info: 0×0
Align: 0×4
Ent. Size: 0×0

$ ./dumpsection sample .data
[=] Section .data:
Name: .data
Type: 0×1
Flags: 0×3
Addr: 0×8049618
Offset: 0×618
Size: 0xc
Link: 0×0
Info: 0×0
Align: 0×4
Ent. Size: 0×0

E assim podemos observar informações de algumas das seções do ELF, informação
que será útil futuramente.
Ainda precisamos evitar o “Segmentation fault” dos exemplos anteriores, ver outras
funções e começar a aplicar o conhecimento que vem sendo adquirido.

1 Comment »

  1. lucas machado said

    Primeiramente gostaria de agradecer, pois seus códigos para acesso do cabeçalho e seções do elf foram de grande valia! Uma dica construtiva, no nosso caso, tivemos que alterar a função get_section. No loop for, no final do código, o ponteiro shdr não incrementava! É isso. Muito obrigado.

RSS feed for comments on this post · TrackBack URI

Leave a Comment