elf 格式分析----函数解析

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     8
LOAD:00000000004003A0 ; ELF RELA Relocation Table
LOAD:00000000004003A0                 Elf64_Rela <600FF8h, 400000006h, 0> ; R_X86_64_GLOB_DAT __gmon_start__
LOAD:00000000004003B8 ; ELF JMPREL Relocation Table
LOAD:00000000004003B8                 Elf64_Rela <601018h, 100000007h, 0> ; R_X86_64_JUMP_SLOT puts
LOAD:00000000004003D0                 Elf64_Rela <601020h, 200000007h, 0> ; R_X86_64_JUMP_SLOT printf
LOAD:00000000004003E8                 Elf64_Rela <601028h, 300000007h, 0> ; R_X86_64_JUMP_SLOT __libc_start_main
LOAD:0000000000400400                 Elf64_Rela <601030h, 400000007h, 0> ; R_X86_64_JUMP_SLOT __gmon_start__
LOAD:0000000000400400 LOAD            ends

00000000004003A0  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 Requirements
LOAD: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 Table
LOAD:0000000000400428                 Elf64_Rela <600FF8h, 500000006h, 0> ; R_X86_64_GLOB_DAT __gmon_start__
LOAD:0000000000400440 ; ELF JMPREL Relocation Table
LOAD:0000000000400440                 Elf64_Rela <601018h, 100000007h, 0> ; R_X86_64_JUMP_SLOT write
LOAD:0000000000400458                 Elf64_Rela <601020h, 200000007h, 0> ; R_X86_64_JUMP_SLOT __stack_chk_fail
LOAD:0000000000400470                 Elf64_Rela <601028h, 300000007h, 0> ; R_X86_64_JUMP_SLOT read
LOAD:0000000000400488                 Elf64_Rela <601030h, 400000007h, 0> ; R_X86_64_JUMP_SLOT __libc_start_main
LOAD:00000000004004A0                 Elf64_Rela <601038h, 600000007h, 0> ; R_X86_64_JUMP_SLOT perror
LOAD:00000000004004B8                 Elf64_Rela <601040h, 700000007h, 0> ; R_X86_64_JUMP_SLOT exit
LOAD:00000000004004B8 LOAD            ends
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
deepin-elf-verify软件包是一个用于验证ELF文件(Executable and Linkable Format,可执行和可链接格式)的工具。ELF是一种常用的二进制文件格式,包含了可执行程序、共享库和核心转储等。该软件包提供了一组命令行工具,可以对ELF文件进行各种检查和验证。 deepin-elf-verify软件包的主要功能包括: 1. ELF文件格式验证:该软件包可以对ELF文件格式进行验证,确保文件满足规范的格式要求。它可以检查文件头部、节头部和节内容等,以确保文件结构正确。 2. 依赖库检查:ELF文件通常依赖于其他共享库文件,该软件包可以检查ELF文件所需的共享库是否存在,以及是否满足版本要求。这对于确保程序在运行时能够找到所需的库文件非常重要。 3. 符号表检查:ELF文件中包含了符号表,用于记录函数和变量的信息。该软件包可以检查符号表的正确性,包括符号是否定义、重复定义等,以确保程序在链接时能够正确解析符号。 4. 安全验证:ELF文件在加载和执行过程中,可能存在一些安全风险,如缓冲区溢出、代码注入等。该软件包可以对ELF文件进行安全验证,以确保文件没有被篡改或潜在的恶意代码。 总之,deepin-elf-verify软件包是一个强大的工具,可以帮助开发者和系统管理员验证和确保ELF文件的正确性和安全性。通过使用该软件包,我们可以更好地理解和保护我们的二进制文件

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值