Solidity

如何跳轉到已部署合約中的任意位置

  • January 29, 2019

我想知道是什麼阻止我編寫一個知道合約地址並呼叫一些任意函式的彙編程式碼,即使通過簡單的 JUMP 聲明為“內部”也是如此。

理論上我可以:1)發現跳轉到分析字節碼並使用一些可訪問地址作為基地址的位置;2)編寫我自己的彙編程式碼,將所需的參數載入到堆棧中;3) 跳轉到 (1) 中發現的位置。

應該阻止我這樣做的機制是什麼?

(我知道各種“呼叫”類型的操作碼會跳轉到被呼叫程式碼的初始位置,但顯然 JUMP 和 JUMPI 指令沒有這樣的限制。閱讀黃皮書第 9.4.2 和 9.4.3 節以及 Geth 實現顯然可以與跳轉到任意絕對地址的可能性並不矛盾,但對於“允許的跳轉範圍”的定義不明確,這顯然只是要求在 EVM 跳轉的位置存在 JUMPDEST 操作碼。這在被攻擊的地方很容易找到合約操作碼。需要進一步分析,之前對類似問題的回答過於粗暴和直接,不提供證據

您不能跳入被呼叫合約的任意位置。您只能通過 CALL/CALLCODE/DELEGATECALL 呼叫它。例如,當您使用 CALL 操作碼時,您只能為呼叫提供輸入,但程序計數器在目的地處從 0 開始。在目的地執行的第一件事(如果字節碼已由solidity編譯器生成)是將輸入數據(函式簽名)的前4個字節與公共函式的位置進行匹配。由於內部函式不是此“開關”的一部分,因此您將無法呼叫它們。

請參閱Solidity組裝乙太坊黃皮書

call(g, a, v, in, insize, out, outsize)     

call contract at address a with input mem[in..(in+insize)) providing g gas 
and v wei and output area mem[out..(out+outsize))
returning 0 on error (eg. out of gas) and 1 on success

附加資訊:有關函式選擇字節碼的範例,請參閱“如何在 evm 字節碼中分離函式? ”。

如需深入了解,您可以查看 geth 的實現。入口點是:

引用自:https://ethereum.stackexchange.com/questions/66266