泚意 むヌサリアムのSはセキュリティの略です。 パヌト4.ツヌル


Solidity蚀語およびEthereumプラットフォヌム党䜓のスマヌトコントラクトに固有の兞型的な脆匱性、攻撃、および問題領域に専念するシリヌズの第4郚を玹介したす。 ここでは、スマヌトコントラクトのセキュリティを分析するためのツヌルの存圚ず、それらが必芁な䞍芁な理由に぀いお説明したす。


前半では、フロントランニング攻撃、さたざたな乱数生成アルゎリズム、および暩限蚌明コンセンサスを䜿甚したネットワヌクの埩元力に぀いお説明したした。 2番目は、敎数オヌバヌフロヌ、ABI゚ンコヌド/デコヌド、初期化されおいないストレヌゞポむンタヌ、タむプの混乱、およびバックドアの䜜り方に぀いお話したした。 第3郚では、Solidityのいく぀かの特城的な機胜に觊れ、契玄で芋぀かった論理的な脆匱性のいく぀かを調べたした。 このパヌトでは、スマヌトコントラクトを分析するための既存のツヌルの抂芁を提䟛したす。


すべおのツヌルをいく぀かのカテゎリに分類しお、次のこずができるようにしたした。



次に、それぞれに觊れたす。 䞀郚のツヌルはスマヌトコントラクトの゜ヌスコヌドでのみ機胜し、他のツヌルでは機胜したせん。 すぐに、私たちは、パブリックドメむンにあるこずがわかっおおり、私たちが協力したツヌルに぀いおのみ話すこずを予玄したす。 このトピックに関する他のツヌルの経隓がある堎合は、コメントしおください:)


デバッグ


珟圚、゜ヌスコヌドでスマヌトコントラクトをデバッグする機䌚は1぀たたは唯䞀の䟿利な Remix IDEのみです。 たた、バむトコヌドを理解する必芁がある堎合は、 Radare2たたはMythrilTraceExplorerが圹立ちたす 。


Remix IDE


開発者の堎合、ほずんどの堎合、デバッグにRemixを䜿甚したすほずんどの堎合、それを行いたす。 ロヌカル倉数スタックの状態、メモリ、ストレヌゞ、消費ガスなどの状態を監芖するこずは非垞に䟿利です。


図1. Remix IDEむンタヌフェヌス

[ストレヌゞが完党にロヌドされたした]タブの内容が䞍安な堎合は、 ストレヌゞデバむスを扱うこずをお勧めしたす。 マむナス面は、JavaScript VMの定期的なバグず、アセンブラヌ挿入を䜿甚する堎合、行ごずのデバッグを期埅できないこずです。


Radare2


Remixが気に入らないがコン゜ヌルが奜きなら、Rarere2を詊しおください。 これにより、コントラクトを分解およびデバッグできたす。 トレヌスは、デバッグ発生したトランザクションの蚘録に䜿甚されたす。 rpcレヌダヌはノヌドに接続し ganache-cliが䟿利、トランザクションを繰り返すのに必芁なデヌタを圧瞮したす。


グラフィカルモヌドでは、スタックずメモリの内容でタむルを開くこずができたす。


図2. Radare 2むンタヌフェヌス

ブレヌクポむントを蚭定しおメモリに曞き蟌むこずはできたすが、ストレヌゞを調べたり倉曎したりする方法は芋぀かりたせんでした。


Positive Technologiesの瀟員には、Radarを䜿甚しお契玄を分解およびデバッグする䟋がありたす。 レヌダヌは最も盎感的なツヌルではありたせんので、レヌダヌのコマンドを確認しおください。


自動脆匱性スキャン


私たちの前に、3぀の楜噚の比范が既に行われおいたす-ミスリル、マンティコア、オむ゚ンテ。 この分析の結果によるず、Mythrillはリヌドし、Oyenteは最悪の結果を出したす。 テスト䞭に、著者はツヌルにコントラクトの゜ヌスコヌドを「䟛絊」したため、結果は生のバむトコヌドをどれだけうたく凊理しおいるかを反映しおいたせんが、基本的に私たちの印象ず䞀臎したす。


ミスリル


Mythrilには、スマヌトコントラクトの゜ヌスコヌドずバむトコヌドの䞡方の分析を含む幅広い機胜がありたす。 チェヌン䞊でも機胜するこず、぀たり、オンラむンでノヌドにオンラむンで接続し、契玄を収瞮させお分析できるこずは泚目に倀したす。 たた、逆アセンブラヌであり、適切なグラフを䜜成できたすただし、泚意しおください。これはしばしば正しく行われないため、EthersplayたたはIDA-EVMを詊しおください。 Mythrilは、MythrilTraceExplorerずいうツヌルの状態を生成するこずもできたす。これにより、文字倉数を䜿甚しおスマヌトコントラクトのバむトコヌドをデバッグできたす。


図3. MythrilTraceExplorerむンタヌフェヌス

MythilおよびMythrilTraceExplorerオプションの完党なリストはドキュメントに蚘茉されおおり、 ここにはない秘密のフラグを芋぀けるこずができたす。


Consensysテストからeth_tx_order_dependence_minimalコントラクトを取埗したす


゜ヌスeth_tx_order_dependence_minimal
 contract Benchmark { address public owner; bool public claimed; uint public reward; function Benchmark() public { owner = msg.sender; } function setReward() public payable { require (!claimed); require(msg.sender == owner); owner.transfer(reward); reward = msg.value; } function claimReward(uint256 submission) { require (!claimed); require(submission < 10); msg.sender.transfer(reward); claimed = true; } } 

Mythrilがどのように゜ヌスコヌドを凊理するかを芋おください


 user% myth -x eth_tx_order_dependence_minimal.sol ==== Ether send ==== Type: Warning Contract: Benchmark Function name: claimReward(uint256) PC address: 693 In the function 'claimReward(uint256)' a non-zero amount of Ether is sent to msg.sender. Call value is storage_1. There is a check on storage index 7. This storage slot can be written to by calling the function 'claimReward(uint256)'. -------------------- 

そしお今それらなしで


 user% myth -x -c 60806040523...5f9dc0029 The analysis was completed successfully. No issues were detected. 

ご芧のずおり、Mythrilの生のバむトコヌドは分析できたせんでした。


オ゚ンテ


Pythonで蚘述された、スマヌトコントラクトの脆匱性を怜出するための独自のシンボリック実行゚ンゞンを備えたツヌル。 少し前たで、開発者は入力デヌタに関する情報の出力を最終的に远加したした。これにより、問題がトリガヌされたす。 このツヌルは、゜ヌスコヌドを䜿甚しお契玄を分析する堎合にのみ、ある皋床適切な結果を生成したす。 バむトコヌドに蚭定するず、その䞀郚しかカバヌされないため、ほずんどの堎合、バグは芋぀かりたせん。


Mythrilずの類掚により、Oyenteに経隓を積んで、Oyenteが゜ヌスコヌドの有無にかかわらず脆匱性をどの皋床芋おいるかを確認したす。


 user% oyente -s eth_tx_order_dependence_minimal.sol INFO:root:contract eth_tx_order_dependence_minimal.sol:Benchmark: INFO:oyente.symExec: ============ Results =========== INFO:oyente.symExec: EVM Code Coverage: 98.3% INFO:oyente.symExec: Integer Underflow: False INFO:oyente.symExec: Integer Overflow: False INFO:oyente.symExec: Parity Multisig Bug 2: False INFO:oyente.symExec: Callstack Depth Attack Vulnerability: False INFO:oyente.symExec: Transaction-Ordering Dependence (TOD): True INFO:oyente.symExec: Timestamp Dependency: False INFO:oyente.symExec: Re-Entrancy Vulnerability: False INFO:oyente.symExec:Flow1 eth_tx_order_dependence_minimal.sol:14:9: Warning: Transaction-Ordering Dependency. owner.transfer(reward) Flow2 eth_tx_order_dependence_minimal.sol:22:9: Warning: Transaction-Ordering Dependency. msg.sender.transfer(reward) INFO:oyente.symExec: ====== Analysis Completed ====== 

次に、このコントラクトのバむトコヌドを蚭定したす。


 user% oyente -b -s eth_tx_order_dependence_minimal.bin INFO:oyente.symExec: ============ Results =========== INFO:oyente.symExec: EVM Code Coverage: 18.0% INFO:oyente.symExec: Callstack Depth Attack Vulnerability: False INFO:oyente.symExec: Transaction-Ordering Dependence (TOD): False INFO:oyente.symExec: Timestamp Dependency: False INFO:oyente.symExec: Re-Entrancy Vulnerability: False INFO:oyente.symExec: ====== Analysis Completed ====== 

ご芧のずおり、カバレッゞは倧幅に枛少し98から18パヌセント、ツヌルは契玄に関する問題を怜出したせん。


Oyenteの開発は、たあ非垞に悪いコヌドのために簡単ではありたせん。 たずえば、パラメヌタヌはグロヌバル倉数を介しおモゞュヌルからモゞュヌルに枡されたす。 最も可胜性が高いのは、このプロゞェクトに取り組んでいる人が1.5人以䞋だからです。


念のため、ツヌルボックスにOyenteを保持する䟡倀はありたすが、Oyenteが開発および改善されるかどうかはわかりたせん。


気孔率


おそらく最も誇匵された逆コンパむラ。 その䞻な機胜は、機胜しないこずです。


この機胜を実蚌するために、おもちゃのコントラクトを逆コンパむルしたしょう。これは、実隓の玔床のために、2017幎7月1日から比范的叀いバヌゞョンのsolc'a 0.4.12を収集したす。 Porosityが2018幎1月に最埌に曎新されたため、ツヌルが圓瀟の契玄に察応できるず蚈算できるこずに泚意しおください。


オリゞナル


 contract sample { uint y; function foobar (uint x) { if (x == 0) { y = 0x1337; } else { y = 0xb33f; } } } 

ナニヌクな逆コンパむラ出力


 .\porosity.exe --code $binRuntime --decompile function func_14ba3f12 { if (!msg.value) { } if (arg_4 != 0x0) { store[var_xrpMC] = 0xB33F; } store[var_zdGc8] = 0x1337; return; return; } 

ツヌルを簡単にするためにabiも枡そうずするず、Porosityがクラッシュしたす。


Porosityのアプリケヌションを芋぀けるこずができたせんでした。䜿甚する詊みはすべお、意味のない結論を受け取るか、ツヌルをクラッシュさせるこずで終了したした。


マンティコア


プログラムのシンボリック実行のためのツヌル。 少し前に、EVMサポヌトが远加され、開発されおいたすそしお、 氞続的な開発者が登堎すれば、事態はさらに速くなりたす。 倚くのチップが搭茉されおいたすが、テストされおおらず、ほずんどの堎合機胜したせん。 プロゞェクトにはかなり悪いドキュメントもありたすが、コミュニティがこの欠点をすぐに修正するこずを願っおいたす。


Manticoreの䜿甚䟋を芋る前に、指で「シンボリック実行」を説明する䟡倀がありたす。たた、Michael Hicksによるプレれンテヌション「バグを芋぀けるためのシンボリック実行」のスラむドが圹立ちたす。


画像
図4.バグを芋぀けるためのシンボリック実行。 マむケル・ヒックス

シンボリック実行を䜿甚するず、特定のポむントに関数/プログラムを䞎えるために必芁な入力を理解できたす。 倧たかに蚀えば、シンボリック実行䞭に、特定のポむントぞの実行方法に関するすべおの制限条件が収集され、これらの制限から匏が䜜成され、必芁な入力を取埗したす。


デモンストレヌションのために、Positive Hack Days 8で開催されたEtherHackコンテストの「The Lock」タスクを解決したす。参加者には゜ヌスコヌドは枡されず、契玄のアドレスのみが枡されたした。 タスクを解決するには、正しいPINコヌドで契玄を呌び出す必芁がありたしたその怜蚌はフォヌルバックで実装されたす。 ゜リュヌションには、ピンコヌド怜蚌アルゎリズムを理解するためのリバヌス゚ンゞニアリングが含たれおいたした。


この問題の解決策を自動化したしょう。 ただし、契玄の逆アセンブルされたコヌドを芋お、参加者が有効なPINコヌドを送信した堎合に䜕が起こるたたは起こらないかを調べる必芁がありたす。 ぀たり、プログラムにはsstore呜什が1぀しかないこずに泚意する䟡倀があり、チェストのキヌが正しく遞択された堎合に実行されるず安党に想定できたす。


残念ながら、Manticoreのバグは問題の正盎な解決策を提䟛したせんバグレポヌトを開発者に送信したした。できればすぐに゚ラヌを修正するこずを願っおいたす。出お行かなければなりたせん。乗算珟圚のManticoreのバグにより、シンボリックベヌスでべき乗を゚ミュレヌトできたせん。 もちろん、コンテスト䞭にこのようなひねくれた方法でタスクを解決するこずは無意味ですが、ツヌルをデモンストレヌションするだけであるこずを忘れないでください たた、゜ヌスコヌドが存圚しおも、シンボリック実行はバむトコヌドではなくシンボリック実行では機胜するため、䜜業は単玔化されたせん。


十分な蚀い蚳ず保護がありたすので、スクリプトを芋おみたしょう。


ロック゜ルバヌ
 from manticore.ethereum import ManticoreEVM from manticore.core.smtlib import Operators from struct import pack m = ManticoreEVM() m.verbosity(0) contract_source_code = ''' contract lock { uint public unlocked; function unlock(bytes4 cPincode) payable { uint digitPowers = 0; uint iPincode = 0; for (uint i = 0; i < 4; i++) { if (cPincode[i] >= 0x30 && cPincode[i] <= 0x39) { // manticore can't handle pow with symbolic input at the moment uint digit = (uint(cPincode[i]) - 0x30); digit *= digit; digit *= digit; digitPowers += digit; iPincode += (uint(cPincode[i]) - 0x30) * 10**(3-i); } else { revert(); } } if (uint(iPincode) == 0 || uint(iPincode) == 1) { revert(); } if (digitPowers == uint(iPincode)) { unlocked = 0x31337; } } } ''' user_account = m.create_account(balance=10**18) m.world.set_balance(user_account, 10**18) contract_account = m.solidity_create_contract(contract_source_code, owner=user_account) print "[+] Created a contract account 0x%x" % contract_account print '[+] Sending transaction with symbolic input' symbolic_data = m.make_symbolic_buffer(36) m.transaction(caller=user_account, address=contract_account, data=symbolic_data, value=10**18) pincodes = None for state in m.all_states: world = state.platform for where, what in world.get_storage_items(int(contract_account)): _input = Operators.CONCAT(8*4, *world.human_transactions[-1].data[4:8]) # getting 4 bytes after function signature print '[+] Storage write 0x%x' % state.solve_one(what) pincodes = state.solve_n(_input, 10) print '[+] Found %i pincodes:' % len(pincodes) for pincode in sorted(pincodes): print ' "%s"' % pack('>I', pincode) break if pincodes is not None: break 

実行するず、次の結論が埗られたす。


 [+] Created a contract account 0x1bfa530d5d685155e98cd7d9dd23f7b6a801cfef [+] Sending transaction with symbolic input [+] Storage write 0x31337 [+] Found 3 pincodes: "1634" "8208" "9474" 

私たちは䜕が起こっおいるのかを扱いたす。 たず、契玄コヌドを芋おください。 ロック解陀関数は、入力に4バむトを䜿甚したす。この入力では、4桁の10進数のテキスト衚珟が衚瀺されたす。 それらのピンコヌドのみが適切であり、4番目の次数の数字の合蚈は、ピンコヌド自䜓ず等しく、0ず1を陀きたす。 確かに

14+64+34+44=$163


ピンコヌドがこれらの条件を満たしおいる堎合、ストレヌゞにあるunlockedされおいunlocked倉数に数倀0x31337が曞き蟌たれたす。

それでは、スクリプトを理解したしょう。 最初の郚分で䜕が起こるかは簡単に理解できたす。ナヌザヌアカりントが䜜成され、次に契玄が䜜成されたす。 トランザクションは、シンボリック入力で開始されたす。 このアクションを䜿甚するず、シンボリック実行がアクティブになり、数分かかりたす。 完了したら、すべおの最終状態を調べお、䜕かがストレヌゞに曞き蟌たれおいるかどうかを確認し、曞き蟌たれおいる堎合は、トランザクションが行われた入力を調べたす。 呌び出された関数の眲名の4バむト埌に、それらからPINコヌドを抜出したす。 問題を解決し、契玄が予想するPINコヌドの桁数がわからない堎合、4バむトではなく32バむトすべおEVMのメモリセルのデフォルトサむズが埗られたす。 次に、画面䞊に同様の数字が衚瀺されたす。


 0x3136333434343434343434343434343434343434343434343434343434343434 0x3832303800000000000000000000000000000000000000000000000000000000 

Manticoreの分析結果を䜿甚しお、おもちゃのパズルを解くだけでなく、おもちゃ契玄のおもちゃのバグを探すこずもできたす。「契玄を含むすべおのブロヌドキャストが䜏所に届くように、契玄に䜕を送信すればよいですか」


EthCC 2018ワヌクショップの安党でないりォレットの䟋を芋おみたしょう


保護されおいない財垃
 from manticore.ethereum import ManticoreEVM from manticore.core.smtlib import solver m = ManticoreEVM() # initiate the blockchain source_code = ''' contract UnprotectedWallet{ address public owner; modifier onlyowner { require(msg.sender==owner); _; } function UnprotectedWallet() public { owner = msg.sender; } // this function should be protected function changeOwner(address _newOwner) public { owner = _newOwner; } function deposit() payable public { } function withdraw() onlyowner public { msg.sender.transfer(this.balance); } } ''' # Generate the accounts. Creator has 10 ethers; attacker 0 creator_account = m.create_account(balance=10*10**18) attacker_account = m.create_account(balance=0) contract_account = m.solidity_create_contract(source_code, owner=creator_account) print "Creator account: 0x%x" % creator_account print "Attacker account: 0x%x" % attacker_account # Deposit 1 ether, from the creator contract_account.deposit(caller=creator_account, value=10**18) # Two raw transactions from the attacker symbolic_data = m.make_symbolic_buffer(320) m.transaction(caller=attacker_account, address=contract_account, data=symbolic_data, value=0) symbolic_data = m.make_symbolic_buffer(320) m.transaction(caller=attacker_account, address=contract_account, data=symbolic_data, value=0) for state in m.running_states: # Check if the attacker can ends with some ether balance = state.platform.get_balance(attacker_account) state.constrain(balance > 1) if solver.check(state.constraints): print "Attacker can steal the ether! see %s"%m.workspace m.generate_testcase(state, 'WalletHack') 

明らかに、開発者はchangeOwnerに属性onlyOwnerを䞎えるこずを忘れおいたした。 このため、2぀のトランザクションの攻撃者が資金を埗るこずができたす。 い぀ものように、最も興味深いのはスクリプトの最埌です。 状態を列挙しお、「攻撃者はどれにコむンを持っおいたすか」ずいう質問をしたす。 そしお、マンティコアは圌に答えるこずができたす。 WalletHack_00000000.txファむルのmcore_XXXフォルダヌで回答を探したす。


画像
図5. Manticoreの䜜業の結果。

圌らがManticoreを攟棄しなければ、スマヌトコントラクトの柔軟な分析のための優れたツヌルに成長したすが、珟実の䞖界ず実際のタスクに盎面する準備はただ敎っおいたせん。


゚キドナ 段階的


゚キドナは、スマヌトコントラクトをファゞングするために蚭蚈された実隓的なツヌルです。 しかし、これはあなたが考えるこずができるファズではありたせん。 Echidnaがスマヌトコントラクトの機胜をファゞングするには、特別な方法でコントラクトを準備する必芁がありたす。


 //  contract EchidnaTest { function sensitiveFunc(uint num, bool stop) { if (num > 5 && !stop) { selfdestruct(msg.sender); } } } 

埌
 contract EchidnaTest { uint num; bool stop; function num_setter(uint _num) public { num = _num; } function stop_setter(bool _stop) public { stop = _stop; } function echidna_sensitiveFunc() public returns (bool) { if (num > 5 && stop) { selfdestruct(msg.sender); } return true; } } 

぀たり、プロファむリングする機胜を「ねじ解陀」する必芁がありたす。 Echidnaは、 num_setterおよびstop_setterを呌び出しおからnum_setterを呌び出したす。 たた、Echidnaはすべおが順調に進んだずきに関数がtrueを返すこずを期埅しおいるこずに泚意しおくださいただし、明瀺的には䌝えたせん。 したがっお、 false 、 revert() 、 selfdestruct(0)などをselfdestruct(0) revert()により、「間違った」動䜜をマヌクできたす。


 p4lex@ubuntu:~/tools/echidna$ echidna-test echid.sol ━━━ echid.sol ━━━ ✗ "echidna_sensitiveFunc" failed after 23 tests and 51 shrinks. │ Call sequence: num_setter(6); │ stop_setter(false); ✗ 1 failed. 

たた、゚キドナが倉曎する特定の入力デヌタを蚭定できないこずにも泚意しおください。したがっお、耇雑なタスクの堎合、このようなファゞングの有効性には倚くのこずが望たれたす。 しかし、プロファゞングする必芁がある各関数を曞き盎さなければならないずいう事実は、おそらく気づいたでしょう。 公平に蚀えば、Haskellで蚘述できる堎合でも、可胜な倀のセットから特定のドメむンを提䟛するように入力倀ゞェネレヌタヌを蚭定できるこずに泚意しおくださいたずえば、 numは5以䞊でなければならないこずを知っおいたす。


䞀般に、ファゞングは実を結ぶこずができたす。 脆匱性が長いアクションチェヌンの埌にのみ珟れる堎合、シンボリック実行にはファゞングずは察照的にCPUずメモリの倧きな消費が必芁になりたすただし、ある皋床の確率でのみこの脆匱性を怜出したす。 ゚キドナで䜿甚されおいるアプロヌチの詳现に぀いおは、 こちらをご芧ください 。


スマヌトチェック


再入可胜性はどこにでもあるように思える、非垞に実隓的なクロヌズド゜ヌスのツヌルです。 気持が良いから契玄を送信フォヌムに貌り付けるか、githubぞのリンクを指定できたす。 たた、静的コヌド分析が䜿甚されるため、契玄をコンパむルする必芁さえありたせん。 次のようになりたす。


図6. SmartCheckむンタヌフェヌス

この䟋では、Ether転送埌に残高がリセットされたす。これはSmartCheckの眲名です。 ただし、 send機胜ずtransfer機胜のみを䜿甚するず再入可胜性が防止されるため 第3郚でこれに぀いお説明したした、䞊のスクリヌンショットでは誀怜出が芋られたす。


リバヌス゚ンゞニアリング


珟圚、オヌプンアクセスにはオヌプンデコンパむラが存圚しないため、このロゞックたたはそのコントラクトが実装するロゞックを理解するために、逆コンパむラを䜿甚する必芁がありたす。 䞀般に、逆コンパむラが存圚する可胜性がありたす。 最初の詊みはPorosityで行われたしたが、おそらく解決策は機胜したすが、残念なこずに、RET2の人たちは閉じたものを持っおいたす。 それたでは、バむトコヌドだけを残しお、できるこずを芋おみたしょう。


EVMdis


最も叀く、最も䟿利な逆アセンブラヌ。 矎しいむンタヌフェヌスを自慢するこずはできたせんが、他のツヌルにはないチップがありたすたず、シヌケンスの代わりに呜什を折りたたみ、もう1぀の読みやすい匏を衚瀺し、次に各ベヌスナニットに぀いおEVMdisが入力でスタックを衚瀺したす蚘号化された倉数を含むブロックに。 EVMはスタックされたマシンであるため、このデヌタがなければスタックを関数の最初から埩元する必芁があるため、これによりコヌドのロゞックを理解するプロセスが倧幅に高速化されたす。


䟋


 # Stack: [] 0x33 PUSH(0xFFFFFFFF & CALLDATALOAD(0x0) / 0x100000000000000000000000000000000000000000000000000000000) 0x34 DUP1 0x3E JUMPI(:label5, 0x2F54BF6E == POP()) ... :label36 # Stack: [@0x420 @0x408 0x0 @0x2A1 @0x282 :label22 @0x33] 0x43F POP() 0x440 POP() 0x443 PUSH(MLOAD(0x40)) ... 

0x33では、倀がcalldataから返され、スタックにプッシュされたす。 この倀は䞍明であるため、蚘号化されおいたす。 さらに、他のシンボリックおよび特定の倀番号および遷移アドレスの䞭で、ベヌスブロックラベル36のスタックでそれを芳察できたす。


私たちの意芋では、これは契玄の逆展開のための最も䟿利なツヌルです。


Ethersplay


EVMアヌキテクチャのサポヌトを远加するバむナリニンゞャプラグむン。 EVMはスタックされたマシンであるため、忍者の䞭間衚珟LLILおよびMLILは機胜したせん。したがっお、ベアアセンブラヌの指瀺を読む必芁がありたす。 気持が良いからプラグむンには{ : }ペアを持぀蟞曞があるため、すぐに倚くの有名な関数を定矩できたすたずえば、ERC暙準の異なるむンタヌフェヌスを実装する。


画像
図7. Ethersplayプラグむンを䜿甚したバむナリNinjiaむンタヌフェヌス

プラグむンには、各呜什のスタックの状態を瀺す機胜もありたす。


画像
図8. Ethersplayで衚瀺されるスタックステヌタス

ただし、すべおのシンボリック倉数をUnknownずいう単語に眮き換えたすが、EVMdisは代わりに、このシンボリック倉数がスタック䞊で出珟したアドレスを曞き蟌みたす。


Ethersplayは私たちの兵噚庫に定着しおいたせんが、おそらく有甚なツヌルになる段階たで開発されるでしょう。


アむダ゚ノム


IDA Proがコントラクトを分解できるようにするプロセッサモゞュヌル。 たた、Ethersplayのような関数プロトタむプの蟞曞もありたす。


画像
図9. IDA-EVMプロセッサモゞュヌルを備えたIDAむンタヌフェむス

ただし、これは、プログラム党䜓のスタックの状態を手動で解決する必芁があるため、コントラクトの䟿利なリバヌス開発には十分ではありたせん。 私たちの意芋では、このツヌルは開発を受けるこずはほずんどなく、珟圚の圢では圹に立たないため、このツヌルは泚目に倀したせん。


テスト䞭


このセクションでは、実際にあなたの契玄から安党な契玄をする傟向があるもの、すなわちテストに぀いおお話したいず思いたす。 実践が瀺すように、テストで少なくずも95がカバヌされるスマヌトコントラクトでは、深刻な脆匱性の可胜性はわずかです。 テストを䜜成するプロセスでは、倚くの堎合、必芁なチェックが倚く远加されたすが、平気ではありたせん。経隓豊富なセキュリティ監査員たたは開発者のみが語るこずができたす。 たずえば、契玄が実装するサブゞェクト゚リアの0day脆匱性、たたはその他の論理゚ラヌを芋぀けるか、特定の契玄メカニズムDAppをより効率的にする方法を提案したす。


トリュフ


Truffleを䜿甚しお「その堎で」テストを実行するのが最も䟿利ですほずんどのスマヌトコントラクトが開発されおいたす。 テストフォルダヌ truffle init埌に衚瀺されtruffle init で、テストを䜜成し、 truffle testコマンドを䜿甚しお実行できたす。 ただし、公匏ドキュメントよりもトリュフを䜿甚したテストに぀いお詳しく説明できる人はほずんどいたせん。 たた、 ゜リッドカバレッゞツヌルを䜿甚したテストでカバレッゞを枬定するこずを忘れないでください。


web3.js


䜕らかの理由倚くの堎合でTruffleがあなたに合わない堎合、web3ラむブラリを䜿甚しおテストを曞くこずができたすそれらは異なる蚀語で利甚可胜です。 蚘述されたテストコヌドは、ロゞックの䞀郚ずしお将来のDAppに簡単に転送できるため、web3.jsを䜿甚するのが最も䟿利です。 唯䞀の泚意点は、web3.jsバヌゞョン^ 1.0.0を䜿甚するこずです。 未来は圌女のものであり、Googleの最初の行ずなるバヌゞョン0.14.0では互換性がありたせん。 䟋を考えおみたしょう


゜ヌスコヌド
 pragma solidity ^0.4.23; contract Testable { address public human; uint private counter; constructor() { human = tx.origin; } event CallmeLog(); function callme(uint times) public { counter++; if (times > 1) { callme(--times); } else { emit CallmeLog(); } } } 

テスト自䜓に進む前に、ネットワヌクに新しいコントラクトをアップロヌドする関数を䜜成する必芁がありたす。これは䞀床だけ行う必芁があるためです:)


テスト
 const solc = require('solc'); const fs = require('fs'); const Web3 = require('web3'); const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545')); const code = fs.readFileSync('./testable.sol'); async function main() { // when use unlocked account from node let defaultAccs = await web3.eth.getAccounts(); web3.eth.defaultAccount = defaultAccs[0]; // this is for known private key // web3.eth.accounts.wallet.add(privKey.key); let Testable = await deploy(); human_test(Testable); callme_tx_status_test(Testable, 3); callme_event_test(Testable, 3); // let's got new instance Testable = await deploy(); callme_storage_test(Testable, 5); } async function deploy() { let output = solc.compile(code.toString(), 1); let TestableABI = output.contracts[Object.keys(output.contracts)[0]].interface; let TestableBytecode = output.contracts[Object.keys(output.contracts)[0]].bytecode; let Testable = new web3.eth.Contract(JSON.parse(TestableABI),{ from: web3.eth.defaultAccount }); let gasCount = await Testable.deploy({ data: TestableBytecode }).estimateGas(); Testable = await Testable.deploy({ data: TestableBytecode }).send({ gas: gasCount }); return Testable; } async function human_test(instance) { // let's test that contract has owner (human) // use "call" for public variables and constant methods let humanAddress = await instance.methods.human().call(); if (humanAddress !== web3.eth.defaultAccount) { throw "✕ human address is wrong" } else { console.log(" human_test passed"); } } ... 

, ( ) . web3_utilz/Testing .



, , , , , , CTF.


(reverse engineering), , . , , - ( cryptoKittes ). , reverse engineering. , , , .


, , p4lex Igor1024 .



Source: https://habr.com/ru/post/J353676/


All Articles