$ cat writeup.md…
$ cat writeup.md…
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.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
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.
/rpc, /flag, /connection_info, /docsSetup (0x4e07...):
isSolved(address) — checks items[2].owner == player_address on ShopTARGET() — Shop contract addressSilverCoins (0x045d...) — ERC20 token:
Shop (0xf39e...) — shop with 3 items:
| Item | Name | Price | Owner |
|---|---|---|---|
| 0 | Diamond Necklace | 1,000,000 | Shop |
| 1 | Ancient Stone | 70,000 | Shop |
| 2 | Golden Key | 25,000,000 | Shop |
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.
When analyzing the ERC20 token bytecode, two different internal _transfer functions were discovered:
_transfer for transferFrom() (offset 0x63b): Correctly checks require(balances[from] >= amount)....
$ grep --similar