patternpythonMinor
Python Hash-Cracker
Viewed 0 times
crackerpythonhash
Problem
This is my first actual python tool I've written and I'm certainly happy with the way it works, but I'm sure there's better ways to do things in the code. Any ideas on how to speed it up would also be nice too!
Code:
```
#!/usr/bin/python
import StringIO
import getopt
import hashlib
import sys
import os
print " "
print "Python Hash-Cracker"
print "Version 3.0-2 Stable"
def info():
print " "
print "Information:"
print "[*]Options:"
print "* Hash"
print "* Type [See supported hashes]"
print "* Wordlist"
print "* Numbers bruteforce"
print "* Verbose [{WARNING}Slows cracking down!]"
print "[*]Examples:"
print "[>]./Hash-Cracker.py -h -t md5 -w DICT.txt"
print "[>]./Hash-Cracker.py -h -t sha384 -n -v"
print "[*]Supported Hashes:"
print "[>]md5, sha1, sha224, sha256, sha384, sha512"
print "[*]Thats all folks!\n"
def check_os():
if os.name == "nt":
operating_system = "windows"
if os.name == "posix":
operating_system = "posix"
return operating_system
class hash:
def hashcrack(self, hash, type):
self.num = 0
if (type == "md5"):
h = hashlib.md5
elif (type == "sha1"):
h = hashlib.sha1
elif (type == "sha224"):
h = hashlib.sha224
elif (type == "sha256"):
h = hashlib.sha256
elif (type == "sha384"):
h = hashlib.sha384
elif (type == "sha512"):
h = hashlib.sha512
else:
print "[-]Is %s a supported hash type?" % type
exit()
wordlist1 = open(wordlist, "r")
wordlist2 = wordlist1.read()
buf = StringIO.StringIO(wordlist2)
while True:
line = buf.readline().strip()
if (line == ""):
print "\n[-]Hash not cracked:"
print "[*]Reached end of wordlist"
print "[*]Try another wordlist"
print "[*]Words tryed: %s" % self.num
break
hash2 = h(line).hexdigest()
if (ver == "yes"):
sys.stdout.write('\r' + str(line) +
Code:
```
#!/usr/bin/python
import StringIO
import getopt
import hashlib
import sys
import os
print " "
print "Python Hash-Cracker"
print "Version 3.0-2 Stable"
def info():
print " "
print "Information:"
print "[*]Options:"
print "* Hash"
print "* Type [See supported hashes]"
print "* Wordlist"
print "* Numbers bruteforce"
print "* Verbose [{WARNING}Slows cracking down!]"
print "[*]Examples:"
print "[>]./Hash-Cracker.py -h -t md5 -w DICT.txt"
print "[>]./Hash-Cracker.py -h -t sha384 -n -v"
print "[*]Supported Hashes:"
print "[>]md5, sha1, sha224, sha256, sha384, sha512"
print "[*]Thats all folks!\n"
def check_os():
if os.name == "nt":
operating_system = "windows"
if os.name == "posix":
operating_system = "posix"
return operating_system
class hash:
def hashcrack(self, hash, type):
self.num = 0
if (type == "md5"):
h = hashlib.md5
elif (type == "sha1"):
h = hashlib.sha1
elif (type == "sha224"):
h = hashlib.sha224
elif (type == "sha256"):
h = hashlib.sha256
elif (type == "sha384"):
h = hashlib.sha384
elif (type == "sha512"):
h = hashlib.sha512
else:
print "[-]Is %s a supported hash type?" % type
exit()
wordlist1 = open(wordlist, "r")
wordlist2 = wordlist1.read()
buf = StringIO.StringIO(wordlist2)
while True:
line = buf.readline().strip()
if (line == ""):
print "\n[-]Hash not cracked:"
print "[*]Reached end of wordlist"
print "[*]Try another wordlist"
print "[*]Words tryed: %s" % self.num
break
hash2 = h(line).hexdigest()
if (ver == "yes"):
sys.stdout.write('\r' + str(line) +
Solution
Summary:
Big things:
-
First time I tried to run the program, it immediately hit an error:
Turns out I’d forgotten the
-
You should read PEP 8, the Python style guide. Among other things: indentation is inconsistent (Python standard is 4 spaces, but this file uses 2, 3 and 4 interchangeably); class names should be CamelCase, two blank lines between functions.
-
I would consider using something like docopt to do the command-line argument parsing. Even if you don’t use docopt, it’s worth looking at the style of usage message it requires:
-
There are no comments or docstrings in this code, which makes it hard to work out what something is doing (and by extension, whether it’s doing it correctly).
-
A function should either do something (e.g. print to the screen) or return a value. Your functions tend to intersperse printing with computation. If I want to get the result of a function but without the printing, that's quite hard to do. Separating the two will make it easier to reuse your code.
(You could use something like the
More generally, I’d consider breaking your code down into smaller functions. Each function can be written and tested individually, and it tends to make it easier to see what’s going on.
And smaller comments:
-
Common convention is that if a program runs successfully, it exits with code 0; any other outcome is a non-zero exit code. If I ask to check with a non-existent hash, the
-
Rather than a big branch of
-
Your code could be better about handling user input. For example, this command:
I claim that the hash function I want to use is obvious to a human reader, but this causes the script to error.
-
Don’t use
-
You definitely shouldn’t name a class
-
Your
-
Don’t print anything at the module level outside the
-
It’s common practice for Python modules/libraries to present a
- Better comments and docstrings.
- Separate code that prints messages and computes values.
- Try not to do too much in a single function.
Big things:
-
First time I tried to run the program, it immediately hit an error:
$ tail -n 1 /usr/share/dict/words
Zyzzogeton
$ md5 -s "Zyzzogeton"
MD5 ("Zyzzogeton") = 4f9c55496b14676f23f40117cc89e641
$ python hashcrack.py -h "4f9c55496b14676f23f40117cc89e641" -t md5 /usr/share/dict/words
Python Hash-Cracker
Version 3.0-2 Stable
[Running on posix]
[*]Hash: 4f9c55496b14676f23f40117cc89e641
[*]Hash type: md5
[*]Wordlist: None
[+]Cracking...
Traceback (most recent call last):
File "hashcrack.py", line 172, in
main(sys.argv[1:])
File "hashcrack.py", line 157, in main
h.hashcrack(hash1, type)
File "hashcrack.py", line 52, in hashcrack
wordlist1 = open(wordlist, "r")
TypeError: coercing to Unicode: need string or buffer, NoneType found
Turns out I’d forgotten the
-w flag – your program should be better about handling malformed user input.-
You should read PEP 8, the Python style guide. Among other things: indentation is inconsistent (Python standard is 4 spaces, but this file uses 2, 3 and 4 interchangeably); class names should be CamelCase, two blank lines between functions.
-
I would consider using something like docopt to do the command-line argument parsing. Even if you don’t use docopt, it’s worth looking at the style of usage message it requires:
- There’s a standard format for usage messages on command-line tools. Sticking to this format will make it easier for other people to quickly pick up using your tool.
- There’s a long-standing convention of using
-hor--helpto print help information. Using-ito get info is fairly unusual.
- And using docopt would allow you to simplify a big chunk of your argument-parsing code.
-
There are no comments or docstrings in this code, which makes it hard to work out what something is doing (and by extension, whether it’s doing it correctly).
-
A function should either do something (e.g. print to the screen) or return a value. Your functions tend to intersperse printing with computation. If I want to get the result of a function but without the printing, that's quite hard to do. Separating the two will make it easier to reuse your code.
(You could use something like the
logging module for messages you want to print mid-computation, as logging is easier to turn off than printing to stdout.)More generally, I’d consider breaking your code down into smaller functions. Each function can be written and tested individually, and it tends to make it easier to see what’s going on.
And smaller comments:
-
Common convention is that if a program runs successfully, it exits with code 0; any other outcome is a non-zero exit code. If I ask to check with a non-existent hash, the
exit() on line 91 will print an error, then exit with code 0. Also, errors should be printed to stderr, not stdout.-
Rather than a big branch of
if … elif statements in hashcracknum(), use a dict for the lookup of hash name to hash function. Python hash tables are very efficient.-
Your code could be better about handling user input. For example, this command:
python hashcrack.py -h notahash -t MD5 -w /usr/share/dict/wordsI claim that the hash function I want to use is obvious to a human reader, but this causes the script to error.
-
Don’t use
type as a variable name; overriding built-in functions is a recipe for weirdness.-
You definitely shouldn’t name a class
hash. This overrides a builtin Python function (that’s used in quite a few places), classes should have CamelCase names, and it’s not particularly descriptive.-
Your
check_os() function will throw a NameError if called on a platform where os.name isn't nt or posix. If you want a human-readable platform name, you might want to look at the platform module, which tends to have more granular names.-
Don’t print anything at the module level outside the
main() function – if anybody tries to import this file, those prints will be executed no matter what. That makes it very annoying to reuse your code.-
It’s common practice for Python modules/libraries to present a
__version__ attribute – it would be good to do that for your version string.Code Snippets
python hashcrack.py -h notahash -t MD5 -w /usr/share/dict/wordsContext
StackExchange Code Review Q#135110, answer score: 8
Revisions (0)
No revisions yet.