文章目录
  1. 1. 寻找Gadgets
  2. 2. 通用Gadgets

寻找Gadgets

x86中参数都是保存在栈上,但在x64中前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9寄存器里,如果还有更多的参数的话才会保存在栈上。所以我们需要寻找一些类似于pop rdi; ret的这种gadget。如果是简单的gadgets,我们可以通过objdump来查找。比如objdump -d black_hole(文件名)后我们找到了类似于pop rdi;ret的gadget。

对于复杂的一些gadgets,我们可以借助工具。比较有名的工具如下:

  1. ROPEME: https://github.com/packz/ropeme
  2. Ropper: https://github.com/sashs/Ropper
  3. ROPgadget: https://github.com/JonathanSalwan/ROPgadget/tree/master
  4. rp++: https://github.com/0vercl0k/rp

例如ROPgadget的效果,我们查找文件black_hole的gadets:

通用Gadgets

其实在x64下有一些万能的gadgets可以利用。比如说我们用objdump -d ./test观察一下__libc_csu_init()这个函数。一般来说,只要程序调用了libc.so,程序都会有这个函数用来对libc进行初始化操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
.text:0000000000400840 ; =============== S U B R O U T I N E =======================================
.text:0000000000400840
.text:0000000000400840
.text:0000000000400840 public __libc_csu_init
.text:0000000000400840 __libc_csu_init proc near ; DATA XREF: _start+16o
.text:0000000000400840 push r15
.text:0000000000400842 mov r15d, edi
.text:0000000000400845 push r14
.text:0000000000400847 mov r14, rsi
.text:000000000040084A push r13
.text:000000000040084C mov r13, rdx
.text:000000000040084F push r12
.text:0000000000400851 lea r12, __frame_dummy_init_array_entry
.text:0000000000400858 push rbp
.text:0000000000400859 lea rbp, __do_global_dtors_aux_fini_array_entry
.text:0000000000400860 push rbx
.text:0000000000400861 sub rbp, r12
.text:0000000000400864 xor ebx, ebx
.text:0000000000400866 sar rbp, 3
.text:000000000040086A sub rsp, 8
.text:000000000040086E call _init_proc
.text:0000000000400873 test rbp, rbp
.text:0000000000400876 jz short loc_400896
.text:0000000000400878 nop dword ptr [rax+rax+00000000h]
.text:0000000000400880
.text:0000000000400880 loc_400880: ; CODE XREF: __libc_csu_init+54j
.text:0000000000400880 mov rdx, r13
.text:0000000000400883 mov rsi, r14
.text:0000000000400886 mov edi, r15d
.text:0000000000400889 call qword ptr [r12+rbx*8]
.text:000000000040088D add rbx, 1
.text:0000000000400891 cmp rbx, rbp
.text:0000000000400894 jnz short loc_400880
.text:0000000000400896
.text:0000000000400896 loc_400896: ; CODE XREF: __libc_csu_init+36j
.text:0000000000400896 add rsp, 8
.text:000000000040089A pop rbx
.text:000000000040089B pop rbp
.text:000000000040089C pop r12
.text:000000000040089E pop r13
.text:00000000004008A0 pop r14
.text:00000000004008A2 pop r15
.text:00000000004008A4 retn
.text:00000000004008A4 __libc_csu_init endp
.text:00000000004008A4
.text:00000000004008A4 ; ---------------------------------------------------------------------------

x64中的前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9中

1
2
3
4
5
6
7
r13=rdx=arg3
r14=rsi=arg2
r15d=edi=arg1
r12=call address

这段gadgets用于在X64下进行rop,根本原因是X64使用寄存器传参无法直接用栈进行rop。具体用法如下:

分为两部分使用,利用这些gates可以把r12-r15控好,call qword ptr [r12+rbx8]的时候可以将rbp等于1,rbx等于0才能继续ret下去。(执行完call qword ptr [r12+rbx8]之后,程序会对rbx+=1,然后对比rbp和rbx的值,如果相等就会继续向下执行并ret到我们想要继续执行的地址。所以为了让rbp和rbx的值相等,我们可以将rbp的值设置为1,因为之前已经将rbx的值设置为0了)

1.执行gad1

1
2
3
4
5
6
7
.text:000000000040089A pop rbx 必须为0
.text:000000000040089B pop rbp 必须为1
.text:000000000040089C pop r12 call!!!!
.text:000000000040089E pop r13 arg3
.text:00000000004008A0 pop r14 arg2
.text:00000000004008A2 pop r15 arg1
.text:00000000004008A4 retn ——> to gad2

2.再执行gad2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.text:0000000000400880 mov rdx, r13
.text:0000000000400883 mov rsi, r14
.text:0000000000400886 mov edi, r15d
.text:0000000000400889 call qword ptr [r12+rbx*8] call!!!
.text:000000000040088D add rbx, 1
.text:0000000000400891 cmp rbx, rbp
.text:0000000000400894 jnz short loc_400880
.text:0000000000400896 add rsp, 8
.text:000000000040089A pop rbx
.text:000000000040089B pop rbp
.text:000000000040089C pop r12
.text:000000000040089E pop r13
.text:00000000004008A0 pop r14
.text:00000000004008A2 pop r15
.text:00000000004008A4 retn ——> 构造一些垫板(7*8=56byte)就返回了

这些函数都可以利用

  1. _init
  2. _start
  3. call_gmon_start
  4. deregister_tm_clones
  5. register_tm_clones
  6. __do_global_dtors_aux
  7. frame_dummy
  8. __libc_csu_init
  9. __libc_csu_fini
  10. _fini
文章目录
  1. 1. 寻找Gadgets
  2. 2. 通用Gadgets