kassane Posted February 17, 2018 Posted February 17, 2018 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_gcc.zip
Administrators Fernando Mercês Posted February 21, 2018 Administrators Posted February 21, 2018 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? Abraços, Fernando
kassane Posted February 21, 2018 Author Posted February 21, 2018 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
bornman Posted February 21, 2018 Posted February 21, 2018 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?
Administrators Fernando Mercês Posted February 21, 2018 Administrators Posted February 21, 2018 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?
kassane Posted February 21, 2018 Author Posted February 21, 2018 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
Administrators Fernando Mercês Posted February 22, 2018 Administrators Posted February 22, 2018 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: 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. Você implementou seu próprio hash de maneira correta e ele não é quebrável. 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
kassane Posted February 22, 2018 Author Posted February 22, 2018 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: 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. Você implementou seu próprio hash de maneira correta e ele não é quebrável. 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.
Administrators Fernando Mercês Posted February 22, 2018 Administrators Posted February 22, 2018 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!
kassane Posted February 22, 2018 Author Posted February 22, 2018 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!!
gzn Posted February 22, 2018 Posted February 22, 2018 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
Pimptech Posted April 29, 2018 Posted April 29, 2018 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 =))
Aof Posted May 30, 2018 Posted May 30, 2018 fiquei perdido quando o @Fernando Mercês falou em ```"brutar". rs como que faz isso ? alguém pode me ajudar?
Recommended Posts
Archived
This topic is now archived and is closed to further replies.