# 2025-12-04_"Leaked Flag Checker": 251217 {%preview https://alpacahack.com/daily/challenges/leaked-flag-checker %} answer: Alpaca{lucky} Level: Easy Type: Rev solved day: 2025,12,17 ## solution ```python with open('challenge', 'rb') as f: binary_data = f.read() prefix_xor = b'|krdl~z' offset = binary_data.find(prefix_xor) if offset == -1: print("Not found") else: print(f"found in {offset}") encrypted_flag = b'' current_offset = offset while current_offset < len(binary_data) and binary_data[current_offset] != 0: encrypted_flag += binary_data[current_offset:current_offset+1] current_offset += 1 print(f"encrypted byte sequence: {encrypted_flag}") print(f"len: {len(encrypted_flag)}") decoded_flag = "" for byte in encrypted_flag: decoded_flag += chr(byte ^ 7) print(f"flag: Alpaca{decoded_flag}") ``` ``` >>> python solution.py found in 4628 encrypted byte sequence: b'|krdl~z' len: 7 flag: Alpaca{lucky} ``` ## 解説 このチャレンジの解法は、提供されたC言語のソースコードを読み解くことから始まります。 `challenge.c` を見ると、プログラムのロジックは非常にシンプルです。ユーザーが入力した文字列を1文字ずつ取り、**7でXOR(排他的論理和)した結果**が、プログラム内部に保持されている `xor_flag` という文字列と一致するかを調べています。 つまり、フラグを復元するには、バイナリファイル `challenge` にハードコードされている `xor_flag` の内容を特定し、その各バイトを再度7でXORすればよいことになります。 ### バイナリからのフラグ抽出 `strings` コマンドでもある程度の情報は得られますが、暗号化されたデータの中にNULLバイト(`\x00`)のような「表示できない文字」が含まれていると、そこで文字列が途切れてしまい、完全なフラグを取得できない可能性があります。 そこで、より確実な方法として、Pythonスクリプトでバイナリファイルを直接バイト列として解析します。手順は以下の通りです。 1. **フラグの接頭辞を特定する**: CTFのフラグ形式は `Alpaca{...}` であることがわかっています(解答入力欄参照)。この接頭辞 `Alpaca{` を、プログラムのロジック通り7でXORすると `|krdl~z` というバイト列になります。 2. **バイナリ内を探索する**: この `|krdl~z` という特徴的なバイト列を、バイナリデータの中から探し出します。ここが暗号化されたフラグの開始位置です。 3. **フラグの終端までを読み取る**: C言語の文字列は通常NULLバイト(`\x00`)で終端されます。そのため、発見した開始位置から1バイトずつ読み進め、NULLバイトに到達するまでを暗号化されたフラグの全体として抽出します。 4. **復号する**: 最後に、抽出したバイト列の各バイトを7でXORすることで、元のフラグを復元します。 この方法で完全なフラグ `Alpaca{lucky}` を確実に取り出すことができました。単純なXOR暗号と、バイナリからのデータ抽出という、Reversingの基本的なテクニックが問われる良い問題でした。