Hack The Box(HTB) - CTF Try Out : Don't Panic! Walkthrough

 Hack The Box(HTB) - CTF Try Out : Don't Panic! Walkthrough


又是一題僅有檔案的 CTF



檔案下載後一樣僅有一個檔案



一樣是個 ELF 檔案,這一次 strings 沒有任何 HTB 字眼



執行看看,輸入 yes or no 都讓他恐慌



參考這一篇 : https://medium.com/@ranachouchen4/hackthebox-dont-panic-reverse-engineering-writeup-897bcc6cd809


編寫一個 python code 如下

import pexpect
import re
import string
import random

# Initial random flag (HTB format + 27 random letters)
flag = "HTB{111111111111111111111111111"
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
# Regex to extract character from disassembled cmp line
cmp_re = re.compile(r"cmp\s+\$?0x([0-9a-fA-F]+).*%dil", re.IGNORECASE)
for i in range(31):
gdb = pexpect.spawn("gdb -q ./dontpanic", encoding="utf-8", timeout=3)
gdb.expect_exact("(gdb)")
gdb.sendline("b src::check_flag")
gdb.expect_exact("(gdb)")
gdb.sendline("run")
gdb.expect(r"Have you got a message for me\?")
gdb.sendline(flag) # Send current flag
gdb.expect_exact("Breakpoint 1") # Wait until we hit the breakpoint
gdb.expect_exact("(gdb)")
steps = 63 + i * 12
for j in range(steps):
gdb.sendline("si")
gdb.expect("(gdb)")
gdb.sendline("disas")
gdb.expect_exact("(gdb)")
output = gdb.before
output = ansi_escape.sub('', output)
match = cmp_re.search(output)
if match:
byte = int(match.group(1), 16)
flag_list = list(flag)
flag_list[i] = chr(byte)
flag = "".join(flag_list)
print(f"Found char at position {i}: {flag[i]}")
else:
print(f"Failed to extract char at position {i}")

gdb.close()

print("Recovered flag:", "".join(flag))


執行後如下獲取 flag : HTB{d0nt_p4n1c_c4tch_the_3rror}




原理說明 :

想像這程式像一台自動驗證輸入的機器,它會一個字一個字地比對你輸入的 flag 對不對。只要有一個字不對,它就會「驚慌失措」地說:

😱 You made me panic!


 我們的目標是:

找出正確的 flag,每個位置該放什麼字元。


Rust 程式做了什麼?

這支 Rust 寫的 binary,在執行時會把你輸入的整段文字(像是 HTB{aaaaaaa})逐字送去 check_flag() 函數裡。

然後 check_flag() 裡會用組合語言的方式做類似這樣的事:

cmp $0x48, %dil ; 檢查第 1 字元是不是 H (0x48) cmp $0x54, %dil ; 檢查第 2 字元是不是 T (0x54) cmp $0x42, %dil ; 檢查第 3 字元是不是 B (0x42) ... 以此類推

一旦有錯,就會 panic。

Python 做了什麼?

  1. 每次送一組錯的 flag(一開始用全是 1HTB{111...

  2. 每次 在 GDB 裡停在 check_flag() 的某一步驟,然後用 disas 拿到 disassembly 組合語言

  3. 用正規表達式 cmp.*%dil 找出比較的是哪個字元

  4. 把它轉回字元,寫進對應的位置

  5. 重複 31 次,直到整段 flag 都被拼出來


每次就是這樣:

  • 程式說:「你的第 6 個字應該是 p 呀」

  • 你說:「好,我改成 p

  • 下一輪再來看第 7 個是什麼

這樣來回問、改、問、改,很快就拿到整段正確 flag!


🧩 小總結:這叫「逐字元爆破(byte-by-byte bruteforce)」

  • 藉由 GDB 停在 check_flag() 的某一行

  • 看到機器用 cmp 檢查哪個字元

  • 自動把它換成正確的

  • 重複直到完成



留言

這個網誌中的熱門文章

Challenge 0 - Secura(2)

Challenge 0 - Secura(1)

Challenge 8 - Poseidon(1)