ret2dlresolve 笔记
TOC
- 1. 前导知识
- 1.1. dlresolve
- 1.1.1. Elf32_Rel
- 1.1.2. Elf32_Sym
- 1.2. _dl_runtime_resolve(link_map, rel_offset)
- 1.2.1. 具体步骤
- 1.2.2. 手动解析
- 2. ret2dlresolve
- 2.1. 主要步骤
- 3. 绕过
- 4. 总结
- 5. ret2dl64
- 6. 其他资料
本博客内容主要借鉴自文章: bbs.pediy.com。
这里做个笔记,方便以后查阅。ret2dlresolve主要是用于32的程序,因为32的程序方便我们控制栈里面的参数,所以文章后面内容都是基于32位的glibc。
前导知识
如果我们要利用dlresolve
的话,就先必须了解dlresolve
的原理。
dlresolve
首先我们需要了解两个结构体,在进行动态链接的时候,主要是通过这连个结构体进行解析的。
Elf32_Rel
typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; } Elf32_Rel;
|
用IDA查看一下他的布局。
00000000 Elf32_Rel struc ; (sizeof=0x8, align=0x4, copyof_2) 00000000 r_offset dd ? 00000004 r_info dd ? 00000008 Elf32_Rel ends
|
可以看到这里主要是8个字节。
Elf32_Sym
typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Section st_shndx; }Elf32_Sym;
|
用IDA查看一下他的布局。
00000000 Elf32_Sym struc ; (sizeof=0x10, align=0x4, mappedto_1) 00000000 st_name dd ? 00000004 st_value dd ? 00000008 st_size dd ? 0000000C st_info db ? 0000000D st_other db ? 0000000E st_shndx dw ? 00000010 Elf32_Sym ends
|
这里总共是16个字节。
_dl_runtime_resolve(link_map, rel_offset)
第一个参数,[0x804a004]是一个link_map的指针,这个结构是干什么的,我们不关心,但是有一点要知道,它包含了.dynamic的指针,通过这个link_map,_dl_runtime_resolve函数可以访问到.dynamic这个section。
第二个参数,是当前要调用的导入函数在.rel.plt中的偏移(不过64位的话就直接是index下标)。
接下来然我们看看一个程序的一些表的位置,可以用命令readelf -S 程序
进查看,下面是运行的结果。
ex@Ex:~/test$ readelf -S helloworld There are 30 section headers, starting at offset 0xe78:
Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048134 000134 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048148 000148 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048168 000168 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0804818c 00018c 000020 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481ac 0001ac 000050 10 A 6 1 4 [ 6] .dynstr STRTAB 080481fc 0001fc 00004a 00 A 0 0 1 [ 7] .gnu.version VERSYM 08048246 000246 00000a 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 08048250 000250 000020 00 A 6 1 4 [ 9] .rel.dyn REL 08048270 000270 000008 08 A 5 0 4 [10] .rel.plt REL 08048278 000278 000010 08 AI 5 23 4 [11] .init PROGBITS 08048288 000288 000023 00 AX 0 0 4 [12] .plt PROGBITS 080482b0 0002b0 000030 04 AX 0 0 16 [13] .plt.got PROGBITS 080482e0 0002e0 000008 08 AX 0 0 8 [14] .text PROGBITS 080482f0 0002f0 0001c2 00 AX 0 0 16 [15] .fini PROGBITS 080484b4 0004b4 000014 00 AX 0 0 4 [16] .rodata PROGBITS 080484c8 0004c8 000014 00 A 0 0 4 [17] .eh_frame_hdr PROGBITS 080484dc 0004dc 000044 00 A 0 0 4 [18] .eh_frame PROGBITS 08048520 000520 000110 00 A 0 0 4 [19] .init_array INIT_ARRAY 08049630 000630 000004 04 WA 0 0 4 [20] .fini_array FINI_ARRAY 08049634 000634 000004 04 WA 0 0 4 [21] .dynamic DYNAMIC 08049638 000638 0000e8 08 WA 6 0 4 [22] .got PROGBITS 08049720 000720 000004 04 WA 0 0 4 [23] .got.plt PROGBITS 08049724 000724 000014 04 WA 0 0 4 [24] .data PROGBITS 08049738 000738 000008 00 WA 0 0 4 [25] .bss NOBITS 08049740 000740 000004 00 WA 0 0 1 [26] .comment PROGBITS 00000000 000740 000029 01 MS 0 0 1 [27] .symtab SYMTAB 00000000 00076c 000410 10 28 44 4 [28] .strtab STRTAB 00000000 000b7c 0001f7 00 0 0 1 [29] .shstrtab STRTAB 00000000 000d73 000105 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude),
|
注意这里我们要重点关注 .rel.plt 、.dynsym 、 .dynstr 的值。
具体步骤
- 用link_map访问.dynamic,取出.dynstr, .dynsym, .rel.plt的指针
- .rel.plt + 第二个参数求出当前函数的重定位表项Elf32_Rel的指针,记作rel
- rel->r_info >> 8作为.dynsym的下标,求出当前函数的符号表项Elf32_Sym的指针,记作sym
- .dynstr + sym->st_name得出符号名字符串指针
- 在动态链接库查找这个函数的地址,并且把地址赋值给*rel->r_offset,即GOT表
- 调用这个函数
就相当于下面的调用结果:
_dl_runtime_resolve(link_map, rel_offset);
|
根据rel_offset找到rel _entry:(JMPREL就是.rel.plt
的地址)
Elf32_Rel * rel_entry = JMPREL + rel_offset;
|
由rel_entry->r_info定位符号信息,SYMTAB是表示的是结构体Elf32_Sym
的一个数组,而这个数组的基地址就是 .dynsym
。
Elf32_Sym *sym_entry = SYMTAB[ELF32_R_SYM(rel_entry->r_info)];
|
再定位符号信息中的符号名,STRTAB是.dynstr
的地址,也就是说所有的程序名字的寻址,都是通过这个地址进行偏移的。
char *sym_name = STRTAB + sym_entry->st_name;
|
根据得到的符号名搜索动态库,找到地址后填充至.got.plt对应位置。
手动解析
这么多概念性的东西,正常人一般都会看的比较云里雾里。这时候就需要我们自己动手解析一遍了。
在手动解析之前,我么必须要知道 .rel.plt 、.dynsym 、 .dynstr 的值。用readelf命令来获取。
ex@Ex:~/test$ readelf -S helloworld There are 30 section headers, starting at offset 0xe78:
Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048134 000134 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048148 000148 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048168 000168 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0804818c 00018c 000020 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481ac 0001ac 000050 10 A 6 1 4 [ 6] .dynstr STRTAB 080481fc 0001fc 00004a 00 A 0 0 1 [ 7] .gnu.version VERSYM 08048246 000246 00000a 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 08048250 000250 000020 00 A 6 1 4 [ 9] .rel.dyn REL 08048270 000270 000008 08 A 5 0 4 [10] .rel.plt REL 08048278 000278 000010 08 AI 5 23 4 [11] .init PROGBITS 08048288 000288 000023 00 AX 0 0 4 [12] .plt PROGBITS 080482b0 0002b0 000030 04 AX 0 0 16 [13] .plt.got PROGBITS 080482e0 0002e0 000008 08 AX 0 0 8 [14] .text PROGBITS 080482f0 0002f0 0001c2 00 AX 0 0 16 [15] .fini PROGBITS 080484b4 0004b4 000014 00 AX 0 0 4 [16] .rodata PROGBITS 080484c8 0004c8 000014 00 A 0 0 4 [17] .eh_frame_hdr PROGBITS 080484dc 0004dc 000044 00 A 0 0 4 [18] .eh_frame PROGBITS 08048520 000520 000110 00 A 0 0 4 [19] .init_array INIT_ARRAY 08049630 000630 000004 04 WA 0 0 4 [20] .fini_array FINI_ARRAY 08049634 000634 000004 04 WA 0 0 4 [21] .dynamic DYNAMIC 08049638 000638 0000e8 08 WA 6 0 4 [22] .got PROGBITS 08049720 000720 000004 04 WA 0 0 4 [23] .got.plt PROGBITS 08049724 000724 000014 04 WA 0 0 4 [24] .data PROGBITS 08049738 000738 000008 00 WA 0 0 4 [25] .bss NOBITS 08049740 000740 000004 00 WA 0 0 1 [26] .comment PROGBITS 00000000 000740 000029 01 MS 0 0 1 [27] .symtab SYMTAB 00000000 00076c 000410 10 28 44 4 [28] .strtab STRTAB 00000000 000b7c 0001f7 00 0 0 1 [29] .shstrtab STRTAB 00000000 000d73 000105 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude),
|
从上面可得 .rel.plt 的值是0x08048278
、.dynsym 的值是0x080481ac
、 .dynstr 的值是0x080481fc
。
下面是我们要实验的代码:
; int __cdecl main(int argc, const char **argv, const char **envp) public main main proc near
argc= dword ptr 8 argv= dword ptr 0Ch envp= dword ptr 10h
lea ecx, [esp+4] and esp, 0FFFFFFF0h push dword ptr [ecx-4] push ebp mov ebp, esp push ebx push ecx call __x86_get_pc_thunk_ax add eax, 130Ah sub esp, 0Ch lea edx, (aHelloWorld - 8049724h)[eax] ; "hello world" push edx mov ebx, eax call _puts add esp, 10h mov eax, 0 lea esp, [ebp-8] pop ecx pop ebx pop ebp lea esp, [ecx-4] retn main endp
|
我们在call _puts
出下断点,然后在_dl_runtime_resolve
出下来。
pwndbg> 0x0804842b in main () LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ─────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────── EAX 0x8049724 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049638 (_DYNAMIC) ◂— 0x1 EBX 0x8049724 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049638 (_DYNAMIC) ◂— 0x1 ECX 0xffffcd70 ◂— 0x1 EDX 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ EDI 0x0 ESI 0xf7fae000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d6c EBP 0xffffcd58 ◂— 0x0 ESP 0xffffcd40 —▸ 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ EIP 0x804842b (main+37) —▸ 0xfffe90e8 ◂— 0x0 ──────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────── 0x804841a <main+20> add eax, 0x130a 0x804841f <main+25> sub esp, 0xc 0x8048422 <main+28> lea edx, [eax - 0x1254] 0x8048428 <main+34> push edx 0x8048429 <main+35> mov ebx, eax ► 0x804842b <main+37> call puts@plt <0x80482c0> s: 0x80484d0 ◂— 'hello world' 0x8048430 <main+42> add esp, 0x10 0x8048433 <main+45> mov eax, 0 0x8048438 <main+50> lea esp, [ebp - 8] 0x804843b <main+53> pop ecx 0x804843c <main+54> pop ebx ───────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────── 00:0000│ esp 0xffffcd40 —▸ 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ 01:0004│ 0xffffcd44 —▸ 0xffffce04 —▸ 0xffffcff6 ◂— '/home/ex/test/helloworld' 02:0008│ 0xffffcd48 —▸ 0xffffce0c —▸ 0xffffd00f ◂— 'CLUTTER_IM_MODULE=xim' 03:000c│ 0xffffcd4c —▸ 0x804841a (main+20) ◂— add eax, 0x130a 04:0010│ 0xffffcd50 —▸ 0xffffcd70 ◂— 0x1 05:0014│ 0xffffcd54 ◂— 0x0 ... ↓ 07:001c│ 0xffffcd5c —▸ 0xf7deee81 (__libc_start_main+241) ◂— add esp, 0x10 ─────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────── ► f 0 804842b main+37 f 1 f7deee81 __libc_start_main+241 pwndbg> si 0x080482c0 in puts@plt () LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ─────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────── EAX 0x8049724 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049638 (_DYNAMIC) ◂— 0x1 EBX 0x8049724 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049638 (_DYNAMIC) ◂— 0x1 ECX 0xffffcd70 ◂— 0x1 EDX 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ EDI 0x0 ESI 0xf7fae000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d6c EBP 0xffffcd58 ◂— 0x0 ESP 0xffffcd3c —▸ 0x8048430 (main+42) ◂— add esp, 0x10 EIP 0x80482c0 (puts@plt) ◂— jmp dword ptr [0x8049730] ──────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────── ► 0x80482c0 <puts@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_+12] <0x8049730> 0x80482c6 <puts@plt+6> push 0 0x80482cb <puts@plt+11> jmp 0x80482b0 ↓ 0x80482b0 push dword ptr [_GLOBAL_OFFSET_TABLE_+4] <0x8049728> 0x80482b6 jmp dword ptr [0x804972c] <0xf7feae10> ↓ 0xf7feae10 <_dl_runtime_resolve> push eax 0xf7feae11 <_dl_runtime_resolve+1> push ecx 0xf7feae12 <_dl_runtime_resolve+2> push edx 0xf7feae13 <_dl_runtime_resolve+3> mov edx, dword ptr [esp + 0x10] 0xf7feae17 <_dl_runtime_resolve+7> mov eax, dword ptr [esp + 0xc] 0xf7feae1b <_dl_runtime_resolve+11> call _dl_fixup <0xf7fe4f40> ───────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────── 00:0000│ esp 0xffffcd3c —▸ 0x8048430 (main+42) ◂— add esp, 0x10 01:0004│ 0xffffcd40 —▸ 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ 02:0008│ 0xffffcd44 —▸ 0xffffce04 —▸ 0xffffcff6 ◂— '/home/ex/test/helloworld' 03:000c│ 0xffffcd48 —▸ 0xffffce0c —▸ 0xffffd00f ◂— 'CLUTTER_IM_MODULE=xim' 04:0010│ 0xffffcd4c —▸ 0x804841a (main+20) ◂— add eax, 0x130a 05:0014│ 0xffffcd50 —▸ 0xffffcd70 ◂— 0x1 06:0018│ 0xffffcd54 ◂— 0x0 ... ↓ ─────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────── ► f 0 80482c0 puts@plt f 1 8048430 main+42 f 2 f7deee81 __libc_start_main+241 pwndbg> b _dl_runtime_resolve Breakpoint 2 at 0xf7feae10: file ../sysdeps/i386/dl-trampoline.S, line 35. pwndbg> c Continuing.
Breakpoint 2, _dl_runtime_resolve () at ../sysdeps/i386/dl-trampoline.S:35 35 ../sysdeps/i386/dl-trampoline.S: No such file or directory. LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ─────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────── EAX 0x8049724 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049638 (_DYNAMIC) ◂— 0x1 EBX 0x8049724 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049638 (_DYNAMIC) ◂— 0x1 ECX 0xffffcd70 ◂— 0x1 EDX 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ EDI 0x0 ESI 0xf7fae000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d6c EBP 0xffffcd58 ◂— 0x0 ESP 0xffffcd34 —▸ 0xf7ffd940 ◂— 0x0 EIP 0xf7feae10 (_dl_runtime_resolve) ◂— push eax ──────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────── 0x80482c0 <puts@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_+12] <0x8049730> 0x80482c6 <puts@plt+6> push 0 0x80482cb <puts@plt+11> jmp 0x80482b0 ↓ 0x80482b0 push dword ptr [_GLOBAL_OFFSET_TABLE_+4] <0x8049728> 0x80482b6 jmp dword ptr [0x804972c] <0xf7feae10> ↓ ► 0xf7feae10 <_dl_runtime_resolve> push eax <0x8049724> 0xf7feae11 <_dl_runtime_resolve+1> push ecx 0xf7feae12 <_dl_runtime_resolve+2> push edx 0xf7feae13 <_dl_runtime_resolve+3> mov edx, dword ptr [esp + 0x10] 0xf7feae17 <_dl_runtime_resolve+7> mov eax, dword ptr [esp + 0xc] 0xf7feae1b <_dl_runtime_resolve+11> call _dl_fixup <0xf7fe4f40> ───────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────── 00:0000│ esp 0xffffcd34 —▸ 0xf7ffd940 ◂— 0x0 01:0004│ 0xffffcd38 ◂— 0x0 02:0008│ 0xffffcd3c —▸ 0x8048430 (main+42) ◂— add esp, 0x10 03:000c│ 0xffffcd40 —▸ 0x80484d0 ◂— push 0x6f6c6c65 /* 'hello world' */ 04:0010│ 0xffffcd44 —▸ 0xffffce04 —▸ 0xffffcff6 ◂— '/home/ex/test/helloworld' 05:0014│ 0xffffcd48 —▸ 0xffffce0c —▸ 0xffffd00f ◂— 'CLUTTER_IM_MODULE=xim' 06:0018│ 0xffffcd4c —▸ 0x804841a (main+20) ◂— add eax, 0x130a 07:001c│ 0xffffcd50 —▸ 0xffffcd70 ◂— 0x1 ─────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────── ► f 0 f7feae10 _dl_runtime_resolve f 1 8048430 main+42 f 2 f7deee81 __libc_start_main+241 Breakpoint _dl_runtime_resolve pwndbg>
|
可以从上面的调试代的栈中看出,link_map
的值是0xf7ffd940
,而rel_offset
的值是0
。
00:0000│ esp 0xffffcd34 —▸ 0xf7ffd940 ◂— 0x0 01:0004│ 0xffffcd38 ◂— 0x0
|
接下来我们就来手动解析一遍,首先找到对应的Elf32_Rel
,也就是重定向表,用Elf32_Rel * rel_entry = JMPREL + rel_offset;
公式进行查找。也就是相对于.rel.plt 的值(0x08048278)的偏移。其结果如下:
Breakpoint _dl_runtime_resolve pwndbg> p *(Elf32_Rel *)(0x08048278 + 0x0) $1 = { r_offset = 134518576, r_info = 263 }
|
然后找到对应的Elf32_Sym
,也就是符号表,用Elf32_Sym *sym_entry = SYMTAB[ELF32_R_SYM(rel_entry->r_info)];
公式进行查找。SYMTAB是相对于.dynsym 的值(0x080481ac)的数组偏移,而ELF32_R_SYM
就可以看成是将值向右移8位,也就是不要最后字节。其结果如下:
pwndbg> p ((Elf32_Sym *)0x080481ac)[ 263>>8 ] $2 = { st_name = 26, st_value = 0, st_size = 0, st_info = 18 '\022', st_other = 0 '\000', st_shndx = 0 }
|
最后我们通过char *sym_name = STRTAB + sym_entry->st_name;
能找到我们对应的函数名字符串了,STRTAB的值就是 .dynstr 的值(0x080481fc)。其结果如下:
pwndbg> p (char *)(0x080481fc + 26) $3 = 0x8048216 "puts"
|
到此我们完成了一次手动解析。
ret2dlresolve
当你知道dlresolve原理
之后,其实进行ret2dlresolve
操作也就是不难了,主要是通过控制程序流,来构建假的Elf32_Rel
和假的Elf32_Sym
,然后让_dl_runtime_resolve
函数解析我们自己的字符串,比如system
字符串,这样我们就可以直接调用system函数来拿shell。
主要步骤
- 通过将eip覆盖为
_dl_runtime_resolve
地址,rel_offset参数我们要实先构造号,让它能通过 .rel.plt地址 的偏移找到假的Elf32_Rel
。
- 伪造 rel_entry 使 sym_entry落在可控区域,伪造 sym_entry 使 sym_name 落在可控区域;
- 伪造sym_name为‘system’
光这么看是比较难理解这个漏洞的,理解这个漏洞最好的办法就是手动构造一遍。
绕过
在执行ret2dl-solve时,还有一点必须绕过,那就是.gnu.version
+ELF32_R_SYM(rel_entry->r_info) * 2
必须是一个较小的值,否则下面的代码就会执行错误。
In file: /glibc/glibc-2.23/elf/dl-runtime.c 87 if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL) 88 { 89 const ElfW(Half) *vernum = 90 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]); 91 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff; ► 92 version = &l->l_versions[ndx]; 93 if (version->hash == 0) 94 version = NULL; 95 }
|
总结
仅仅是光看文章来理解ret2dlresolve
的话是很困难的,最好能动手操作一下。
ret2dl64
下面是ret2dl64的实例代码,原理就是伪造 link_map 来进行地址偏移后调用。
layout = [ 0, 0x601230, 0, 0x601230 , 0 , 0x601230, libc.bss() - libc.symbols['__libc_start_main'], p32(0x7), p32(1), 0, (p32(0), p8(0), p8(1), p16(0), (libc.symbols['system'] - libc.symbols['__libc_start_main'] + 0x10 ** 16) % (0x10 ** 16), 0), ]
sh.send(flat(layout))
sh.interactive()
|
一般为了方便 rel_offset 设置为0。
0x7ffff7de4dfe <_dl_fixup+14> mov rax, qword ptr [rdi + 0x68] ► 0x7ffff7de4e02 <_dl_fixup+18> mov rdi, qword ptr [rax + 8] 0x7ffff7de4e06 <_dl_fixup+22> mov rax, qword ptr [r10 + 0xf8] 0x7ffff7de4e0d <_dl_fixup+29> mov rax, qword ptr [rax + 8] 0x7ffff7de4e11 <_dl_fixup+33> lea r8, [rax + rdx*8] 0x7ffff7de4e15 <_dl_fixup+37> mov rax, qword ptr [r10 + 0x70] 0x7ffff7de4e19 <_dl_fixup+41> mov rcx, qword ptr [r8 + 8]
|
上面这些我们要注意的值,对应的结构如下:
[val_0x68+8]==STRTAB dynstr [val_0x70+8]==SYMTAB dynsym [val_0xf8+8]==JMPREL rel_plt
|
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
对应上面的 p32(0x7), p32(1)
,其中7是magic,1是symtab的数据偏移。
其他资料