博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
elf 格式分析----函数解析
阅读量:2344 次
发布时间:2019-05-10

本文共 11618 字,大约阅读时间需要 38 分钟。

https://github.com/elfmaster/libelfmaster

这里是个不错的解析elf的c代码。

寻找导出函数对应偏移

我感觉文字没有代码明白,看下别人怎么写的,立马明白了。

mem指向elf文件加载的地址连续空间。

typedef struct{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ Elf64_Half e_type; /* Object file type */ Elf64_Half e_machine; /* Architecture */ Elf64_Word e_version; /* Object file version */ Elf64_Addr e_entry; /* Entry point virtual address */ Elf64_Off e_phoff; /* Program header table file offset */ Elf64_Off e_shoff; /* Section header table file offset */ Elf64_Word e_flags; /* Processor-specific flags */ Elf64_Half e_ehsize; /* ELF header size in bytes */ Elf64_Half e_phentsize; /* Program header table entry size */ Elf64_Half e_phnum; /* Program header table entry count */ Elf64_Half e_shentsize; /* Section header table entry size */ Elf64_Half e_shnum; /* Section header table entry count */ Elf64_Half e_shstrndx; /* Section header string table index */} Elf64_Ehdr;
typedef struct{
Elf64_Word sh_name; /* Section name (string tbl index) */ Elf64_Word sh_type; /* Section type */ Elf64_Xword sh_flags; /* Section flags */ Elf64_Addr sh_addr; /* Section virtual addr at execution */ Elf64_Off sh_offset; /* Section file offset */ Elf64_Xword sh_size; /* Section size in bytes */ Elf64_Word sh_link; /* Link to another section */ Elf64_Word sh_info; /* Additional section information */ Elf64_Xword sh_addralign; /* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */} Elf64_Shdr;typedef struct {
Elf32_Word st_name; //符号表项名称。如果该值非0,则表示符号名的字 //符串表索引(offset),否则符号表项没有名称。 Elf32_Addr st_value; //符号的取值。依赖于具体的上下文,可能是一个绝对值、一个地址等等。 Elf32_Word st_size; //符号的尺寸大小。例如一个数据对象的大小是对象中包含的字节数。 unsigned char st_info; //符号的类型和绑定属性。 unsigned char st_other; //未定义。 Elf32_Half st_shndx; //每个符号表项都以和其他节区的关系的方式给出定义。             //此成员给出相关的节区头部表索引。} Elf32_sym;
obj->ehdr64 = (Elf64_Ehdr *)mem;obj->shdr64 = (Elf64_Shdr *)&mem[obj->ehdr64->e_shoff];obj->section_count = section_count = obj->ehdr64->e_shnum;obj->shstrtab =	(char *)&mem[obj->shdr64[obj->ehdr64->e_shstrndx].sh_offset];for (i = 0; i < section_count; i++) {
const char *sname = (obj->e_class == elfclass32) ? &obj->shstrtab[obj->shdr32[i].sh_name] : &obj->shstrtab[obj->shdr64[i].sh_name]; if (strcmp(sname, ".strtab") == 0) {
obj->strtab = (char *)&mem[sh_offset]; } else if (strcmp(sname, ".symtab") == 0) {
uint64_t sh_offset = (obj->e_class == elfclass32) ? obj->shdr32[i].sh_offset : obj->shdr64[i].sh_offset; obj->symtab_count = obj->shdr64[i].sh_size /sizeof(Elf64_Sym); obj->symtab64 =(Elf64_Sym *)&mem[sh_offset]; }}for (i = 0; i < obj->symtab_count; i++) symbol->name = &obj->strtab[symtab64[i].st_name]; symtab64 = obj->symtab64; //函数符号 symbol->value = symtab64[i].st_value; //函数偏移 symbol->size = symtab64[i].st_size; //函数大小 }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

rel.plt和rel.dyn

Section Headers:  [Nr] Name              Type             Address           Offset       Size              EntSize          Flags  Link  Info  Align  [ 5] .dynsym           DYNSYM           00000000004002b8  000002b8       0000000000000078  0000000000000018   A       6     1     8  [ 6] .dynstr           STRTAB           0000000000400330  00000330       0000000000000044  0000000000000000   A       0     0     1  [ 9] .rela.dyn         RELA             00000000004003a0  000003a0       0000000000000018  0000000000000018   A       5     0     8  [10] .rela.plt         RELA             00000000004003b8  000003b8       0000000000000060  0000000000000018  AI       5    23     8LOAD:00000000004003A0 ; ELF RELA Relocation TableLOAD:00000000004003A0                 Elf64_Rela <600FF8h, 400000006h, 0> ; R_X86_64_GLOB_DAT __gmon_start__LOAD:00000000004003B8 ; ELF JMPREL Relocation TableLOAD:00000000004003B8                 Elf64_Rela <601018h, 100000007h, 0> ; R_X86_64_JUMP_SLOT putsLOAD:00000000004003D0                 Elf64_Rela <601020h, 200000007h, 0> ; R_X86_64_JUMP_SLOT printfLOAD:00000000004003E8                 Elf64_Rela <601028h, 300000007h, 0> ; R_X86_64_JUMP_SLOT __libc_start_mainLOAD:0000000000400400                 Elf64_Rela <601030h, 400000007h, 0> ; R_X86_64_JUMP_SLOT __gmon_start__LOAD:0000000000400400 LOAD            ends00000000004003A0  F8 0F 60 00 00 00 00 00  06 00 00 00 04 00 00 00  ..`.............00000000004003B0  00 00 00 00 00 00 00 00  18 10 60 00 00 00 00 00  ..........`.....00000000004003C0  07 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  ................00000000004003D0  20 10 60 00 00 00 00 00  07 00 00 00 02 00 00 00   .`.............00000000004003E0  00 00 00 00 00 00 00 00  28 10 60 00 00 00 00 00  ........(.`.....00000000004003F0  07 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  ................0000000000400400  30 10 60 00 00 00 00 00  07 00 00 00 04 00 00 00  0.`.............  [12] .plt              PROGBITS         0000000000400440  00000440       0000000000000050  0000000000000010  AX       0     0     16  [21] .dynamic          DYNAMIC          0000000000600e28  00000e28       00000000000001d0  0000000000000010  WA       6     0     8  [22] .got              PROGBITS         0000000000600ff8  00000ff8       0000000000000008  0000000000000008  WA       0     0     8  [23] .got.plt          PROGBITS         0000000000601000  00001000       0000000000000038  0000000000000008  WA       0     0     8  [27] .symtab           SYMTAB           0000000000000000  00001098       0000000000000618  0000000000000018          28    46     8  [28] .strtab           STRTAB           0000000000000000  000016b0       00000000000001e2  0000000000000000           0     0     1  [29] .shstrtab         STRTAB           0000000000000000  00001892       0000000000000108  0000000000000000           0     0     1

这个重定位表用来标识got.plt重定位信息如上,指出了got.plt中的位置和定位类型。符号不是这里指定的。

plt表在代码中的体现。

.plt:00000000004004F0 sub_4004F0      proc near               ; CODE XREF: .plt:000000000040050B↓j.plt:00000000004004F0                                         ; .plt:000000000040051B↓j ....plt:00000000004004F0 ; __unwind {
.plt:00000000004004F0 push cs:qword_601008.plt:00000000004004F6 jmp cs:qword_601010.plt:00000000004004F6 sub_4004F0 endp.plt:00000000004004F6.plt:00000000004004F6 ; ---------------------------------------------------------------------------.plt:00000000004004FC align 20h.plt:0000000000400500 ; [00000006 BYTES: COLLAPSED FUNCTION _write. PRESS CTRL-NUMPAD+ TO EXPAND].plt:0000000000400506 ; ---------------------------------------------------------------------------.plt:0000000000400506 push 0.plt:000000000040050B jmp sub_4004F0.plt:0000000000400510 ; [00000006 BYTES: COLLAPSED FUNCTION ___stack_chk_fail. PRESS CTRL-NUMPAD+ TO EXPAND].plt:0000000000400516 ; ---------------------------------------------------------------------------.plt:0000000000400516 push 1.plt:000000000040051B jmp sub_4004F0.plt:0000000000400520 ; [00000006 BYTES: COLLAPSED FUNCTION _read. PRESS CTRL-NUMPAD+ TO EXPAND].plt:0000000000400526 ; ---------------------------------------------------------------------------.plt:0000000000400526 push 2.plt:000000000040052B jmp sub_4004F0.plt:0000000000400530 ; [00000006 BYTES: COLLAPSED FUNCTION ___libc_start_main. PRESS CTRL-NUMPAD+ TO EXPAND].plt:0000000000400536 ; ---------------------------------------------------------------------------.plt:0000000000400536 push 3.plt:000000000040053B jmp sub_4004F0.plt:0000000000400540 ; [00000006 BYTES: COLLAPSED FUNCTION _perror. PRESS CTRL-NUMPAD+ TO EXPAND].plt:0000000000400546 ; ---------------------------------------------------------------------------.plt:0000000000400546 push 4.plt:000000000040054B jmp sub_4004F0.plt:0000000000400550 ; [00000006 BYTES: COLLAPSED FUNCTION _exit. PRESS CTRL-NUMPAD+ TO EXPAND].plt:0000000000400556 ; ---------------------------------------------------------------------------.plt:0000000000400556 push 5.plt:000000000040055B jmp sub_4004F0.plt:000000000040055B ; } // starts at 4004F0.plt:000000000040055B _plt ends.plt:000000000040055B

每个plt中的函数在第一次调用的时候都会跳到00000000004004F0 ,这个地址将会跳转到got[0]进行dlresolve。函数地址查询,之后所有的函数地址将会填写到相应的got表中,二次调用将会直接jmp到相应的位置。

got表位置

.got.plt:0000000000601000 ; ===========================================================================.got.plt:0000000000601000.got.plt:0000000000601000 ; Segment type: Pure data.got.plt:0000000000601000 ; Segment permissions: Read/Write.got.plt:0000000000601000 _got_plt        segment qword public 'DATA' use64.got.plt:0000000000601000                 assume cs:_got_plt.got.plt:0000000000601000                 ;org 601000h.got.plt:0000000000601000 _GLOBAL_OFFSET_TABLE_ dq offset _DYNAMIC.got.plt:0000000000601008 qword_601008    dq 0                    ; DATA XREF: sub_4004F0↑r.got.plt:0000000000601010 qword_601010    dq 0                    ; DATA XREF: sub_4004F0+6↑r.got.plt:0000000000601018 off_601018      dq offset write         ; DATA XREF: _write↑r.got.plt:0000000000601020 off_601020      dq offset __stack_chk_fail.got.plt:0000000000601020                                         ; DATA XREF: ___stack_chk_fail↑r.got.plt:0000000000601028 off_601028      dq offset read          ; DATA XREF: _read↑r.got.plt:0000000000601030 off_601030      dq offset __libc_start_main.got.plt:0000000000601030                                         ; DATA XREF: ___libc_start_main↑r.got.plt:0000000000601038 off_601038      dq offset perror        ; DATA XREF: _perror↑r.got.plt:0000000000601040 off_601040      dq offset exit          ; DATA XREF: _exit↑r.got.plt:0000000000601040 _got_plt        ends.got.plt:0000000000601040

函数重定位信息: Elf64_Rela <601028h, 300000007h, 0> ; 可以定位到got表的read函数。

LOAD:00000000004003F8 ; ELF GNU Symbol Version RequirementsLOAD:00000000004003F8                 Elf64_Verneed <1, 2, offset aLibcSo6 - offset byte_400378, 10h, 0> ; "libc.so.6"LOAD:0000000000400408                 Elf64_Vernaux <0D696914h, 0, 3, offset aGlibc24 - offset byte_400378, \ ; "GLIBC_2.4"LOAD:0000000000400408                                10h>LOAD:0000000000400418                 Elf64_Vernaux <9691A75h, 0, 2, offset aGlibc225 - offset byte_400378, \ ; "GLIBC_2.2.5"LOAD:0000000000400418                                0>LOAD:0000000000400428 ; ELF RELA Relocation TableLOAD:0000000000400428                 Elf64_Rela <600FF8h, 500000006h, 0> ; R_X86_64_GLOB_DAT __gmon_start__LOAD:0000000000400440 ; ELF JMPREL Relocation TableLOAD:0000000000400440                 Elf64_Rela <601018h, 100000007h, 0> ; R_X86_64_JUMP_SLOT writeLOAD:0000000000400458                 Elf64_Rela <601020h, 200000007h, 0> ; R_X86_64_JUMP_SLOT __stack_chk_failLOAD:0000000000400470                 Elf64_Rela <601028h, 300000007h, 0> ; R_X86_64_JUMP_SLOT readLOAD:0000000000400488                 Elf64_Rela <601030h, 400000007h, 0> ; R_X86_64_JUMP_SLOT __libc_start_mainLOAD:00000000004004A0                 Elf64_Rela <601038h, 600000007h, 0> ; R_X86_64_JUMP_SLOT perrorLOAD:00000000004004B8                 Elf64_Rela <601040h, 700000007h, 0> ; R_X86_64_JUMP_SLOT exitLOAD:00000000004004B8 LOAD            ends

转载地址:http://nnjvb.baihongyu.com/

你可能感兴趣的文章
C++对象的内存模型
查看>>
C++函数编译原理和成员函数的实现
查看>>
this指针详解
查看>>
static静态成员变量和静态成员函数
查看>>
构造函数的执行顺序
查看>>
二维数组指针
查看>>
逗号表达式
查看>>
迭代器失效
查看>>
常引用
查看>>
变量在内存中的存储
查看>>
assert()
查看>>
Linux下socket的五种IO模型
查看>>
1--ip首部
查看>>
2--第四层
查看>>
3--TCP三次握手
查看>>
4--网关
查看>>
4.内存非连续分配管理方式
查看>>
5.虚拟内存的概念、特征以及虚拟内存的实现
查看>>
mmap()函数:建立内存映射
查看>>
munmap()函数:解除内存映射
查看>>