11#!/usr/bin/env python3
22
3- import angr ,sys
3+ import angr
4+ import claripy
5+ import sys
46
57def main ():
6- secret_key = b""
7- sys .stdout .buffer .write (secret_key )
8+ # 1. 載入執行檔
9+ # auto_load_libs=False 可以加快速度,因為這個挑戰不需要共享函式庫的複雜互動
10+ project = angr .Project ("./chal" , auto_load_libs = False )
11+
12+ # 2. 設定符號化輸入
13+ # chal.c 中的 gate 函式期望輸入長度為 8
14+ KEY_LEN = 8
15+
16+ # 創建 KEY_LEN 個 8 位元的符號變數 (代表字元)
17+ sym_input_chars = [claripy .BVS (f'char_{ i } ' , 8 ) for i in range (KEY_LEN )]
18+ # 將這些符號字元串接成一個大的位元向量
19+ sym_stdin_bvv = claripy .Concat (* sym_input_chars )
20+
21+ # 3. 創建初始狀態
22+ # 將符號位元向量作為 stdin 傳遞給程式的入口點狀態
23+ # angr 的 SimProcedures 會模擬 fgets 從這個符號 stdin 中讀取數據
24+ initial_state = project .factory .entry_state (stdin = sym_stdin_bvv )
25+
26+ # 4. (可選) 新增限制條件
27+ # 限制每個符號字元都在可列印 ASCII 範圍內 (32 到 126)
28+ # 這有助於 angr 更快找到有意義的解,並避免非預期的字元
29+ for char_sym in sym_input_chars :
30+ initial_state .solver .add (char_sym >= 32 ) # 空格 ' '
31+ initial_state .solver .add (char_sym <= 126 ) # 波浪號 '~'
32+
33+ # 5. 創建 SimulationManager
34+ simgr = project .factory .simulation_manager (initial_state )
35+
36+ # 6. 探索路徑
37+ # 目標是找到一個狀態,其 stdout 包含 "Correct!"`
38+ # 同時,我們可以避免那些明確打印 "Wrong key!" 的路徑 (雖然不是嚴格必要,但可能加快搜索)
39+ find_condition = lambda state : b"Correct!" in state .posix .dumps (1 )
40+ avoid_condition = lambda state : b"Wrong key!" in state .posix .dumps (1 )
41+
42+ simgr .explore (find = find_condition , avoid = avoid_condition )
43+
44+ secret_key_found = b""
45+
46+ # 7. 檢查結果並解析金鑰
47+ if simgr .found :
48+ found_state = simgr .found [0 ]
49+
50+ # 從找到的狀態中,解析出每個符號字元的具體值
51+ key_parts = []
52+ for i in range (KEY_LEN ):
53+ key_parts .append (found_state .solver .eval (sym_input_chars [i ], cast_to = bytes ))
54+
55+ secret_key_found = b"" .join (key_parts )
56+
57+ # (用於本地測試調試)
58+ # sys.stderr.buffer.write(b"Found secret key: " + secret_key_found + b"\n")
59+
60+ else :
61+ # (用於本地測試調試)
62+ # sys.stderr.buffer.write(b"Could not find the secret key.\n")
63+ pass
64+
65+ # 8. 將秘密金鑰寫入 stdout
66+ # validate.sh 會讀取這個 stdout
67+ sys .stdout .buffer .write (secret_key_found )
68+ sys .stdout .buffer .flush ()
869
970
1071if __name__ == '__main__' :
11- main ()
72+ main ()
0 commit comments