【问题标题】:How to find the offset of the section header string table of an elf file?如何找到elf文件的节头字符串表的偏移量?
【发布时间】:2013-04-06 07:07:13
【问题描述】:

我必须编写一个打印 ELF 文件的 C 程序。我无法确定节标题字符串表的位置。

假设我有一个文件,它给了我以下输出:

readelf -h

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

并与:

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)

如何计算节标题字符串表的位置?

【问题讨论】:

  • 如果您在ghex 中找到它,您不能通过查看找到它的文件中的地址来查看偏移量吗?我不熟悉它,但是当我用谷歌搜索它时,屏幕截图显示文件中视图的地址在左侧列中。

标签: c linux elf


【解决方案1】:

这就是我的工作:

#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);
  }

  // ...
}

【讨论】:

    【解决方案2】:

    这里是你将如何获得部分名称字符串表:

    • ELF Executable Header (EHDR) 的 e_shstrndx 字段指定描述包含节名称的字符串表的节头表条目的索引。
    • EHDR 的e_shentsize 字段指定每个节头表条目的大小(以字节为单位)。
    • EHDR 的e_shoff 字段指定了到节头表开头的文件偏移量。

    因此字符串表的标题条目将位于文件偏移量:

    header_table_entry_offset = (e_shentsize * e_shstrndx) + e_shoff
    

    根据对象的 ELF 类,此头表条目将是 Elf32_ShdrElf64_Shdr。请注意,头表条目的文件表示形式可能与其在您的程序运行所在的主机上的内存中表示形式不同。

    标题条目中的sh_offset字段将指定字符串表的起始文件偏移量,而sh_size字段将指定其大小。

    进一步阅读:“libelf by Example”教程更深入地介绍了 ELF 可执行文件头和 ELF 节头表。

    【讨论】:

      【解决方案3】:

      您想要的似乎是 STRTAB,它的偏移量为 0x441c(第 [20] 行)。标头在文件中开始 17636 字节(根据

      Start of section headers:          17636 (bytes into file)
      

      所以我猜你的字符串表从文件开始的 17636 + 17436 = 35072 字节开始。

      我可能完全错了,但这就是我要开始的地方。你知道如何使用od 或类似的工具来转储文件字节吗?

      【讨论】:

      • 那么字符串表将在文件中的 17436 字节处?应该很容易检查其中任何一个是否正确。
      【解决方案4】:

      节标题表从starting point of your file + e_shoff 开始。 elf.h 文件已经有 Elfxx_Shdr 结构和 Elfxx_Ehdr 结构,其中 xx 分别是 3264 用于 32 位或 64 位。

      您可以使用Elfxx_Ehdr 中的e_shentsize 来获取节标题字符串表索引,然后使用Elfxx_Shdr 中的sh_namesh_offsetsh_name 将为您提供strtab 的索引,如果您在其中添加sh_offset。这将为您提供该部分的全名。使用sh_typesh_flag等对类型、标志和其他相同。

      我建议你去executable and linkable format wikipedia articleefl.h file man page

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-14
        • 2012-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多