Cracker de senha SHA256 - força bruta

Nov 16 2020

Eu escrevi um cracker de senha SHA256. Eu inicialmente usei listas para armazenar as informações em list1.txte, list2.txtmas acabaria recebendo sobrecargas de memória. Portanto, agora uso arquivos. Percebi que quando fiz essa transição, a velocidade do programa reduziu enormemente. Existe uma maneira de otimizar a velocidade dessa programação sem enfrentar problemas de sobrecarga de memória?

obrigado

import hashlib
import time
import os

def extract_password(fname):
    if fname == 0:
        filename = "list2.txt"
    else:
        filename = "list1.txt"
    for line in open(filename, "r"):
        yield line.strip()


def save_password(fname, password):
    if fname == 0:
        filename = "list1.txt"
    else:
        filename = "list2.txt"

    file = open(filename, "a")
    file.write(password)
    file.write("\n")
    file.close()



def next_password(lsta, item,next_char, secure_password):
    found = 0
    guess = item + chr(next_char)
    if hash_password(guess) == secure_password:
        print(guess)
        found = 1
    save_password(lsta, guess)
    return found

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

def delete_file(ltsa):
    try:
        if ltsa == 1:
            os.remove("list2.txt")
        else:
            os.remove("list1.txt")
    except:
        pass

def reset_file_status():
    try:
        os.remove("list2.txt")
        os.remove("list1.txt")
    except:
        pass

def find_password(secure_password):
    #Brute force to find original password
    found = 0
    lsta = 1
    for length in range(1, 15):
        if found == 1: break
        lsta = lsta^1
        delete_file(lsta)
        for next_char in range(65, 123):
            if found == 1: break
            if length == 1:
                found = next_password(lsta, "", next_char, secure_password)
                if found == 1: break
            else:
                for item in extract_password(lsta):
                    found = next_password(lsta, item, next_char, secure_password)
                    if found == 1: break

if __name__ == "__main__":
    reset_file_status()
    start = time.time()
    secure_password = hash_password("AAAA")
    find_password(secure_password)
    print(f"{(time.time() - start)} seconds")

Respostas

4 LevM. Nov 16 2020 at 06:40

A otimização que você está procurando é muito simples:
pergunte a si mesmo - o que eu realmente preciso manter?

A resposta: apenas a senha que estou verificando no momento.

Não há necessidade de armazenar todas as suposições antigas, portanto, não há necessidade de arquivos ou listas enormes.

Tudo que você realmente precisa é de uma string que continuará atualizando.

Para visualizar isso, pense em sua string como um número crescente, com cada letra sendo um dígito de base 58.

Agora. tudo que você realmente precisa é fazer um +1 no primeiro dígito, verificando se há transporte e atualizando os dígitos seguintes, se necessário, como a adição normal.

Infelizmente, as strings do Python não permitem atribuição por índice, mas oferecem suporte ao fatiamento .

Aqui está uma função que geraria senhas sequenciais passando por todas as letras e aumentando o comprimento conforme necessário (uma senha por chamada!):

def make_next_guess(guess):
    carry = 1
    next_guess = guess

    for i in range(len(guess)):
        cur_char = ord(guess[i]) + carry
        if cur_char > ord('z'):
            cur_char = ord('A')
            carry = 1
        else:
            carry = 0

        next_guess = next_guess[:i] + chr(cur_char) + guess[i + 1:]
        if carry == 0:
             break

    if carry = 1:
        next_guess += 'A'

    return next_guess

Com isso, você pode usar um loop para todas as possibilidades até o comprimento máximo:

guess = 'A'

for _ in range(58 ** 14): #password maximum length 14 and there are 58 characters that can be used
    
    if hash_password(guess) == secure_password:
        print(guess)
        break

    guess = make_next_guess(guess)