El formato binario de Amcache.hve, en la práctica

La primera vez que abres Amcache.hve en un editor hexadecimal ves los cuatro bytes ASCII regf en el offset cero y te decepcionas un poco. No hay esquema exótico. Amcache es una hive de Registro de Windows perfectamente normal, que es a la vez la razón por la que se parsea fácil y la razón por la que casi cualquier analista escribe un mal parser antes de escribir uno bueno.

Este post es la versión de "cómo está organizado el archivo" que me hubiera gustado que alguien me pusiera en la mano antes de empezar a preocuparme por los offsets. Tiene opinión sobre qué subclaves se ganan tu tiempo y cuáles no he tocado en un caso real.

regf, muy brevemente#

regf es el formato en disco de todas las hives NTUSER.DAT, SYSTEM, SOFTWARE, SAM y SECURITY, además de Amcache. Lo documenta Microsoft suficientemente bien y lo re-documenta mejor la comunidad open source, en particular el proyecto yarp de Maxim Suhanov y las notas de Eric Zimmerman que vienen con sus herramientas.

Algunos hechos que importan cuando estás depurando un parse roto:

  • El archivo está dividido en bloques de 4 KiB llamados "hbins". Los primeros 4 KiB son la cabecera del archivo. Todo lo demás son hbins.
  • Cada hbin contiene una cadena de celdas. Las celdas con campo Size positivo están libres, las celdas con campo Size negativo están asignadas. Sí, eso es al revés de cómo se diseñaría hoy, y sí, todo parser ha tropezado con esto.
  • Las claves son celdas nk. Los valores son celdas vk. Las listas de subclaves son lf, lh, ri, li. Los valores grandes usan celdas db. Si alguna vez has visto "unknown cell signature" en un log de parser, suele ser porque la tabla de tipos de celda está incompleta o porque la hive está corrupta en el borde del bin.
  • La hive lleva arriba un par de números de secuencia. Si primary y secondary no coinciden, la hive se estaba escribiendo cuando fue capturada, y hay que replayar los logs de transacción antes de poder confiar en el contenido.

Amcache no usa ninguna de estas estructuras de forma inusual. Lo que sea que escribió tu parser favorito de NTUSER.DAT leerá la Amcache, salvo bugs.

Las subclaves que pagan el alquiler#

El contenido interesante vive bajo Root\InventoryApplication, Root\InventoryApplicationFile, Root\InventoryDeviceContainer, Root\InventoryDriverBinary, Root\InventoryDriverPackage y Root\InventoryApplicationShortcut. Hay otros roots, incluidos Root\InventoryApplicationFramework y el legacy Root\File en builds antiguos de Windows 7, pero los seis de arriba es donde paso el 95% del tiempo.

InventoryApplication#

Una subclave por aplicación instalada (o que en algún momento lo estuvo), nombrada con el ProgramId, un identificador de 16 bytes derivado del publisher, nombre y versión. Los valores dentro son la vista del software desde el ojo del instalador: Name, Publisher, Version, InstallDate, RootDirPath, Source (MSI / AddRemoveProgram / etc.), Type (Application / Game / Hotfix), Language. Los instaladores MSI suelen rellenar estos campos bien. Software bundleado o sideloaded, menos.

InstallDate aquí es un valor DateTime-como-string, no un FILETIME. Es lo que reportó el instalador, no lo que vio el sistema de archivos. Trátalo como indicativo.

InventoryApplicationFile#

La subclave que leerás más a menudo. Una entrada por ejecutable que Appraiser ha indexado, nombrada con una clave como notepad.exe|abcd1234ef567890. Cada entrada lleva FileId (el SHA-1 con prefijo 0000), LowerCaseLongPath, OriginalFileName, Name, Publisher, ProductName, ProductVersion, Version, BinaryType, Size, LinkDate, Language, IsPeFile, IsOsComponent y una referencia al ProgramId padre.

El valor en el que menos confío es LowerCaseLongPath. Es la ruta que Appraiser vio en el momento del escaneo, lo cual está bien, pero los archivos renombrados o movidos dejan entradas obsoletas con rutas que ya no corresponden a nada. El valor en el que más confío es FileId. Los hashes no mienten aunque las rutas sí.

InventoryDeviceContainer#

Dispositivos que el sistema ha visto, tanto internos como externos. Indexado por container ID. Los valores incluyen Manufacturer, ModelName, ModelNumber, FriendlyName, Categories y varios campos específicos de BLE/USB. Esta es la subclave a la que recurro cuando necesito corroborar una historia USB, idealmente cruzada con SYSTEM\ControlSet001\Enum\USBSTOR de las hives principales del Registro.

No sustituye los artefactos USB propios. Amcache te dirá que un receptor Logitech ha estado en esta máquina; no te dirá qué usuario enchufó qué pendrive a qué hora. Úsala por amplitud, no por profundidad.

InventoryDriverBinary e InventoryDriverPackage#

Dos claves relacionadas que cubren el inventario de drivers en modo kernel. InventoryDriverBinary es una entrada por archivo .sys que Appraiser ha visto, con los usuales FileId, DriverName, DriverCompany, Service, DriverSigned, DriverInBox, DriverIsKernelMode, más el LinkDate y los strings de producto. InventoryDriverPackage cubre paquetes .inf, con Class, ClassGuid, Date, Provider, Version y los flags inbox/signed.

Estas dos claves son por las que las investigaciones de "Bring Your Own Vulnerable Driver" casi siempre empiezan por Amcache. Un atacante deja caer gdrv.sys o RTCore64.sys, lo carga, explota, lo borra. El binario ya no está en disco cuando llegas. La entrada InventoryDriverBinary, con su SHA-1, a menudo sí.

InventoryApplicationShortcut#

Cada subclave corresponde a un archivo LNK que Appraiser examinó, identificado por un hash y con la ruta en minúsculas. Menos campos que los otros inventarios, pero es una de las pocas fuentes que te dice que existía un .lnk apuntando a un medio removible en el host. Combínalo con el parser de LNK para los detalles reales del destino, ya que el registro de Amcache es superficial.

Parsearlo sin inventar tus propios bugs#

Hay tres herramientas que uso de verdad en trabajo de casos, en orden aproximadamente descendente de cuánto tocan la hive en mi workstation de analista.

AmcacheParser de Eric Zimmerman#

El predeterminado. AmcacheParser.exe -f Amcache.hve --csv .\out\ -i te dará una CSV por subclave de inventario, con -i habilitando la inclusión de archivos no-PE (útil para cazar scripts que se hayan colado). El esquema que emite es, para bien o para mal, al que se normalizaron las demás herramientas. Si necesitas escribir tooling interno, replica los nombres de columna.

Dos flags que siempre pongo: --mp para mantener precisión de milisegundos en los timestamps (el formato redondeado por defecto oculta detalles temporales que ocasionalmente importan), y --nl para mantener entradas sin LinkDate (saltárselas por defecto me ha mordido persiguiendo drivers de kernel).

RegRipper#

rip.exe de Harlan Carvey con el plugin amcache (y el más nuevo amcache_tln para salida en timeline). Más viejo pero aún útil, particularmente en hives de Windows 7 donde la subclave legacy Root\File sigue presente y AmcacheParser a veces se la salta. La salida del plugin es texto, no CSV. Vive con ello, o grepea.

yarp#

La biblioteca regf en Python puro de Maxim Suhanov. Esto es lo que uso cuando necesito hacer algo que las herramientas existentes no hacen, como recorrer celdas libres buscando registros borrados o comparar dos snapshots de la misma hive. La API expone celdas crudas, replay de logs de transacción y un modelo de objetos cuerdo para claves y valores. yarp-print es una CLI cómoda cuando solo quieres volcar una hive.

Si estás construyendo automatización, yarp es el piso correcto sobre el que construir. Si estás respondiendo a un incidente a las 02:00, AmcacheParser es más rápido.

Los logs de transacción no son opcionales#

Amcache.hve.LOG1 y Amcache.hve.LOG2 son los dirty-page logs que el kernel usa para mantener la hive consistente entre crashes. El formato está documentado (bloques HvLE para Windows moderno, el más antiguo DIRT en Win7). Te importan porque:

  1. Si la adquisición pasó mientras la hive se estaba escribiendo, el archivo principal queda inconsistente y los logs tienen las páginas que faltan. AmcacheParser y yarp los replayean automáticamente cuando están. RegRipper, según versión, no.
  2. Subclaves recientemente borradas suelen seguir existiendo en las páginas del log. He recuperado entradas de .LOG1 que se habían purgado de la hive principal minutos antes de la adquisición. Lleva siempre los LOGs junto a la hive, nunca solo el .hve.
  3. Un número de secuencia desparejado en la hive es tu señal de que necesitas los logs. Si primary != secondary en la cabecera, no parsees sin ellos. Las herramientas buenas se negarán; las malas producen basura sin avisar.

Lo que nunca toco#

Lista honesta. Nunca he cerrado un caso usando InventoryApplicationFramework, la subclave Orphan o InventoryMiscellaneousMemorySlotArrayInfo (sí, existe). Son ruido. Si te encuentras escarbando ahí porque las claves obvias salieron vacías, probablemente te han entregado un host donde Appraiser estaba deshabilitado, y tu tiempo está mejor invertido en la MFT, el journal USN y el log de eventos de seguridad.

Lecturas adicionales#

Artículos relacionados

Volver a todos los artículos