I'm trying to solve this -simple- small CTF challenge, the goal is to change the solver value to our address by calling the talk function:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Rivals {
    event Voice(uint256 indexed severity);

    bytes32 private encryptedFlag;
    bytes32 private hashedFlag;
    address public solver;

    constructor(bytes32 _encrypted, bytes32 _hashed) {
        encryptedFlag = _encrypted;
        hashedFlag = _hashed;

    function talk(bytes32 _key) external {
        bytes32 _flag = _key ^ encryptedFlag;
        if (keccak256(abi.encode(_flag)) == hashedFlag) {
            solver = msg.sender;
            emit Voice(5);
        } else {
            emit Voice(block.timestamp % 5);

The whole idea of the challenge is to predict the _key value needs to be passed to talk function that when it's passed to the keccak256 it will produce the hasedFlag, the keccak256 is a hash algorithm, and so it is one way, how can we predict the input? Or are we talking here about possible hash collision? I did some research and I found that keccak256 is collision-safe for now.

PS: we can easily get the values of ecryptedFlag and hashedFlag by querying the storage.

  • There's something missing, reversing keccak256 isn't feasible. Either it is a well known value like empty string, or there's an alternative way to calculate it.
    – Ismael
    Commented Oct 13, 2023 at 18:31
  • I also got confused too. I've provided everything provided by the challenge. Commented Oct 16, 2023 at 11:23

1 Answer 1


You have all the values needed to re-validate js. _key will have to be picked up by brute force.

Maybe this code will help

import { ethers } from "ethers";

const encryptedFlag = 'your_flag_value';  //bytes32
const hashedFlag = '0xYourHashedFlag';

let key = 1;
while(true) {
  const _key = ethers.encodeBytes32String(key.toString());
  const flagXOR = _key ^ encryptedFlag;
  const encodedFlag = ethers.AbiCoder.defaultAbiCoder().encode(['bytes32'], [flagXOR]);
  const flagHash = ethers.keccak256(encodedFlag);

  if (flagHash === hashedFlag) {
    console.log(`key: ${key}`);

  • There are up to 2^256 possibilities, I believe we can not brute force it unless the wanted value is on the first ranges. Commented Oct 12, 2023 at 17:13
  • Right, I know. Are you trying CTF )) Commented Oct 12, 2023 at 18:01
  • Yes, I'm x) Your proposed solution worth a try, I can see no alternative. Commented Oct 13, 2023 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.