2013-04-13 12 views
6

Bir ELF dosyası basan bir C programı yazmam gerekiyor. Bölüm başlık dizgisi tablosunun nerede olduğunu bulmakta zorlanıyorum.Elf dosyasının bölüm üstbilgi dizesi tablosunun ofsetini nasıl bulunur?

ı ile bana şu çıktıyı verdi bir dosya var diyelim:

readelf

ELF Header: 
    Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
    Class:        ELF32 
    Data:        2's complement, little endian 
    Version:       1 (current) 
    OS/ABI:       UNIX - System V 
    ABI Version:      0 
    Type:        REL (Relocatable file) 
    Machine:       Intel 80386 
    Version:       0x1 
    Entry point address:    0x0 
    Start of program headers:   0 (bytes into file) 
    Start of section headers:   17636 (bytes into file) 
    Flags:        0x0 
    Size of this header:    52 (bytes) 
    Size of program headers:   0 (bytes) 
    Number of program headers:   0 
    Size of section headers:   40 (bytes) 
    Number of section headers:   23 
    Section header string table index: 20 

-h ve şununla:

readelf -S:

There are 23 section headers, starting at offset 0x44e4: 
Section Headers: 
    [Nr] Name    Type   Addr  Off Size ES Flg Lk Inf Al 
    [ 0]     NULL   00000000 000000 000000 00  0 0 0 
    [ 1] .text    PROGBITS  00000000 000034 000028 00 AX 0 0 4 
    [ 2] .rel.text   REL    00000000 0049d0 000018 08  21 1 4 
    [ 3] .data    PROGBITS  00000000 00005c 000000 00 WA 0 0 4 
    [ 4] .bss    NOBITS   00000000 00005c 000000 00 WA 0 0 4 
    [ 5] .rodata   PROGBITS  00000000 00005c 00000a 00 A 0 0 1 
    [ 6] .debug_info  PROGBITS  00000000 000066 00008f 00  0 0 1 
    [ 7] .rel.debug_info REL    00000000 0049e8 0000b0 08  21 6 4 
    [ 8] .debug_abbrev  PROGBITS  00000000 0000f5 000041 00  0 0 1 
    [ 9] .debug_loc  PROGBITS  00000000 000136 000038 00  0 0 1 
    [10] .debug_aranges PROGBITS  00000000 00016e 000020 00  0 0 1 
    [11] .rel.debug_arange REL    00000000 004a98 000010 08  21 10 4 
    [12] .debug_line  PROGBITS  00000000 00018e 0001b3 00  0 0 1 
    [13] .rel.debug_line REL    00000000 004aa8 000008 08  21 12 4 
    [14] .debug_macinfo PROGBITS  00000000 000341 003fb9 00  0 0 1 
    [15] .debug_str  PROGBITS  00000000 0042fa 0000bf 01 MS 0 0 1 
    [16] .comment   PROGBITS  00000000 0043b9 00002b 01 MS 0 0 1 
    [17] .note.GNU-stack PROGBITS  00000000 0043e4 000000 00  0 0 1 
    [18] .eh_frame   PROGBITS  00000000 0043e4 000038 00 A 0 0 4 
    [19] .rel.eh_frame  REL    00000000 004ab0 000008 08  21 18 4 
    [20] .shstrtab   STRTAB   00000000 00441c 0000c5 00  0 0 1 
    [21] .symtab   SYMTAB   00000000 00487c 000130 10  22 16 4 
    [22] .strtab   STRTAB   00000000 0049ac 000021 00  0 0 1 
Key to Flags: 
    W (write), A (alloc), X (execute), M (merge), S (strings) 
    I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
    O (extra OS processing required) o (OS specific), p (processor specific) 

Bölüm üstbilgisi dizgesi tablosunun konumunu nasıl hesaplayabilirim?

+1

Eğer 'ghex' içinde bulduysanız, bulduğunuz dosyadaki adrese bakarak ofseti göremiyor musunuz? Ben buna aşina değilim, ama ben googled zaman ben bir ekran görüntüsü sol sütunundaki dosyaya görünüm önerdi. – Floris

cevap

2

İstediğinizin, 0x441c (satır [20]) ofseti olan STRTAB olduğu anlaşılıyor. başlıkları (

Start of section headers:   17636 (bytes into file) 

yüzden senin dize tablosu dosyasının baştan 17636 + 17436 = 35072 bayt başlar tahmin edeceğim göre dosya içine 17636 bayt başlar.

olabileceğimi . tamamen yanlış, ama ben başlamak istiyorum olduğunu dosya bayt dökümü yapmak od ya da bazı tür yarar kullanmayı biliyor musunuz

+0

Hayır, ofsetler mutlaktır. – zch

+0

Sonra dize tablosu dosyaya 17436 bayt olur? Bunlardan birinin doğru olup olmadığını kontrol etmek kolay olmalı. – Floris

13

Bu benim yaptığım:?

#pragma pack(push,1) 

typedef struct 
{ 
    uint8 e_ident[16]; 
    uint16 e_type; 
    uint16 e_machine; 
    uint32 e_version; 
    uint32 e_entry; 
    uint32 e_phoff; 
    uint32 e_shoff; 
    uint32 e_flags; 
    uint16 e_ehsize; 
    uint16 e_phentsize; 
    uint16 e_phnum; 
    uint16 e_shentsize; 
    uint16 e_shnum; 
    uint16 e_shstrndx; 
} Elf32Hdr; 

typedef struct 
{ 
    uint32 sh_name; 
    uint32 sh_type; 
    uint32 sh_flags; 
    uint32 sh_addr; 
    uint32 sh_offset; 
    uint32 sh_size; 
    uint32 sh_link; 
    uint32 sh_info; 
    uint32 sh_addralign; 
    uint32 sh_entsize; 
} Elf32SectHdr; 

#pragma pack(pop) 

{ 
    FILE* ElfFile = NULL; 
    char* SectNames = NULL; 
    Elf32Hdr elfHdr; 
    Elf32SectHdr sectHdr; 
    uint idx; 

    // ... 

    // read ELF header 
    fread(&elfHdr, 1, sizeof elfHdr, ElfFile); 

    // read section name string table 
    // first, read its header 
    fseek(ElfFile, elfHdr.e_shoff + elfHdr.e_shstrndx * sizeof sectHdr, SEEK_SET); 
    fread(&sectHdr, 1, sizeof sectHdr, ElfFile); 

    // next, read the section, string data 
    SectNames = malloc(sectHdr.sh_size); 
    fseek(ElfFile, sectHdr.sh_offset, SEEK_SET); 
    fread(SectNames, 1, sectHdr.sh_size, ElfFile); 

    // read all section headers 
    for (idx = 0; idx < elfHdr.e_shnum; idx++) 
    { 
    const 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; 
    printf("%2u %s\n", idx, name); 
    } 

    // ... 
} 
4
  • ELF Çalıştırılabilir Başlık (EHDR) ait e_shstrndx alan dize tablosu içeren bölüm adları açıklayan bölüm başlığı tablo girişinin indeksi belirtir: BuradaEğer bölüm adı dize tabloya alacağı nasıl.
  • EHDR'nin e_shentsize alanı, her bir bölüm başlığı tablosu girdisinin bayt cinsinden boyutunu belirtir.
  • EHDR'nin e_shoff alanı, bölüm başlık tablosunun başlangıcına göre dosya ofsetini belirtir.

Böylece dosyanın olacak dize tablo için başlık giriş offset:

header_table_entry_offset = (e_shentsize * e_shstrndx) + e_shoff 

nesnenin ELF sınıfına bağlı olarak, bu başlık tablosu girişi ya bir Elf32_Shdr veya Elf64_Shdr olacaktır. Üstbilgi tablosu girişinin dosya gösteriminin, programınızın çalışmakta olduğu ana bilgisayardaki bellek içi temsilinden farklı olabileceğini unutmayın.

Başlık girişindeki sh_offset alanı, dize tablosunun başlangıç ​​dosya ofseti belirtirken, sh_size alanı boyutunu belirtir.

Daha fazla okuma: "libelf by Example" öğretici, ELF Executable Header ve ELF Section Header Table'ı daha ayrıntılı olarak kapsar.

İlgili konular