Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
Tags
- writeup
- EVM
- solidity
- coin flip
- Ethererum
- Wargame
- byte code
- ethernaut
- NaughtCoin
- libray
- web3
- openzepplin
- approve
- Assembly
- Block
- chain reorganization
- web assembly
- syntax
- transaction
- ethereum virtual machine
- Smart contract
- audit
- tx.origin
- secureum
- Coin
- ethereum
- Oracle Cloud
- TransferFrom
- hard fork
- soft fork
Archives
- Today
- Total
c0mpos3r
[Ethernaut] 18. MagicNumber WriteUp 본문
1. 문제 분석
To solve this level, you only need to provide the Ethernaut with a Solver, a contract that responds to whatIsTheMeaningOfLife() with the right 32 byte number.
Easy right? Well... there's a catch.
The solver's code needs to be really tiny. Really reaaaaaallly tiny. Like freakin' really really itty-bitty tiny: 10 bytes at most.
Hint: Perhaps its time to leave the comfort of the Solidity compiler momentarily, and build this one by hand O_o. That's right: Raw EVM bytecode. Good luck!
이 레벨을 해결하기 위해, 이더 러나에게 솔버에게만 제공하면 32 바이트 번호가있는 WhathisthemeaningofLife ()에 응답하는 계약입니다.
쉬운? 글쎄 ... 캐치가 있습니다솔버의 코드는 정말 작아야합니다. 정말로 작은. Freakin '처럼 정말로 정말 작은 비트 : 최대 10 바이트
힌트 : 아마도 Solidity 컴파일러의 편안함을 잠시 안락하고 O_O 로이 제품을 구축 할 시간입니다. 맞습니다 : RAW EVM 바이트 코드
1-1. Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MagicNum {
address public solver;
constructor() {}
function setSolver(address _solver) public {
solver = _solver;
}
/*
____________/\\\_______/\\\\\\\\\_____
__________/\\\\\_____/\\\///////\\\___
________/\\\/\\\____\///______\//\\\__
______/\\\/\/\\\______________/\\\/___
____/\\\/__\/\\\___________/\\\//_____
__/\\\\\\\\\\\\\\\\_____/\\\//________
_\///////////\\\//____/\\\/___________
___________\/\\\_____/\\\\\\\\\\\\\\\_
___________\///_____\///////////////__
*/
}
whatIsTheMeaningOfLife() 함수 호출 시 42를 반환하는 컨트랙트를 만드는 것입니다. 하지만 핵심 제약사항이 있다.
- 런타임 바이트코드가 최대 10개의 opcode로 제한
- Solidity 컴파일러 없이 Raw EVM 바이트코드로 직접 작성해야 함
1-2. Magic Number Contract 분석
EVM ByteCode 구조 이해
Contract ByteCode의 구성
- 배포 코드 (Creation Code): 컨트랙트 배포 시에만 실행되는 초기화 코드 (constructor)
- 런타임 코드 (Runtime Code): 실제 컨트랙트에 저장되어 함수 호출 시 실행되는 코드
문제에서 제한하는 것은 런타임 코드의 opcode 개수입니다.
런타임 코드 작성 (42 반환)
필요한 작업 순서
- 42를 Stack에 Push
- Memory에 42 저장
- Memory에서 42를 반환
필요한 OPCode
1. PUSH1 0x2a // 42(0x2a)를 스택에 올림
2. PUSH1 0x80 // 메모리 위치 0x80을 스택에 올림
3. MSTORE // 메모리[0x80]에 42를 저장
4. PUSH1 0x20 // 반환할 크기 32바이트를 스택에 올림
5. PUSH1 0x80 // 메모리 시작 위치 0x80을 스택에 올림
6. RETURN // 메모리[0x80]부터 32바이트를 반환
Bytecode 변환
602a // PUSH1 0x2a
6080 // PUSH1 0x80
52 // MSTORE
6020 // PUSH1 0x20
6080 // PUSH1 0x80
f3 // RETURN
최종 런타임 코드: 0x602a60805260206080f3
해결 과정
- 런타임 코드 작성: 0x602a60805260206080f3 (10바이트, 6개 opcode)
- 컨트랙트 배포: Constructor를 사용한 간단한 방법 활용
- Solver 등록: 배포된 컨트랙트 주소를 setSolver(address) 함수에 전달
핵심 포인트
- EVM opcode 직접 조작: Solidity 컴파일러 없이 Raw 바이트코드 작성
- 메모리 구조 이해: MSTORE/RETURN의 오프셋과 크기 관리
- 배포 vs 런타임 코드 구분: 제약사항이 런타임 코드에만 적용됨을 이해
- Constructor 활용: 배포 코드를 직접 작성하지 않고도 런타임 코드만 남길 수 있는 방법
1-3. Reference 분석
배포 코드 (Creation Code)
- Contract를 만들 때만 실행되는 코드
- Constructor가 여기에 해당
- 실행 후 사라짐 (블록체인에 저장되지 않음)
런타임 코드 (Runtime Code)
- Contract 주소에 실제로 저장되는 코드
- 함수를 호출할 때 실행되는 코드
- 문제에서 제한하는 것이 바로 이것!
Creation Bytecode란:
- SmartContract를 BlockChain에 배포할 때 사용되는 ByteCode
- Contract의 생성자(constructor) Code와 Runtime Code를 포함
- 배포 트랜잭션에서 data 필드에 포함됨
구성요소:
- Constructor bytecode: 초기화 로직 실행
- Runtime bytecode: 실제 컨트랙트 기능 코드
- Constructor parameters: 생성자 매개변수 (ABI 인코딩됨)
동작 과정:
- Creation bytecode 실행 → 초기화
- Runtime bytecode를 블록체인에 저장
- 이후 컨트랙트 호출 시 runtime bytecode 사용
2. Solving
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Script, console} from "forge-std/Script.sol";
import { MagicNum } from "../src/MagicNumber.sol";
contract Attack {
constructor() {
assembly {
mstore(0, 0x602a60805260206080f3)
return(0x16, 0x0a)
}
}
}
contract CounterScript is Script {
address public instance = 0x3332959970ffD99F06fE8671f10021D79d6fCbB6;
function run() public {
vm.startBroadcast();
MagicNum target = MagicNum(instance);
Attack attack = new Attack();
address payload = address(attack);
target.setSolver(payload);
vm.stopBroadcast();
}
}

3. 결론
솔리디티 코드는 겉모습일 뿐이며, 스마트 컨트랙트의 실제 동작과 보안은 EVM 바이트코드 수준에서 결정된다.
따라서 이 저수준(low-level) 동작을 이해하는 것이 가스비 최적화, 숨은 취약점 발견, 그리고 EVM의 완전한 기능 활용을 위한 핵심이다.
'Web3 > Hacking' 카테고리의 다른 글
| [Ethernaut] 21. Shop WriteUp (0) | 2025.08.20 |
|---|---|
| [Ethernaut] 19. Alien Codex WriteUp (2) | 2025.08.09 |
| [Ethernaut] 17. Recovery WriteUp (1) | 2025.08.08 |
| [Ethernaut] 16. Preservation WriteUp (1) | 2025.08.08 |
| [Ethernaut] 15. Naught Coin WriteUp (1) | 2025.08.07 |