VTSTech Posted August 14, 2014 Share Posted August 14, 2014 (edited) import sys, os, hashlib, binascii, time from passlib.apps import custom_app_context as pwd_context from passlib.context import CryptContext if sys.platform.startswith('win32'): import msvcrt pwd_context = CryptContext(schemes=["hex_md5", "hex_md4", "hex_sha1", "nthash" ]) def banner(): print "#########################################" print "# VTSTech-32hex v0.36 Python Version #" print "# Facebook: facebook.com/VTSTech #" print "# Twitter: @VTSTech_ #" print "# Web: www.VTS-Tech.org #" print "# E-mail: veritas@vts-tech.org #" print "# XMPP: veritas@creep.im #" print "# BTC 1VTSgzD24bjkSGdD7kvauxkxHZ4yiwhdU #" print "#########################################" StartTime = time.time() ETime = 0 silent = 1 Cracked = "" lines = 0 linet = 0 CrkCnt = 0 cnt = "" TotalTime = "" LastAlgo = "" numpass = open('passwords.dat') num_pass = sum(1 for line in numpass) numpass.close() if len(sys.argv) == 1: banner() print "" print "Usage: VTStech-32hex.py -l hashlist.txt - List mode using hashlist.txt" print "" print "Options" print "" print "-l hashlist.txt, load target hashes from hashlist.txt" print "-s speed per sec updates (60s interval)" print "" print "Press any key to display speed/sec" print "" print "Supports the following encryption methods:" print "" print "MD5 md5()" print "MD4 md4()" print "NTLM" print "RAdmin v2.x" print "MD5-SHA1 md5(sha1())" print "MD5-UP-MD5 md5(strtoupper(md5()))" print "Double MD5 md5(md5())" print "Triple MD5 md5(md5(md5()))" print "Quadruple MD5 md5(md5(md5(md5())))" print "Quintuple MD5 md5(md5(md5(md5(md5()))))" print "Hextuple MD5 md5(md5(md5(md5(md5(md5())))))" print "Double MD4 md4(md4())" print "Triple MD4 md4(md4(md4()))" print "Quadruple MD4 md4(md4(md4(md4())))" print "Quintuple MD4 md4(md4(md4(md4(md4()))))" print "Hextuple MD4 md4(md4(md4(md4(md4(md4())))))" sys.exit() else: banner() print "Press any key to display speed/sec" if len(sys.argv[1]) == 2: if sys.argv[1] == "-l": target = sys.argv[2] hashes = open(sys.argv[2]) elif sys.argv[2] == "-l": target = sys.argv[3] hashes = open(sys.argv[3]) elif sys.argv[3] == "-l": target = sys.argv[4] hashes = open(sys.argv[4]) if sys.argv[1] == "-s": silent = 0 elif sys.argv[2] == "-s": silent = 0 md5 = CryptContext(schemes=["hex_md5"],) md5sha_hash = CryptContext(schemes=["hex_sha1"],) md4 = CryptContext(schemes=["hex_md4"],) nt_hash = CryptContext(schemes=["nthash"],) numhash = open(target) line=0 num_hash = sum(1 for line in numhash) print "" print num_pass,"passwords,", num_hash,"hashes loaded." print "" TotalPass = (num_pass * num_hash) * 16 numhash.close() hashes = open(target) for lineh in hashes: passwd = open("passwords.dat") CurrHash = lineh CurrTime = time.time() TotalTime = CurrTime - StartTime if sys.platform.startswith('win32'): while msvcrt.kbhit(): msvcrt.getch() progress = str(cnt),chr(47),str(TotalPass) pcnt = "(",str(round(float(float(cnt) / float(TotalPass))*100,2)),"%)" duration = str(round(TotalTime,2)),"s" print "Elapsed:",''.join(duration),"Progess:",''.join(progress),''.join(pcnt),"Speed:", round((cnt / TotalTime),2),"Hash/s" if ((CurrTime - ETime) > 60) or ((CurrTime - ETime) == CurrTime): if (TotalTime > 1): if silent == 0: progress = str(cnt),chr(47),str(TotalPass) pcnt = "(",str(round(float(float(cnt) / float(TotalPass))*100,2)),"%)" duration = str(round(TotalTime,2)),"s" print "Elapsed:",''.join(duration),"Progess:",''.join(progress),''.join(pcnt),"Speed:", round((cnt / TotalTime),2),"Hash/s" ETime = CurrTime for linep in passwd: lines += 1 CurrPass = linep CurrHash = CurrHash.strip(chr(13)) CurrHash = CurrHash.strip(chr(10)) CurrHash = CurrHash.strip(chr(34)) CurrPass = CurrPass.strip(chr(13)) CurrPass = CurrPass.strip(chr(10)) CurrPass = CurrPass.strip(chr(34)) md51x = md5.encrypt(CurrPass) md52x = md5.encrypt(md51x) md53x = md5.encrypt(md52x) md54x = md5.encrypt(md53x) md55x = md5.encrypt(md54x) md56x = md5.encrypt(md55x) md5sha1 = md5.encrypt(md5sha_hash.encrypt(CurrPass)) md41x = md4.encrypt(CurrPass) md42x = md4.encrypt(md41x) md43x = md4.encrypt(md42x) md44x = md4.encrypt(md43x) md45x = md4.encrypt(md44x) md46x = md4.encrypt(md45x) CurrPass2 = str(CurrPass + str((chr(0) * 100))) radmin = md5.encrypt(CurrPass2[0:100]) md5umd5 = md5.encrypt(md51x.upper()) cnt = (lines * 16) CurrTime = time.time() try: CurrPass.decode('ascii') except UnicodeDecodeError: ntlm = md4.encrypt(" ".encode('utf-16le')) else: ntlm = md4.encrypt(CurrPass.encode('utf-16le')) TotalTime = CurrTime - StartTime if md51x == CurrHash: Algo = "MD5" Cracked = md51x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md52x == CurrHash: Algo = "Double MD5" Cracked = md52x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md53x == CurrHash: Algo = "Triple MD5" Cracked = md53x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md54x == CurrHash: Algo = "Quadruple MD5" Cracked = md54x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md55x == CurrHash: Algo = "Quintuple MD5" Cracked = md55x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md56x == CurrHash: Algo = "Hextuple MD5" Cracked = md56x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md5sha1 == CurrHash: Algo = "MD5(SHA1())" Cracked = md5sha1,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md41x == CurrHash: Algo = "MD4" Cracked = md41x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md42x == CurrHash: Algo = "Double MD4" Cracked = md42x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md43x == CurrHash: Algo = "Triple MD4" Cracked = md43x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md44x == CurrHash: Algo = "Quadruple MD4" Cracked = md44x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md45x == CurrHash: Algo = "Quintuple MD4" Cracked = md45x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break elif md46x == CurrHash: Algo = "Hextuple MD4" Cracked = md46x,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break break elif ntlm == CurrHash: Algo = "NTLM" Cracked = ntlm,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo == Algo CrkCnt = CrkCnt + 1 break break elif radmin == CurrHash: Algo = "radmin" Cracked = radmin,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break break elif md5umd5 == CurrHash: Algo = "MD5-UP-MD5" Cracked = md5umd5,":",CurrPass if LastAlgo == Algo: print ''.join(Cracked) else: print "Encryption Method:",Algo print ''.join(Cracked) LastAlgo = Algo CrkCnt = CrkCnt + 1 break break print "" print "" DidWeWin = "Recovered: ",str(CrkCnt),"/",str(num_hash)," (",str(round(float(CrkCnt) / float(num_hash)*100,2)),"%)" progress = str(cnt),chr(47),str(TotalPass) pcnt = "(",str(round(float(float(cnt) / float(TotalPass))*100,2)),"%)" duration = str(round(TotalTime,2)),"s" print ''.join(DidWeWin) print "" print "Elapsed time:",''.join(duration),"Progess:",''.join(progress),''.join(pcnt),"Speed:", round((cnt / TotalTime),2),"Hash/s" print "Recovery complete." sys.exit() http://www.vts-tech.org/32hex-v0-2/Uses PassLib https://pypi.python.org/packages/source/p/passlib/passlib-1.6.2.tar.gz Download VTSTech-32hex.py-036.rar Edited September 7, 2014 by VTSTech Quote Link to comment Share on other sites More sharing options...
cooper Posted August 15, 2014 Share Posted August 15, 2014 The main purpose of this program is to identify a 32hex hashtype, once the hashtype has been identified there is much faster methods of recovery. Regardless of its purpose, looking at the code I don't think that's a proper description of what it does. What you're doing is taking a single hash and a wordlist and you encrypt the words from the wordlist to make various hashes, comparing against the single hash. If at the end of the run you find you had a match, you say you cracked the hash, what it is and what the associated password is. So, what I think you've created is a very slow password cracker that doesn't limit itself to a single hashing algorithm. Improvement suggestions: - Use a dictionary to map a computed hash to the hash type and password. Lets you get rid of that *MASSIVE* if. - Break the for-loop when a match is found. - Don't print your banner for each line in your wordlist file. It'll probably be VERY annoying. - md52x and up all get populated with one more MD5 iteration than what the name suggests. - Reuse the previous MD5/MD4 calculation when you're computing multiple iterations. This code does 26 MD5 calculations and should be able to do the same with just 6. Same for MD4 (from 21 to 6). - Going beyond the above, you should put the repeat-iterations in a loop so you can have a global set to the maximum amount of iterations rather than hard-coding 6. - Are repeated iterations of MD5/MD4 actually being used??? Repeating the algo just increases the chance of collisions. - Include SHA256. - Your md5sha_hash class actually gets populated with the sha1 implementation. No MD5 comes into play so this is a very misleading name for a variable. And I just don't get it. If you have the SHA1, why bother with MD5? Is this actually used? In, like, REAL software?? - Why are you first looping through the lines of the wordlist to get a 'linet' value which you're not going to use anyways? - I don't get this line: print Cracked[0],chr(58),Cracked[2]. Cracked[1] always gets populated with that char 58. If you're not using it, remove it from the Cracked array. Better yet, populate Cracked with a formatted string and just print that. Makes everything much clearer. Quote Link to comment Share on other sites More sharing options...
VTSTech Posted August 15, 2014 Author Share Posted August 15, 2014 Regardless of its purpose, looking at the code I don't think that's a proper description of what it does. What you're doing is taking a single hash and a wordlist and you encrypt the words from the wordlist to make various hashes, comparing against the single hash. If at the end of the run you find you had a match, you say you cracked the hash, what it is and what the associated password is. So, what I think you've created is a very slow password cracker that doesn't limit itself to a single hashing algorithm. Improvement suggestions: - Use a dictionary to map a computed hash to the hash type and password. Lets you get rid of that *MASSIVE* if. - Break the for-loop when a match is found. - Don't print your banner for each line in your wordlist file. It'll probably be VERY annoying. - md52x and up all get populated with one more MD5 iteration than what the name suggests. - Reuse the previous MD5/MD4 calculation when you're computing multiple iterations. This code does 26 MD5 calculations and should be able to do the same with just 6. Same for MD4 (from 21 to 6). - Going beyond the above, you should put the repeat-iterations in a loop so you can have a global set to the maximum amount of iterations rather than hard-coding 6. - Are repeated iterations of MD5/MD4 actually being used??? Repeating the algo just increases the chance of collisions. - Include SHA256. - Your md5sha_hash class actually gets populated with the sha1 implementation. No MD5 comes into play so this is a very misleading name for a variable. And I just don't get it. If you have the SHA1, why bother with MD5? Is this actually used? In, like, REAL software?? - Why are you first looping through the lines of the wordlist to get a 'linet' value which you're not going to use anyways? - I don't get this line: print Cracked[0],chr(58),Cracked[2]. Cracked[1] always gets populated with that char 58. If you're not using it, remove it from the Cracked array. Better yet, populate Cracked with a formatted string and just print that. Makes everything much clearer. I havent put a lot of work into the python version yet ;) But thanks for the suggestions. I'm not too too concerned with speed as I'm never going to get MHash/sec using these methods. In the GUI Version I'm reading everything into arrays first. Quote Link to comment Share on other sites More sharing options...
VTSTech Posted September 8, 2014 Author Share Posted September 8, 2014 (edited) VTSTech-32hex.py Pictorial Changelog :) http://imgur.com/a/JWBrg#0 Current Version Edited September 8, 2014 by VTSTech Quote Link to comment Share on other sites More sharing options...
cooper Posted September 8, 2014 Share Posted September 8, 2014 - Are repeated iterations of MD5/MD4 actually being used??? Repeating the algo just increases the chance of collisions. - If you have the SHA1, why bother with MD5? Is this actually used? In, like, REAL software?? Quote Link to comment Share on other sites More sharing options...
VTSTech Posted September 8, 2014 Author Share Posted September 8, 2014 (edited) - Are repeated iterations of MD5/MD4 actually being used??? Repeating the algo just increases the chance of collisions. - If you have the SHA1, why bother with MD5? Is this actually used? In, like, REAL software?? Served me well in a recent password cracking competition. Was a number of 5x MD5 i wouldnt have found using Hashcat. Also because SHA1 is a 40 character hash and not a 32 character hash it is not attempted with this script. See VTSTech-40hex.py for that at www.vts-tech.org/32hex-v0-2/ Edited September 8, 2014 by VTSTech Quote Link to comment Share on other sites More sharing options...
cooper Posted September 9, 2014 Share Posted September 9, 2014 Fair enough. In general though, in case people are developing applications that include some login module and are wondering how best to store the password in encrypted form, please read this StackOverflow question and in particular its chosen answer. The short and sweet of it is that repeating a hash as-is doesn't make the hash more secure and in fact decreases the quality of the hash by making hash collisions more likely (look up the Birthday Paradox for an explanation). There are a number of hashing algorithms (bcrypt and PBKDF2 to name 2) which have been explicitly designed to be repeated and in doing so don't lose quality. What you gain with this is control over the amount of work that needs to be performed to compute a single hash (and thus the amount of work that needs to be performed to brute-force the hash). The core problem people try to solve by repeat-hashing a value is that the value to hash is predictable allowing people to create a rainbow table with precomputed hashes of commonly used values up to a given length and only needing a quick lookup to discover the password for the hash, defeating it by simply not needing to perform the hard work. Repeat-hashing means you need to have multiple rainbox tables - one for each number of repeats. Making those rainbow tables takes quite some time and a LOT of storage so having more of them around becomes more and more unattractive. When you realise that common values for repeating your hash with PBKDF2 lie somewhere between 60.000 and 120.000 iterations, you do the math... It will take your server a bit longer to verify the validity of a password hash, but that's a small price to pay. And if due to some advancement in computing the computation of the hash suddenly can be done in 1/10th the time you simply up the iterations to compensate, making the work needed to crack a single hash constant over time rather than decreasing due to advances in math and computing tech. A far cheaper way to solve the core problem is SEED YOUR HASHES! It's best to seed with a few values unique to your user, so the username, email and user id (if appliccable) come to mind. Most databases have some unique id for the database record storing your user object, so you can use that and I also recommend using a value that is kept outside of the database. Some configuration file with a big random in it should work just fine. The 'security by obscurity' bit is that your attacker needs to know what you used in what order to seed your hashes on top of the actual data itself. If your attacker still manages to acquire all the data (which would be impressive), figures out the order in which the various parts need to be fed through the algorithm (also quite impressive), (s)he still needs to break the algorithm itself... Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.