domingo, 31 de julio de 2011

Jugando con python-registry

Nada mejor para una tranquila tarde de domingo después de ver la Formula 1 y conseguir que se duerma la niña que jugar un poco con el registro de Windows y python. Sí, he dicho bién, con python y los ficheros que componen el registro de Windows.

Hasta el momento, o al menos hasta donde yo conocía, era posible trabajar con el registro de Windows de un sistema online, ya fuera local o remoto, utilizando el modulo _winreg, o winreg si se trataba de python 3.0. Pero, ¿y si la máquina en cuestión era un sistema offline objeto de un análisis forense?

Para estos casos lo mejor era (y sigue siendo) utilizar regripper, una gran herramienta desarrollada por Harlan Carvey cuya característica más potente es la posibilidad de añadir de forma sencilla plugins que extienden y potencian su funcionalidad.

Pero como lo que más nos gusta es ser un poco como juán palomo, que yo me lo guiso y yo me lo como, y además pensamos que perl es demasiado críptico, la publicación de python-registry por parte de Willi Ballenthin nos viene como caída del cielo.

Qué es python-registry

Pués básicamente se trata de un módulo que permite trabajar de forma offline y, lo más importante para un análisis forense en modo de solo lectura, con los ficheros que componen el registro de Windows. Y además proporciona una interfaz de alto nivel para abstraernos de los detalles o una interfaz de bajo nivel para trabajar y aprender cómo son las cosas "por debajo".

Como mi intención básicamente es jugar un poco con la librería he preferido abstraerme de los detalles y meterme directamente en faena basándome en los ejemplos disponibles tanto en la página del proyecto como en el blog de mandiant.

Pero lo primero es descargar el módulo y para ello clonaremos localmente el repositorio utilizando git:

$ git clone https://github.com/williballenthin/python-registry.git

Initialized empty Git repository in /home/javi/python-registry/.git/
remote: Counting objects: 321, done.
remote: Compressing objects: 100% (150/150), done.
remote: Total 321 (delta 156), reused 319 (delta 154)
Receiving objects: 100% (321/321), 186.78 KiB | 99 KiB/s, done.
Resolving deltas: 100% (156/156), done.

Y una vez descargado lo instalaremos:
$ cd python-registry/

$ python setup.py build
$ python setup.py install

Y una vez instalado ya podemos empezar a jugar. Suponiendo que tenemos el fichero software de un sistema Windows XP y queremos ver el contenido de la clave Run podemos utilizar el siguiente script:
#!/usr/local/bin/python

# -*- coding: utf-8 -*-

import sys
from Registry import Registry

reg = Registry.Registry(sys.argv[1])

try:
key = reg.open("Microsoft\\Windows\\CurrentVersion\\Run")
except Registry.RegistryKeyNotFoundException:
print "Couldn't find Run key. Exiting..."
sys.exit(-1)

repeated = len(key.path().replace(reg.root().name(),"SOFTWARE"))
print "%s" % "=" * repeated
print "%s" % key.path().replace(reg.root().name(),"SOFTWARE")
print "%s" % "=" * repeated
print "Last modified: %s [UTC]\n" % key.timestamp()

for value in key.values():
print "%s - %s" % (value.name(), value.value())

que lanzaremos así:
$ python get_runkey.py software

Y ahora, suponiendo que tenemos el fichero system de un sistema Windows XP y queremos obtener un listado de los servicios configurados podemos utilizar el siguiente script:
#!/usr/local/bin/python

# -*- coding: utf-8 -*-

import sys
from Registry import Registry

def get_CurrentControlSet(r):
""" Obtiene el valor para la clave CurrentControlSet """

try:
key = reg.open("Select")
except Registry.RegistryKeyNotFoundException:
print "Couldn't find SYSTEM\Select key. Exiting..."
sys.exit(-1)

for value in key.values():
if value.name() == "Current":
return value.value()

def print_ServiceInfo(s):
""" Muestra la informacion obtenida para cada servicio """

Start = { 0 : "Boot",
1 : "System",
2 : "Auto load",
3 : "Load on demand",
4 : "Disabled" }

dType = { 1 : "Kernel device driver",
2 : "File system driver",
4 : "Arguments for an adapter",
8 : "File system driver interpreter",
16 : "Own process",
32 : "Share process",
272 : "Independent interactive program",
288 : "Shared interactive program" }

print " Service name: %s" % s["SERVICE_NAME"]
print "Modified time: %s [UTC]" % s["ModifiedTime"]

if s.has_key("DisplayName"):
print " Display name: %s" % "".join(s["DisplayName"]).encode('utf8')

if s.has_key("ImagePath"):
print " ImagePath: %s" % s["ImagePath"]

if s.has_key("Type"):
print " Type: %s" % dType[s["Type"]]

if s.has_key("Start"):
print " Start: %s" % Start[s["Start"]]

if s.has_key("Group"):
print " Group: %s" % s["Group"]

print "\n"

def get_ServiceParams(k):
""" Obtiene los valores de cada subclave de Services """

service = {}

service["SERVICE_NAME"] = k.name()
service["ModifiedTime"] = k.timestamp()

for value in k.values():
service[value.name()] = value.value()

print_ServiceInfo(service)

def rec_ServicesKey(r, currentcontrolset):
""" Recorre los servicios presentes en la clave Services """

serviceskey = "ControlSet00%d\\Services" % currentcontrolset

try:
key = reg.open(serviceskey)
except Registry.RegistryKeyNotFoundException:
print "Couldn't find Services key. Exiting..."
sys.exit(-1)

for subkey in key.subkeys():
get_ServiceParams(subkey)

reg = Registry.Registry(sys.argv[1])
num = get_CurrentControlSet(reg)
rec_ServicesKey(reg, num)

que lanzaremos así:
$ python get_services.py system

Fácil, rápido y sencillo. Ahora sí que no hay excusas para jugar con python y con el registro de Windows.

Enlaces de interés

Adding Python Information to the Windows Registry

CurrentControlSet\Services Subkey Entries

Components Guide: Services

3 comentarios:

Anónimo dijo...

Buenos dias,
Espero no apartarme demasiado del tema de tu entrada, pero ultimamente estoy estudianto todo lo concerniente al registro de windows y me gustaria hacerte una pregunta, dado que comentas algo sobre el analisis forense del registro. ¿Cuando tu eliminas una entrada del registro esos datos se pueden recuperar? ¿hay alguna herramienta de borrado seguro para las entradas del registro o cuando son eliminadas desde el mismo registro se pueden luego encontrar por ejemplo en el unallocated?
Gracias de antemano

neofito dijo...

Pues siento no poder contestarte dado que no he estudiado demasiado el registro de Windows a tan bajo nivel. Quizas pueda serte de utilidad el siguiente paper:
http://sentinelchicken.com/data/TheWindowsNTRegistryFileFormat.pdf

No obstante si encuentro algo mas te voy informando.

Saludos

neofito dijo...

Pues despues de ojear un poco por encima el paper que te recomendaba en mi entrada anterior creo que he localizado dos papers mas referenciados alli que pueden serte de utilidad:

http://bit.ly/q6dF1L
http://bit.ly/qQcYnY

Saludos