Cracker de senha SHA256 - força bruta
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
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)