Forense automatizado a un whatsapp

16 comments











Buenas a todos, ya hace un tiempo que no escribo algún que otro articulo y hoy aburrido hablando con unos amigos por whatsapp me quedo la duda de si whatsapp guardaba los logs de todo lo que hicíera y efectivamente whatsapp lo hacia.

Viendo la de cositas que se estaban guardando :
      - Conversaciones de tlfn a tlfn
      - Chats activos
      - Fotos de los perfiles que mire
      - Imágenes, audios, videos que me pasarón o que pase

      (Por ejemplo).

Pues me apetecio hacerle un forense y al tiempo que lo hago os haré una demo del forense a un whatsapp y vereís todos los datos que podemos sacar de utilidad.

Recrearemos un entorno en el que dispongo de acceso físico a un terminal.
El whatsapp es una buena forma de extraer información sobre el día día de la persona, se podría aplicar algo como "Dime con quien andas y te diré quien eres" pero convertido al método geek.


Empezamos con la DEMO :

Bueno, los ficheros de whatsapp se guardan por defecto en /storage/sdcard0/WhatsApp/ , y yo me enviaré los ficheros con Airdroid, una estupenda app para compartir archivos PC - Smartphone vía wifi.



























Para pasar a estar conectados en "Modo de conexión remota" como ahí podeís ver solo hay que acceder a web.android.com y te logueas con tu cuenta.

















Y tan solo te queda acceder al directorio y descargar los arhivos de los que extraeremos los metadatos.

















Una vez descargados los ficheros voy a proceder a comentaros que podemos encontrar en cada uno de los directorios y cómo podríamos extraerles el jugo.

Tenemos "Databases", "Media" y "Profile Pictures", he hecho un script para que extraiga los metadatos de los db.crypt, tambien extrae los ficheros de la carpeta media(imágenes, audios, videos) y tambien extrae las imágenes encontradas en Profile Pictures.

Databases : Aqui podremos encontrarnos una serie de ficheros con extensión "db.crypt", Whatsapp cifra los archivos SQLite con AES pero siempre usa la misma key "346a23652a46392b4d73257c67317e352e3372482177652c" y de este modo podré decodificarlos.

Media : Aqui nos encontramos con una seríe de archivos (imágenes, audios, videos y wallpapers).

Profile Pictures : Aqui nos encontraremos con todas las imágenes de perfil(de usuario) que hemos mirado desde nuestro whatsapp.


NOTA IMPORTANTE : Para extraer la información de todos estos archivos que hemos obtenido he codeado un script que automatiza todo el proceso (a excepción del proceso de obtención de los ficheros , puesto que se supone que tenemos acceso físico al terminal.)
































Ahora os mostraré un esquema en forma de arbol para comprender un poco como funciona el script que he preparado:

· WhatsApp Metadata Extractor :
       - main_manage.py (main de consola en forma de cliente)
       - DB_Extractor.py (extrae los metadatos de la BD)
       - metaimg_extractor.py (extrae los metadatos de los .jpg encontrados)


He dividido el proyecto en 3 scripts, main_manage es el encargado de interactuar con el cliente (el que debemos ejecutar), DB_Extractor es el encargado de realizar las consultas con la BD para extraer toda la información(la que nos interesa) y metaimg_extractor es el encargado de buscar en "Media" y en "Profile Pictures" en busca de metadatos en los archivos .jpg (La mayoria vienen con ellos eliminados por defecto pero no me digas por qué algunas imágenes no se filtran y son subidas sin filtrarse).

Sin más os dejo los codes :

main_manage.py :

# -*- coding: utf-8 *-*
import DB_Extractor, metaimg_extractor

class WhatsApp_Extractor():

    def __init__(self):
        self.__opt()

    def __opt(self):
        #Uncomment the OPTION that you want to use

        #self.__opt1()  #-> DB METADATA EXTRACTOR
        #self.__opt2()  #-> IMG METADATA EXTRACTOR
        #self.__opt3()  #-> BOTH, OPT1 AND OPT2

    def __opt1(self):
        print "DB METADATA"
        print "------------"
        DB_Extractor.DB_Extractor()
        print "------------"

    def __opt2(self):
        print "IMG META"
        print "------------"
        metaimg_extractor.IMG_Meta()
        print "------------"

    def __opt3(self):
        print "DB METADATA"
        print "------------"
        DB_Extractor.DB_Extractor()
        print "------------"
        print "\nIMG META"
        print "------------"
        metaimg_extractor.IMG_Meta()
        print "------------"

WhatsApp_Extractor()

DB_Extractor.py :

# -*- coding: utf-8 *-*
#Script to extract the metadata from the WhatsApp crypted DB

import sqlite3
from Crypto.Cipher import AES

class DB_Extractor():

    def __init__(self):
        self._manage_do()

    def _manage_do(self):
        try:
            self.__DB_Breaker('msgstore.db.crypt')
            self.__DB_conn()
            self.__SQL_Consulter()
            #Log exporter
        except:
            print "Error starting the script"

    def __DB_Breaker(self, DBPath):
        self.DBPath = DBPath
        #breaking the hash
        f = open(self.DBPath, 'rb')
        key = "346a23652a46392b4d73257c67317e352e3372482177652c"
        #triying to break the hash
        try:
            key = key.decode('hex')
            cipher = AES.new(key, 1)
            decoded = cipher.decrypt(f.read())
            #Saving into a new db file
            try:
                decoded_DB = open('metadb.db', 'wb')
                decoded_DB.write(decoded)
                decoded_DB.close()
                print "metadb.db has been created in the same directory"
            except:
                print "An error has ocurred creating the decoded DB"
        except:
            print "Error decoding the hash"


    def __DB_conn(self):
        #triying to connect with the sqlite database
        try:
            self.conn = sqlite3.connect('metadb.db')
            self.consult = self.conn.cursor()
        except:
            print "An error has ocurred connecting with the SQLite DB"


    def __SQL_Consulter(self):
        #Divided in :
            # Messages
            # Chat_list

        def __Messages():
            #SQLConsult
            try:
                self.consult.execute("SELECT key_remote_jid, key_from_me, \
                remote_resource, status, datetime(timestamp), data, media_url, media_mime_type, \
                media_size, latitude, longitude FROM messages;")

            except:
                print "An error has ocurred doing the SQL Consult"

            def __Shower():
                #Message details
                #nota : parsear status, comprobar si yo envio o recivo

                for data in self.consult:
                    try:
                        print "\nMessages Details:"
                        print "----------------------"

                        if str(data[2]):
                            if str(data[1]) == '1':
                                print "From: me"
                                print "To: %s(group), integrant: %s"%(str(data[0]), str(data[2]))
                            else:
                                print "From: %s(group), integrant: %s"%(str(data[0]), str(data[2]))
                                print "To: me"
                        else:
                            if str(data[1]) == '1':
                                print "From: me"
                                print "To: " + str(data[0])
                            else:
                                print "From: " + str(data[0])
                                print "To: me"

                        print "Status: " + str(data[3])
                        print "Timestamp: " + str(data[4])
                        print "Message: " + str(data[5])
                        print "Media content: %s, type: %s, size: %s"%(str(data[6]), str(data[7]), str(data[8]))
                        print "Location(Lat: %s, Long: %s)"%(str(data[9]), str(data[10]))
                        print "----------------------"

                    except:
                        continue
                        print "ERROR showing message details"

            __Shower()


        def __Chat_list():
            #SQLConsult
            try:
                self.consult.execute("SELECT id, \
                key_remote_jid FROM chat_list;")

            except:
                print "An error has ocurred doing the SQL Consult"

            def __Shower():
                #Chat list details
                for data in self.consult:
                    try:
                        print "\nChat_list"
                        print "ID: " + str(data[0])
                        print "Number: " + str(data[1])
                        print "----------------------"
                    except:
                        continue
                        print "ERROR showing chat list details"

            __Shower()

        #Initializing
        __Messages()
        __Chat_list()


metaimg_extractor.py :

# -*- coding: utf-8 *-*
import os, exif

class IMG_Meta():

    def __init__(self):
        try:
            self.__Media_extractor()
            print "------------------------------------------------------\n"
            self.__Profile_extractor()
        except:
            print "An error has ocurred starting the script"
    def __Media_extractor(self):
        try:
            images = os.listdir('Media/WhatsApp Images/')
        except:
            print "An error has ocurred listing the files into the directory"

        def __Shower():
            for i in images:
                print "-------------"
                print i
                obj = exif.extract_EXIF('Media/WhatsApp Images/%s' % i)
                print "-------------"

        __Shower()

    def __Profile_extractor(self):
        try:
            images = os.listdir('Profile Pictures/')
        except:
            print "An error has ocurred listing the files into the directory"

        def __Shower():
            for i in images:
                print "-------------"
                print i
                obj = exif.extract_EXIF('Profile Pictures/%s' % i)
                print "-------------"

        __Shower()


Unas imágenes trabajando :


DB_Extractor :




























IMG extractor :




























El archivo "Exif" que importamos en el metaimg_extractor podemos encontrarlo en el proyecto de grampus en bitbucket

PD : El Forense podría llegar a hacerse en mayor profundidad, en este caso solo tratamos los datos que podrían ser más relevantes como conversaciones, envio de archivos y el análisis de los metadatos de las imágenes.

En fin, esto es todo, el script os automatizará todo el trabajo "duro"


Saludos !! , Sanko.

16 comentarios

  1. Esto esta buenisimo, es hora de ponerlo ne marcha :)

    ResponderEliminar
  2. como funciona , como hago ejecutar los codes ? Perdon soy u ignorante .. ;)

    ResponderEliminar
  3. Guarda los scripts y ejecutas desde la terminal python nombreSript.py y listo.

    ResponderEliminar
  4. Me han instalado en el móvil un programa que reenvia mis conversaciones de wasap. Qué carpeta puedo buscar y como consigo deshacerme de ella?

    ResponderEliminar
  5. Si podrias decir que aplicaciones es? con gusto te colaboro

    Regards,
    Snifer

    ResponderEliminar
  6. Elimine cuenta wasap no hice copias puedo recuperar conversaciones con ese metodo

    ResponderEliminar
    Respuestas
    1. Estimado puedes volver a leer el post!

      En ningun lado se indica recuperación o recovery por lo tanto no es posible, la manera que puedes recuperar tus conversaciones es realizando un carving.

      Regards,
      Snifer

      Eliminar
  7. Con el metodo de carving regards snifer puedo recuperar conversaciones de wasap habiendo eliminado mi cuenta y no hice copias de seguridad?

    ResponderEliminar
    Respuestas
    1. xD primero sabes lo que hablas? regards snifer xD! busca en un traductor que quiere decir.


      Lee sobre informatica forense y a partir de ello saldras de tus dudas.

      Regards,
      Snifer

      Eliminar
  8. Elimine mi cuenta whatsap no hice copias de seguridad con ese metodo de carving puedo recuperar conversaciones chats de whatsap?

    ResponderEliminar
    Respuestas
    1. xD lo mismo que el comentario de arriba lee sobre Informatica Forense para que tengas alguna idea.

      Regards,
      Snifer

      Eliminar
  9. Puedo a través de fotogramas de algún vídeo .Avi independientemente la calidad gráfica la procedencia? Ya que el vídeo esta filtrado sin ninguna información extraible

    ResponderEliminar
    Respuestas
    1. Con este metodo no, porque solo hace es recuperar datos de la bd que anden cifrados consdierando que este metodo ya esta obsoleto.

      Referente a lo mencionado, seria analizando cada frame y haciendo una busqueda reversa? pero lo veo poco probable ya que no obtendrias nada que es lo que deseas obtener? Metadatos? geolocalizacion?

      Regards,
      Snifer

      Eliminar
  10. Genial lo único que pusiste mal la web que es http://web.airdroid.com

    ResponderEliminar
  11. No soy capaz de hacerlo. Me dan errores todos los scripts.

    ResponderEliminar
    Respuestas
    1. Lastimosamente Juan, estos scripts ya no funcionan en nuevas versiones de Whatsapp mira la publicación del mismo data del 2013 ya se hicieron cambios y este ya no es valido.

      Regards,
      Snifer

      Eliminar