如果一個漏洞需要「先呼叫 A 函數、再把 B 變數設定為特定值、最後 C 函數的運算結果剛好等於 0」才會觸發,Slither 這種只看程式碼表面的工具通常會無能為力。這時候,我們就需要請出區塊鏈資安界的重裝武器:基於符號執行 (Symbolic Execution) 的檢測工具——Mythril。
什麼是符號執行 (Symbolic Execution)?
要理解 Mythril 的強大,我們必須先搞懂「符號執行」的運作原理。
想像合約是一個巨大的迷宮。
靶機:隱藏在深處的提款後門
讓我們來看一個刻意隱藏邏輯後門的合約。這個後門條件非常嚴苛,一般的隨機測試(甚至人眼)幾乎不可能掃得出來:
'''
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract HiddenBackdoor {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
// 正常的提款函數
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
// 隱藏的後門:只有當傳入的兩個數字滿足特定複雜方程式時,才能清空合約!
function secretWithdraw(uint256 a, uint256 b) public {
// 條件:a 的平方必須等於 b,且 a 必須大於 10000
require(a > 10000, "Condition 1 failed");
require(a * a == b, "Condition 2 failed");
// 觸發後門,把合約裡的錢全轉給駭客
payable(msg.sender).transfer(address(this).balance);
}
}
'''
如果你用 Slither 掃描這個合約,它大概只會警告你 transfer 沒加防護,但它算不出要怎麼觸發。這時候就輪到 Mythril 上場了。
Mythril 安裝與實戰掃描
Mythril 是由 ConsenSys 開發的工具。最簡單的安裝與執行方式是使用 Docker(這樣就不會弄髒你的本地 Python 環境)。
打開終端機,在你的專案目錄下執行以下指令來分析 HiddenBackdoor.sol:
'''
docker run -v $(pwd):/tmp/app -w /tmp/app mythril/myth analyze src/HiddenBackdoor.sol
'''
Mythril 終端機輸出解析:
因為 Mythril 是在做極度耗費運算資源的數學推演,所以掃描時間會比 Slither 慢上許多(可能需要幾分鐘)。但當它跑完後,它會給你一個令人驚豔的報告:
'''
==== Unprotected Ether Withdrawal ====
SWC ID: 105
Severity: High
Contract: HiddenBackdoor
Function name: secretWithdraw(uint256,uint256)
PC address: 456
Estimated Gas Usage: 6000 - 25000
The contract balance is sent to an arbitrary user.
Any user can withdraw the contract's entire balance by executing this function.
Transaction Sequence to trigger this issue:
兩大工具的黃金組合
在實務的資安稽核中,Slither 和 Mythril 不是競爭關係,而是完美的互補:
這次見識到了符號執行強大的數學破壞力,它讓所有隱藏的邏輯後門無所遁形。