Ir para conteúdo
  • Cadastre-se
kassane

Keygen Me 2018

Posts Recomendados

Olá Pessoal, blz?

Neste meu primeiro tópico, gostaria que vocês dessem uma "bisbilhotada" neste simples crackme feito por mim, usando (C++ STL => *MinGW32_dwarf 7.2 - Static*).

Qualquer erro/falha favor reportar!

Desde já agradeço!

 

Screenshot:

crackme.jpg.9b40912863b1eb085714b79635a874b8.jpg

crackme_gcc.zip

Editado por kassane
imagem

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi @kassane blz e você?

Acho que o você fez é um keygenme, já que imagino que a solução seja descobrir a senha. ;)

Cara, eu olhei aqui e vi que se a string de entrada tiver mais que 3 caracteres, você converte grupos de 4 caracteres da string para inteiro e depois faz um monte de cálculos entre XOR, shifts e multiplicações. Por fim compara o resultado com 0xed5dd719.

Eu tentei brutar com strings de 4 caracteres mas não consegui chegar nesse valor. Ficou uma coisa na minha cabeça: você conseguiu resolver este crackme? Digo, sem saber a senha, olhando o código em Assembly, você conseguiu resolver? Se sim, dá uma dica? :P

Abraços,

Fernando

Compartilhar este post


Link para o post
Compartilhar em outros sites

Beleza @Fernando Mercês! Sou iniciante nesta área.

Mas é foi um bom começo, você não ter resolvido. Isso significa que a tecnica usada foi boa. kkkk (Pensava que já tinha matado a charada de primeira)

Eu compilei essa aplicação em MinGW(que é este) e MSVC 2017 e em ambos inicialmente eu quebrei a função de comparação com um "jump". Desta forma aceitaria qualquer senha.

Quanto ao código, eu coloquei uma comparação entre o hash (gerado pelo compilador) da senha digitada com o já embutido, que obviamente é a senha real. Não tem a senha correta em string somente o hash dele.

Refs.: 

http://www.cplusplus.com/reference/functional/hash/

http://en.cppreference.com/w/cpp/utility/hash

Este é o resolvido: crackme_gcc_cracked.zip

Editado por kassane

Compartilhar este post


Link para o post
Compartilhar em outros sites
36 minutos atrás, kassane disse:

Beleza @Fernando Mercês! Sou iniciante nesta área.

Mas é foi um bom começo, você não ter resolvido. Isso significa que a tecnica usada foi boa. kkkk (Pensava que já tinha matado a charada de primeira)

Eu compilei essa aplicação em MinGW(que é este) e MSVC 2017 e em ambos inicialmente eu quebrei a função de comparação com um "jump". Desta forma aceitaria qualquer senha.

Quanto ao código, eu coloquei uma comparação entre o hash (gerado pelo compilador) da senha digitada com o já embutido, que obviamente é a senha real. Não tem a senha correta em string somente o hash dele.

Refs.: 

http://www.cplusplus.com/reference/functional/hash/

http://en.cppreference.com/w/cpp/utility/hash

Este é o resolvido: crackme_gcc_cracked.zip

Olá @kassane, nesse caso teria que quebrar o hash para descobrir a senha real, correto?

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
3 horas atrás, kassane disse:

eu quebrei a função de comparação com um "jump". Desta forma aceitaria qualquer senha.

Eu pensei que você queria a senha correta. É que patchear o jump é fácil po. rs

Mas como chegar na senha? Teria que quebrar essa função de hash como o @bornman falou. Era aí que eu tava trabalhando... ;)

Qual era a senha correta?

Compartilhar este post


Link para o post
Compartilhar em outros sites
33 minutos atrás, Fernando Mercês disse:

Eu pensei que você queria a senha correta. É que patchear o jump é fácil po. rs

Mas como chegar na senha? Teria que quebrar essa função de hash como o @bornman falou. Era aí que eu tava trabalhando... ;)

Qual era a senha correta?

Mas o objetivo é este quebrar o hash. Quanto ao "jump" foi um método mais rápido que eu usei para verificar a real diferença entre os compiladores que citei anteriormente.

Senha Correta: Tucaluca

Compartilhar este post


Link para o post
Compartilhar em outros sites
20 horas atrás, kassane disse:

Mas o objetivo é este quebrar o hash

Mas é possível mesmo? Por isso perguntei se você quebrou, entende? Uma função de hashing, se bem implementada, é one-way, ou seja, não dá pra "voltar" ao original.

Então eu tentei brutar os 3 caracteres e todas as combinações ASCII possíveis não funcionaram, ou seja, em nenhum caso na faixa dos caracteres imprimíveis para s[0], s[1] e s[2] é possível fazer com que eax seja 0xed5dd719.

unsigned eax;
char s[] = "???";

eax = (s[2] << 0x10) ^ 0xC70F6904;
eax ^= (s[1] << 8);
eax ^= s[0];
eax *= 0x5BD1E995;
eax ^= (eax >> 0xd);
eax *= 0x5BD1E995;
eax ^= (eax >> 0xf);

// Depois disso tudo eax tem que ser igual a 0xed5dd719;

Com 8 caracteres (que é o caso da senha correta) o algoritmo usado pela função é outro:

char s[] = "????????";

for (int i=0; i < 8; i++) {
	tmp = (unsigned *) &s[i*4];
	edi = *tmp * 0x5BD1E995;
	edx = edi >> 0x18;
	edx ^= edi;
	edi = eax * 0x5BD1E995;
	eax = edx * 0x5BD1E995;
	eax ^= edi;
}

edx = eax >> 0xd;
eax ^= edx;
eax *= 0x5BD1E995;
edx = eax >> 0xf;
eax ^= edx;

//eax tem que ser igual a 0xED5DD719

Mas com 8 caracteres já fica inviável brutar:

$ crunch 8 8 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 \!\"#$%&'()*+,-./:;<=>?@[\\]^_\`{|}"
Crunch will now generate the following amount of data: 54861204468697344 bytes
52319721668 MB
51093478 GB
49895 TB
48 PB

Então vejo 3 possibilidades:

  1. Você usou a função hash e conseguiu revertê-la quebrando seu próprio crackme, chegando na senha, o que significa que essa função é fraca, mas mais forte que eu. :D
  2. Você implementou seu próprio hash de maneira correta e ele não é quebrável.
  3. Você usou a função hash mas não quebrou o crackme e fez um crackme impossível, não por sua culpa, mas por ter usado uma função de hash segura.

Ajuda? :)

Abraço,

Fernando

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 horas atrás, Fernando Mercês disse:

Mas é possível mesmo? Por isso perguntei se você quebrou, entende?

Então eu tentei brutar os 3 caracteres e todas as combinações ASCII possíveis não funcionaram, ou seja, em nenhum caso na faixa dos caracteres imprimíveis para s[0], s[1] e s[2] é possível fazer com que eax seja 0xed5dd719.


unsigned eax;
char s[] = "???";

eax = (s[2] << 0x10) ^ 0xC70F6904;
eax ^= (s[1] << 8);
eax ^= s[0];
eax *= 0x5BD1E995;
eax ^= (eax >> 0xd);
eax *= 0x5BD1E995;
eax ^= (eax >> 0xf);

// Depois disso tudo eax tem que ser igual a 0xed5dd719;

Com 8 caracteres (que é o caso da senha correta) o algoritmo usado pela função é outro:


char s[] = "????????";

for (int i=0; i < 8; i++) {
	tmp = (unsigned *) &s[i*4];
	edi = *tmp * 0x5BD1E995;
	edx = edi >> 0x18;
	edx ^= edi;
	edi = eax * 0x5BD1E995;
	eax = edx * 0x5BD1E995;
	eax ^= edi;
}

edx = eax >> 0xd;
eax ^= edx;
eax *= 0x5BD1E995;
edx = eax >> 0xf;
eax ^= edx;

//eax tem que ser igual a 0xED5DD719

Mas com 8 caracteres já fica inviável brutar:


$ crunch 8 8 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 \!\"#$%&'()*+,-./:;<=>?@[\\]^_\`{|}"
Crunch will now generate the following amount of data: 54861204468697344 bytes
52319721668 MB
51093478 GB
49895 TB
48 PB

Então vejo 3 possibilidades:

  1. Você usou a função hash e conseguiu revertê-la quebrando seu próprio crackme, chegando na senha, o que significa que essa função é fraca, mas mais forte que eu. :D
  2. Você implementou seu próprio hash de maneira correta e ele não é quebrável.
  3. Você usou a hash mas não quebrou o crackme e fez um crackme impossível, não por sua culpa, mas por ter usado uma função de hash segura.

Ajuda? :)

Abraço,

Fernando

Olá @Fernando Mercês.

Bom, realmente eu usei a opção 2 (das possibilidades). Compilei o crackme com o hash da string exibido na tela anteriormente. E depois implementei somente o hash da string e removendo o mesmo.

Conseguir burlar de forma diferente! Mudando a senha.

Quanto ao fato de descobrir a senha se torna inviável até o momento pois vai depender muito do compilador!

*O hash é gerado de forma exclusiva pelo compilador, como se fosse um MAC address/Chassi/CPF).

O que eu fiz:

1) Compilei o arquivo com o hash da string na tela ex: fernando -> meu compilador gerou um hash(2436023558) e (convertendo esse hash para Hex = 0x9132C506)

O mesmo vale para a senha original ([string]Tucaluca = [int]3982350105 = [hex]0xED5DD719)

2) Já no Debugger eu troquei 0xED5DD719 -> 0x9132C50 . Agora ele aceita como senha "fernando".

 

Não sei informar de forma mais técnica, devido a minha falta de experiência!! Acredito que deu para ter uma noção.

Editado por kassane

Compartilhar este post


Link para o post
Compartilhar em outros sites

Opa!

1 hora atrás, kassane disse:

realmente eu usei a opção 2 (das possibilidades)

Então.. Fiquei um pouco confuso: você que escreveu a função que faz o hash? Ou usou uma função pronta da biblioteca de C++?

1 hora atrás, kassane disse:

Conseguir burlar de forma diferente! Mudando a senha.

Sim, querido, patcheando dá pra fazê-lo aceitar qualquer coisa. Só que você disse que o desafio era quebrar o hash (eu entendi que era descobrir a senha, não burlar a checagem).

Tá tudo certo e também foi legal pra estudar um pouco. Tinha tempo que eu não brutava nada e tal. Foi uma noite e tanto. :)

Abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites
9 minutos atrás, Fernando Mercês disse:

Opa!

Então.. Fiquei um pouco confuso: você que escreveu a função que faz o hash? Ou usou uma função pronta da biblioteca de C++?

Usei o próprio std::hash.

Fonte:

Spoiler

#include <iostream>
#include <functional>
#include <string>

int main (void)
{
  //std::string passwd = "Tucaluca";
  std::hash<std::string> ptr_hash;
  std::string senha="";
  
  setlocale(LC_ALL,"");
  
  //MENU
  std::cout << std::string(50, '=') << '|' << std::endl;
  std::cout << "\t  Crack Me! 2018. - Mente Binária\t  |" << std::endl;
  std::cout << std::string(50, '=') << '|' << std::endl;
  
  //Pergunta
  std::cout << "Qual eh a palavra-chave: ";
  cin >> senha;
  
  std::cout << "\n\nVoceh digitou: " << senha << std::endl;
  std::cout << std::endl;
  
  // *Exibir Hash das senhas:*
  //std::cout << "hash da Senha: " << ptr_std::hash(passwd) << endl;
  //std::cout << "hash da Senha: " << ptr_std::hash(senha) << endl;
  
  const int hashed = 3982350105;// == ptr_std::hash(passwd)
  
  if(ptr_hash(senha) == hashed) std::cout << "Correto!\n";
  else std::cerr << "Errado!\n";
  
  return 0;
}

 

 

17 minutos atrás, Fernando Mercês disse:

Só que você disse que o desafio era quebrar o hash (eu entendi que era descobrir a senha, não burlar a checagem).

Sim o intuito/objetivo era realmente esse inicialmente, porém no atual momento percebi que é impossível. Pois pelo que pude aprender aqui (embora não tenha achado uma explicação analítica do std::hash, devido ser muito complexo) depende muito do compilador que está usando. Por exemplo eu testei em outro compilador g++(MinGW) mesmo x86  e nele me resultou outro hash a mesma string. 

Mas independentemente deste resultado que é igual *0*, continuarei estudando sobre o assunto e qualquer novidade irei compartilha-lo já que nenhuma tecnologia é perfeita.

15 minutos atrás, Fernando Mercês disse:

Tá tudo certo e também foi legal pra estudar um pouco. Tinha tempo que eu não brutava nada e tal. Foi uma noite e tanto. :)

Abraço!

Eu que lhe agradeço pela paciência!! :D

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu não sei nada de c++ ou sobre sua biblioteca padrão mas fiquei curioso, que hash é esse? md5, sha1, se é algo da biblioteca padrão deve ser algo bem estudado para ser seguro e no mínimo deve estar presente neste link. Por favor, estou curioso para saber que hash é esse, quando alguém souber o algorítimo (o nome) publiquem aqui pra eu e mais pessoas aprendermos. obrigado

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em 22/02/2018 em 19:05, gzn disse:

Eu não sei nada de c++ ou sobre sua biblioteca padrão mas fiquei curioso, que hash é esse? md5, sha1, se é algo da biblioteca padrão deve ser algo bem estudado para ser seguro e no mínimo deve estar presente neste link. Por favor, estou curioso para saber que hash é esse, quando alguém souber o algorítimo (o nome) publiquem aqui pra eu e mais pessoas aprendermos. obrigado

Falai, gzn.. Bele ?

Não usa nenhum algoritmo conhecido, pois é implementation-dependent (http://en.cppreference.com/w/cpp/utility/hash). Ou seja, depende muito do compilador que você usa e etc, quer dizer que pode variar de uma compilação para outra. Esse hashing não é feito para segurança/criptografia, ele tem uma porcentagem de ser único dependendo do argumento que você passa e tem um limite. É extremamente difícil de ser igual com dois argumentos diferentes, mas é probabilístico. std::hash é principalmente feito para que você possa montar sua própria "hashtable" para mapear dados de forma não ordenada.

http://en.cppreference.com/w/cpp/concept/Hash

Se eu falei merda, por favor me corrijam.. haha =))

  • Agradecer 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

×