Dzisiaj napiszemy proste narzędzie do łamania haszy MD5/SHA1 metodą bruteforce. Skryptów umożliwiających takie operacje w internecie jest masa. My też skorzystamy z gotowego skryptu znalezionego w internecie, napisanego przez Juza. Nasze narzędzie będzie się różnić tym że będziemy mogli je wykorzystać na wielu komputerach i poprzez interfejs www.
Co potrzebujemy?
* Wiedzy czym jest MD5 i/lub SHA1
* Serwer z www, php i mysql (otwarte na dostęp z zewnątrz link)
* Najlepiej kilka maszyn z dostępem do shell oraz poleceniem mysql
Zacznijmy od stronki dzięki której będziemy wrzucać hasze. Na początek struktura bazy:
-- phpMyAdmin SQL Dump -- http://www.phpmyadmin.net SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; CREATE TABLE IF NOT EXISTS `hash` ( `id` int(5) NOT NULL AUTO_INCREMENT, `hash` varchar(100) NOT NULL, `typ` varchar(4) NOT NULL, `min` varchar(2) NOT NULL, `max` varchar(2) NOT NULL, `value` varchar(255) NOT NULL, `status` varchar(1) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=38 ; INSERT INTO `hash` (`id`, `hash`, `typ`, `min`, `max`, `value`, `status`) VALUES (9, '38f7a8a334cc90d8400ae9e6eeb31340', 'md5', '4', '8', 'juza', '3'), (10, '9743a66f914cc249efca164485a19c5c', 'md5', '4', '8', 'dupa', '3'), (25, '7c37ed5b5b72d2c6927e25357e6c488a', 'md5', '1', '8', 'reksio', '3'), (27, '7635e7b8be884a1f4acfba286ec27061', 'md5', '1', '8', 'piesek', '3'), (28, '391b91114b10392a6ae72ff8dc7395e8', 'md5', '1', '8', 'zuch', '3'), (30, 'f21f1b67653b4fc32e8f915ae82e344b', 'md5', '1', '10', 'youtt', '3'), (31, '85a057cb845658bd35be5e2458429a42', 'md5', '1', '10', 'mutt', '3'), (36, '6d9fdb16ed509488eeef6af2f842a744', 'md5', '1', '8', 'dupa.8', '3');
Następnie połączenie z bazą:
<?php
//stałe bazy danych
$mysql_host = 'localhost';
$mysql_login = 'login';
$mysql_haslo = 'haslo';
$mysql_baza = 'login';
// połączenie z bazą danych
$polaczenie = mysql_connect($mysql_host, $mysql_login, $mysql_haslo) or die('Błąd: nie udało się nawiązać połączenia z bazą danych.');
// połączenie ze schematem bazy danych
mysql_select_db($mysql_baza) or die('Błąd: nie udało się wybrać schematu bazy danych.');
?>
Następnie potrzebny nam interfejs www :)
<?php
include('db.php');
if($_SERVER["REQUEST_METHOD"] == "POST")
{
$hash=$_POST['hash'];
$wynik = mysql_query("SELECT * FROM hash WHERE hash='$hash'");
if(isset($_POST['submit']) && $_POST['hash']=='' && mysql_num_rows($wynik) <> 0)
{
echo '<p>Wypełnij kurwa pola lub hash znajduje się już w bazie</p>';
} else {
$hash = $_POST['hash'];
$typ = $_POST['typ'];
$min = $_POST['min'];
$max = $_POST['max'];
$status = '1';
if($min==''){
$min = '1';
}
if($max==''){
$max = '6';
}
mysql_query("INSERT INTO `hash` SET `hash` = '$hash', `typ` = '$typ', `min` = '$min', `max` = '$max', `status` = '$status';");
echo '<p>Dodano</p>';
}
}
if($_GET['action']==''){
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MD5/SHA1 crack</title>
</head><body>
<a href="index.php">Home</a> <a href="index.php?action=list">Lista</a><br><br>
<p>Wypełnij poniższe pola</p>
<form action='index.php' method="POST">
<table>
</td></tr>
<tr><td align=right>Hash md5/sha1 </td><td>
<input size="50" type='text' name='hash' value="">
</td></tr>
<tr><td align=right>Rodzaj </td><td>
<select name="typ">
<option value="md5">md5</option>
<option value="sha1">sha1</option>
</select>
</td></tr>
<tr><td align=right>Min liczba znaków </td><td>
<input size="2" type='text' name='min' value="">
</td></tr>
<tr><td align=right>Max liczba znaków </td><td>
<input size="2" type='text' name='max' value="">
</td></tr>
</table>
<br><br>
<input name="submit" type='submit' value='Save'>
</form>
</body>
</html>
<?php
}
if($_GET['action']=='list'){
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MD5/SHA1 crack</title>
</head><body>
<a href="index.php">Home</a> <a href="index.php?action=list">Lista</a><br><br>
<?
echo '<table align=\"center\"><tr><td>Hash</td><td>Rodzaj</td><td>Status</td><td>Hasło</td></tr>';
$wynik = mysql_query("SELECT * FROM `hash` ORDER BY id DESC;") or die('Błąd zapytania');
if(mysql_num_rows($wynik) > 0) {
/* jeżeli wynik jest pozytywny, to wyświetlamy dane */
while($r = mysql_fetch_assoc($wynik)) {
if($r['status']=='1'){
$status = 'Waiting to add';
}
if($r['status']=='2'){
$status = 'In progress';
}
if($r['status']=='3'){
$status = 'Finish';
}
if($r['status']=='4'){
$status = 'Error';
}
echo '<tr><td>'.$r['hash'].'</td><td>'.$r['typ'].'</td><td>'.$status.'</td><td>'.$r['value'].'</td></tr>';
}
echo "</table></center>";
echo " </body></html>";
}
}
?>
Skoro mamy już stronę skąd można dodawać i pobierać hasze zajmijmy się budową nodów. Do tego celu będziemy potrzebować 3 plików. Dwa zwykłe bashowe i jeden napisany w pythonie.
Pierwszy nazwijmy go bot.sh będzie sprawdzał czy w bazie pojawił się nowy hasz:
#!/bin/bash ### BOT/MASTER ### USER="login" HASLO="haslo" BAZA="login" HOST="ip lub domena do bazy mysql" until false do zm=`mysql -u $USER -h $HOST -p$HASLO $BAZA -e "SELECT id FROM hash WHERE status='1' LIMIT 1;" | cut -d " " -f 2 | tail -n 1`; if [[ `echo $zm` == "" ]]; then sleep 5 else process=`ps -ef | grep node.sh | wc -l` if [[ `echo $process` -lt 1 ]] then hash=`mysql -u $USER -h $HOST -p$HASLO $BAZA -e "SELECT hash FROM hash WHERE id=$zm;" | cut -d " " -f 2 | tail -n 1`; CMD="mysql -u $USER -h $HOST -p$HASLO $BAZA" $CMD -e "UPDATE hash SET status='2' WHERE hash='$hash'" ./node.sh $hash & fi fi done exit 0
Drugi plik node.sh będzie nam trzymał skrypt pythona oraz robił update do bazy jeśli hasz zostanie znaleziony:
#!/bin/bash # NOD # USER="login" HASLO="haslo" BAZA="login" HOST="ip lub domena do bazy mysql" min=`mysql -u $USER -h $HOST -p$HASLO $BAZA -e "SELECT min FROM hash WHERE hash='$1';" | cut -d " " -f 2 | tail -n 1`; max=`mysql -u $USER -h $HOST -p$HASLO $BAZA -e "SELECT max FROM hash WHERE hash='$1';" | cut -d " " -f 2 | tail -n 1`; typ=`mysql -u $USER -h $HOST -p$HASLO $BAZA -e "SELECT typ FROM hash WHERE hash='$1';" | cut -d " " -f 2 | tail -n 1`; CMD="mysql -u $USER -h $HOST -p$HASLO $BAZA" zm=`./start.py -t $typ -h $1 -w ABCDEFGHIJKLMNOPRSTUWXYZ1234567890abcdefghijklmnopqrstuvwxyz -a $max -i $min -v | grep Value | cut -d " " -f 4`; if [[ `echo $zm` == "" ]]; then $CMD -e "UPDATE hash SET status='4' WHERE hash='$1'" else $CMD -e "UPDATE hash SET value='$zm', status='3' WHERE hash='$1'" fi
Pozostał już tylko plik w pythonie nazywamy go start.py:
#!/usr/bin/python
#####################################
# Hash Crack by Juza #
# juzase[at]gmail[dot]com #
# 2007/9/10 #
#####################################
# [+]Crack MD5, SHA1 Hashes #
# [+]Brute Force Attack #
#####################################
import sys , string , time
"""
Hash Crack 1.0 version
"""
def main():
"Main"
title = "HC : Hash Crack"
print "\n" + title.center(45) + "\n"
def usage():
"Usage"
print "[-] Exemple : HashCrack.py -t md5 -h 38F7A8A334CC90D8400AE9E6EEB31340 -w 1234567890 -a 8 -i 5 -v"
def usagelarge():
"Usage Large"
print "\n Usage: python HashCrack.py <options>\n"
print "\n Example: python HashCrack.py -t md5 -h 38F7A8A334CC90D8400AE9E6EEB31340 -w 1234567890 -a 8 -i 5 -v"
print "\t[options]"
print "\t -h/-hash <md5/sha1> : Hash to Crack"
print "\t -w/-word <words> : Words"
print "\t -a/max-write <max len> : Maximun Lenght"
print "\t -i/min-write <min len> : Minimun Lenght"
print "\t -v/-verbose : Verbose Mode\n"
def timer():
"Time"
now = time.localtime(time.time())
return time.asctime(now)
if '__main__' == __name__ :
if len(sys.argv) <= 5:
main()
usagelarge()
sys.exit(1)
hhash = words = maxw = minw = typeh = ""
verbose = 0
for arg in sys.argv[1:]:
try:
if arg.lower() == "-v" or arg.lower() == "-verbose":
verbose = 1
if arg.lower() == "-h" or arg.lower() == "-hash":
hhash = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-a" or arg.lower() == "-max":
maxw = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-i" or arg.lower() == "-min":
minw = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-w" or arg.lower() == "-words":
words = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-t" or arg.lower() == "-type":
typeh = sys.argv[int(sys.argv[1:].index(arg))+2]
except(IndexError):
print "[-] Obrigatory Arguments -t(hash type) -h(hash) -w(words) -max(max word)"
usage()
sys.exit(1)
if minw == "" : minw = '1'
main()
for args in (typeh, hhash, words, maxw, minw):
try:
if args != "":
if args == typeh :
if typeh.lower() != 'md5' or 'sha':
if typeh.lower() == "md5" :
typeh = '1'
print "[+] Hash Type : MD5"
elif typeh.lower() == "sha" :
typeh = '2'
print "[+] Hash Type : SHA1"
else:
print "[-] Invalid hash type"
sys.exit(1)
if args == hhash :
if typeh == '1' :
if len(hhash) == 32 :
print "[+] MD5 Hash : " + hhash
else:
print "[-] Invalid MD5 hash"
sys.exit(1)
if typeh == '2' :
if len(hhash) == 40 :
print "[+] SHA1 Hash : " + hhash
else:
print "[-] Invalid SHA1 hash"
sys.exit(1)
if args == words :
print "[+] Words : " + words
if args == maxw :
if maxw.isdigit() != False :
if int(maxw) >= 15 :
print "[-] Max Word : 15 : " + maxw
sys.exit(1)
else:
if int(maxw) > int(minw):
print "[+] Max Word : " + maxw
else:
print "[-] Max Word > Min Word"
sys.exit(1)
else:
print "[-] Max Word = Digit"
sys.exit(1)
if args == minw :
if minw.isdigit() != False :
if int(minw) < int(maxw) :
print "[+] Min Word : " + minw
else:
print "[-] Min Word < Max Word"
sys.exit(1)
else:
print "[-] Min Word = Digit"
sys.exit(1)
else:
print "[-] Obrigatory Arguments -t(hash type) -h(hash) -w(Words) -max(Max Word)"
usage()
sys.exit(1)
except(ValueError):
print "[-] Bad Fromat of Argumets"
sys.exit(1)
f = open("CRACK.py",'w')
f.write("#!/usr/bin/env python\n")
if (typeh == '1') : f.write("import sys , md5 , string , time\n")
if (typeh == '2') : f.write("import sys , sha , string , time\n")
tab = '\t'
f.write("def timer():\n")
f.write(tab + "now = time.localtime(time.time())\n")
f.write(tab + "return time.asctime(now)\n")
f.write("def crackhash():\n")
i = 0 ; inwords = ""
f.write(tab + "hashh = '" + hhash.lower() +"'\n")
f.write(tab + "try:\n")
#print words
for i in words:
if i == str(words[int(len(words)-1)]) :
inwords += "'" + i + "'"
break
inwords += "'" + i + "',"
#print inwords
i = int(minw) ; iwords = "" ; a = 0
while (int(i) != int(maxw) + 1) :
for a in range(i):
if int(i) != (int(a) + 1):
iwords += "i" + str(i) + str(a) + " + "
else:
iwords += "i" + str(i) + str(a)
data = (int(a + 2) * tab + "for i" + str(i) + str(a) + " in (" + inwords + "):\n")
f.write(data)
f.write(int(i + 2) * tab + "word = '' ; value = ''\n")
f.write(int(i + 2) * tab + "word = " + iwords + "\n")
if typeh == '1' : f.write(int(i + 2) * tab + "hash = md5.new()\n")
if typeh == '2' : f.write(int(i + 2) * tab + "hash = sha.new()\n")
f.write(int(i + 2) * tab + "hash.update(str(word))\n")
f.write(int(i + 2) * tab + "value = hash.hexdigest()\n")
if verbose == 1 : f.write(int(i + 2) * tab + "print " + iwords + ' + " : " + str(value)\n')
f.write(int(i + 2) * tab + "if str(hashh) == str(value):\n")
f.write(int(i + 3) * tab + "raise Exception\n")
iwords = ""
i += 1
f.write(tab + "except(Exception):")
f.write('\n'+ 2 * tab + "print '****Cracked' + 36 * '*'")
f.write('\n' + 2 * tab + "print '[=] Hash :', hashh")
f.write('\n' + 2 * tab + "print '[=] Hash Attack :', value")
f.write('\n' + 2 * tab + "print '[=] Value :', str(word)")
f.write('\n' + 2 * tab + "print '[=] Time :', timer()")
f.write('\n' + 2 * tab + "sys.exit(1)")
f.write('\n' + tab + "except(KeyboardInterrupt):")
f.write('\n' + 2 * tab + "print '[-] Process Ended ',timer()")
f.write('\n' + 2 * tab + "sys.exit(1)")
f.write("\ncrackhash()")
f.close()
print '[-] Time : ', timer()
import CRACK
CRACK.crackhash()
3 ostatnie pliki wgrywamy na dowolny shell z dostępem do komendy mysql. Aby uruchomić ustrojstwo należy w katalogu gdzie znajdują sie skrypty wydać polecenie bot.sh &
Od teraz bot.sh będzie sobie sprawdzał co 5 sekund czy pojawiły się nowe hasze i pobierał je. Oczywiście decyduje prędkość połączenia zdalnego serwera z serwerem mysql. Ten serwer który pierwszy pobierze hasz i sprawdzi czy nie ma już procesów zmieni status i rozpocznie łamanie.

