ROP(x64)
(学习记录)跟着蒸米学ROP
- JarvisOJ-Pwn-level0
- JarvisOJ-Pwn-level2_x64
- JarvisOJ-Pwn-level3_x64
- JarvisOJ-Pwn-level5
原理
待施工
题目
JarvisOJ level0
发现callsystem函数,函数地址为0x400596,对应的小端序为:\x96\x05\x40\x00;于是可以构造payload=0x88*‘a’ + “\x96\x05\x40\x00”,于是用pwntools编写攻击代码
1 | from pwn import * |
JarvisOJ level2_x64
由于x64并不直接由栈传参,而是通过寄存器,所以这道题目和x86最大的不同在于要找到pop rdi; ret这个gadget,首先通过ROPgadget查找pop rdi; ret。
1 | nick@nick-machine:~/wyx/JarvisOJ-pwn-level2_x64$ ROPgadget --binary level2_x64 --only "pop|ret" |
可以看到pop rdi; ret的地址为0x00000000004006b3,所以编写exp.py函数如下
1 | from pwn import * |
JarvisOJ level3_x64
没有找到pop rsi; pop rdi; pop rdx; ret的gadgets,就用一个pop rsi; ret和一个pop rdi; pop r15; ret
1 | from pwn import * |
JarvisOJ level5
由于mmap需要的参数过多,很难找到符合条件的gadgets。参考其他大佬的做法是,先将shellcode写到.bss段,然后用函数mprotect修改.bss段的权限,使其可执行。由此,基本思路是,首先泄露内存地址,然后调用read(0,bss_addr,0x100)将shellcode写入.bss段,然后调用mprotect(0x600000,0x1000,7)修改.bss段的权限,最后执行shellcode即可。
1 | from pwn import * |
在上述实现代码中,构造gadget的时候,首先通过pop rdi,ret和pop rsi,pop r15,ret泄露地址,然后得到libc的基质,然后通过libc中的pop rdx,ret传递第三个参数,执行mprotect()。除此之外,还可以通过__libc_csu_init中的代码构造gadget,可利用的代码部分如下
1 | 0x0000000000400690 <+64>: mov rdx,r13 |
首先调用0x00000000004006aa处的gadget,再调用0x0000000000400690处的gadget。由此可以实现对rdi、rsi、rdx三个寄存器赋值,并且跳转到r12+rbx*8处执行。实现代码如下