Como posso forçar um script a usar mais recursos?

3

Estou executando um script muito demorado, que leva muitas horas para terminar. Observando top , vejo que, na melhor das hipóteses, ocupa apenas 5% da CPU, geralmente em torno de 3%.

Existe alguma maneira de forçar o script a usar mais CPU para terminar mais rápido?

Editar:

Basicamente, o script é bruteforcing com 5 palavras-chave de comprimento de caracteres, dadas o sal e o hash.

Não está em casa agora, mas algo como:

charset = ['a','b',.........'z'];
for i in $charset do
   for j in $charset do
       for k in $charset do
           for l in $charset do
              for m in $charset do
                  pass = 'openssl passwd -salt $1 $i$j$k$l$m'
                  if [ pass == $2 ]]; then
                     echo "Password: $i$j$k$l$m";
                     exit;
                  fi
               done
            done
        done
    done
 done
    
por yzT 12.03.2014 / 10:04

5 respostas

7

Melhoria # 1 - Loops

Sua estrutura de loop parece completamente desnecessária se você usar expansões de chaves, pode ser condensado da seguinte forma:

$ more pass.bash 
#!/bin/bash

for str in $(echo {a..z}{a..z}{a..z}); do
  pass=$(openssl passwd -salt $1 $str)
  if [[ "$pass" == "$2" ]]; then
    echo "Password: $str"
    exit;
  fi
done

# vim: set nolist ts=2 :

Estou exibindo 4 caracteres apenas para torná-lo mais rápido, basta adicionar mais chaves {a..z} para caracteres adicionais para o tamanho da senha.

Exemplo é executado

4 caracteres
$ openssl passwd -salt ab hhhh
abBYJnOuV8dUA

$ time ./pass.bash ab abBYJnOuV8dUA
Password: hhhh

real    18m3.304s
user    6m58.204s
sys     9m34.468s

Por isso, completou em 18 minutos.

5 caracteres
$ openssl passwd -salt ab ccccc
abZwsITAI6uwM

$ time ./pass.bash ab abZwsITAI6uwM
Password: ccccc

real    426m37.234s
user    16m34.444s
sys     398m20.399s

Isso levou ~ 426 minutos. Eu na verdade Ctrl + C isso, então não tinha terminado, mas eu não queria esperar mais do que isso!

OBSERVAÇÃO: Essas duas execuções estavam nessa CPU:

brand = "Intel(R) Core(TM) i5 CPU       M 560  @ 2.67GHz

Melhoria # 2 - Usando bom?

A próxima etapa lógica seria nice das execuções acima, para que elas consumam mais recursos.

 $ nice -n -20 ./pass.bash ab hhhhh

Mas isso só vai te levar tão longe. Uma das "falhas" em sua abordagem é a chamada de openssl repetidamente. Com {a..z}^5 , você está chamando openssl 26 ^ 5 = 11881376 vezes.

Uma melhoria importante seria gerar os padrões de {a..z}.... e salvá-los em um arquivo e, em seguida, passar isso como um único item para openssl uma vez. Felizmente, openssl tem dois recursos principais que podemos explorar para conseguir o que queremos.

Melhoria # 3 - nossa estrutura de chamadas para o openssl

A ferramenta de linha de comando openssl fornece as opções -stdin e -table , que podemos usar aqui para ter uma única chamada de openssl , independentemente de quantas senhas queremos passar para ela. Esta é uma única modificação que removerá toda a sobrecarga de ter que invocar openssl , fazer o trabalho e, em seguida, sair dela, em vez disso, manteremos uma única instância aberta indefinidamente, alimentando-a quantas senhas quisermos.

A opção -table também é crucial, pois informa openssl para incluir a senha original ao lado da versão das cifras, para que possamos fazer um trabalho bastante rápido de procurar a correspondência.

Veja um exemplo usando apenas três caracteres para mostrar o que estamos mudando:

$ openssl passwd -salt ab abc
abFZSxKKdq5s6

$ printf "%s\n" {a..z}{a..z}{a..z} | \
    openssl passwd -stdin -table -crypt -salt ab | grep -m1 abFZSxKKdq5s6
abc abFZSxKKdq5s6

Agora, podemos realmente reformular nosso script pass.bash original da seguinte forma:

$ cat pass2.bash 
#!/bin/bash

pass=$(printf "%s\n" {a..z}{a..z}{a..z}{a..z}{a..z} | \
  openssl passwd -stdin -table -crypt -salt $1 | grep -m1 $2)

if [[ "$pass" =~ "$2" ]]; then
  echo "Password: $pass"
fi

# vim: set nolist ts=2 :

Agora, quando executamos:

$ time ./pass2.bash ab aboznNh9QV/Q2
Password: hhhhh aboznNh9QV/Q2

real    1m11.194s
user    1m13.515s
sys     0m7.786s

Esta é uma melhoria massiva! Essa mesma pesquisa que estava demorando mais de 426 minutos agora é feita em ~ 1 minuto! Se pesquisarmos para dizer "nnnnn", mais ou menos no meio do espaço do conjunto de caracteres {a..z}^5 . {a..n} tem 14 caracteres e estamos usando 5 deles.

$ echo "14^5" | bc 
537824

$ openssl passwd -salt ab nnnnn
abRRCp5N3WN32

$ time ./pass2.bash ab abRRCp5N3WN32
Password: nnnnn abRRCp5N3WN32

real    1m10.865s
user    1m12.842s
sys     0m8.530s

Esta pesquisa demorou ~ 1,1 minutos. OBSERVAÇÃO: Podemos pesquisar o espaço inteiro de senhas de 5 caracteres em ~ 1 minuto também.

$ time ./pass2.bash ab abBQdT5EcUvYA
Password: zzzzz abBQdT5EcUvYA

real    1m10.783s
user    1m13.556s
sys     0m8.251s

Conclusões

Então, com uma reestruturação, estamos correndo muito mais rápido. Essa abordagem também é muito melhor à medida que adicionamos um caractere 6º, 7º etc. à duração total da senha.

Esteja avisado que estamos usando um pequeno conjunto de caracteres, principalmente apenas os caracteres alfabéticos minúsculos. Se você misturar todo o número, os dois casos e os caracteres especiais, normalmente poderá obter ~ 96 caracteres por posição. Isso pode não parecer grande coisa, mas isso aumenta tremendamente seu pool:

$ echo 26^5 | bc
11881376
$ echo 96^5 | bc
8153726976

Adicionando todos esses caracteres aumentou em 2 ordens de magnitude nosso espaço de busca. Se chegarmos a 10-12 caracteres de comprimento para a senha, isso realmente coloca uma metodologia de hacking de força bruta fora de alcance.

Usar um NONCE de sal e outro adicional em toda a construção de uma senha com hash pode adicionar ainda mais obstáculos.

O que mais?

Você mencionou o uso de John (John the Ripper) ou de outras ferramentas inovadoras. Provavelmente, o estado da arte atualmente seria HashCat .

Onde o John é uma versão mais enxuta da abordagem que você está tentando usar, o HashCat leva isso para outro nível ao incluir o uso de GPUs (até 128) para realmente fazer suas tentativas de hackers voar.

Você pode até usar o CloudCrack , que é uma versão hospedada, e por apenas US $ 17 você pode pagar para ter um tentativa de quebra de senha.

Referências

por 12.03.2014 / 19:55
6

Seu roteiro não está apenas sentado em suas mãos! Provavelmente está esperando por um recurso diferente da CPU; talvez ele esteja manipulando muitos arquivos e aguardando os discos, ou enviando muitas coisas pela rede e esperando por isso.

Veja as linhas de uso agregado de recursos na parte superior de top e você verá algo como

%Cpu(s): 28.6 us, 28.6 sy,  0.0 ni, 42.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

O número us é a quantidade de CPU realmente usada pela lógica do seu script (ou outras coisas que ele chama). sy e wa são tempo de CPU gasto em chamadas do sistema e esperando por E / S. Se esses números forem altos enquanto o script estiver sendo executado e não houver outra atividade no sistema, então algo além da CPU é o seu gargalo.

    
por 12.03.2014 / 10:16
3

Seu script provavelmente está usando mais de 3%, como explicado pelo Flup, mas você também está perdendo muito tempo gerando uma cópia de openssl toda vez que você quiser criar uma senha (que é provavelmente a principal razão para a falta cpu time). Se você tiver uma máquina multicore / encadeada, você também não será capaz de enfatizar mais do que um único encadeamento de execução com seu script, então você estará usando 1/max_number_of_threads do tempo de CPU possível.

Você será melhor implementando o código em algo diferente de um shell script, que pode fazer a criptografia nativamente para você. Seu comando openssl está incompleto, então minhas sugestões são um pouco vagas, mas geralmente perl, python e ruby terão módulos que implementam o material padrão (como scrypt e bcrypt )

Outras maneiras de gerar o crypt passwd

$ openssl passwd -salt ab abcde
abHBZlaDwNzc2

$ gem install unix-crypt
$ ruby -e 'require "unix_crypt"; print UnixCrypt::DES.build("abcde","ab");'
abHBZlaDwNzc2

$ perl -e 'print crypt("abcde","ab");'
abHBZlaDwNzc2

Apenas não os use no loop mais interno! Implemente os loops no perl ou no que você executar na função crypt.

Como Stephane mencionou, você pode criar uma lista de senhas e canalizá-las para openssl

echo -e "abcde\nabcde" | openssl passwd -salt ab -stdin 

Em seguida, teste a saída para a senha correta.

Deixarei a implementação para você =)

    
por 12.03.2014 / 12:30
1

renice é o utilitário para alterar a gentileza e aumentar ou diminuir a prioridade, mas você precisa da raiz para tornar algo mais agressivo.

Inicie bloco-cole :

Terminal

Se você estiver em um terminal, pode usar renice

renice [-n] priority [[-p] pid ...] [[-g] pgrp ...] [[-u] user ...]

Um exemplo simples seria

renice 8 31043
31043: old priority 5, new priority 8

Você também pode passar bandeiras difíceis, mas segue essa ordem

renice -p 31043 -n 5
31043: old priority 8, new priority 5

As prioridades funcionam em uma escala de -20 a 20 - Quanto menor o número, maior a prioridade no sistema.

Finalizar bloco e colar.

    
por 12.03.2014 / 10:13
1

Além das várias otimizações de implementação na resposta do @slm , há uma enorme otimização algorítmica a ser feita. (Também pode haver alguns ataques criptoanalíticos, não tenho certeza de quão strong é o algoritmo de criptografia do UNIX, mas isso provavelmente está além do escopo de um script de shell)

O problema que você está tentando resolver provavelmente foi descrito como "força bruta de senha". Para fazer isso, você gerou todas as possibilidades em ordem alfabética e as testou, saindo no primeiro jogo. Se você modelar uma senha como "string aleatória de 5 caracteres", isso é realmente ideal.

Um poucos pessoas usará uma senha aleatória. Alguns, não mais. Mesmo para as coisas onde eles realmente deveriam. Especialmente por coisas que eles não consideram importantes. Tivemos isso confirmado recentemente e repetidamente por vários bancos de dados de senha vazados.

A senha que você está procurando pode ser dbKbuW . Mas é muito mais provável que sejam qwerty , abc123 ou 123456 . Sabemos, a partir dos bancos de dados vazados, que as mais importantes senhas mais comuns irão quebrar a maioria das contas.

Assim, a velocidade real é gerar seus palpites em uma ordem melhor. No mínimo, classifique suas listas de letras por frequência em inglês (ou, melhor ainda, em senhas). Você deve estar tentando e muito antes de z . Percorra uma lista de 1000 ou mais senhas comuns primeiro, antes mesmo de iniciar a iteração de força bruta no espaço de pesquisa (desperdiça um pouco de tempo se não funcionar, mas, dependendo dos usuários, ele funciona bem mais da metade do tempo ).

Se você observar como as ferramentas reais de quebra de senhas funcionam, elas passam por algumas listas de senhas comuns, depois por meio de um dicionário e depois por variações (por exemplo, "alterar e para " "), depois através de várias estratégias de geração de senha, e somente se nada disso funcionar, então finalmente comece a iterar pelo espaço de busca.

    
por 12.03.2014 / 20:48