fang

Fang is a multi service threaded MD5 cracker

fang.conf
POST|http://www.onlinehashcrack.com/free-hash-reverse.php[hashToSearch:{HASH},searchHash:Search]|Plain text \: ]*>([^<]+)
POST|http://www.md5decryption.com/[hash:{HASH},submit:Decrypt+It%21]|>Decrypted Text: <\/b>(.+)<\/font>
GET|http://md5.gromweb.com/?md5={HASH}|name="string" value="(.+)" id="form_string" maxlength="255" size="40" />
GET|http://www.stringfunction.com/md5-decrypter.html?st={HASH}|(.+)
GET|http://md5.noisette.ch/md5.php?hash={HASH}|
POST|http://md5.my-addr.com/md5_decrypt-md5_cracker_online/md5_decoder_tool.php[md5:{HASH},x:23,y:8]|Hashed string: (.+)\s*
POST|http://md5pass.info/[hash:{HASH},get_pass:Get+Pass]|Password - (.+)\s*

#!/usr/bin/python
# This file is part of Fang.
#
# Copyright(c) 2010-2011 Simone Margaritelli
# evilsocket@gmail.com
# <a href="http://www.evilsocket.net<br />
#<br />
#" title="http://www.evilsocket.net<br />
#<br />
#">http://www.evilsocket.net<br />
#<br />
#</a> This file may be licensed under the terms of of the
# GNU General Public License Version 2 (the ``GPL'').
#
# Software distributed under the License is distributed
# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
# express or implied. See the GPL for the specific language
# governing rights and limitations.
#
# You should have received a copy of the GPL along with this
# program. If not, go to <a href="http://www.gnu.org/licenses/gpl.html<br />
#" title="http://www.gnu.org/licenses/gpl.html<br />
#">http://www.gnu.org/licenses/gpl.html<br />
#</a> or write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

import getopt, sys, os, urllib, urllib2, re, urlparse, os, threading, signal
from optparse import OptionParser, OptionGroup

class Service(threading.Thread):
def __init__ ( self, type, url, regex, exit_on_match, hash ):
threading.Thread.__init__(self)

self.type = type
self.url = url
self.hash       = hash if hash != None else ""
self.regex = regex.replace( '{HASH}', self.hash )
self.args = {}
self.name = urlparse.urlparse(url)[1]
self.exit_on_match = exit_on_match

if self.type == 'POST':
self.args = self.__parseArgs()

def run( self ):       
global cracked

cleartext = self.__crack(self.hash)
if cleartext != None:
print "!!!\tThe plaintext of %s is '%s' (found on %s)" % ( self.hash, cleartext, self.name )
if self.exit_on_match == True:
os.kill( os.getpid(), signal.SIGTERM )

def __crack( self, hash ):
data = ''
try:
if self.type == 'GET':
url = self.url.replace( '{HASH}', hash )
data = self.__exec_get(url)
else:
url = self.url.replace( '{HASH}', hash )       
args = self.args
for name,value in args.iteritems():
args[name] = value.replace( '{HASH}', hash )
data = self.__exec_post(url,args)      
except:
pass

return self.__xtract_data(data)

def __xtract_data( self, data ):
m = re.search( self.regex, data )
return m.group(1) if m is not None else None

def __exec_get( self, url ):
return urllib2.urlopen( urllib2.Request(url) ).read()

def __exec_post( self, url, data ):
return urllib2.urlopen( urllib2.Request( url, urllib.urlencode(data) ) ).read()

def __parseArgs( self ):
m = re.search( "([^\[]+)\[([^\]]+)\]", self.url )
self.url = m.group(1)
params = m.group(2)
params  = params.split(',')
args    = {}

for param in params:
(k,v) = param.split(':')
args[k] = v

return args

try:
print "\n\tFang 1.2 - A multi service threaded MD5 cracker.\n \
\tCopyleft Simone Margaritelli <evilsocket@gmail.com>\n \
\thttp://www.evilsocket.net\n\thttp://www.backbox.org\n"
;
               
parser = OptionParser( usage = "usage: %prog [options] [--hash <hash>]\n\n" +
                                   "EXAMPLES:\n" +
                                   " %prog --hash 7815696ecbf1c96e6894b779456d330e\n" +
                                   " %prog --threads 10 --exit-first --hash 7815696ecbf1c96e6894b779456d330e\n" +
                                   " %prog --input hashlist.txt\n" +
                                   " %prog --list" )

parser.add_option( "-H", "--hash", action="store", dest="hash", default=None, help="The hash to crack, mandatory." )
parser.add_option( "-t", "--threads", action="store", dest="threads", default=10, help="Specify how many threads to use, default 10." )
parser.add_option( "-e", "--exit-first", action="store_true", dest="exit_on_first", default=False, help="Stop execution upon first positive match." )
parser.add_option( "-i", "--input", action="store", dest="input", default=None, help="Read a list of hashes from the given file." )

(o,args) = parser.parse_args()
   
conf = open( "fang.conf", "rt" )
services = []
hashes = []

if o.input != None:
o.exit_on_first = False
hashlist = open( o.input, "rt" )
for line in hashlist:
md5 = line.rstrip()
if md5 != '':
hashes.append(md5)     

elif o.hash != None:
hashes.append( o.hash )

else:
parser.error( "No hash specified!" )

for line in conf:
( type, url, regex ) = line.rstrip().split('|')
for md5_hash in hashes:
services.append( Service( type, url, regex, o.exit_on_first, md5_hash ) )

conf.close()

i =
for si, service in enumerate(services):
print "Searching for '%s' on %s ..." % ( service.hash, service.name )
service.start()
i += 1
if i >= o.threads or si >= len(services):
service.join()
i =

except IOError as e:
print e
except:
raise