Introdução
Frequentemente obtemos arquivos zip com senha e nem fazemos idéia de qual senha foi usada para encriptar esse arquivo. Recuperar o arquivo original sem a devida senha exige métodos complexos de ataque, pois o objetivo desses ataques é direcionado para o algoritmo de encriptação em si, que em muitos casos é muito seguro, como o AES. O que sobra então é o velho método da força bruta em que testamos exaustivamente todas as senhas de uma lista de palavras esperando que uma delas seja igual a senha do arquivo.
Nesse post iremos desenvolver um shell script que realiza ataques de força bruta em arquivos zipados com senha. Em seguida iremos melhorar o desempenho desse script por meio da paralelização com o xargs [3].
O programa unzip
Basicamente, usaremos o programa unzip para realizar nosso ataque. Então, antes de tudo, certifique-se de o unzip de sua distribuição é compatível com o que eu estou usando.
As opções usadas aqui serão a -P (ou –password), -t, e -q.
$ man unzip .... -P password use password to decrypt encrypted zipfile entries (if any). THIS IS INSECURE! .... $ zip --help .... -t test compressed archive data .... -q quiet mode (-qq => quieter) ....
A versão que estou usando é a:
$ unzip -v UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spieler. ..... Compiled with gcc 4.6.0 20110205 (Red Hat 4.6.0-0.6) for Unix (Linux ELF) on Feb 8 2011. .....
O método
O método de descobrir a senha por força bruta não é nada complexo e usaremos o próprio programa unzip para isso.
Vamos elaborar o método aos poucos, fazendo testes em alguns arquivos zip. Primeiro criamos um zip com senha de nome arquivozipcomsenha.zip:
# Criamos o arquivo arquivozipcomsenha.zip que compacta um arquivo qualquer (ex: /etc/passwd). # A senha do zip é `minhasenha123' $ zip -P minhasenha123 /etc/passwd arquivozipcomsenha.zip adding: etc/passwd (deflated 61%)
Vamos tentar unzipar esse arquivo com uma senha inválida:
$ unzip -P senhaerrada arquivozipcomsenha.zip Archive: arquivozipcomsenha.zip skipping: etc/passwd incorrect password
agora com a senha correta:
$ unzip -P minhasenha123 arquivozipcomsenha.zip Archive: arquivozipcomsenha.zip inflating: etc/passwd
Pelas duas saídas anteriores obtemos um padrão para diferenciar quando uma senha está correta ou não: Se a saída contém a string “incorrect password”, a senha passada está incorreta. Caso contrário a senha está correta. Embora esse padrão seja bom ele não é muito rápido, pois o unzip pode tentar extrair um arquivo mesmo a senha estando errada (mais detalhes disso em [1]). Isso então me motivou a procurar um modo mais rápido para essa verificação e acabei encontrando na man page[1] do programa as opções -t e -q. Veja:
$ man unzip To test letters.zip, printing only a summary message indicating whether the archive is OK or not: unzip -tq letters
O que a opção -t faz é testar a integridade do arquivo zip sem a necessidade de extrair seu conteúdo. Vejamos:
# Senha inválida $ unzip -tq -P senhainvalida arquivozipcomsenha.zip Caution: zero files tested in arquivozipcomsenha.zip. 1 file skipped because of incorrect password. # Senha correta $ unzip -tq -P minhasenha123 arquivozipcomsenha.zip No errors detected in compressed data of arquivozipcomsenha.zip.
Com esse novo método mais rápido de se testar a validade de uma senha, podemos elaborar um método geral para o ataque de força bruta:
1) Se há palavras no dicionário para ler: Leia uma palavra do dicionário de palavras para a variável senhateste. 2) Execute: unzip -tq -P senhateste arquivozipcomsenha.zip. 3) Verifique se a saída contém a string "No errors detected in comprressed data of". Se sim: a senha do arquivo é senhateste e finalize o processo. 4) Volte para o passo 1.
Esse procedimento pode ser implementado em qualquer linguagem de programação, só que aqui montaremos um shell script.
O script: quebrazip.sh
Esse script recebe o arquivo zipado no primeiro parâmetro e o dicionário de palavras no segundo.
#!/bin/bash # [quebrazip.sh] # Quebra senha de arquivos zip pelo método # da força bruta. # # [Autor] # Marcos Paulo Ferreira (Daemonio) # undefinido gmail com # https://daemoniolabs.wordpress.com # # [Uso] # $ ./quebrazip.sh arquivozipcomsenha.zip wordlist.txt # .... # .... # Senha: "senha" # # Versão 1.0, by daemonio @ Sun May 27 11:35:02 BRT 2012 # # Arquivo zip com senha ARQUIVOZIP= # Dicionário de senhas WORDLIST= # Recebe cada senha do dicionário senhateste= # Função de ajuda. function show_help { echo 'quebrazip.sh - by daemonio' echo '[uso] $ ./quebrazip.sh arquivozipcomsenha.zip wordlist.txt' exit 1 } # Função chamada quando se interrompe # o script com um ctrl+c. Essa função mostra # a senha usada no momento da interrupção. function pegarctrlc { echo "[+] Processo abortado. Senha atual: $senhateste" exit 1 } # Instala um signal handler pro ctrl+c trap pegarctrlc SIGINT # Obtém os parâmetros. ARQUIVOZIP="$1" WORDLIST="$2" # Flag. Tem valor 1 se a senha foi quebrada e # 0 caso contrário. SENHAQUEBRADA=0 # Testa os parâmetros. [ -e "$ARQUIVOZIP" ] && [ -e "$WORDLIST" ] || show_help # Processo de quebragem. echo '[+] Espere. Quebrando a senha...' while read senhateste do SAIDA=$(unzip -tq -P "$senhateste" "$ARQUIVOZIP" 2>&1) [[ "$SAIDA" =~ 'No errors detected in compressed data of' ]] && SENHAQUEBRADA=1 && break done < "$WORDLIST" # Informa se a senha foi quebrada ou não. if [ "$SENHAQUEBRADA" = '1' ] then echo '[+] Senha quebrada: '$senhateste else echo '[+] Senha NAO quebrada. Tente outra lista de palavras.' fi #EOF
A seguir um pequeno teste:
# Senha: 45312 $ zip -P 45312 arquivozipcomsenha.zip /etc/passwd # Gera uma wordlist usando o brutus.sh. Baixe # esse script na referência [2]. $ ./brutus.sh -c 12345 -r 5 > senhas.txt # Executa o quebrazip.sh $ ./quebrazip.sh arquivozipcomsenha.zip senhas.txt [+] Espere. Quebrando a senha... [+] Senha quebrada: 45312
Paralelizar?
Sabemos por [3] que podemos paralelizar as execuções de determinado programa usando o comando xargs. Utilizaremos dessa técnica para acelerar o processo de força bruta, e para isso teremos que modificar o script quebrazip.sh. A diferença agora é que o novo script receberá as senhas pela linha de comando e não por uma lista de palavras.
#!/bin/bash # [xquebrazip.sh] # Quebra senha de arquivos zip pelo método # da força bruta. # # [Autor] # Marcos Paulo Ferreira (Daemonio) # undefinido gmail com # https://daemoniolabs.wordpress.com # # [Uso] # $ ./xquebrazip.sh arquivozipcomsenha.zip senha1, senha2, ..., senhaN # .... # .... # Senha: "senha" # # Versão 1.0, by daemonio @ Sun May 27 12:11:02 BRT 2012 # # Função de ajuda. function show_help { echo 'xquebrazip.sh - by daemonio' echo '[uso] $ ./quebrazip.sh arquivozipcomsenha.zip senha1, senha2, ..., senhaN' exit 1 } # Obtém os parâmetros. ARQUIVOZIP="$1" # Flag. Tem valor 1 se a senha foi quebrada e # 0 caso contrário. SENHAQUEBRADA=0 # Testa os parâmetros. [ -e "$ARQUIVOZIP" ] || show_help # Desloca os parâmetros. shift # Lê as senhas da linha de comando. for senhateste in $* do SAIDA=$(unzip -tq -P "$senhateste" "$ARQUIVOZIP" 2>&1) [[ "$SAIDA" =~ 'No errors detected in compressed data of' ]] && SENHAQUEBRADA=1 && break done # Informa se a senha foi quebrada ou não. if [ "$SENHAQUEBRADA" = '1' ] then echo '[+] Senha quebrada: '$senhateste # Executando esse script no xargs precisamos matar # o próprio xargs (processo pai) para finalizar as # outras threads. kill $PPID fi #EOF
Testando:
$ cat senhas.txt | xargs -n 20 -P 10 ./xquebrazip.sh arquivozipcomsenha.zip [+] Senha quebrada: 45312 Terminated.
O xargs criará 10 threads (parâmetro -P) e cada uma receberá 20 senhas (parâmetro -n).
Comparando os tempos de execução
Teoricamente a versão paralela do nosso cracker deve ter um tempo de execução menor do que a versão sequencial. Isso é verdade para um número razoável de senhas na wordlist, porque para entradas pequenas a diferença de tempo é muito pequena. O problema é que o tempo de execução da versão paralela depende também dos processos cat e xargs e para entradas pequenas, esse tempo é bem considerável.
Para mostrar que a versão paralela é mais rápida em alguns casos, executei esses dois scripts com uma wordlist maior, e medindo o tempo de execução com o comando time.
# Senha: 9999 $ zip -P 9999 arquivozipcomsenhazip.zip /etc/passwd # Wordlist com 10^5 senhas $ ./brutus.sh -d -r 5 > senhas2txt # Tempo para a versão sequencial $ time ./quebrazip.sh arquivozipcomsenha.zip senhas2.txt [+] Espere. Quebrando a senha... [+] Senha quebrada: 99999 real 8m37.681s user 1m27.752s sys 5m38.155s # Tempo para a versão paralela. # (10 threads) $ time cat senhas2.txt | xargs -n 20 -P 10 ./xquebrazip.sh arquivozipcomsenha.zip [+] Senha quebrada: 99999 Terminated real 3m57.972s user 1m15.832s sys 4m11.389s
Obviamente esses tempos podem mudar de sistema para sistema. O importante aqui é que a paralelização se mostrou muito eficiente na redução do tempo de execução. E outra, ajeitando o parâmetro -P do xargs para um número razoavelmente grande, de modo que não se onere o processo, o tempo de execução diminuirá mais ainda.
Conclusão
Métodos de força bruta para descobrir senhas estão disponíveis praticamente em qualquer situação. A desvantagem desses métodos é que a quantidade de tempo total gasto neles é muito grande. Nesse post vimos como realizar um simples ataque de força bruta utilizando o próprio programa unzip. Para reduzir o tempo do ataque, utilizamos opções de validação mais rápidas fornecidas pelo próprio comando e, no final, tiramos vantagem da paralelização de processos.
Outro modo de agilizar o ataque seria olhar a estrutura interna dos arquivos zip e encontrar campos específicos que estão relacionados com a verificação da senha. Desse modo abandonamos de vez a nossa dependência do programa unzip, que influencia bastante no tempo de execução. Mas isso é assunto para outro post, quem sabe mais na frente (se você tiver algum material sobre isso, poste nos comentários). :D
Referências
[1] Man page do unzip (Acessado em: Maio/2012)
$ man unzip
[2] Shell Script Para Ataques Brute Force, by Daemonio (Acessado em: Maio/2012)
https://daemoniolabs.wordpress.com/2011/07/28/shell-script-para-ataques-brute-force/
[3] Paralelismo com o xargs, by Daemonio (Acessado em: Maio/2012)
https://daemoniolabs.wordpress.com/2012/04/07/paralelismo-com-o-xargs/
Pingback: Quebrando A Senha De Arquivos Rar Por Brute Force | Daemonio Labs
Pode-se retirar o UUOC e fazer:
$ xargs -n 20 -P 10 ./xquebrazip.sh arquivozip < senhas.txt
acredito que o tempo de execução caia ainda mais devido a diminuição do processo desnecessário.
Outro detalhe é que se o zip estiver usando criptografia “forte” (ex: AES-256) então o unzip não irá rodar, já que ele não dá suporte. A solução é usar a suíte p7zip de modo semelhante ao que vimos aqui. Não irei abordar essa solução, então deixarei essa tarefa para o leitor;