Sin embargo y dada su naturaleza se dice que el OTFE (incluido Truecrypt) sólo protege los datos cifrados “en descanso”. Es decir, una vez que un volumen cifrado se monta permanecerá accesible a los usuarios del sistema como si de texto plano se tratara hasta que se desmonte dicho volumen o se apague el sistema. El por qué está claro: en definitiva la contraseña para acceder al volumen cifrado se encuentra en la información volátil de la memoria física (RAM) y, si la obtenemos (un técnica forense muy común), nuestro único problema será sólo identificarla. Véamos cómo.
Obteniendo un volcado de la memoria RAM
En nuestro ejemplo utilizaremos un equipo con sistema operativo Windows 7 de 64 bits, 4 gb de memoria RAM y TrueCrypt 7.1a instalado.
Lo primero que haremos será obtener una foto o adquisición de la memoria física.
Existen varias herramientas que pueden ayudarnos a obtener el volcado. En nuestro caso por sencillez utilizaremos DumpIt de Moonsols que funciona en máquinas en x86 (32-bits) y x64 (64-bits):
D:\Python27\Tools\volatility-2.1>DumpIt.exe
DumpIt - v1.3.2.20110401 - One click memory memory dumper
Copyright (c) 2007 - 2011, Matthieu Suiche
Copyright (c) 2010 - 2011, MoonSols
Address space size: 5234491392 bytes ( 4992 Mb)
Free space size: 110475653120 bytes ( 105357 Mb)
* Destination = \??\D:\Python27\Tools\volatility-2.1\W7PTVMOTOS-20130430-125054.raw
--> Are you sure you want to continue? [y/n] y
+ Processing... Success.
El resultado como podéis comprobar es un fichero en crudo o raw de algo menos de 5 Gbs. Podría parecer que el volcado de memoria obtenido es un conjunto de datos desordenados pero la realidad sin embargo es que está altamente estructurado. Además Truecrypt especifica que los datos sensibles no son almacenados en la memoria paginada (por seguridad y rendimiento), por lo que siempre la contraseña estará en la memoria física.
Para la búsqueda de la contraseña usaremos principalmente Volatility, un framework con una buena colección de herramientas en Python para el análisis y extración de datos de memoria volatil (RAM). Antes de comenzar comprobamos la existencia del proceso TrueCrypt.exe, si bien aviso que de nada os servirá recorrer las strings de un volcado del proceso:
D:\Python27\Tools\volatility-2.1>vol.py -f W7PTVMOTOS-20130430-125054.raw --profile=Win7SP0x64 volshell
Volatile Systems Volatility Framework 2.1
Current context: process System, pid=4, ppid=0 DTB=0x187000
Welcome to volshell! Current memory image is:
file:///D:/Python27/Tools/volatility-2.1/W7PTVMOTOS-20130430-125054.raw
To get help, type 'hh()'
>>> ps()
Name PID PPID Offset
[...]
TrueCrypt.exe 2132 2036 0xfffffa800abbb060
...]
>>>
Reducir el espacio de búsqueda
Una vez que ya tenemos el volcado de memoria, lo siguiente será reducir el espacio de búsqueda de direcciones virtuales para centrarnos sólo en la información útil concerniente a Truecrypt.
Como cualquier otro software de cifrado completo de discos o contenedores, Truecrypt posee componentes en modo usuario y en modo kernel. Los primeros hacen referencia al interfaz mediante el cual el usuario interactua con el programa y los segundos se presentan normalmente como un driver de dispositivo que maneja todas las operaciones de cifrado/descifrado. Como comentaba, el driver esencialmente intercepta las peticiones de lectura y escritura "al vuelo" y se encarga de automatizar el proceso para que el resto de aplicaciones y el sistema operativo acceda al disco como si de un volumen normal se tratara. En consecuencia, podemos asumir que la contraseña estará en el espacio de direcciones de este driver. Por lo tanto, si reducimos el espacio de búsqueda a modo kernel descartaremos más del 50% del total de información a analizar.
Ahora bien, la forma más rápida es centrarse en los datos correctos es mediante la identificación de etiquetas o Pool tagging que debería utilizar el driver si sigue las recomendaciones de Microsoft. En Windows, cualquier dispositivo Truecrypt tiene asociado un bloque de memoria llamado DEVICE_EXTENSION, que es el espacio que debe tener residente para llevar a cabo todas las operaciones de E/S y que por ende contendrá la clave correspondiente. El puntero hacia la estructura de DEVICE_EXTENSION se encuentra en DEVICE_OBJECT/DRIVER_OBJECT, que es el ejecutable que Windows tiene que localizar para usar el driver.
Mediante el plugin devicetree de Volatitity obtendremos las relaciones del objeto del driver de Truecrypt con su correspondiente dispositivo:
D:\Python27\Tools\volatility-2.1>vol.py -f W7PTVMOTOS-20130430-125054.raw --prof
ile=Win7SP0x64 devicetree > test.txt
Volatile Systems Volatility Framework 2.1
DRV 0x1353e4aa0 \Driver\truecrypt
---| DEV 0xfffffa800abca080 TrueCryptVolumeX FILE_DEVICE_DISK
---| DEV 0xfffffa800af4f080 TrueCryptVolumeW FILE_DEVICE_DISK
---| DEV 0xfffffa8006946e30 TrueCrypt FILE_DEVICE_UNKNOWN
Como véis, el offset del driver de Truecrypt es 0x1353e4aa0 y mediante IoCreateDevice ha creado varios objetos de dispositivo de tipo FILE_DEVICE_DISK (particiones de disco) con sus direcciones de memoria virtuales correspondientes.
En nuestro ejemplo nos centraremos en obtener la clave del volumen que se montó con la letra X. Dentro de volshell, exploraremos con dt (Display Type) los type information de los objetos del dispositivo para conocer su estructura de datos:
>>> dt("_DEVICE_OBJECT", 0xfffffa800abca080)
[_DEVICE_OBJECT _DEVICE_OBJECT] @ 0xFFFFFA800ABCA080
0x0 : Type 3
0x2 : Size 1840
0x4 : ReferenceCount 67
0x8 : DriverObject 18446738026506635936
0x10 : NextDevice 18446738026579423360
0x18 : AttachedDevice 0
0x20 : CurrentIrp 0
0x28 : Timer 0
0x30 : Flags 80
0x34 : Characteristics 256
0x38 : Vpb 18446738026463075744
0x40 : DeviceExtension 18446738026575733200
0x48 : DeviceType 7
0x4c : StackSize 7
0x50 : Queue 18446738026575732944
0x98 : AlignmentRequirement 0
0xa0 : DeviceQueue 18446738026575733024
0xc8 : Dpc 18446738026575733064
0x108 : ActiveThreadCount 0
0x110 : SecurityDescriptor 18446735964904258368
0x118 : DeviceLock 18446738026575733144
0x130 : SectorSize 512
0x132 : Spare1 0
0x138 : DeviceObjectExtension 18446738026575734704
0x140 : Reserved 0
>>>
El resultado nos muestra el DeviceExtension del dispositivo, así que mostraremos el espacio de direcciones en hexadecimal con db(address, length=128, width=16, space=None):
>>> db(18446738026575733200, 1600)
[...]
0xfffffa800abca460 00 f0 52 e1 01 00 00 00 00 10 00 00 00 00 00 00 ..R.............
0xfffffa800abca470 00 00 53 e1 01 00 00 00 00 10 00 00 00 00 00 00 ..S.............
0xfffffa800abca480 00 c0 da 0a 80 fa ff ff 00 00 00 40 06 00 00 00 ...........@....
0xfffffa800abca490 00 00 00 00 00 00 00 00 01 00 06 00 00 00 00 00 ................
0xfffffa800abca4a0 a0 a4 bc 0a 80 fa ff ff a0 a4 bc 0a 80 fa ff ff ................
0xfffffa800abca4b0 00 00 00 00 00 00 00 00 01 00 06 00 01 00 00 00 ................
0xfffffa800abca4c0 c0 a4 bc 0a 80 fa ff ff c0 a4 bc 0a 80 fa ff ff ................
0xfffffa800abca4d0 00 32 56 05 00 00 00 00 00 2c 02 0a 00 00 00 00 .2V......,......
0xfffffa800abca4e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0xfffffa800abca4f0 00 00 00 00 00 00 00 00 01 00 06 00 00 00 00 00 ................
0xfffffa800abca500 00 a5 bc 0a 80 fa ff ff 00 a5 bc 0a 80 fa ff ff ................
0xfffffa800abca510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0xfffffa800abca520 01 00 00 00 00 00 00 00 5c 00 3f 00 3f 00 5c 00 ........\.?.?.\.
0xfffffa800abca530 46 00 3a 00 5c 00 4d 00 69 00 6f 00 5c 00 63 00 F.:.\.M.i.o.\.c.
0xfffffa800abca540 69 00 66 00 72 00 61 00 64 00 6f 00 32 00 2e 00 i.f.r.a.d.o.2...
0xfffffa800abca550 74 00 63 00 00 00 00 00 00 00 00 00 00 00 00 00 t.c.............
0xfffffa800abca560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0xfffffa800abca570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0xfffffa800abca580 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[...]
Como veis, al comenzar a explorar la memoria desde la dirección del DeviceExtension (18446738026575733200) ya obtenemos un dato muy útil: el contenedor del volumen de Truecrypt es F:\Mio\cifrado2.
Ahora bien, si queremos obtener la contraseña para descifrar este contenedor mediante una revisión manual resultará prácticamente imposible dada la cantidad de datos que manejamos, así que tendremos que volcar todo el espacio ejecutable del driver de Truecrypt y realizar posteriormente una búsqueda basada en formato.
La forma fácil para encontrar donde "vive" el driver de Truecrypt es mediante el módulo driverscan de Volatility, sin embargo, podemos utilizar el DriverObject (18446738026506635936) mostrado anteriormente:
>>> dt("_DRIVER_OBJECT", 18446738026506635936)
[_DRIVER_OBJECT _DRIVER_OBJECT] @ 0xFFFFFA80069E4AA0
0x0 : Type 4
0x2 : Size 336
0x8 : DeviceObject 18446738026575732864
0x10 : Flags 18
0x18 : DriverStart 18446735827444617216
0x20 : DriverSize 266240
0x28 : DriverSection 18446738026505988352
0x30 : DriverExtension 18446738026506636272
0x38 : DriverName \Driver\truecrypt
0x48 : HardwareDatabase 18446735277674784088
0x50 : FastIoDispatch 0
0x58 : DriverInit 18446735827444871912
0x60 : DriverStartIo 0
0x68 : DriverUnload 18446735827444650112
0x70 : MajorFunction -
Y ahora que conocemos donde empieza exactamente el driver y cual es su tamaño podemos volcarlo en hexadecimal para centrar nuestro análisis:
>>> db(18446735827444617216, 266240)
Current context: process System, pid=4, ppid=0 DTB=0x187000
>>> Memory unreadable at fffff880044ed000
>>>
Realmente el mensaje devuelto significa que algunos bytes no son legibles. Este error suele ocurrir cuando existen datos del objeto paginados pero, como hemos comentado, Truecrypt no pagina nada, por lo que el problema tiene que deberse a algún bug en el proceso de adquisición de la memoria. No obstante si ajustamos los límites podremos volcar correctamente la información que necesitamos:
echo "db(0xfffff880044ed000, 0x3c7ff)" | python vol.py -f W7PTVMOTOS-20130430-125054.raw --profile=Win7SP0x64 volshell > volcado.txt
Búsqueda de la contraseña basada en formato
Analizando el código fuente de Truecrypt, concretamente el fichero de cabecera Password.h, la contraseña debe tener el siguiente formato:
typedef struct
{
// Modifying this structure can introduce incompatibility with previous versions
unsigned __int32 Length;
unsigned char Text[MAX_PASSWORD + 1];
char Pad[3]; // keep 64-bit alignment
} Password;
Esta estructura fue introducida en la versión 4.0 y posteriormente en la versión 5.0 se añadió el padding. Lo que deberíamos buscar entonces es una contraseña con valor de longitud (un valor entre 1 y 64 almacenado en el primero de los cuatro bytes), 65 bytes de datos de contraseña y luego 3 bytes de relleno o padding para mantener la alineación de 64 bits. Los datos deben contener exactamente los caracteres ASCII de la contraseña y el resto de bytes restantes deben ser ceros exceptuando el padding que tiene un valor aleatorio.
Una opción podría ser recorrer el volcado en hexadecimal mediante un editor de texto normal tipo Notepad++ y por ejemplo buscar patrones "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00". En mi caso existen 950 ocurrencias y es fácil encontrar la contraseña, o mejor dicho las contraseñas en plural porque de golpe podemos obtener las contraseñas de los dos volumenes cifrados que estaban montados en el equipo en el momento de la adquisión de memoria:
La otra opción sería escribir un script que busque ese patrón (en hexadecimal o en raw) o no reinvertar la rueda y utilizar alguna herramienta ya hecha (llamarme script kiddie) como cryptoscan o incluso Forensic Disk Decryptor de Elcomsoft con la que sin ningún conocimiento y por menos de 300 euros se pueden descifrar volúmenes TrueCrypt y también de BitLocker y PGP.
Conclusiones
La conclusión principal es que, una vez que un volumen cifrado de Truecrypt es montado en el equipo objetivo, la contraseña para descifrarlo queda residente en la memoria RAM y cualquier atacante puede obtenerla "fácilmente" mediante la adquisión de la misma y posterior análisis.
Recordemos que el volcado de memoria puede realizarse directamente o mediante hiberfil.sys si el equipo ha sido hibernado y, sobretodo, que no necesariamente tenemos que estar delante del equipo y validados con un usuario para obtener un volcado de la memoria.
Por ejemplo, exiten ataques DMA a través de Firewire, ExpressCard, Thunderbolt o cualquier puerto de expansión como PCI o PCI-Express que permiten el acceso directo a la memoria evadiendo las restricciones del sistema operativo debido a la especificación OHCI 1394 (spoofeando un dispositivo SBP2). O imaginad un artefacto de malware residente en el equipo que vuelque la memoria de forma oculta al usuario y envíe los datos de vuelta al servidor C&C.
Existen varios vectores de ataque y muchas posibilidades... ¿a qué hora no te sientes tan seguro sólo por tener tus datos en un volumen cifrado? ;)
Referencias:
Cyber Defense Exercise 2013: Extracting cached passphrases in Truecrypt
RAM is Key. Extracting Disk Encryption Keys From Volatile Memory
Volatility Command Reference
TrueCrypt Volume Format Specification
Truecrypt Encryption Scheme
Truecrypt Header Key Derivation, Salt, and Iteration Count
Updated Cryptoscan for the Volatility Framework
Fuente:http://www.hackplayers.com/2013/05/extrayendo-passwords-en-memoria-de-truecrypt.html
No hay comentarios:
Publicar un comentario