Speeding up Brute force password guesser - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Speeding up Brute force password guesser (/thread-4043.html) |
Speeding up Brute force password guesser - Gamervote - Jul-19-2017 Hi, I'm new to python and was wondering how I could speed up my brute force password guesser. I just started python this summer so sorry if it isn't very python-ish Here's my code: #imports (im not insulting your inteligence, im just new. :) ) import string, time #sets printables var = 3 if var == 1: printable = list(string.printable) for i in range(5): del printable[-1] elif var == 2: printable = list(str(string.ascii_uppercase + string.ascii_lowercase)) elif var == 3: printable = list(string.ascii_lowercase) #variable assignment password = raw_input("What is the password? -> ") guess = [printable[0]] place = 0 limit = 8 correct = False #sees if the current guess is correct, returns true if so def ispass(): if "".join(guess) == password: return True else: return False #reverts all elements of guess list to first element of printables def zitup(): for i in range(len(guess)): guess[i] = printable[0] guess.append(printable[0]) #moves inncorrect guess to the next string def next(): if guess[place] == printable[-1]: guess[place] = printable[0] else: try: guess[place] = printable[printable.index(guess[place])+1] except ValueError: print(guess, place) #if ispass() returns false detects if all elements of guess are the last element of printable, if so exicutes zitup(), else sets the next non last element of printables to the next possible element while len(guess) < limit: correct = ispass() if correct: break else: place = len(guess)-1 while guess[place] == printable[-1] and place > -1: guess[place] = printable[0] place += -1 if place < 0: zitup() print("Char added") else: next() #prints correct guess, or incorrect if len(guess) exceded limit print("The password is: " + "".join(guess)) RE: Speeding up Brute force password guesser - wavic - Jul-19-2017 Hello! Look at concurrent.futures. The ProcessPoolExecutor class. RE: Speeding up Brute force password guesser - nilamo - Jul-19-2017 (Jul-19-2017, 10:39 AM)Gamervote Wrote: def ispass(): You don't need the if blocks... def ispass(): return "".join(guess) == passwordBut that's besides the point. There's a pretty cool profiler included in the standard lib, which can help narrow down where you should focus on improvement: https://docs.python.org/3.6/library/profile.html As a demo, I changed your program slightly so that the while loop at the end is a function, and then I call that function with the profiler. The code: # imports (im not insulting your inteligence, im just new. :) ) import string import time # sets printables var = 3 if var == 1: printable = list(string.printable) for i in range(5): del printable[-1] elif var == 2: printable = list(str(string.ascii_uppercase + string.ascii_lowercase)) elif var == 3: printable = list(string.ascii_lowercase) # variable assignment password = input("What is the password? -> ") guess = [printable[0]] place = 0 limit = 8 correct = False # sees if the current guess is correct, returns true if so def ispass(): if "".join(guess) == password: return True else: return False # reverts all elements of guess list to first element of printables def zitup(): for i in range(len(guess)): guess[i] = printable[0] guess.append(printable[0]) # moves inncorrect guess to the next string def next(): if guess[place] == printable[-1]: guess[place] = printable[0] else: try: guess[place] = printable[printable.index(guess[place]) + 1] except ValueError: print(guess, place) # if ispass() returns false detects if all elements of guess are the last element of printable, if so exicutes zitup(), else sets the next non last element of printables to the next possible element place = 0 def find_password(): global place while len(guess) < limit: correct = ispass() if correct: break else: place = len(guess) - 1 while guess[place] == printable[-1] and place > -1: guess[place] = printable[0] place += -1 if place < 0: zitup() print("Char added") else: next() import cProfile cProfile.run("find_password()") # prints correct guess, or incorrect if len(guess) exceded limit print("The password is: " + "".join(guess)) I don't have the patience to wait for a 5 character input, but we can already see that there are a massive number of calls to ispass() and next(), which take up most of the running time. Those functions aren't terribly complicated, which means the focus of improvement shouldn't be on making those functions better, but instead should focus almost entirely on having less loops. Specifically, if you can get rid of the while loop that's within the while loop, you'd likely see much better performance.
RE: Speeding up Brute force password guesser - Gamervote - Jul-20-2017 Thannks for your help but I'm comfused on one thing, is it the fact that there is a nested while loop that is making the program so slow while "cracking" 5+ digit passwords, or is it because the functions ispass() and next() are called so much? RE: Speeding up Brute force password guesser - nilamo - Jul-20-2017 Both? A nested loop by itself doesn't mean anything, but it's because of the loop that you're calling the functions so much. If I were to take a guess at a better way to do it (again, this is a guess, I haven't actually tried this or tested it or anything), I would generate all possible passwords that are X characters long, test them, and then do it again for X+1 characters long, and keep increment X until I hit paydirt. That way, you can use itertools to generate the combinations (https://docs.python.org/3.6/library/itertools.html#itertools.product). RE: Speeding up Brute force password guesser - nilamo - Jul-20-2017 For example, let's rewrite your program to use itertools. If there's no other benefit, I hope you'd agree that it's at least easier to read (and much shorter), which is a nice benefit, but is unrelated to speed. import itertools import string import time var = 3 if var == 1: printable = list(string.printable) for i in range(5): del printable[-1] elif var == 2: printable = list(str(string.ascii_uppercase + string.ascii_lowercase)) elif var == 3: printable = list(string.ascii_lowercase) password = input("What is the password? -> ") def ispass(guess): return "".join(guess) == password def find_password(): attempt_length = 0 while True: attempt_length += 1 guesses = itertools.product(printable, repeat=attempt_length) for guess in guesses: if ispass(guess): return guess print("char added") #guess = find_password() import cProfile cProfile.run("guess = find_password()") # prints correct guess, or incorrect if len(guess) exceded limit print("The password is: " + "".join(guess))The profiler gives us this: This is much faster (0.767 seconds down to 0.165 seconds). Now we see that the ispass() function and the inbuilt str.join() methods are the big hogs. So, let's rewrite the ispass() function to avoid calling str.join...# convert it to a tuple # "spam" => ("s", "p", "a", "m") password = tuple(password) def ispass(guess): return guess == password BOOM! Now it's fast enough for us to do 5 character passwords without hating our life too much... There's a few other things we can do, but that's all I've got time for now.
|