可重定位文件.strtab section和.symtab section分析

一 ELF的.strtab section

1 readelf -x 10 add.o

[root@localhost 0401]# readelf -x 10 add.o

Hex dump of section '.strtab':
  0x00000000 00616464 2e637070 00726573 756c7400 .add.cpp.result.
  0x00000010 5f5a3361 64646969 00                _Z3addii.

上面是以16进制方式显示指定段内内容。0x00 0x61 0x64 0x64对应''、'a'、'd'、'd'

2 realelf -S add.o

[root@localhost 0401]# readelf -S add.o
There are 11 section headers, starting at offset 0x240:

Section Headers:
  [Nr] Name              Type             Address           Offset      Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000    0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040    0000000000000014  0000000000000000  AX       0     0     1
  [ 2] .data             PROGBITS         0000000000000000  00000054    0000000000000004  0000000000000000  WA       0     0     4
  [ 3] .bss              NOBITS           0000000000000000  00000058    0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .comment          PROGBITS         0000000000000000  00000058    000000000000002e  0000000000000001  MS       0     0     1
  [ 5] .note.GNU-stack   PROGBITS         0000000000000000  00000086    0000000000000000  0000000000000000           0     0     1
  [ 6] .eh_frame         PROGBITS         0000000000000000  00000088    0000000000000038  0000000000000000   A       0     0     8
  [ 7] .rela.eh_frame    RELA             0000000000000000  00000228    0000000000000018  0000000000000018   I       9     6     8
  [ 8] .shstrtab         STRTAB           0000000000000000  000000c0    0000000000000054  0000000000000000           0     0     1
  [ 9] .symtab           SYMTAB           0000000000000000  00000118    00000000000000f0  0000000000000018          10     8     8
  [10] .strtab           STRTAB           0000000000000000  00000208    0000000000000019  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

3 hexdump -s 0x208 -n  25 -c add.o

[root@localhost 0401]# hexdump -s 0x208 -n  25 -c add.o
0000208  \0   a   d   d   .   c   p   p  \0   r   e   s   u   l   t  \0
0000218   _   Z   3   a   d   d   i   i  \0

这些字符串所表示的内容,通常是程序中定义的函数名称,所定义过的变量等。

当对象文件中其他地方需要和一个这样的字符串关联的时候,往往会在对应的地方先存储.strtab section中的索引值。

4 .shstrtab section的查看方法

[root@localhost 0401]# readelf -x 8 add.o

Hex dump of section '.shstrtab':
  0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab
  0x00000010 002e7368 73747274 6162002e 74657874 ..shstrtab..text
  0x00000020 002e6461 7461002e 62737300 2e636f6d ..data..bss..com
  0x00000030 6d656e74 002e6e6f 74652e47 4e552d73 ment..note.GNU-s
  0x00000040 7461636b 002e7265 6c612e65 685f6672 tack..rela.eh_fr
  0x00000050 616d6500                            ame.

.shstrtab section也是字符串表,其中存储的是section的名字,而非函数或者变量的名称。

参考

https://www.jianshu.com/p/7a75324e98ab

二 ELF的.symtab section

1 点睛

符号表保存了程序实现或使用的所有全局变量和函数。

.symtab确定符号的名称与其值之间的关联,其中名称不是直接以字符串形式出现的,而是表示为某一字符串数组(.strtab)的索引。

.strtab保存了字符串数组(.shstrtab包含了节名称字符串表)。

2 查看方法

readelf -s file:显示符合表段中的项。

[root@localhost 0401]# readelf -s add.o

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS add.cpp
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     8: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    2 result
     9: 0000000000000000    20 FUNC    GLOBAL DEFAULT    1 _Z3addii

3 符号表定义

typedef struct elf64_sym {
    Elf64_Word st_name;          // 符号名称,字符串表中的索引
    
    // STT_OBJECT表示符号关联到一个数据对象,如变量、数组或指针;
    // STT_FUNC表示符号关联到一个函数;
    // STT_NOTYPE表示符号类型未指定,用于未定义引用
    unsigned char st_info;         // 类型和绑定属性:STB_LOCAL/STB_GLOBAL/STB_WEAK;
    unsigned char st_other;      // 语义未定义,0
    Elf64_Half st_shndx;           // 相关节的索引,符号将绑定到该节,此外SHN_ABS指定符号是绝对值,不因重定位而改变,SHN_UNDEF标识未定义符号。
    Elf64_Addr st_value;           // 符号的值
    Elf64_Xword st_size;          // 符号的长度,如一个指针的长度或struct对象中包含的字节数。
}Elf64_Sym;

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码可否提供? 可以的,以下是一个简单的示例代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <elf.h> int main(int argc, char **argv) { if (argc < 4) { printf("Usage: %s <elf_file> <section_name> <new_file>\n", argv[0]); return 1; } const char *elf_file = argv[1]; const char *section_name = argv[2]; const char *new_file = argv[3]; FILE *f = fopen(elf_file, "rb"); if (f == NULL) { printf("Error opening file: %s\n", elf_file); return 1; } fseek(f, 0, SEEK_END); size_t file_size = ftell(f); fseek(f, 0, SEEK_SET); char *elf_data = (char *)malloc(file_size); fread(elf_data, file_size, 1, f); fclose(f); Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elf_data; if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) { printf("Not an ELF file\n"); return 1; } Elf32_Shdr *shdr_start = (Elf32_Shdr *)(elf_data + ehdr->e_shoff); Elf32_Shdr *shdr_strtab = shdr_start + ehdr->e_shstrndx; char *shstrtab = elf_data + shdr_strtab->sh_offset; int section_index = -1; for (int i = 0; i < ehdr->e_shnum; i++) { Elf32_Shdr *shdr = shdr_start + i; char *section_name_at = shstrtab + shdr->sh_name; if (strcmp(section_name_at, section_name) == 0) { section_index = i; break; } } if (section_index == -1) { printf("Section not found: %s\n", section_name); return 1; } FILE *new_f = fopen(new_file, "rb"); if (new_f == NULL) { printf("Error opening new file: %s\n", new_file); return 1; } fseek(new_f, 0, SEEK_END); size_t new_file_size = ftell(new_f); fseek(new_f, 0, SEEK_SET); char *new_data = (char *)malloc(new_file_size); fread(new_data, new_file_size, 1, new_f); fclose(new_f); Elf32_Shdr *shdr = shdr_start + section_index; char *section_data = elf_data + shdr->sh_offset; size_t section_size = shdr->sh_size; // Resize the section to fit the new data if (new_file_size > section_size) { char *new_section_data = (char *)realloc(section_data, new_file_size); if (new_section_data == NULL) { printf("Error reallocating memory\n"); return 1; } section_data = new_section_data; memset(section_data + section_size, 0, new_file_size - section_size); } // Copy the contents of the new file into the section memcpy(section_data, new_data, new_file_size); // Update the section size shdr->sh_size = new_file_size; // Write the modified ELF file back to disk FILE *out_f = fopen(elf_file, "wb"); if (out_f == NULL) { printf("Error opening output file: %s\n", elf_file); return 1; } fwrite(elf_data, file_size, 1, out_f); fclose(out_f); printf("Section '%s' updated in file '%s' with contents of file '%s'\n", section_name, elf_file, new_file); return 0; } ``` 这个程序接受三个参数:ELF 文件路径,需要更新的段名和新文件路径。它打开 ELF 文件,查找指定的段,将指定的新文件的内容覆盖到该段中,然后将新的 ELF 文件写回磁盘。您可以将这个程序编译成可执行文件,然后以以下格式运行: ``` ./program <elf_file> <section_name> <new_file> ``` 其中 `<elf_file>` 是需要更新的 ELF 文件的路径,`<section_name>` 是需要更新的段的名字,`<new_file>` 是需要合并到段中的新文件的路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值