WaniCTF'21-spring writeup
WaniCTF'21-springに参加しました。
3023ptで353人中63位でした。
CTFに絶賛入門中なので、知らないツールや概念が多く勉強になりました。
こういうCTFが毎月あればかなり強くなれそうです。
あと何より多くの問題を解けたので楽しかったです(小並感)。
目次
Crypto
Simple conversion [Beginner]
問題
戻し方を忘れました…
与えられるファイル
- cry-simple-conversion.zip
解法
整数をバイト列に変換する。
def integer_to_bytes(x): x= x.to_bytes((x.bit_length() + 7) // 8, byteorder='big') return x input=int(input()) print(integer_to_bytes(input))
FLAG{7h1s_i5_h0w_we_c0nvert_m3ss@ges_1nt0_num63rs}
Easy [Easy]
問題
手始めに
与えられるファイル
- cry-easy.zip
解法
アフィン暗号なので
http://www.quipqiup.com/
を使った。
最初の4文字はFLAGであることが分かっているので指定して復号。
FLAG{WELCOMETOCRYPTOCHALLENGE}
Extra [Normal]
問題
いつものRSA?
与えられるファイル
- cry-extra.zip
解法
N, Mがわかっているので、まず2次方程式をSympyで解いてp,qを求める。
あとはRSAを復号する。解が2つあるが片方はbyteからstringへdecodeできない。
使っているpythonのバージョンが3.7だったので逆元は自分で求めた。
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes import sympy import math N=int(input()) M=int(input()) e=int(input()) c=int(input()) p=sympy.Symbol("p") sol = sympy.solve (-2*p**2 + M*p -N, p) p=int(sol[1]) q=M-2*p def xgcd(a, b): x0, y0, x1, y1 = 1, 0, 0, 1 while b != 0: q, a, b = a // b, b, a % b x0, x1 = x1, x0 - q * x1 y0, y1 = y1, y0 - q * y1 return a, x0, y0 def modinv(a, m): g, x, y = xgcd(a, m) return x % m def lcm(a, b): return a // math.gcd(a, b) * b def decrypt(c): d=modinv(e, lcm(p-1, q-1)) plaintext=pow(c, d, N) plaintext=long_to_bytes(plaintext) return plaintext if __name__ == "__main__": _plaintext = decrypt(c) print(_plaintext.decode())
FLAG{@n_ex7ra_param3ter_ru1n5_3very7h1n9}
Can't restore the flag? [Hard]
問題
ちりつもですよ
nc crt.cry.wanictf.org 50000
与えられるファイル
- cry-cant-restore-the-flag.zip
解法
サーバはflagをある数で割った余りを無限に返してくれるので、中国剰余定理を使う。
flagは以下なので300以下の素数を使えば十分。
入力は手作業でやった()
あとは出てきた数をbyteに変換する。
from functools import reduce from Crypto.Util.number import long_to_bytes def xgcd(a, b): x0, y0, x1, y1 = 1, 0, 0, 1 while b != 0: q, a, b = a // b, b, a % b x0, x1 = x1, x0 - q * x1 y0, y1 = y1, y0 - q * y1 return a, x0, y0 def modinv(a, m): g, x, y = xgcd(a, m) if g != 1: raise Exception('modular inverse does not exist') else: return x % m def chinese_remainder(a, n): # a := [a1, a2, ..., ak] # n := [n1, n2, ..., nk] total = 0 prod = reduce(lambda x, y: x*y, n) for n_i, a_i in zip(n, a): b_i = prod // n_i total += a_i * b_i * modinv(b_i, n_i) return total % prod if __name__ == "__main__": n=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293] a=[0, 2, 0, 2, 10, 7, 8, 10, 17, 17, 24, 7, 31, 30, 18, 43, 2, 31, 44, 14, 1, 50, 67, 48, 21, 54, 47, 105, 80, 43, 103, 74, 104, 83, 56, 140, 148, 13, 154, 96, 76, 162, 49, 43, 182, 168, 73, 49, 158, 39, 95, 40, 189, 206, 245, 242, 205, 67, 89, 0, 282, 222] print(long_to_bytes(chinese_remainder(a, n)).decode())
FLAG{Ch1n3s3_r3m@1nd3r_7h30r3m__so_u5eful}
Forensics
presentation [Beginner]
問題
このままじゃFLAGをプレゼンできない...
与えられるファイル
- for-presentation.zip
解法
まずpresentation.ppsxの拡張子をzipに変えて解凍してみた。
するといっぱいファイルが出てくる。
それっぽい画像ファイルがあったので、strings試したりexifとか調べたが何もない。
Beginnerから難しい問題だ……と思ったが、ppsxを開くのではなく、powerpointから開くと編集できるらしい。
青い図形を除くとフラグが現れる。
FLAG{you_know_how_to_edit_ppsx}
MixedUSB [Very hard]
問題
USBにパーティションを設定したら、どこにFLAGを保存しているのかわからなくなってしまいました...
与えられるファイル
- MixedUSB.img
解法
stringsコマンドを使うだけ。
これがVery hardな訳がないのでおそらく出題ミス。
FLAG{mixed_file_allocation_table}
Misc
binary [Beginner]
問題
文字も所詮1と0の集合です。
sample.pyを参考に復号器を作ってみてください。
与えられるファイル
- misc-binary.zip
解法
sampleの後半を少し変えるだけで復号できる。
s = "" c = 0 for i in range(336): val = int(input()) c = (c << 1) | val if i % 8 == 7: s = s + chr(c) c = 0 print(s)
FLAG{the_basic_knowledge_of_communication}
Pwn
01 netcat [Beginner]
問題
nc netcat.pwn.wanictf.org 9001
netcat (nc)と呼ばれるコマンドを使うだけです。
つないだら何も出力されなくても知っているコマンドを打ってみましょう。
使用ツール例
- netcat (nc)
解法
問題文の通りncコマンドを使って接続してcatコマンドを使う。
$ cat flag.txt FLAG{the_basic_knowledge_of_communication}
02 free hook [Easy]
問題
nc free.pwn.wanictf.org 9002
ヒント
free_hookの仕組みを理解する必要があります。
使用ツール例
- netcat (nc)
与えられるファイル
- pwn-02-free-hook.zip
解法
(pwn) kitten - HackMD
を参考にした。
親切にも__free_hookにはsystemがセットされてる。
さらに、メモを削除する際にfreeするコードになっている。
ということは/bin/shのメモを削除することで、free("/bin/sh")させればいい。
FLAG{malloc_hook_is_a_tech_for_heap_exploitation}
03 rop machine easy [Easy]
問題
nc rop-easy.pwn.wanictf.org 9003
ヒント
ropでsystem("/bin/sh")を実行して下さい。
"/bin/sh"のアドレスは提供されています
rop machineの使い方->wani-hackase/rop-machine
使用ツール例
- netcat (nc)
与えられるファイル
- pwn-03-rop-machine-easy.zip
解法
ROPを調べたら去年のWaniCTFが出てきた。
WaniCTF 2020 Writeup - m412uのメモ
- "pop rdi; ret" addr
- "/bin/sh"のアドレス
- "system" addr
の順にすればいいらしい。
FLAG{this-is-simple-return-oriented-programming}
04 rop machine normal [Easy]
問題
nc rop-normal.pwn.wanictf.org 9004
ヒント
ropでexecve("/bin/sh", 0, 0)を実行して下さい。
"/bin/sh"のアドレスは提供されています
execveのsyscall番号は0x3bです。
rop machineの使い方->wani-hackase/rop-machine
使用ツール例
- netcat (nc)
与えられるファイル
- pwn-04-rop-machine-normal.zip
解法
ヒントが意味するのは、引数を3つセットし、execveをsyscallで呼び出せということらしい。
アセンブラは忘れてしまっていたので色々調べた。
引数はrdi, rsi, rdxの順に入れるといいことが分かった。
syscallで呼び出すのはraxにsyscall番号をセットすればできる。
FLAG{now-you-can-call-any-system-calls-with-syscall}
05 rop machine hard [Normal]
問題
nc rop-hard.pwn.wanictf.org 9005
ヒント
ROPgadgetコマンドの使い方を覚えましょう。
rop machineの使い方->wani-hackase/rop-machine
使用ツール例
- netcat (nc)
- ROPgadget
与えられるファイル
- pwn-05-rop-machine-hard.zip
解法
前問同様、引数を3つセットし、execveをsyscallで呼び出すことを目指す。
残念ながらpop rdi ; retなどは与えられていないので自分で探さなくてはならない。
ROPgadgetというのはpop rdi ; retなどの場所を見つけてくれるツールらしい(参考:めちゃくちゃ遅れてきたSECCON2018 Writeup · 八階ないブログ)。
色々探してみるとそれらしいものが見つかる。
0x40128f pop rdi ; ret
0x401611 pop rsi ; pop r15 ; ret
0x40129c pop rdx ; ret
0x4012a9 pop rax ; ret
Ghidra(後述)でsyscallと"bin/sh"を探した。
0x4012b6 syscall
0x404078 "bin/sh"
pop rsi ; retはないので適当な値(今回は0xaaaaaaaa)をpopする必要がある(参考:x64 ELF Binary リモートエクスプロイト(Blind ROP) | by Ryota yaoi (nop) | Medium)。
FLAG{y0ur-next-step-is-to-use-pwntools}
Reversing
secret [Beginner]
問題
この問題では Linux の ELF 実行ファイル(バイナリ)である「secret」が配布されています。
このバイナリを実行すると secret key を入力するように表示されます。
試しに「abcde」と入力してみると「Incorrect」と言われました。
$ file secret secret: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1daf4ab43cfa357911806c3ccae34a1b6e027913, for GNU/Linux 3.2.0, not stripped $ sudo chmod +x secret $ ./secret ... Input secret key : abcde Incorrect $ ./secret ... Input secret key : ?????? Correct! Flag is ??????
このバイナリが正しいと判断する secret key を見つけて読み込んでみましょう!
(secret key とフラグは別の文字列です)
(このファイルを実行するためには Linux 環境が必要となりますので WSL や VirtualBox で用意してください)
ヒント
「表層解析」や「静的解析」を行うことで secret key が見つかるかも...?
使用ツール例
- 表層解析ツール strings
- 静的解析ツール Ghidra
与えられるファイル
- rev-secret.zip
解法
言われたとおりGhidraで解析してみる。
デコンパイルしたmainを見たところ、以下の文字列と比較していることがわかった。
wani_is_the_coolest_animals_in_the_world!
FLAG{ana1yze_4nd_strin6s_and_execu7e_6in}
execute [Easy]
問題
コマンドを間違えて、ソースコードも消しちゃった!
今残っているファイルだけで実行して頂けますか?
(reverse engineeringすれば、実行しなくても中身は分かるみたいです。)
与えられるファイル
- rev-execute.zip
解法
$ as -o main.o main.s
でオブジェクトファイルを生成。
$ gcc -shared -o main main.o libprint.so
で実行ファイルを生成。
stringsでFLAGを探すとそれっぽいのが出てくる。
FLAG{c4nH _y0u_exeH cu4e_th1H s_fi1e}
何となく最後のHを消したら通った。
FLAG{c4n_y0u_execu4e_th1s_fi1e}
timer [Hard]
問題
フラグが出てくるまで待てますか?
super_complex_flag_print_function 関数でフラグを表示しているようですが、難読化されているため静的解析でフラグを特定するのは難しそうです...
GDBを使って動的解析してみるのはいかがでしょうか?
与えられるファイル
rev-timer.zip
解法
言われた通りGDBを使った。
- timerにbreakpointを設定。
- retでtimerを抜ける。
- continueでsuper_complex_flag_print_functionを実行。
FLAG{S0rry_Hav3_you_b3en_wai7ing_lon6?_No_I_ju5t_g0t_her3}
Web
fake [Beginner]
問題文
偽物を見破れますか?
解法
開発者ツールでリンクを見つける。
https://fake.web.wanictf.org/144c9defac04969c7bfad8efaa8ea194.html
FLAG{wow_y0u_h4ve_3po4ted_th3_7ake}
Wani Request 1 [Easy]
問題文
RequestBinを使ってみよう!!
https://request1.web.wanictf.org/
この問題ではあどみんちゃんから自分のサーバにアクセスしてもらう必要があります。
自前でサーバを用意するのが難しい方はRequestBinなどのサービスを利用してみましょう。
サーバが用意出来たらいよいよ本番です。
問題ページにアクセスし、あなたが用意したサーバのURLを送信してください。
送信するとあどみんちゃんの秘密のページにあなたの送信したURLのリンクが表示されます。
あどみんちゃんは表示されたリンクをクリックしてあなたのサーバにアクセスしてくれます。
あどみんちゃんからのアクセスを分析して秘密のページを探してみてください。
ヒント
HINT1 : HTTP ヘッダー
HINT2 : xss問題ではありません。
解法
問題文に出てくるRequestBinを使った。
RequestBinで作ったURLを送信するとGETリクエストが来た。
refererにURLがあったので開いてみるとフラグがあった。
FLAG{h77p_r3f3r3r_15_54f3_42a2cc2f275}