¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Hacking y Forensic
  3. Análisis forense
Extrait - Hacking y Forensic Desarrolle sus propias herramientas en Python
Extractos del libro
Hacking y Forensic Desarrolle sus propias herramientas en Python Volver a la página de compra del libro

Análisis forense

Introducción

Se entiende por informática forense o investigación digital forense la aplicación de técnicas y protocolos de investigación digitales respetando los procedimientos legales, y destinada a proporcionar pruebas digitales bajo demanda de una institución de tipo judicial por requerimiento, auto o sentencia. También podemos definirla como el conjunto de conocimientos y métodos que permiten recopilar, almacenar y analizar pruebas obtenidas a partir de soportes digitales para producirlos dentro del marco de una acción judicial.

El objetivo de este capítulo es comprender el uso de Python para crear pequeños scripts que nos permitirán encontrar pruebas informáticas, recuperar los elementos dispersos en el disco duro o en otros medios de comunicación. Descubriremos, además de las ya vistas en capítulos anteriores, otras librerías de Python como Volatility y libPST.

Existen en la Web múltiples herramientas de Forensic como Autopsy, por ejemplo. Las herramientas están agrupadas en distribuciones como BackTrack o Bugtraq, pero, ¿qué ocurre cuando la herramienta que se desea no existe?

Los expertos en análisis forense saben muy bien que a menudo llegamos a una situación en que las herramientas de mercado no existen, o son demasiado complejas para el objetivo buscado.

Vamos a explorar la forma en que podemos...

Criptografía y otros

A menudo, vamos a tener que enfrentarnos a archivos codificados; el objetivo será ocultar la información.

1. ROT13

Según Wikipedia, "el ROT13 (rotate by 13 places) es un caso particular del cifrado de César, un algoritmo simple de cifrado de texto. Como su nombre indica, se trata de desfasar 13 caracteres cada letra del texto a cifrar. El defecto de este cifrado es que aunque trata las letras, no se ocupa de símbolos y de la puntuación. Por eso se debe suprimir cualquier acento del texto a cifrar. No se ocupa tampoco de los números, lo que no tenía importancia, ya que los Romanos escribían sus cifras con letras (I, V, X, L, M, etc.). Para utilizarlo hoy en día basta con convertir primero las cifras utilizando la notación romana, o en letras ("UNO" para 1, "DOS" para 2...)".

La letra O se convierte en B, la letra P se convierte en C...

La librería string de Python contiene una función llamada maketrans que permite sustituir un carácter por otro.


ROT13=string.maketrans  
('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ',   
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM')
 

En el script siguiente, vamos a abrir todos los archivos .txt y ejecutar el cifrado ROT13 para cada línea de cada archivo. Vamos entonces a comprobar si la línea contiene una palabra que figura en el diccionario que hemos abierto al principio.

Si fuera el caso, mostraremos un mensaje indicando que hemos encontrado un mensaje codificado en ROT13.

cap8_script1.py


#!/usr/bin/env python 
#--*-- coding:UTF-8 --*-- 
import sys, os, string 
ROT13=string.maketrans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ 
RSTUVWXYZ','nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM') 
archivo = open("dictionario") 
archivo = archivo.readlines() 
for root, dir, files in os.walk(str(sys.argv[1])):   
        for file in files:   
                if ".txt" in str(file):   
                        encpalabra = 0 
                        nopalabra = 0 
            ...

Extracción de metadatos de los archivos

Los metadatos de los archivos nos permiten conocer la fecha de creación del archivo, quién lo ha creado y con qué herramienta.

Comenzaremos por un script bastante divertido que recupera los metadatos de un archivo MP3

1. Metadatos MP3

La librería eyeD3 nos permitirá examinar los metadatos de los archivos MP3.

Podemos recuperar mediante getArtist(), getAlbum(), getTitle() por ejemplo los datos propios del archivo MP3 obtenidos por eyeD3.tag().

cap8_script9.py


#!/usr/bin/env python   
#--*-- coding:UTF-8 --*-- 
import eyeD3   
tag = eyeD3.Tag()   
ruta=raw_input("proporcione la ruta del archivo mp3\n")   
tag.link(ruta)   
print tag.getArtist()   
print tag.getAlbum()   
print tag.getTitle()
 
images/08-05.png

También podemos leer el archivo y acceder a su etiqueta (tag).


if eyeD3.isMp3File(f):  
      audioFile = eyeD3.Mp3AudioFile(f)  
      tag = audioFile.getTag()
 

También podemos recuperar los frames, si existen.


import eyeD3   
tag = eyeD3.Tag()   
tag.link("/home/javier/canciones/01 More Than a Feeling.mp3")   
for frame in tag.frames:   
    print frame
 

También podemos añadir información a los tags


tag = eyeD3.Tag()  
tag.link("/home/javier/canciones/rush/the camera eye.mp3") 
tag.header.setVersion(eyeD3.ID3_V2_3)  
tag.setArtist('HFT')  ...

Archivos ZIP

1. Leer de un archivo ZIP

Queremos examinar directamente uno o varios archivos contenidos en un archivo en formato ZIP, sin descomprimirlo en el disco.

Existe una librería zipfile que nos permitirá trabajar directamente sobre los datos contenidos en los archivos ZIP.


#!/usr/bin/env python  
import zipfile  
z=zipfile.ZipFile("archivo.zip","r")  
for nombre in z.namelist() :  
      print 'el archivo', nombre,  
      nb_bytes=z.read(nombre)  
      print 'contiene ', len(nb_bytes),'bytes.'
 

También podemos consultar el contenido de los archivos.


#!/usr/bin/env python  
import zipfile  
z = zipfile.ZipFile('test.zip', 'r')  
names = z.namelist()  
for name in names:  
    print 'Esperando %s' % name  
    print z.read(name)  
for name in names:  
    print 'en Espera de %s' % name  
    f = z.open(name)  
    contents = f.read()
 

2. Ataque de fuerza bruta de contraseñas

Algunos archivos zip están protegidos por contraseña. Podemos intentar crackear las contraseñas a partir de un diccionario, que aquí llamaremos passFile y proporcionaremos como segundo argumento...

Leer de un archivo OpenOffice o Word

1. Recorrer un árbol

Debemos examinar un directorio o un árbol de directorios que se encuentran en una carpeta determinada para iterar en los archivos cuyos nombres corresponden a determinados patrones.

El generador os.walk, usado antes en otras partes de este libro, basta para esta tarea.


#!/usr/bin/env python  
import os, fnmatch  
def todos_los_archivos ( raiz, patrones='*', un_solo_nivel=False,   
directorios = False):  
      patrones=patrones.split('') 
 for ruta, sub_dirs, archivos in os.walk(raiz):  
            if directorios:  
                  archivos.extend(sub_dirs)  
            archivos.sort()  
            for nombre in archivos:  
                  for patron in patrones:  
                        if fnmatch.fnmatch(nombre,patron):  
                              yeld os.path.join(ruta,nombre)  
                              break  
          ...

E-mail

1. Encontrar e-mails en los archivos

Si queremos recuperar a partir de una lista de archivos todas las direcciones de e-mail que figuran en estos archivos, el script siguiente nos podrá ayudar.

cap8_script12.py


def grab_email(files = []):  
    found = []  
    if files != None:  
        mailsrch = re.compile(r'[\w\-][\w\-\.]+@[\w\-][\w\-\.]  
+[a-zA-Z]{1,4}')  
          
        for file in files:  
            for line in open(file,'r'):  
                found.extend(mailsrch.findall(line))  
    u = {}  
    for item in found:  
        u[item] = 1  
    return u.keys()  
file=['texto1.txt','texto2.txt','texto3.txt']  
  
devolver=grab_email(file)  
print devolver 
 

En el mismo directorio, vamos a colocar tres archivos de texto, texto1.txt, texto2.txt y texto3.txt; he aquí su contenido.


::::::::::::::   
texto1.txt 
::::::::::::::   
Un pequeño texto simpático 
que contiene un mail fasm@acissi.net y eso es todo 
pero miramos el próximo 
::::::::::::::   
texto2.txt ...

Esteganografía

La esteganografía es una rama específica de la criptografía que no consiste en hacer el mensaje ininteligible, sino en camuflarlo en un contenedor para ocultar su presencia.

1. Buscar información en una imagen

Para aplicar Python a la esteganografía, vamos a tomar una imagen, oxygen.png, disponible para descargar en Internet, que contiene datos ocultos.

Observamos que esta imagen contiene una barra con un degradado en gris, el mensaje oculto debe estar aquí.

images/08-09.png

Vamos a utilizar de nuevo la librería PIL que ya hemos visto, en particular Image.


#!/usr/bin/env python  
import Image  
im = Image.open("oxygen.png")  
print "Image info:",im.format, im.size, im.mode  
#limitación de la zona gris  
y_begin = 0  
while True:  
      p = im.getpixel((0, y_begin))  
      if p[0] == p[1] == p[2]:  
            break  
      y_begin += 1  
x_end = 0  
while True:  
      p = im.getpixel((x_end, y_begin))  
      if not p[0] == p[1] == p[2]:  
            break  
      x_end += 1  
print "Y first coordinate:", y_begin,"nX last coordinate:",x_end  
message=[]  
for i in range(0,x_end,7):  
      p = im.getpixel((i, y_begin))  
      message.append(chr(p[0]))  
print ''.join(message),  
#First run gives: [105, 110, 116, 101, 103, 114, 105, 116, 121]  
message=[105, 110, 116, 101, 103, 114, 105, 116, 121]  
print '(',''.join([chr(x) for x in message]),')'
 

Todas las librerías, funciones y métodos han sido vistos antes, no volveremos a hablar aquí sobre ellos.

2. Ocultar un mensaje en una imagen

Cada píxel se define mediante una tripleta de números enteros comprendidos entre 0 y 255; el primero proporciona el componente rojo, el segundo el verde...

Volatility

El análisis del contenido de la memoria aleatoria (RAM) permite encontrar diferentes datos, sobre el estado del sistema por ejemplo.

El análisis de la memoria RAM permitirá descubrir conexiones de red abiertas, las contraseñas usadas recientemente, los archivos borrados, el contenido del registro de Windows, etc.

Volatility es uno de los grandes proyectos open source para el análisis forense. Es un framework Python con muchas librerías que permiten extraer los datos de las memorias volátiles.

La estructura de Volatility permite desarrollar módulos para extraer los datos específicos de la RAM.

Por defecto los módulos son:

  • Visualización de la lista de conexiones de red abiertas y escaneo de objetos de conexión.

  • Visualización de la lista de DLL cargadas por cada proceso.

  • Visualización de archivos abiertos para cada proceso.

  • Realización de diferentes dump.

  • Identificación de la propiedad de las imágenes, incluyendo los datos, el horario, la fecha y el lugar.

  • Visualización de una lista de claves de registro para cada proceso encontrado en la tabla de procesos.

Los plugins han sido agregados por diversas personas, entre ellos los siguientes:

  • CryptoScan: encuentra las passphrases TrueCrypt.

  • Suspicious: encuentra los procesos sospechosos.

  • Keyboardbuffer: extrae el buffer de teclado utilizado por el BIOS.

  • Getsids: encuentra la información del usuario que inició el proceso (SID).

1. Información de la imagen

Volatility es bastante sencillo de instalar, existen ejemplos de uso bien documentados en el sitio. Aquí, para ponerle la miel en la boca, mostramos un ejemplo proveniente del sitio de Volatility.

Búsqueda en el archivo dump de información sobre el sistema.

images/08-10.png

2. Proceso y DLL

Búsqueda en el archivo dump de los procesos y DLL ejecutados y utilizados por el sistema.

images/08-11.png

3. Captura de contraseñas hash

Obtener las contraseñas hash después de penetrar en un sistema Windows es común para un atacante.

Volatility permite esto con mucha facilidad. Vamos primero a ver cómo usar los plug-ins necesarios para ello y tratar de encontrar las contraseñas, y luego escribiremos un pequeño script para hacerlo de forma automática.

Windows almacena las contraseñas locales en el registro SAM (hash) y la clave de boot Windows (Windows boot key)...

Análisis de puntos de acceso inalámbrico en base al registro

El registro de Windows contiene una base de datos jerárquica que contiene la configuración del sistema donde se puede encontrar la información sobre el acceso inalámbrico.

En Windows 10, por ejemplo, encontraremos esta información en: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ NetworkList\Signatures\Unmanaged.

Podemos a partir de la línea de comandos (cmd.exe) listar todo:


reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\
CurrentVersion\NetworkList\Signatures\Unmanaged" /s  
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\
NetworkList\Signatures\Unmanaged\010103000F0000F0080000000F0000F04 
B9C1145A2729A13ABD15F1AACEA2FBAD2FDB36EEDEC1D5D460D6A0928CD855E  
    ProfileGuid    REG_SZ    {201540A1-8C46-42A6-A440-BB65A56E3942}  
    Description    REG_SZ    Red  
    Source    REG_DWORD    0x8  
    DnsSuffix    REG_SZ    localdomain  
    FirstNetwork    REG_SZ    Red  
    DefaultGatewayMac    REG_BINARY    00115024687F000
 

El registro almacena la dirección MAC de la pasarela como tipo REG_BINARY. En el ejemplo anterior, la encontramos en la forma 00115024687F0000, es decir \x00\x11\x50\x24\x68\x7f\x00\x00...

Recuperar los elementos eliminados (de la papelera)

La papelera, en función del sistema operativo, puede tener un nombre diferente en el árbol de directorios.

Podemos crear un pequeño script que probará esto y nos proporcionará la ruta adecuada. Tendremos, por supuesto, que informarnos de forma amplia sobre la lista definida para los sistemas en otros idiomas.


import os   
def returnDir():   
    dirs=['C:\\Recycler\\','C:\\Recycled\\','C:\\$Recycle.Bin\\']   
    for recycleDir in dirs:   
        if os.path.isdir(recycleDir):   
            return recycleDir   
    return None
 

Una vez descubierta la ruta de la papelera de Windows, deberemos inspeccionar su contenido.


C:\RECYCLER>dir /a   
    Volume in drive C has no label.   
    Volume Serial Number is 882A-6E93   
    Directory of C:\RECYCLER   
04/12/2011 09:24 AM     <DIR>        .  
04/12/2011 09:24 AM     <DIR>        ..   
04/12/2011 09:56 AM     <DIR>        S-1-5-21-1275210071-1715567821- 
725345543-1005   
04/12/2011 09:20 AM     <DIR>        S-1-5-21-1275210071-1715567821- ...

Puesta en práctica

1. Descifrado

Enunciado

Tenemos esta frase:

nkxtg uwt nc ugewtkvg kphqtocvkswg gv ng gvjkecn jcemkpi : vqwv kphqtocvkekgp ugpukdknkug cw eqpegrv fg nc ugewtkvg kphqtocvkswg ocku- pqxkeg qw fgdwvcpv fcpu ng fqockpg fg nc ugewtkvg fgu uauvgogu f’kphqtocvkqpu. Sqp cfcig guv crrtgpftg ngu cvvcswgu rqwt okgwz ug fghgpftg.

Programe un script que la descifre.

Corrección


#!/usr/bin/env python 
#--*-- coding:UTF-8 --*-- 
 
import string 
cyphertext = "Lkdtq uqdtg nc ugiwtkfcf kphqtoávkec a jcemkpi évkeq: 
nc eqpekgpekc fgn eqpegrvq fg nc ugiwtkfcf kphqtoávkec, ugc pqxcvq 
q rtkpekrkcpvg gp gn ecorq fg nc ugiwtkfcf fg nqu ukuvgocu fg 
kphqtocekóp. Sw ngoc gu crtgpfgt c fghgpfgtug oglqt fg nqu cvcswgu." 
fromlist = "abcdefghijklmnopqrstuvwxyz" 
tolist =   "cdefghijklmnopqrstuvwxyzab" 
transtable = string.maketrans(tolist,fromlist) 
print string.translate(cyphertext, transtable)
 

2. OCR

Enunciado

Encontrará en las descargas desde la página Información un archivo de texto llamado ocr.txt.

Se encuentra una palabra oculta y cada una de sus letras es muy "rara" en el archivo. Busque las letras que solo aparecen una vez.

Corrección


mess = open("ocr.txt").read()  
dict = {}  
for ch in mess:  
        dict[ch] = dict.get(ch, 0) + 1  
print "".join(ch for ch in mess if dict[ch]...