【CTF Writeups】VolgaCTF Quals 2020 - F-Hash
這題給了一個 x86-64 ELF Executable,直接跑下去跑不出來,一直卡在那裡,逆向一下會發現 13B0
這個函式是一個遞迴函式,他的虛擬碼大概長下面這樣,會一直遞迴呼叫前兩層的答案,很明顯的有很多重複的子問題,這時候就是要用 Dynamic Programming 的思路來把算過的答案記下來就不會跑那麼久了,所以這題就是要優化這個函式,把程式跑完就會印出 flag。
1 | def _13B0(depth, a, b): |
以下提供三種解法,讀者可以跟著練習一下。
Rewrite Function with Python
最直覺的方法就是把 IDA decompile 出來的 code 搬到 python 上重寫一下,沒什麼技術,這是我在賽中用的方法,但就是要注意一下型態的問題,比如兩個 unsigned int 相乘可能 overflow 在 python 裡面要 mod (1 << 32)
,更多細節請看下面的程式碼。
1 | #!/usr/bin/env python3 |
GDB
另一個方法是我在賽後看 別人 用的,在 gdb 寫 python 去 hook 13B0
的開頭和結尾,在開頭判斷這組參數有沒有出現過了,跑過就把參數的 depth
設成 1 也就是 base case 讓他不要再往下遞迴了,而因為同一組函式的 Start, End
Hook 沒辦法共享資訊,所以需要維護一個 state
來放目前的參數,在結尾的時候一樣是看這組參數有沒有出現過,有就把答案寫上去,沒有就把答案存起來下次就不會再跑一次了。
1 | import gdb |
gdb f-hash
之後,在 gdb 裡面執行 source solve-gdb.py
就可以跑上面的程式碼了
或是也可以在執行 gdb 的時候就載入 gdb -x solve-gdb.py f-hash
Frida
這個方法也是我賽後看 別人 用的,frida 真的是好東西,之前剛好有研究一點 frida,第一次用在比賽中,基本上跟前一個解法一樣去 hook 函式的開頭和結尾,不過 frida 又更方便了,請看下面程式碼。
1 | var base = ptr(Process.enumerateModulesSync()[0].base) |
最後執行 frida --no-pause --runtime=v8 -l solve-frida.js ./f-hash
就可以了
Flag
1 | VolgaCTF{16011432ba16efc8dcf779477985b3b9} |