picoCTF 2021 writeup (Reversing)
picoCTF 2021 の Rev 問題の Writeup.
難易度 medium のみ
crackme-py
- Python ファイルが配られる
decode_secret()
という関数と暗号化されたフラグらしきbezos_cc_secret
という変数が存在- 試しに以下のコードを回したところフラグが出てきた
decode_secret(bezos_cc_secret)
keygenme-py
- Python ファイルが配られる
- コードを読むとキーの部分が 3 つのパートに分かれており, 真ん中のパート (
key_part_dynamic1_trial
) が伏字になっている check_key
関数でキーの比較をしているようなので, 同じ処理を行いキーを復元するとフラグになった
sha_key = hashlib.sha256(bUsername_trial).hexdigest() trial_key = key_part_static1_trial + sha_key[4] + sha_key[5] + sha_key[3] + sha_key[6] + sha_key[2] + sha_key[7] + sha_key[1] + sha_key[8] + "}"
Shop
- 32 bit 実行ファイルが渡される
- Ubuntu 環境で実行するとどれかのアイテムを購入することができるプログラムになっていた
- objdump などで調べてみたが中身を調べてロジックを理解するのは簡単ではなさそう
- 試しに購入時に負の数を品数として指定してみると在庫が増え, コインも増えた
- 自分の持ち金より大きい額のものは購入できなかったりする制約があったので, いくつか試行錯誤した結果フラグの 16 進数リストが得られた
from pwn import * host = "mercury.picoctf.net" port = 37799 sh = remote(host, port) prompt = sh.recvuntil("option:") print(prompt.decode()) sh.sendline("0".encode()) sh.sendline("-100".encode()) prompt = sh.recvuntil("option:") print(prompt.decode()) sh.sendline("2".encode()) sh.sendline("-100".encode()) prompt = sh.recvuntil("is:") print(prompt.decode()) flag_list = sh.recvline().decode().split() flag = "" for ch_hex in flag_list: flag += chr(int(ch_hex.lstrip("[").rstrip("]"))) print("flag:", flag) sh.interactive()
speeds and feeds
- nc コマンドでサーバーに接続すると文字列が送られてきた
- G や X, Y があることから NC 旋盤を動かすプログラムである G-Code であることが推測されるため, シミュレーターに突っ込むとフラグが獲得できた
ARMssembly0
- ARM アセンブリのファイルが渡される
- 入力引数二つに対して出力される数字が何になるか答えればよいらしい
- ヒントより単純な比較プログラムらしい
- func1 において cmp 命令が用いられている
- cmp の次の行の bls 命令は比較して小さい場合に分岐する命令であるため, おそらく小さいほうの数を返すプログラムであると考えられる
- 小さいほうの数字を hex 形式にしてフラグに入れるとクリアできた
ARMssembly1
- ARM アセンブリが渡される
- 入力引数を当てる問題
- ソースコードを読むと, func1 について, 論理左シフトを用いた演算がされており, 結果と入力引数が一致すれば win となるので, func1 の処理で生成される数字がフラグとなることが分かる
- func1 の処理を Python で書き下すしてフラグを獲得 (出力について 32 bit の hex にして形式を整えることを忘れずに)
w0 = 7 w1 = 79 w1 = w1 << w0 w0 = 3 w1 = w1 // w0 print("flag:", hex(w1)[2::])