ICHSA CTF 2021
zlib問題初めて触ったのでメモ
crime_cloud
次のようなサービスが動いてる。
import base64 import os import zlib def rand(n): return os.urandom(n) def xor(a,b): return bytes(x^y for x,y in zip(a,b)) def enc_otp(pt): return xor(pt, rand(len(pt))) def process(req): pt = zlib.compress(b"ICHSA_CTF{fake_flag_to_annoy_you_pay_us_ten_thousand_BTC}" + rand(32) + req) return enc_otp(pt) def main(): print("Wellcome!\nInput an empty line to exit.") while True: req = input("\nYour input: ") if len(req) == 0: print("Bye!") break req_bytes = req.encode() if len(req_bytes) > 128: print(f'Bad input length {len(req_bytes)} > 128') continue print(base64.b64encode(process(req_bytes)).decode()) if __name__ == "__main__": try: main() except: print("Some error occured")
最初はos.urandomが細工されてるのじゃないかという明後日な発想で周期を探したりしたがそんなことはなかった。
zlibについて調べるとDeflateというアルゴリズムで圧縮されているらしく、LZ77とハフマン符号を組み合わせているらしい。 LZ77は同じ文字列が複数回出現する場合、ポインタに置き換えて圧縮するらしい。 ”ICHSA_CTF{”というflagに一致する文字列と”ABDOIJGEA"みたいな適当な文字列を送ってレスポンスを見たところ、適当な文字列を送った場合のほうがレスポンスの長さが大きいことがわかった。
乱数が交じるので若干ブレがあったが大体長さが96〜97のとき正しいフラッグが得られているっぽかったので、ソースコードにちまちま追記しながらフラッグを読んだ。
import pwn import base64 import string io = pwn.remote("crime.ichsa.ctf.today", 8008) rand_initial = None previous = None first_value = None cycle_list = [] i=0 flag = "ICHSA_CTF{compressing_secret_with_input_is_a_crime" #flag = "ICHSA_CTF{" # 最初はここから初めて↑のように継ぎ足して行った。 def bt(io, flag): for i in string.ascii_lowercase + "_}": print(io.readuntil('Your input: ')) payload = flag + i io.sendline(payload) res = io.readline()[:-1] print(res) print("length: ", len(res)) zlibdata = base64.b64decode(res) print("b64decode len: ", len(zlibdata)) if len(zlibdata) in [95, 96, 97]: print(flag+i) bt(io, flag + i) else: return None bt(io, flag)
flag: ICHSA_CTF{compressing_secret_with_input_is_a_crime}
super super mario
スーパーマリオのゲームのコピー?っぽいバイナリが渡される。 各ステージの一番最後にコインでflagが書かれている。 制限時間が少なく普通に遊ぶと1面クリアが精一杯である。
バイナリを読んでいき、時間を減少させている場所をnopで埋めて、死亡処理関数をすぐreturnするように書き換えた。
< uMario: file format elf64-x86-64 --- > custom_uMario: file format elf64-x86-64 22123c22123,22125 < 53a85: 8d 50 ff lea -0x1(%rax),%edx --- > 53a85: 90 nop > 53a86: 90 nop > 53a87: 90 nop 106547c106549 < ab846: 55 push %rbp --- > ab846: c3 retq 106769c106771,106773 < abc2f: 83 e8 01 sub $0x1,%eax --- > abc2f: 90 nop > abc30: 90 nop > abc31: 90 nop
あとは普通に遊んでゴールまでたどり着いて読んでいった。
死なないのにめっちゃ苦労したとか言えない
flag: ICHSA_CTF{R3VERS1NG_IS_NO7_SCA!}