Solidity

如何在 evm 字節碼中分離函式?

  • October 6, 2018

我想從智能合約的字節碼建構控制流圖(CFG)(假設它是通過編譯 Solidity 源文件獲得的)。這個CFG還應該區分智能合約的不同方法。

有沒有辦法這樣做?

如何在 evm 字節碼中分離函式?

Solidity 將在字節碼的開頭為函式呼叫創建一個調度程序塊。類似於 if .. elseif .. elseif .. else

單個函式呼叫將遵循以下重複模式:

DUP1
PUSH4 <4-byte function signature>
EQ
PUSH2 <jumpdestination for the function>
JUMPI

從這個塊中,您可以重構函式並找到它們的跳轉目的地,但是,您將只有 4 字節的簽名,並且沒有原始碼中的名稱。

例如對於這個智能合約程式碼:

contract X {
   uint x;
   uint y;

   function a(uint u) public {
       x = u;
   }

   function b(uint v) public {
       y = v;
   }

   function t(uint v) public {
       a(v);
       b(v);
   }

   function () {
       t(1);
   }
}

調度程序將如下所示:

...
054 DUP1
055 PUSH4 afe29f71
060 EQ
061 PUSH2 0070
064 JUMPI

065 DUP1
066 PUSH4 cd580ff3
071 EQ
072 PUSH2 009d
075 JUMPI

076 DUP1
077 PUSH4 f0fdf834
082 EQ
083 PUSH2 00ca
086 JUMPI
...

如果可以直接用字節碼編寫智能合約,那麼就可以讀取和分析它。考慮到字節碼類似於帶有 LIFO 堆棧的彙程式序,閱讀起來並不友好。沒有函式的名稱,變數的名稱,名稱根本不存在。這是關於彙程式序的類似問題https://reverseengineering.stackexchange.com/questions/10604/how-to-generate-cfg-from-assembly-instructions

為了做到這一點,我會:

例如:

  • 定義操作碼的位置
  • 檢測可能的標籤JUMPDEST
  • 檢測跳轉PUSH2 0x.... JUMP(可以假設為函式呼叫)

注意不同版本的編譯器編譯相同程式碼後結果可能不同,這意味著控制流可能不同。

孔隙度CFG

porosity.exe --code 0x60... --cfg

在此處輸入圖像描述

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