Recentemente mi sono accorto che alcuni servizi di hosting conservano nel database le passwords degli accounts in doppia hash md5.
Per doppia hash intendo
MD5(MD5(password)).
Un tentativo di forzare una password in questo stato facendo uso dei servizi online come Md5Crack o come Gdata,sarebbe totalmente inutile.
Il sistema che ho implementato è banale,prevede la ricerca della password a partire da una hash doppia,facendo uso di un dizionario: di ogni voce del dizionario viene calcolata la hash doppia e viene confrontata con l’input,se vi è un match il programma si arresta e fornisce la voce ottenuta.
Sicuramente una ricerca lineare non è il massimo,l’ideale è implementare un database distribuito come il celebre rainbow tables,ma per le hashes doppie attualmente non sembra esserci altro.
Facendo uso di un buon dizionario di passwords,come questo,il programmino impiega un tempo nell’ordine di 30 secondi per scorrere un tale dizionario,e parliamo di circa 40MB.
Nel codice faccio uso di una funzione molto importante per la gestione dei files da applicativi in C :
la funzione mmap,tale funzione consente di mappare un file sullo spazio di indirizzamento virtuale del processo,in pratica vi muoverete sul file come su un vettore void* ,fate il cast a char*e avrete una vera e propria stringa:potete dimenticarvi quindi delle odiose fseek,fwrite etc…
La funzione MD5,presa dalla libreria libssl, con header in
openssl/md5.h
ha 3 argomenti:stringa da criptare,dimensione in bytes della stringa da criptare,stringa su cui riporre l’hash.
La stringa su cui viene calcolato l’hash si presenta come un vettore di caratteri ascii,poichè non sembra esserci una funzione di libreria atoh,che converta da stringa ascii a stringa esadecimale,l’ho dovuta implementare.
Compilate tutto con
gcc -O3 -lssl md5doublecrack.c -o md5doublecrack
Ecco il codice:
#include <openssl /md5.h>
#include <string .h>
#include <stdlib .h>
#include <sys /types.h>
#include </sys><sys /stat.h>
#include <fcntl .h>
#include <stdio .h>
#include <sys /mman.h>
#define SIZEOF_HMD 32
#define SIZEOF_AMD 16
#define FALSE 0
#define TRUE 1
void crack(char*,const char*);
int filelength(const char*);
void atoh(char*,const char*);
int match(const char* input,const char* token);
void check_parameters(int,char**);
int main(int argc,char* argv[])
{
const char* double_hash_input;
char* file_name;
int fd;
void* file_memory;
void* file_dump;
int file_length;
check_parameters(argc,argv);
double_hash_input=argv[1];
file_name=argv[2];
if(strlen(double_hash_input)!=32)
exit(1);
file_length=filelength(file_name);
fd=open(argv[2],O_RDONLY, S_IRUSR);
file_memory = mmap (0, file_length, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
memcpy(file_dump=malloc(sizeof(char)*file_length),file_memory,file_length);
munmap(file_memory,file_length);
crack((char*)file_dump,double_hash_input);
return;
}
void crack(char* file,const char* input_hash)
{
char* token;
int cracked=FALSE;
char a_hashed_entry[SIZEOF_AMD];
char a_double_hashed_entry[SIZEOF_AMD];
char h_hashed_entry[SIZEOF_HMD];
char h_double_hashed_entry[SIZEOF_HMD];
int string_length;
token=strtok(file,"\n");
cracked=match(input_hash,token);
while(token != NULL && cracked == FALSE )
{
token=strtok(NULL,"\n");
if(token == NULL)
break;
string_length=strlen(token);
MD5(token,string_length,a_hashed_entry);
atoh(h_hashed_entry,a_hashed_entry);
MD5(h_hashed_entry,SIZEOF_HMD,a_double_hashed_entry);
atoh(h_double_hashed_entry,a_double_hashed_entry);
if(strncmp(h_double_hashed_entry,input_hash,SIZEOF_HMD)==0)
cracked=TRUE;
}
if(cracked == TRUE)
printf("Match found with entry %s\n",token);
else
printf("Sorry,no match found\n");
free(file);
}
int filelength(const char* file_name)
{
FILE * file = fopen (file_name,"rb");
/*obtain the file size*/
fseek (file , 0 , SEEK_END);
long int size = ftell(file);
rewind (file);
fclose(file);
return size;
}
int match(const char* input_hash,const char* token)
{
char a_hashed_entry[SIZEOF_AMD];
char a_double_hashed_entry[SIZEOF_AMD];
char h_hashed_entry[SIZEOF_HMD];
char h_double_hashed_entry[SIZEOF_HMD];
int string_length;
if(token == NULL)
exit(1);
string_length=strlen(token);
MD5(token,string_length,a_hashed_entry);
atoh(h_hashed_entry,a_hashed_entry);
MD5(h_hashed_entry,SIZEOF_HMD,a_double_hashed_entry);
atoh(h_double_hashed_entry,a_double_hashed_entry);
return strncmp(h_double_hashed_entry,input_hash,SIZEOF_HMD)==0 ? TRUE : FALSE;
}
void atoh(char* string,const char* bytes)
{
register int i;
for(i=0;i< SIZEOF_AMD ;i++)
{
sprintf(string++,"%x",(bytes[i]&0xff)>>4);
sprintf(string++,"%x",bytes[i]&0xf);
}
}
void check_parameters(int argc,char* argv[])
{
if(argc-1 != 2 || strlen(argv[1])!=SIZEOF_HMD)
{
printf("Usage : %s [double hash] [dictionary]\n",argv[0]);
exit(1);
}
}




















19 Giugno 2008 alle 1:59 pm |
siccome io sono lagnuso ho fatto la stessa cosa in ruby…
Non è ottimizzato…anzi ci sono righe che servono solo per il debug
#!/usr/bin/ruby
require ‘digest/md5′
aFile = File.new(ARGV[1], “r”)
myhash=ARGV[0]
a=0
puts “Scassando §#{myhash}§ con #{ARGV[1]}”
aFile.each_line {|line| line.chomp!
testhash=Digest::MD5.hexdigest(Digest::MD5.hexdigest(line))
a=a+1
if a.modulo(1024)==0 then
puts “#{a/1024}k: #{line} #{testhash} #{myhash}”
end
if testhash==myhash
oFile=File.new(”pass.dat”, “w+”)
oFile.puts “#{line} #{testhash}”
oFile.close
Kernel.exit()
end
}
aFile.close
19 Giugno 2008 alle 2:14 pm |
Ancora co sto ruby ????
BASTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
19 Giugno 2008 alle 2:29 pm |
La versione che ho usato per testare il mio script…che attualmente batte il tuo in prestazioni
è questa:
#!/usr/bin/ruby
require ‘digest/md5′
aFile = File.new(ARGV[1], “r”)
myhash=ARGV[0]
a=0
puts “Scassando §#{myhash}§ con #{ARGV[1]}”
aFile.each_line {|line| line.chomp!
testhash=Digest::MD5.hexdigest(Digest::MD5.hexdigest(line))
if testhash==myhash
puts “#{line} #{testhash}”
Kernel.exit()
end
}
aFile.close
real 0m40.034s
user 0m38.990s
sys 0m0.668s
contro
real 1m4.663s
user 1m4.080s
sys 0m0.112s
19 Giugno 2008 alle 2:51 pm |
Ma ne sei proprio sicuro ?
ordeal@debian:~/hackz$ time ruby1.9 ./md5doublecrack.rb 25869800ff2ef3b940b9358d66ff59f7 all.lst
Scassando 25869800ff2ef3b940b9358d66ff59f7 con all.lst
prova 25869800ff2ef3b940b9358d66ff59f7
real 0m24.703s
user 0m24.588s
sys 0m0.052s
ordeal@debian:~/hackz$ time ./md5doublecrack 25869800ff2ef3b940b9358d66ff59f7 all.lst
Match found with entry prova
real 0m20.898s
user 0m20.688s
sys 0m0.176s
Per non parlare di un not found:
ordeal@debian:~/hackz$ time ruby1.9 ./md5doublecrack.rb 25869800ff2ef3b940b9358d66ff59f8 all.lst
Scassando 25869800ff2ef3b940b9358d66ff59f8 con all.lst
real 2m45.976s
user 2m36.992s
sys 0m0.304s
ordeal@debian:~/hackz$ time ./md5doublecrack 25869800ff2ef3b940b9358d66ff59f8 all.lst
Sorry,no match found
real 2m18.092s
user 2m11.796s
sys 0m0.252s
19 Giugno 2008 alle 5:19 pm |
Ho scritto uno scriptino in Python per provare.
Ecco il codice:
#!/usr/bin/python
from __future__ import with_statement
import hashlib
import sys
doubleHash = sys.argv[1]
print “Provo a scassare ” + doubleHash + “\n”
with open(sys.argv[2],”r”) as dict:
for line in dict:
hashTest = hashlib.md5(hashlib.md5(line.rstrip()).hexdigest()).hexdigest()
if hashTest == doubleHash:
print line.rstrip() + ” ” + doubleHash
sys.exit(0)
Ecco i risultati:
valinor:Desktop feanor$ time ./crack.py b415a0b7e721a8c1ebac6bc01604e16c ./dic-0294.txt
Provo a scassare b415a0b7e721a8c1ebac6bc01604e16c
Karntnerstrasse-Rotenturmstrasse b415a0b7e721a8c1ebac6bc01604e16c
real 0m5.594s
user 0m5.355s
sys 0m0.078s
Ecco i risultato con la stessa hash doppia e lo scriptino in Ruby
:
valinor:Desktop feanor$ time ./cruby.rb b415a0b7e721a8c1ebac6bc01604e16c ./dic-0294.txt
Scassando §b415a0b7e721a8c1ebac6bc01604e16c§ con ./dic-0294.txt
Karntnerstrasse-Rotenturmstrasse b415a0b7e721a8c1ebac6bc01604e16c
real 0m6.255s
user 0m5.861s
sys 0m0.097s
Vince Python!
23 Giugno 2008 alle 11:46 pm |
ciao Rino….ma quantu ni sai?!??!