Outil en ligne de commande pour rechercher des hash sur google

Le ven. 03 décembre 2010 par Kasey

Je dispose de quelques jours de vacances et j'ai eu l'idée de me repencher sur mes problématiques de bot et de cassage de mot de passe. Ainsi, je me suis demandé quelle pourrait être la meilleure méthode pour rechercher des hashs dans Google qui est, après tout, probablement le meilleur et plus performant système de recherche au monde :) J'ai donc pris le temps de réaliser un script casseur de hashs md5 en utilisant Google. Si cela vous intéresse, le code source et un peu de documentation sont disponibles dans la suite du billet.

Recherches

Pour faire mon bot je me suis tout d'abord demandé comment faisaient les projets web fonctionnant sur la toile. Après quelques tests sur l'excellent http://project.kalkulators.org/, je me suis rendu compte que l'un des sites qui remontaient le plus souvent les mots de passe était http://bigtrapeze.com. J'ai donc cherché à savoir comment celui-ci fonctionnait. J'avoue avoir été agréablement surpris de trouver l'ensemble des notes relatives au R&D de l'auteur du blog : http://bigtrapeze.com/?p=33.

Celui-ci propose donc une preuve de concept http://www.bigtrapeze.com/md5/ ainsi que son code source : http://www.bigtrapeze.com/md5/source.php. Je vous laisse y jeter un oeil.

Principe

Le principe est très simple, on fait une recherche dans Google pour le hash désiré. On récupère le contenu de la page web retournée par Google. On fait un rapide trie pour supprimer le HTML du code source et extrait la liste des mots composants la page web. Enfin on convertit tous ces mots en md5. Si un mot correspond au hash md5, c'est que le password a été retrouvé.

Je pense que le principe peut être largement amélioré afin de triturer un peux plus les mots et d’éliminer certaines encapsulations type md5('password') ou hash==password. Mais en l'état le script fonctionne déjà très bien. Je pense rapidement l'intégrer à hashor afin de grossir plus vite la base de données des mots de passe.

Code source

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/env python
#-*-coding: utf-8 -*-

"""
Licence :
---------
Fernandez Lucas aka kasey <contact kasey.fr>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

----

Source :
 * http://www.bigtrapeze.com/md5/source.php
"""

__version__ = "0.0.2"
__author__ = [
    "Lucas Fernandez"
]
__license__ = "GNU General Public License"

import urllib2, cookielib, urllib, hashlib
import re, sys
from random import choice

class GoogleHash:
    hash   = ""
    type   = ""
    hash_t = {'md5':32,'sha1':40}
    h = re
    s = re

    def __init__(self):
        self.h = re.compile(r'<.*?>')
        self.s = re.compile(r'\s+')

    def remove_html_tags(self,data):
        return self.s.sub(' ',self.h.sub(' ',data))

    def find_hash(self,hash,type="md5"):
        self.hash = hash
        self.type = type

        # Sanity checks
        if not type in self.hash_t:
            return (-1, "type de hash inconnu")

        if len(hash) != self.hash_t[self.type]:
            return (-1, "le hash ne semble pas correspondre au type demandé")

        # Web grabber init
        cookiejar = cookielib.CookieJar()
        urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
        useragent = {'User-Agent':'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9a8) Gecko/2007100619 GranParadiso/3.0a8'}

        # do the google request
        request = urllib2.Request('http://www.google.com/search?q=%s' % self.hash, None, useragent)

        # grab and clean the result
        url  = urlOpener.open(request)
        data = self.remove_html_tags(url.read())

        # check hashtype for each word find in the google answer
        for word in re.findall(r'\w+',data):
            if len(word) <= self.hash_t[self.type]:
                if hashlib.md5(word).hexdigest() == self.hash:
                    return (self.hash, word)

        # if any word match the password is not found
        return (-3, "hash %s not found" % self.hash)

if __name__ == "__main__":
    h = GoogleHash()
    if len(sys.argv) != 2 or len(sys.argv[1]) != 32:
            print "Usage : gAPI.py <md5_hash>"
            quit()

    print h.find_hash(sys.argv[1])

Utilisation

Rien de plus simple on passe le premier argument en paramètre.

$ ./gAPI.py 4f36bf59a8f92fc97c01b6550ce06095
4f36bf59a8f92fc97c01b6550ce06095 m4st3r
$ ./gAPI.py 43c535777ddc27e7fe9b896b617eb5fc
43c535777ddc27e7fe9b896b617eb5fc not found

Perspectives

On pourrait pousser le script un peu plus loin pour lui permettre :

  • de stocker en local les mots de passe déjà craqués
  • de gérer une file de hashs à casser en entrée avec lecture sur stdin
  • l'interfacer avec l'API à venir de hashzor

Si j'ai un peu de temps, pourquoi pas :)