Criar Formatos Customizados para John the Ripper

Kali LinuxBeginner
Pratique Agora

Introdução

John the Ripper (JtR) é uma ferramenta poderosa e popular de código aberto para quebra de senhas. Uma de suas principais forças é sua extensibilidade. Embora ele suporte um vasto número de tipos de hash prontos para uso, você pode ocasionalmente encontrar um esquema de hash customizado ou obscuro que o JtR não reconhece. Nesses casos, você pode criar seu próprio formato customizado para ensinar o JtR como quebrá-lo.

Neste laboratório, você aprenderá os conceitos fundamentais por trás da criação de um formato customizado para o JtR. Este laboratório é conceitual e foca na estrutura e no processo, fornecendo o conhecimento fundamental necessário para desenvolver formatos totalmente funcionais. Você não escreverá e compilará um formato totalmente funcional, mas entenderá todos os passos necessários.

Compreender a Estrutura de Formato do John the Ripper

Nesta etapa, você aprenderá sobre a estrutura fundamental de um formato do John the Ripper. Compreender essa estrutura é a primeira e mais crucial parte da criação de um formato customizado.

Os formatos do JtR são definidos em arquivos fonte C (.c) e são construídos em torno de uma estrutura C central chamada struct fmt_main. Essa estrutura atua como um modelo, informando ao JtR tudo o que ele precisa saber sobre o tipo de hash.

Os campos chave dentro de struct fmt_main incluem:

  • fmt_label: Uma string curta e única que você usa para especificar o formato com a opção de linha de comando --format= (por exemplo, md5raw).
  • fmt_tag: Um identificador único usado internamente pelo JtR para distinguir o formato em arquivos de sessão salvos (por exemplo, $dynamic_0$).
  • algorithm_name: Uma string descrevendo o algoritmo de hash e suas propriedades, usada para fins informativos.
  • plaintext_length: O comprimento máximo da senha que o formato pode lidar.
  • binary_size: O tamanho do hash binário bruto. Para MD5, seriam 16 bytes.
  • salt_size: O tamanho do salt, se o tipo de hash o utiliza.
  • methods: Esta é uma estrutura aninhada contendo ponteiros para várias funções que implementam a lógica do formato. As funções mais importantes são:
    • valid(): Verifica se uma determinada string de hash de um arquivo de entrada é válida para este formato. É o primeiro porteiro.
    • split(): Se uma string de hash contiver mais do que apenas o hash (como um nome de usuário), esta função separa os componentes.
    • binary(): Converte a string de hash hexadecimal ou base64 em sua representação binária bruta.
    • salt(): Extrai o salt da string de hash.
    • crypt_all(): A função principal. Ela pega um conjunto de senhas candidatas, as hasheia e as prepara para comparação.
    • cmp_all(): Compara os hashes recém-computados de crypt_all() com o hash alvo para ver se há uma correspondência.

Esta etapa é puramente teórica. Você não precisa executar nenhum comando. Na próxima etapa, examinaremos um arquivo de formato real para ver essa estrutura em ação.

Identificar Definições de Formato Existentes

Nesta etapa, você localizará o código fonte de formatos existentes na árvore de código fonte do John the Ripper. Examinar esses arquivos é a melhor maneira de aprender a construir os seus próprios.

O script de configuração para este laboratório já clonou o código fonte do JtR para o diretório ~/project/john.

Primeiro, navegue até o diretório src, onde os arquivos fonte estão localizados.

cd ~/project/john/src

Agora, liste todos os arquivos que definem um formato. Por convenção, esses arquivos terminam com _fmt_plug.c.

ls *_fmt_plug.c

Você verá uma longa lista de arquivos, cada um correspondendo a um tipo de hash diferente que o JtR suporta.

7z_fmt_plug.c             des_fmt_plug.c          lotus5_fmt_plug.c         ...
afs_fmt_plug.c            django_fmt_plug.c       mdc2_fmt_plug.c
aix_smd5_fmt_plug.c       dmg_fmt_plug.c          md4_fmt_plug.c
aix_ssha_fmt_plug.c       dominosec_fmt_plug.c    md5_fmt_plug.c
...e muitos mais...

Vamos dar uma olhada em um relativamente simples, md5_fmt_plug.c, para ver a struct fmt_main que discutimos. Usaremos cat combinado com head para visualizar apenas a parte superior do arquivo.

cat md5_fmt_plug.c | head -n 50

Na saída, você poderá ver a definição de struct fmt_main fmt_MD5, com seu rótulo (label), tag, nome do algoritmo e ponteiros de método, exatamente como descrevemos na etapa anterior.

Criar um Formato Customizado Simples (Conceitual)

Nesta etapa, criaremos conceitualmente um novo arquivo fonte C para um formato customizado simples. Este exercício ilustrará como você estruturaria um novo arquivo de formato.

Nosso objetivo é criar um formato que reconheça hashes com um prefixo especial: labex_md5$. Por exemplo, um hash como labex_md5$87e4e494b2399b0921d44e03693518f9.

Certifique-se de que você ainda está no diretório ~/project/john/src. Usaremos o editor de texto nano para criar nosso novo arquivo.

nano labex_md5_fmt_plug.c

Agora, copie e cole o seguinte código C no editor nano. Este é um esqueleto simplificado e não é um formato totalmente funcional, mas demonstra os componentes principais.

#if FMT_EXTERNS_H
extern struct fmt_main fmt_labex_md5;
#elif FMT_REGISTERS_H
john_register_one(&fmt_labex_md5);
#else

#include <string.h>
#include "arch.h"
#include "common.h"
#include "formats.h"

#define FORMAT_LABEL        "labex-md5"
#define FORMAT_NAME         "LabEx Custom MD5"
#define ALGORITHM_NAME      "MD5 32/64"
#define PLAINTEXT_LENGTH    32
#define BINARY_SIZE         16
#define SALT_SIZE           0
#define TAG_PREFIX          "labex_md5$"
#define TAG_LENGTH          (sizeof(TAG_PREFIX) - 1)

// Esta função verifica se uma string de hash é válida para o nosso formato
static int valid(char *ciphertext, struct fmt_main *self)
{
    if (strncmp(ciphertext, TAG_PREFIX, TAG_LENGTH))
        return 0;
    char *p = ciphertext + TAG_LENGTH;
    if (hexlenu(p, 0) != 32)
        return 0;
    return 1;
}

struct fmt_main fmt_labex_md5 = {
    {
        FORMAT_LABEL,
        FORMAT_NAME,
        ALGORITHM_NAME,
        BENCHMARK_COMMENT,
        BENCHMARK_LENGTH,
        0,
        PLAINTEXT_LENGTH,
        BINARY_SIZE,
        BINARY_ALIGN,
        SALT_SIZE,
        SALT_ALIGN,
        MIN_KEYS_PER_CRYPT,
        MAX_KEYS_PER_CRYPT,
        FMT_CASE | FMT_8_BIT,
        { NULL },
        { TAG_PREFIX },
        NULL
    }, {
        /* init */      init,
        /* done */      done,
        /* reset */     reset,
        /* prepare */   prepare,
        /* valid */     valid,
        /* split */     split,
        /* binary */    binary,
        /* salt */      salt,
        { NULL },
        /* source */    source,
        {
            /* get_hash* */ get_hash_0,
            /* get_hash* */ get_hash_1,
            /* get_hash* */ get_hash_2,
            /* get_hash* */ get_hash_3,
            /* get_hash* */ get_hash_4,
            /* get_hash* */ get_hash_5,
            /* get_hash* */ get_hash_6
        },
        /* cmp_all */   cmp_all,
        /* cmp_one */   cmp_one,
        /* cmp_exact */ cmp_exact
    }
};

#endif

Após colar o código, salve o arquivo e saia do nano pressionando Ctrl+X, depois Y e, em seguida, Enter.

Você agora criou o arquivo fonte para um novo formato. A parte mais importante é a função valid(), que simplesmente verifica nosso prefixo labex_md5$ e garante que o hash subsequente tenha 32 caracteres de comprimento.

Compilar John the Ripper com Novo Formato (Conceitual)

Agora que você tem um arquivo de formato conceitual, esta etapa explica como integrá-lo ao processo de compilação do John the Ripper e compilá-lo.

Primeiro, certifique-se de que você está no diretório src.

cd ~/project/john/src

O primeiro passo na compilação do JtR é executar o script configure. Este script verifica seu sistema em busca de bibliotecas necessárias e configura o ambiente de compilação.

./configure

Após a conclusão da configuração, você pode compilar o código fonte usando o comando make. Usaremos make clean para remover quaisquer compilações anteriores e make -sj4 para executar a compilação usando 4 jobs paralelos, o que acelera o processo.

make -s clean && make -sj4

A compilação levará um minuto ou dois.

Nota Importante: Em um cenário do mundo real, simplesmente criar o arquivo .c não é suficiente. Você também precisaria editar um arquivo de configuração (como Makefile.in) para informar ao sistema de compilação para incluir seu novo arquivo objeto labex_md5_fmt_plug.o ao vincular o executável final john. Estamos pulando essa modificação por simplicidade neste laboratório. Portanto, a compilação será bem-sucedida, mas nosso novo formato não será realmente incluído no binário final. Isso ilustra uma etapa crítica no processo de desenvolvimento.

Testar Formato Customizado (Conceitual)

Nesta etapa final, discutiremos como você testaria seu formato customizado com o executável John the Ripper recém-compilado.

O binário john compilado está localizado no diretório ~/project/john/run/. Vamos navegar até lá.

cd ~/project/john/run

Você pode listar todos os formatos que sua versão compilada do JtR suporta.

./john --list=formats

Percorra a lista. Você notará que nosso formato labex-md5 não está presente. Isso é esperado, pois, como mencionado na etapa anterior, não modificamos os arquivos de compilação para incluí-lo.

Agora, vamos criar um arquivo de hash de exemplo e uma wordlist para ver como usaríamos o formato se ele tivesse sido compilado com sucesso.

Primeiro, crie um arquivo chamado hashes.txt no diretório raiz do seu projeto contendo um hash que corresponda ao nosso formato customizado. O hash 87e4e494b2399b0921d44e03693518f9 é o hash MD5 da senha "labex".

echo "labex_md5$87e4e494b2399b0921d44e03693518f9" > ~/project/hashes.txt

Em seguida, crie uma wordlist simples contendo a senha correta.

echo "labex" > ~/project/wordlist.txt

Finalmente, este é o comando que você executaria para quebrar o hash usando o formato customizado.

./john --format=labex-md5 --wordlist=~/project/wordlist.txt ~/project/hashes.txt

Ao executar este comando, o JtR relatará um erro porque o formato é desconhecido, confirmando nossa compreensão do processo de compilação.

Unknown format name: "labex-md5"

Isso conclui nossa visão geral conceitual da criação e teste de um formato customizado do JtR.

Resumo

Neste laboratório, você explorou o processo conceitual de criação de formatos customizados para o John the Ripper. Você adquiriu um entendimento fundamental das etapas-chave envolvidas na extensão das capacidades do JtR.

Você aprendeu sobre:

  • A estrutura central struct fmt_main que define cada formato do JtR.
  • Como localizar e examinar definições de formato existentes no código fonte do JtR.
  • O processo de criação de um novo arquivo fonte de formato com uma função valid() básica.
  • O procedimento padrão para compilar o JtR usando ./configure e make.
  • A etapa crítica (e intencionalmente omitida) de modificar os arquivos de compilação para incluir um novo formato.
  • Como testar um formato usando o flag --format e um arquivo de hash de exemplo.

Embora este laboratório não tenha resultado em um formato customizado totalmente funcional, ele forneceu o conhecimento essencial e um roteiro claro para desenvolver seus próprios formatos para lidar com esquemas de hashing de senha exclusivos.