Skip to main content

Fetch the Flag CTF 2022: solução do Treasure Trove

Escrito por

Luke Watts

feature ctf treasure trove

10 de novembro de 2022

0 minutos de leitura

Obrigado por jogar Fetch com a gente! Parabéns às milhares de pessoas que participaram do Fetch the Flag CTF. E um agradecimento especial aos Snykers que criaram, testaram e escreveram as soluções dos desafios!

O Fetch the Flag deste ano foi incrível, mas também deu bastante trabalho! Com 16 desafios e pouco tempo, nem todas as equipes conseguiram concluir todos. Para quem não conseguiu vencer o relógio, vamos mostrar como nossa equipe resolveu o desafio Treasure Trove.

Passo a passo

O enunciado do desafio era: “a versão mais recente do Treasure Trove já saiu, mas onde coloquei minha chave de licença?”. Para começar, há uma tag que diz Engenharia reversa e um arquivo obfuscator.js fornecido.

Também há um link para um site com campos de entrada para caracteres em uma grade 5x5, um botão e uma arte incrível que me faz lembrar de quando eu jogava Curse of Monkey Island.

Jogo de navegador Treasure Trove mostrando um baú acorrentado em uma ilha tropical, um navio pirata, campos de código e o botão “Resgatar e navegar pelos sete mares!”

Ao analisar o código fornecido, você encontra uma ferramenta que transforma código legível por humanos em um monte de lixo.

Agora, vamos dar uma olhada no site. Há um endpoint swashbuckle.js com um método chamado validate. O código parece corresponder à saída que o obfuscator vai gerar. Hmm…

Observando mais de perto, vemos que o método validate está disponível no objeto window e é chamado quando o formulário é enviado. Uau, parece que fazer engenharia reversa de validate é o único caminho… Será que o navegador pode ajudar? Vamos chamar validate.toString() pelo console do navegador. Bingpot!

function anonymous(
) {

const segementOne = document.getElementById('seg-1');
const segementTwo = document.getElementById('seg-2');
const segementThree = document.getElementById('seg-3');
const segementFour = document.getElementById('seg-4');
const segementFive = document.getElementById('seg-5');

const setError = (message) => {
  document.getElementById('error-msg').innerText = message;
}

setError('');
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const key = segementOne.value + segementTwo.value + segementThree.value + segementFour.value + segementFive.value;
if (key.length != 25) {
  setError('Invalid redemtion code!')
  return;
}

let val = 0;
for (let i = 0; i < 25; i++) {
  val += key.charCodeAt(i);
  if (!characters.includes(key[i])) {
    setError('invalid characters');
    return;
  }
}

if (val != 1800) {
  setError('invalid code');
  return;
}

fetch('/api/validatekey/' + key)
.then(async res => {
  const result = await res.json();
  setError('Argg ye got it! ' + result.flag);
});

}

Parece que o código executa as seguintes etapas:

  1. Busca os valores dos campos de entrada do HTML

  2. Verifica se os caracteres estão no intervalo A-Z0-9

  3. Percorre os caracteres, converte-os em charCode e soma esses valores. O método charCodeAt() retorna um número inteiro entre 0 e 65535 que representa a unidade de código UTF-16 no índice informado. Fonte

  4. Gera um erro se o valor não for igual a 1800

  5. Se o valor for igual a 1800, os valores de entrada originais serão enviados a um endpoint de API

A conclusão mais interessante é que, se o valor não for 1800, o código é inválido.

  1. 1800 / 25 (o total de caracteres disponíveis)

  2. 72

  3.  String.fromCharCode(72)

  4. Retorna H

Digite HHHHH em cada campo de entrada

Tela de um jogo no navegador intitulado “Treasure Trove”, mostrando um baú do tesouro acorrentado sob uma palmeira em uma ilha, um navio pirata e a frase “Resgate e navegue em alto-mar!”

Bingpot de novo!

Página do navegador intitulada “Treasure Trove”, com um baú acorrentado em uma ilha com palmeiras, um navio pirata, texto codificado e cinco campos de entrada

Conseguimos resolver esse desafio sem precisar mexer no código do obfuscator. Assim, sobrou bastante tempo para começar o próximo desafio!

Quer saber como encontramos todas as outras flags? Confira a página soluções do Fetch the Flag para ver como fizemos.