Table of Contents
Hello mate, I played MetaRedCTF. I am too late to the party got few hours to play, but solved few blockchain challenges. Challenges are not available after CTF, so I can't explain in detail what the challenge is. I try my best to explain what I did.
Blockchain
GiveMeMoney [500pts]
Challenge is to find network and contract method to call. We are given with contract address.
0xA2720666b2e3D878b0E7FC80bc1D02958EA648DE
Initiated a foundry project quickly.
forge init
Created the solution script under /scripts
.
SolveGiveMeMoney.s.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Script.sol";
contract GiveMeMoneyScript is Script {
function setUp() public {}
function run() public {
vm.startBroadcast();
solveGiveMeMoney();
vm.stopBroadcast();
}
function solveGiveMeMoney() public {
address target = 0xA2720666b2e3D878b0E7FC80bc1D02958EA648DE;
(bool success, ) = target.call{value:0.101 ether}(abi.encodeWithSignature("deposit(string)","ODM1.pHrlmtdBQY9UIYaE-WVDGTPOWP0"));
require(success);
}
}
This script will call the contract method deposit()
with the string provided in the challenge as arguement. We have to send above 0.1 Eth
along with the call.
To run the script we need to find the network of the contract. It is Goerli
, Found from etherscan. We need some test ether mined it from goerli POW faucet.
To run the script :
mj0ln1r@AHLinux:~/$ forge script scripts/SolveGiveMeMoney.s.sol --rpc-url <REDACTED> --private-key <REDACTED> --broadcast
The RPC-URL can create from alchemy, private-key is your testing wallet private key.
We wont get the flag, the challenge will be automatically solved once we run this.
Open [500pts]
Contract : 0x35388184260d8A3cE75B5df5bbA1904b68746b27
This challenge is also kinda same, the solve script is as follows,
SolveOpen.s.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Script.sol";
import {console} from "forge-std/console.sol";
contract OpenScript is Script {
function setUp() public {}
function run() public {
vm.startBroadcast();
solveOpen();
vm.stopBroadcast();
}
function solveOpen() public {
address target = 0x35388184260d8A3cE75B5df5bbA1904b68746b27;
(bool success, bytes memory _data) = target.call(abi.encodeWithSignature("givemetheflag(string)","ODM1.pHrlmtdBQY9UIYaE-WVDGTPOWP0"));
require(success);
console.logBytes(_data);
}
}
To run the script :
mj0ln1r@AHLinux:~/$ forge script scripts/SolveOpen.s.sol --rpc-url <REDACTED> --private-key <REDACTED> --broadcast
Flag will be automatically submitted once we run this script.
Ether Footprint [500pts]
Challenge provided with a contract address. And description says observe the ether dance.
Contract : 0x24D1a591b816C175eBF4cD62277ecCcdA42d1211
When I look the transactions to the given contract on goerli etherscan, there are 37 transactions available. I observed that the eth value in every transaction was different. I saw in the challenge tag something like 9856855-9856895
. These two numbers are block numbers of the starting trransaction and last block number of the transaction to this contract.
Look here to observe : Goerli Etherscan
So, I used web3.py
to list all the transaction to the target contract between these two block numbers. I fetched the value of each transaction in wei. I observed the 0,1 indexes
of the wei string represents the index of the character. And 4,5,6
indexes are the ascii values of the flag.
I wrote this web3.py
script which solves challenge and prints flag for us.
Solve.py
from decimal import Decimal
from web3 import *
START_BLOCK = 9856855
END_BLOCK = 9856895
RPC_URL = "https://eth-goerli.g.alchemy.com/v2/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
def main():
values = []
w3 = Web3(Web3.HTTPProvider(RPC_URL))
for _block in range(START_BLOCK+1, END_BLOCK):
block = w3.eth.get_block(_block, full_transactions=True)
for transaction in block.transactions:
if transaction["to"] == "0x24D1a591b816C175eBF4cD62277ecCcdA42d1211":
print(_block,transaction["value"])
values.append(transaction["value"])
d = {}
for i in values:
string = str(i)
if(len(string) != 15):
string = ((15 - len(string)) * "0") + string + "x"# extra x to identify padded str
if(string[-1] == "x"):
d[int(string[0:2])] = chr(int(string[4:7]))
else:
d[int(string[0:2])] = chr(int(string[4:7]))
for i in range(37):
print(d[i],end="")
if __name__ == "__main__":
main()
# Output
# flag{Gg_g00d_j0b_3th3r3um_1s_4w3s0m3}
Yeah Ethereum is awesome...