Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

Brute Force em C

Collapse
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Brute Force em C

    Nesse post irei mostrar um simples cracker de senhas usando a linguagem C.

    Como quebrar as senhas

    A lógica mais usual que um cracker de senhas usa é a seguinte:

    Ler uma lista de palavras, conhecida como wordlist.
    Para cada palavra da wordlist, cria-se um hash dela usando o mesmo algoritmo e salt utilizados para gerar o hash que queremos quebrar.
    Compara-se os hashes. Se são iguais, então a senha foi quebrada.
    Para mais detalhes, veja o link no início do post e suas referências.

    O programa

    O programa se chama qcrack.c e seu código se encontra no fim deste post. Para compilá-lo, digite:

    $ gcc -o qcrack qcrack.c -lcrypt
    Para executá-lo você precisará de dois arquivos: O primeiro é o arquivo de senhas encriptadas, ou seja, o arquivo /etc/shadow. O segundo é uma wordlist, que nada mais é que uma lista de palavras. Wordlists podem ser encontradas facilmente na internet, mas se você deseja gerar uma usando permutações, veja o script na referência [1].

    Exemplo de uso real

    Para testar o programa criei um usuário em meu sistema cuja senha era uma data qualquer. Senhas em formato de data são muito utilizadas e em geral são facilmente quebradas.

    Com isso criei uma wordlist usando o brutus.sh [1]:

    $ ./brutus.sh -d -r 4 | sed 's/$/88/' > wordlist.txt
    O conteúdo da wordlist é da forma: XXXX88 que inclui todos os dias do ano de 88 (e mais alguns números como 000088 que não são datas válidas).

    Criada a wordlist, agora vamos executar o programa:

    $ sudo su #(precisamos de root para ler o /etc/shadow)
    # ./qcrack /etc/shadow wordlist.txt
    Usuario : daemon9
    Algoritmo : SHA-512
    Salt : Y0R8yeD/
    Hash : OyzjYU8Nfl9A7xXCOZwX1DfejOMBIAoTq7Gbw20juhZu0O8aWr udGaw/ZRVL0efa9O3z0S.T79cdJsUwBFu6I0
    SENHA : 121188
    Depois de algum tempo o programa retornou a senha 121188 que é a senha do usuário daemon9.

    O código

    /*
    * [Autor]
    * Marcos Paulo Ferreira (Daemonio)
    * undefinido gmail com
    * Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
    *
    * [qcrack.c]
    * Programa simples que quebra senhas encriptadas
    * pela função crypt().
    * O arquivo de senhas, na maioria das vezes o
    * arquivo /etc/shadow, DEVE seguir esse formato:
    *
    * <usuario>:$id$salt$encrypt (veja: man crypt)
    * Ex:
    * daemonio:$6$eqwsadsf$c2FpIGRha2kK
    *
    * [Como compilar]
    * $ gcc -o qcrack qcrack.c -lcrypt
    *
    * [Como usar]
    * $ ./qcrack <shadow> <wordlist>
    *
    * Em que:
    * <shadow> : arquivo shadow
    * <wordlist> : wordlist
    *
    * Versão 1.0
    * Ter Ago 23 23:01:11 BRT 2011
    * Qua Ago 24 16:39:27 BRT 2011
    *
    * Versão 1.1
    * Mon May 14 19:27:38 BRT 2012
    */

    /* Necessário para crypt() (veja: $ man crypt)*/
    #define _XOPEN_SOURCE 700

    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    #include <unistd.h>

    /* Tamanhos máximos de alguns campos
    * do arquivo shadow. */
    #define LOGIN_LEN 51
    #define ID_LEN 6
    #define SALT_LEN 101
    #define HASH_LEN 1025

    #define FALSE 0
    #define TRUE 1

    /* Estrutura que contém alguns
    * campos do arquivo shadow. */
    struct st_shadow {
    char login[LOGIN_LEN] ;
    char id[ID_LEN] ;
    char salt[SALT_LEN] ;
    char hash[HASH_LEN] ;
    } ;

    /* Armazena os campos do shadow em uma struct.
    * Os campos são extraídos usando strtok() e
    * armazenados em posições específicas
    * partindo do ponteiro da struct.
    */
    char get_info_shadow(char *linha, struct st_shadow *st) {
    char qtd = 0 ;
    char *token ;
    int i ;
    /* tamanho máximo de cada campo */
    int lengths[] = {LOGIN_LEN, ID_LEN, SALT_LEN, HASH_LEN} ;
    /* p aponta para o campo atual */
    char *p = (char *)st ;

    i = 0;
    while((token=strtok(linha, ":$"))&&(qtd<4)) {
    /* copia o campo para p */
    strncpy(p, token, lengths[i]) ;
    /* contador de campos lidos */
    qtd++ ;
    p+=lengths[i] ;
    /* Na segunda chamada de strtok,
    * linha deve ser NULL. */
    linha = NULL ;
    i++ ;
    }

    /* Formato não suportado do shadow. */
    if ( qtd != 4 ) {
    return FALSE ;
    }

    return TRUE;
    }

    /* Mostra algumas informações. */
    void show_info(struct st_shadow *st) {
    puts("************************") ;
    printf("Usuario : %s\n", st->login) ;

    printf("Algoritmo : ") ;
    if ( !strcmp(st->id, "1") ){
    printf("MD5\n") ;
    } else if ( !strcmp(st->id, "2a") ) {
    printf("Blowfish\n") ;
    } else if ( !strcmp(st->id, "5") ) {
    printf("SHA-256\n") ;
    } else if ( !strcmp(st->id, "6") ) {
    printf("SHA-512\n") ;
    } else {
    printf("Desconhecido...\n") ;
    }

    printf("Salt : %s\n", st->salt) ;
    printf("Hash : %s\n", st->hash) ;
    printf("SENHA : ") ;
    fflush(stdout) ;
    }

    /* Função que quebra a senha. Ela basicamente compara
    * o hash gerado para cada senha da wordlist com o
    * hash do shadow. Se os hashes são iguais, então a
    * senha foi quebrada. */
    void quebrar_senha(struct st_shadow *st, FILE *wordlist) {
    char senha[BUFSIZ], idsaltsenha[BUFSIZ] ;
    char *crypthash ;

    show_info(st) ;

    /* Vá para o início do arquivo. */
    rewind(wordlist) ;

    /* Obtém cada senha da wordlist */
    while(fgets(senha, BUFSIZ, wordlist)) {
    if ( senha[strlen(senha)-1] == '\n' ) {
    senha[strlen(senha)-1] = 0 ;
    }
    /* $id$salt$encrypt*/
    sprintf(idsaltsenha, "$%s$%s$%s", st->id, st->salt, st->hash) ;

    /* gera o hash de `senha' */
    crypthash = (char *)crypt(senha, idsaltsenha) ;

    /* Jackpot!! Quebramos a senha */
    if ( crypthash != NULL ) {
    if ( !strcmp(crypthash, idsaltsenha) ) {
    printf("%s\n", senha) ;
    return ;
    }
    /* Algo errado em crypt(). */
    } else {
    printf("\n>> Erro em crypt(). Impossível criar hash. <<\n") ;
    return ;
    }
    }

    /* Senha não quebrada. */
    printf("<senha nao quebrada>\n") ;
    }

    int main(int argc, char **argv) {
    FILE *shadow, *wordlist ;
    char linhashadow[BUFSIZ] ;
    struct st_shadow stshadow ;

    if ( argc < 3 ) {
    printf("qcrack - by Daemonio\n") ;
    printf("[uso] %s <shadow> <wordlist>\n", argv[0]) ;
    return -1 ;
    }
    /* arquivo shadow */
    if( (shadow=fopen(argv[1], "r")) == NULL ) {
    perror(argv[1]) ;
    return -1 ;
    }

    /* wordlist */
    if( (wordlist=fopen(argv[2], "r")) == NULL ) {
    perror(argv[2]) ;
    return -1 ;
    }

    /* Para cada usuário no shadow, a wordlist
    * é lida para tentar quebrar sua senha. */
    while( fgets(linhashadow, BUFSIZ, shadow) ) {
    if ( get_info_shadow(linhashadow, &stshadow) == TRUE ) {
    /* Formato inválido do arquivo shadow. Aqui
    * só ignoramos a linha. */
    if ( !isdigit(stshadow.id[0]) ) {
    continue ;
    } else {
    quebrar_senha(&stshadow, wordlist) ;
    }
    }
    }

    return 0 ;
    }
    Conclusão

    Esse programa deve ser usado somente para propósitos educacionais, pois ele não foi criado para ser efetivamente um cracker de senhas. Caso queira um cracker mais sofisticado, procure sobre o John The Ripper.

  • Font Size
    #2
    Valeu mesmo pela sua contribuição, vai ser legal quebrar uma senha utilizando esse código, mas meu DEUS está tudo escrito em grego, eu nem consigo me situar no que você está dizendo xD, de qualquer forma meus parabéns.
    sigpic

    Comment


    • Font Size
      #3
      Muito obrigado amigão. Vou testar aqui.

      Comment


      • Font Size
        #4
        Tempo exponencial.

        Muito show, mas da p da uma melhorada no cod. Lembrando q o BT é uns dos algoritmos que mais geram custos computacionais. Custo Exponencial! Muito caro.

        Comment

        X
        Working...
        X