blockchainfreemedium

Token to Wonderland

hackthebox

Task: Buy Golden Key from Shop contract with only 100 SVC tokens when price is 25,000,000. Solution: Exploit integer underflow in Solidity 0.7.x ERC20 token where transfer() skips balance check, causing balance to wrap to 2^256-1, then approve and purchase.

$ ls tags/ techniques/
integer_underflowevm_bytecode_reverseerc20_balance_manipulationdual_transfer_implementation

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

Token to Wonderland — HackTheBox

Description

A group found a map to a treasure guarded by 3 keys. They need to acquire the "Golden Key" from a dwarf's shop, but they don't have enough "SilverCoins" (ERC20 tokens) to buy it. The challenge provides a private Ethereum chain with three contracts: Setup, SilverCoins (ERC20), and Shop.

Goal: Buy the Golden Key (item 2) from the Shop contract, having only 100 SVC tokens while the price is 25,000,000.

Analysis

Infrastructure

  • Private Ethereum chain (chain ID 31337)
  • Web interface: /rpc, /flag, /connection_info, /docs
  • Player receives 5000 ETH and 100 SVC (SilverCoins) tokens

Contracts

Setup (0x4e07...):

  • isSolved(address) — checks items[2].owner == player_address on Shop
  • TARGET() — Shop contract address

SilverCoins (0x045d...) — ERC20 token:

  • Compiled with Solidity 0.7.06 (no built-in overflow/underflow protection!)
  • Total supply: 1e15
  • Player receives 100 tokens, the rest goes to Setup

Shop (0xf39e...) — shop with 3 items:

ItemNamePriceOwner
0Diamond Necklace1,000,000Shop
1Ancient Stone70,000Shop
2Golden Key25,000,000Shop

buyItem Function

1. Loads item from storage
2. Checks item.owner == address(this) (shop must own it)
3. Calls token.transferFrom(msg.sender, address(this), item.price)
4. Checks return value: require(success, "Payment failed!")
5. Sets items[id].owner = msg.sender

buyItem uses transferFrom(), which correctly checks the balance. This means we need to have enough tokens.

Vulnerability: Dual _transfer Implementation

When analyzing the ERC20 token bytecode, two different internal _transfer functions were discovered:

  1. _transfer for transferFrom() (offset 0x63b): Correctly checks require(balances[from] >= amount).

...

$ grep --similar

Similar writeups