Snake [Hack The Box :: Reversing Challenge] PT-BR

r4msolo
6 min readAug 26, 2019

Bom já fazia um tempo que queria iniciar o Hack The Box, e hoje foi o dia D, conforme eu for resolvendo os desafios irei postar os write-ups aqui no Medium. Sem mais delongas bora lá…

A challenge que escolhi de começo foi a Snake da categoria de engenharia reversa, um desafio bem fácil de início.

Use o comando ‘unzip Snake.zip’ para descompactar, digite a senha e dê enter. Agora é só felicidade =D

Primeiramente o arquivo vem em .ZIP e a senha para descompactar é hackthebox até aí tudo bem mas vamos analizar do que se trata o arquivo em python.

Rodei o programa para ver o comportamente e tive a seguinte saída:

O programa pediu um username válido na entrada e eu testei com “root”, óbviamente não estava certo mas pude notar que além disso ele retorna um número lá em cima escrito “Your number is 660”, então fui olhar o código fonte do arquivo.

Bom o username está dentro desse arquivo e precisamos procurar pelo local onde é feito a comparação de entrada com o username primeiro!

user_input é comparado com slither que por sua vez é a variável que guarda o username e… Opa! Olha ela lá em cima. Ela é composta pela soma de outras 8 variáveis, que nessa imagem, já podemos ver 2 delas, aa e rr. Elas guardam uma string em hexadecimal que vai ser covertida em ASCII na hora de exibir então porque não trapacear um pouco e pedir pro programa exibir essa variável quando ele nos pedir o username? Vejamos…

Fiz a alteração, rodei e BINGO! Nosso username é ‘anaconda’ agora ele pediu a senha para anaconda, tranquilo meus jovens bora lá

Okay, para o password ele usa um laço de repetição ‘for’ para cada letra que nós digitar na entrada de password, e em seguida mais um laço ‘for’ para percorrer a lista cujo nome é ‘chars’, caractere por caractere, para ver se são iguais ao da entrada (pass_input).

Chars é uma lista vazia mas logo abaixo vemos o momento que ela é incrementada com o ‘chars.append(keys_encrypt)’, keys_encrypt recebe XOR (caso não saiba o que siginifica é só seguir o link) entre lock e key, onde key é cada elemento da variável lista “keys”, pois está declarado no início do ‘for’, e o lock é um valor recebido atraves da função random, lembra aquele número que falei lá no início? Poisé ele é um número gerado aleatóriamente entre os valores de 0 à 0x3e8 que corresponde a 1000 em hexadecimal, e é definido bem aqui embaixo.

Bom, mas esse número não é beeeem aleatório na variável “lock”, até porque se fosse teriamos password diferentes na hora de conseguir a flag e ela tem que ser única! Mas ele multiplica o valor aleatório por 2, soma 10, divide por 2 e depois diminue lock_pick(o próprio valor aleatório) do total … Viu que aqui ele manipulou os números? Como um truque de mágica forçando a carta nesse caso o valor. Multiplicou por 2 e depois dividiu por 2, operações inversas (deu na mesma), o número 10 adicionado agora passa a valer metade ou seja 5, não interessa qual valor for gerado aleatóriamente o final sempre vai dar 5 já que ele diminui lock_pick desse valor.

Se o valor sempre é 5, é só aplica um XOR entre 5 e a cada elemento dessa lista keys conforme está no código

keys = [0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x21, 0x21]

peguei cada elemento desses e tirei o “0x” ficando assim

70 61 73 73 77 6f 72 64 21 21 se consultares a tabela ASCII no próprio comando “man ascii” no linux e ver os números hexadecimais correspondente pode ver a palavra “password!!”

Use o comando “man ascii” essa tabela é muito útil!

eu usei um algoritimo que desenvolvi em python para facilitar isso e olha que legal

link: https://github.com/r4msolo/scripts/tree/master/cryptography

eu olhei aquela lista com nome “chains” e fiz o mesmo porque não né? =D

chains = [0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x72, 0x6f, 0x6c, 0x6c]

74 68 69 73 20 69 73 20 61 20 74 72 6f 6c 6c

e o resultado disso:

O QUE?!? Fui trollado! Existe algumas variáveis aí que são realmente feitas pra confundir-nos mas não deixei-me abalar 😄. Nesse momento não havia entendido bem o propósito desse texto mas tudo ficou claro no final.

por curiosidade olhei a próxima!

auth = [0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67]

foi a última, e convertendo isso para texto deu a seguinte frase:

Legal! Depois do troll ele nos motivou para continuar tentando e foi o que eu fiz.

bom eu adicionei um print no laço ‘for’ em cada keys_encrypt usando a função chr() que retorna a representação desses inteiros em string (em texto), a saída foi essa:

entrei com usuário mas deixei um print pra vocês verem que existia uma pegadinha aqui

Essa parte que destaquei em verde corresponde a lista que nos deu o resultado “This is a troll” a “chains”, ela foi adicionada ao “chars”, olhando o código percebi que em nenhum momento chains era chamada e comecei a ficar com uma pulga atrás da orelha, até descobrir que ela estava ali apenas para atrapalhar

Eu já havia achado estranho até por conta da mensagem e tive certeza quando tentei entrar com o password dessa forma “udvrjwa$$~rs}*s}*k*~|yvv” como havia ficado chars, e como era de se esperar não deu certo, foi aqui que os pontos se ligaram e começou a fazer sentido a mensagem de chains, até que entrei apenas com “udvrjwa$$” pois equivale exatamente ao número de caracteres de keys e então…

Dei enter e voilè conseguimos!!! E na ordem do desafio estava para enviar nossa flag no seguinte formato

ficando exatamente assim:

HTB{anaconda:udvrjwa$$}

Bom pessoal se leram até aqui vocês são muito doidos 😄 , brincadeiras a parte, foi meu primeiro writeup realmente sou novato nisso mas quero aprender e registrar aqui todo meu progresso, e tentar ajudar quem esta começando assim como eu.

Se quiserem conversar comigo sobre CTF mandem mensagem pelo meu telegram https://t.me/r4msolo vai ser legal e eu não sou tão chato quanto pareço 😆. Obrigado à todos(as), sugestões de melhorias são bem vindas e que a força esteja com vocês!

--

--