寻找Gadgets及通用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,我们可以借助工具。比较有名的工具如下:
- ROPEME: https://github.com/packz/ropeme
- Ropper: https://github.com/sashs/Ropper
- ROPgadget: https://github.com/JonathanSalwan/ROPgadget/tree/master
- rp++: https://github.com/0vercl0k/rp
例如ROPgadget的效果,我们查找文件black_hole的gadets:
通用Gadgets
其实在x64下有一些万能的gadgets可以利用。比如说我们用objdump -d ./test观察一下__libc_csu_init()这个函数。一般来说,只要程序调用了libc.so,程序都会有这个函数用来对libc进行初始化操作。
x64中的前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9中
这段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
2.再执行gad2
这些函数都可以利用
- _init
- _start
- call_gmon_start
- deregister_tm_clones
- register_tm_clones
- __do_global_dtors_aux
- frame_dummy
- __libc_csu_init
- __libc_csu_fini
- _fini