6. Delegation

本關主要難點在於使用底層msg.data呼叫pwn函數,以bytes來組成一個指定的函數呼叫。我們知道智能合約的函數呼叫就是一個transaction,transaction當中的data就是要呼叫的函數及傳入的參數。因此,直接向智能合約傳入byte data來呼叫合約函數是可行的。至於data是以什麼格式去對應函數,參考官方文檔:

The first four bytes of the call data for a function call specifies the function to be called. It is the first (left, high-order in big-endian) four bytes of the Keccak-256 hash of the signature of the function. The signature is defined as the canonical expression of the basic prototype without data location specifier, i.e. the function name with the parenthesised list of parameter types. Parameter types are split by a single comma – no spaces are used.

簡單來說就是把要呼叫的函數名稱Keccak-256 hash了之後取首4 bytes,放在call data 的最前面。

本關另一知識點在於Delegatecall的理解,參考官方文檔:

There exists a special variant of a message call, named delegatecall which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and msg.sender and msg.value do not change their values.

This means that a contract can dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address.

使用Delegatecall的時候,合約就如同呼叫同一個合約的庫,而不是呼叫另一個智能合約,因此執行另一合約代碼時的上下文不會變更。

打開Console (F12),輸入:

> contract.sendTransaction({data:web3.utils.sha3("pwn()").slice(0,10)});

在以上的代碼,我們使用web3庫的sha3函數把pwn()字串進行Hash,再取首10字元(4 bytes即8字元,再加上0x兩個字元),然後用預設的sendTransaction函數送出去。

最後按提交,本關完成。

發表留言

%d 位部落客按了讚: