2013-04-13 2 views
6

ELF 파일을 인쇄하는 C 프로그램을 작성해야합니다. 섹션 헤더 문자열 테이블의 위치를 ​​파악하는 데 문제가 있습니다.elf 파일의 섹션 헤더 문자열 테이블의 오프셋을 찾는 방법은 무엇입니까?

의 내가 저에게 다음과 같은 출력을 준 파일이 있다고 가정 해 봅시다 :

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와 가진 :

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) 

을 섹션 헤더 문자열 테이블의 위치를 ​​어떻게 계산할 수 있습니까?

+1

'ghex'에서 발견 한 경우 파일을 찾은 위치의 주소를보고 오프셋을 볼 수 없습니까? 나는 그것에 익숙하지 않다. 그러나 내가 그것을봤을 때 스크린 샷은 파일에 뷰의 주소가 왼쪽 열에 있음을 제안했다. – Floris

답변

2

원하는 것이 STRTAB이고 오프셋은 0x441c (줄 [20])입니다. 헤더는 (

Start of section headers:   17636 (bytes into file) 

그래서 나는 당신의 문자열 테이블 파일의 시작에서 17,636 + 17,436 = 35,072 바이트에서 시작 추측 하겠어에 따라 파일에 17,636 바이트를 시작합니다.

내가 될 수있다 . 완전히 잘못,하지만 난 시작할 것이라고 어디 그건 당신이 파일 바이트의 덤프를 할 od 또는 일부와 같은 유틸리티를 사용하는 방법을 알아

+0

아니요. 오프셋은 절대 값입니다. – zch

+0

그러면 문자열 테이블이 파일에 17436 바이트가됩니까? 이 중 하나가 올바른지 여부를 쉽게 확인해야합니다. – Floris

13

를이 내가 할 무엇인가?

#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
  • 엘프 실행 파일 헤더 (EHDR)의 e_shstrndx 필드는 문자열 테이블 포함 된 섹션 이름을 설명하는 섹션 헤더 테이블 항목의 인덱스를 지정 : 여기은 섹션 이름 문자열 테이블을 얻을 것입니다 방법이다.
  • EHDR의 e_shentsize 필드는 각 섹션 헤더 테이블 항목의 크기 (바이트)를 지정합니다.
  • EHDR의 e_shoff 필드는 섹션 헤더 테이블의 시작 부분에 대한 파일 오프셋을 지정합니다.

는 따라서 파일에있을 것입니다 문자열 테이블의 헤더 항목 오프셋 :

header_table_entry_offset = (e_shentsize * e_shstrndx) + e_shoff 

객체의 ELF 클래스에 따라이 헤더 테이블 항목은 어느 쪽 Elf32_Shdr 또는 Elf64_Shdr 될 것입니다. 헤더 테이블 항목의 파일 표현은 프로그램이 실행중인 호스트의 메모리 내 표현과 다를 수 있습니다.

헤더 항목의 sh_offset 필드는 문자열 테이블의 시작 파일 오프셋을 지정하고 sh_size 필드는 크기를 지정합니다.

추가 정보 : "libelf by Example"자습서는 ELF 실행 가능 헤더 및 ELF 섹션 헤더 테이블에 대해 자세히 다룹니다.

관련 문제