Cracker de senha SHA256 - v2 com simultaneidade

Nov 17 2020

Eu atualizei meu código anterior com as sugestões. Também implementei a simultaneidade para acelerar os resultados.

Gostaria de receber comentários sobre um uso mais eficiente em simultaneidade / processamento paralelo / hyper-threading

obrigado

import concurrent.futures
import hashlib
import time


def make_next_guess(guess):
    carry = 0
    next_guess = guess
    for i, char in enumerate(next_guess):
        if ord(char) >= ord("z"):
            carry = 1
            next_guess[i] = "!"
        elif ord(char) < ord("z"):
            next_guess[i] = chr(ord(char) + 1)
            carry = 0
        if carry == 0: break
    if carry:
        next_guess.append("!")
    return next_guess


def hash_password(pwrd):
    # Generates hash of original password
    try:
        pwrd = pwrd.encode("UTF-8")
        password = hashlib.sha256()
        password.update(pwrd)
        return password.hexdigest()
    except:
        pass


def find_password(secure_password, guess, integer):
    list_cracked = []
    # Brute force to find original password
    for _ in range(90 ** integer):  # password maximum length 14 and there are 58 characters that can be used
        return_password = "".join(guess)
        if hash_password(return_password) in secure_password:
            # print(f"Another password has been cracked: '{return_password}'")
            list_cracked.append(return_password)
        guess = make_next_guess(guess)
    return f"Finished cracking all passwords of length {integer}", list_cracked, integer


def rainbow_table_check(secure_password):
    global hash
    list_cracked = []
    for password in open("Rainbow.txt", "r", encoding="utf8"):
        try:
            password = password.strip()
            hash = hash_password(password)
        except:
            pass
        if hash in secure_password:
            # print(f"Another password has been cracked: {password}")
            list_cracked.append(password)
    return "Rainbow attack complete - passwords: ", list_cracked, "Rainbow"


def dic_attack(secure_password):
    list_cracked = []
    for password in open("Dic.txt", "r", encoding="utf8"):
        password = password.strip()
        lst = [password.lower(), password.upper(), password.title()]
        for password in lst:
            hash = hash_password(password)
            if hash in secure_password:
                # print(f"Another password has been cracked: {password}")
                list_cracked.append(password)
    return "Dictionary attack complete - passwords: ", list_cracked, "Dictionary"


if __name__ == "__main__":
    all_passwords = []
    start = time.time()
    secure_password = set()
    print("Attempting to crack passwords....")
    password_list = ["ABd", "Abc", "lpo", "J*&", "Njl", "!!!!", "Aqz", "Apple", "Cake", "Biden", "password1"]
    for password in password_list:
        secure_password.add(hash_password(password))
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = [executor.submit(dic_attack, secure_password),
                   executor.submit(rainbow_table_check, secure_password),
                   executor.submit(find_password, secure_password, ['!'], 1),
                   executor.submit(find_password, secure_password, ['!', '!'], 2),
                   executor.submit(find_password, secure_password, ['!', '!', '!'], 3),
                   executor.submit(find_password, secure_password, ['!', '!', '!', '!'], 4),
                   executor.submit(find_password, secure_password, ['!', '!', '!', '!', '!'], 5)]
        for f in concurrent.futures.as_completed(results):
            message, cracked, method = f.result()
            time_run = f"{round((time.time() - start) // 60)} min {round((time.time() - start) % 60)} sec"
            print(f"{message} : {cracked} - {time_run}")
            all_passwords += cracked
    print(f"Complete list of cracked passwords: {set(tuple(all_passwords))}")
    print(f"This operation took: {round((time.time() - start) // 60)} min {round((time.time() - start) % 60)} sec")

Respostas

1 RootTwo Nov 17 2020 at 07:35

Duas observações:

Os métodos em hashlibesperam receber bytes. Em make_next_guess(), use um em bytearrayvez de uma string. Isso evita as chamadas para ''.join(), ord(), ''.encode('UTF-8'), etc. Melhor ainda, fazer a função de um gerador que produz as suposições.

Usar a elsecláusula no for i, byte in enumerate(guess):loop simplifica um pouco a lógica. Quando o loop termina, a elsecláusula é executada. No entanto, a breakignora a elsecláusula. Aqui, se o loop não encontrar bytes para aumentar, a cláusula else adiciona outro byte ao comprimento da estimativa.

Algo como:

def generate_guesses(start):
    ORD_Z = ord('z')
    ORD_BANG = ord("!")
    
    guess = start[:]
    
    while True:
        yield guess
        for i, byte in enumerate(guess):
            if byte < ORD_Z:
                guess[i] += 1
                break
                
            else:
                guess[i] = ORD_BANG
                
        else:
            guess.append(ORD_BANG)

Chamado como:

for guess in generate_guesses(bytearray(b'xzzzz')):
    ... do something with the guess ...

Possivelmente, adicione um argumento stopou countque diga quando o gerador deve parar ou quantas suposições ele deve gerar. Basta alterar a while True:linha para verificar a condição de parada.

A segunda observação é que o último trabalho submetido ao Pool é 90 vezes mais trabalho do que o trabalho anterior. Na verdade, é mais trabalho do que os 4 empregos anteriores combinados (talvez todos os outros empregos). Como resultado, você acaba com os outros trabalhos sendo concluídos mais cedo e um trabalho sendo executado em um núcleo do processador por um longo tempo. Tente dividir os trabalhos em pedaços de tamanhos mais iguais para manter todos os núcleos do processador ocupados. Por exemplo, as tarefas podem funcionar em partes de tamanhos iguais do espaço de pesquisa de senha:

'!'    to 'zzz' 
'!!!!' to 'zzz!'
'!!!"' to 'zzz"'
'!!!#' to 'zzz#' these are all chunks of 729k (90*90*90) guesses
     ...
'!!!z' to 'zzzz'