CryoPod
3 minutos de lectura
Se nos proporciona un Smart Contract llamado CryoPod.sol
:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title CryoPod
* @dev A smart contract that allows each user to create and store a personal pod with a piece of
information.
* The information is stored permanently on the blockchain, and an event is emitted upon each
storage action.
*/
contract CryoPod {
mapping(address => string) private pods;
event PodStored(address indexed user, string data);
/**
* @dev Stores or updates the caller's pod with the provided data.
* @param _data The information to be stored in the user's pod.
*/
function storePod(string memory _data) external {
pods[msg.sender] = _data;
emit PodStored(msg.sender, _data);
}
}
And another Smart Contract called Setup.sol
:
pragma solidity ^0.8.0;
import { CryoPod } from "./CryoPod.sol";
contract Setup {
CryoPod public immutable TARGET;
bytes32 public flagHash = 0x0;
event DeployedTarget(address at);
constructor() payable {
TARGET = new CryoPod();
emit DeployedTarget(address(TARGET));
}
function isSolved(string calldata flag) public view returns (bool) {
return keccak256(abi.encodePacked(flag)) == flagHash;
}
}
También hay una instancia remota en la que obtendremos los parámetros de conexión a la Blockchain:
$ nc 83.136.250.185 45551
1 - Get connection informations
2 - Restart Instance
3 - Get flag
Select action (enter number): 1
[*] No running node found. Launching new node...
Player Private Key : 29297604e2a672bd0178ac2b8672c14a1419236bcc7316c99ee9888b518dd5bb
Player Address : 0xD0b65173e2984c2EF011F7A6cA406f7723A6d7b4
Target contract : 0x44B189e4bA6DB658a8207B2432c4a6FcfD2555bf
Setup contract : 0xBF037deD3881Cb3f0ccC797E00E3F34c0FF79355
Configuración del entorno
En primer lugar, guardemos los parámetros de conexión como variables de shell:
$ PRIVATE_KEY='0x29297604e2a672bd0178ac2b8672c14a1419236bcc7316c99ee9888b518dd5bb'
$ ADDRESS='0xD0b65173e2984c2EF011F7A6cA406f7723A6d7b4'
$ ADDRESS_TARGET='0x44B189e4bA6DB658a8207B2432c4a6FcfD2555bf'
$ ADDRESS_SETUP='0xBF037deD3881Cb3f0ccC797E00E3F34c0FF79355'
$ export ETH_RPC_URL='http://83.136.250.185:44604'
Análisis del código fuente
Ambos Smart Contracts son muy simples, pero en realidad no hay nada que hacer con ellos. Nótese que CryoPod
tiene una sola función para almacenar valores de tipo string
en un mapping
llamado pods
:
function storePod(string memory _data) external {
pods[msg.sender] = _data;
emit PodStored(msg.sender, _data);
}
Una vez que se establece el valor, se emite un evento PodStored
mostrando el usuario y el valor almacenado.
Por otro lado, para resolver el reto, necesitamos pasar isSolved
:
function isSolved(string calldata flag) public view returns (bool) {
return keccak256(abi.encodePacked(flag)) == flagHash;
}
Esto es extraño ya que flagHash
se inicializa como 0x0
, y no podemos encontrar una preimagen para la función hash keccak256
.
Analizando los logs
Lo único que podemos hacer es verificar los eventos emitidos por los Smart Contracts. Afortunadamente, podemos hacerlo con cast logs
:
$ cast logs
- address: 0xa09ab4ac0D70fEB0f7577913183D440768211C44
blockHash: 0x38d2fe8a348b61e6ce8d4f20c4c4ef3bc051e65e5c99ac3ccdad0c35b78c0d8f
blockNumber: 1
data: 0x00000000000000000000000030dd90e431771a5b2d6db874e5bd397c467b5634
logIndex: 0
removed: false
topics: [
0xc26ec5464cc58ea5f3597f1daab5d82585655e1bfd634b0a94fdd5ab63740dbf
]
transactionHash: 0x7d309a2ef9d98df82d53dfd0178c99a01dc6de9b5be9309c4a6582872bb91921
transactionIndex: 0
- address: 0x30dd90e431771a5B2D6dB874E5bD397c467B5634
blockHash: 0x6a56d5533425347ee0a3c95ce610c9e80342fac49d81b8f1f3d8deb669c6e131
blockNumber: 2
data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003d72a2a5065616e75742042757474657220616e64205069636b6c652053616e64776963682a2a3a203220736c69636573206f66206272656164202877686974652c2077686f6c652077686561742c206f7220736f7572646f756768292c2032207461626c6573706f6f6e73206f66205065616e7574204275747465722c20342d362064696c6c207069636b6c6520736c696365732c20612064617368206f6620686f742073617563652c206c6574747563652c206f7220686f6e657920286f7074696f6e616c292e205072657061726174696f6e3a203129204170706c79207065616e757420627574746572206576656e6c79206f6e206f6e652073696465206f66206561636820627265616420736c6963652e203229204c6179657220746865207069636b6c6520736c69636573206f6e206f6e65207065616e7574206275747465722d636f766572656420627265616420736c6963652e20332920416464206120737072696e6b6c65206f662073616c742c20686f742073617563652c206f72206578747261206c6179657273206c696b65206c6574747563652e20342920506c61636520746865207365636f6e6420627265616420736c696365206f6e20746f702c207065616e757420627574746572207369646520646f776e2e2050726573732067656e746c792e2035292043757420646961676f6e616c6c7920666f72206561736965722068616e646c696e6720616e6420656e6a6f792e204465736372697074696f6e3a20456d6261726b206f6e20616e20756e65787065637465642067617374726f6e6f6d6963206a6f75726e65792077697468206f7572205065616e7574204275747465722026205069636b6c652053796d70686f6e792c2061206861726d6f6e696f757320667573696f6e206f6620636f6e7472617374696e6720666c61766f727320616e642074657874757265732074686174207265646566696e652074686520626f756e646172696573206f6620636f6e74656d706f726172792063756973696e652e2054686973206176616e742d6761726465206372656174696f6e206d6172726965732074686520726963682c2076656c76657479206e6f746573206f66206172746973616e616c20637265616d79207065616e7574206275747465722077697468207468652063726973702c2074616e6779207a657374206f662068616e642d73656c65637465642064696c6c207069636b6c65732c206d65746963756c6f75736c79206c617965726564206265747765656e20736c69636573206f662066726573686c792062616b65642c2073746f6e652d67726f756e6420736f7572646f7567682062726561642e000000000000000000
logIndex: 0
removed: false
topics: [
0x8756f21c4a2b6b179da2cf2bfd156724e3ae8c1f5fc7d3e25d9483733e5d9221
0x0000000000000000000000007687cb40c834da6f0feb151ab9636c0c0574aef0
]
transactionHash: 0x528f0c35a7b609862ecde4f1933d4369c145dffa310475f4810a9098cd9d8dc4
transactionIndex: 0
...
Aquí tenemos muchos eventos. Debemos deducir que alguien está almacenando la flag en pods
, Por lo tanto, podremos recuperarla inspeccionando los logs.
Tomemos los algunos caracteres conocidos de la flag en formato hexadecimal para filtrar los eventos:
$ echo -n 'HTB{}' | xxd -p
4854427b7d
$ cast logs | grep 4854427b
data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000184854427b68336c6c305f636834316e5f736330757433727d0000000000000000
$ cast logs | grep -oE '4854427b.*7d'
4854427b68336c6c305f636834316e5f736330757433727d
Flag
En este punto, simplemente podemos decodificar y obtener la flag:
$ echo 4854427b68336c6c305f636834316e5f736330757433727d | xxd -r -p
HTB{h3ll0_ch41n_sc0ut3r}
No es necesario usar la función isSolved
y verificar que hemos resuelto el reto.