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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons no total são permitidos.

×   Seu link foi automaticamente incorporado.   Mostrar como link

×   Seu conteúdo anterior foi restaurado.   Limpar o editor

×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.


  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

×
×
  • Criar Novo...