Formato de los valores BAM: FILETIME, rutas e internos
Un valor de registro BAM byte a byte: el REG_BINARY de 24 bytes, el FILETIME, rutas de dispositivo o nombres de paquete, Version y SequenceNumber.
TL;DR. Cada valor BAM sigue el esquema nombre = ejecutable, datos = REG_BINARY. Los primeros 8 bytes de los datos son un FILETIME little-endian (intervalos de 100 ns desde el 1601-01-01 UTC); en las compilaciones estudiadas los datos miden 24 bytes y los 16 restantes no hacen falta para leer la hora. Los nombres de valor son rutas de dispositivo NT (\Device\HarddiskVolume3\…) o nombres de familia de paquete. Version y SequenceNumber son valores de control, no programas. La hora de última escritura de la propia clave SID es una marca de tiempo extra que viene gratis.
Si solo lees BAM a través de una herramienta, este artículo te cuenta qué hace esa herramienta y dónde puede equivocarse. Para el contexto: la guía completa de BAM/DAM y dónde está la clave BAM.
Anatomía de una clave SID
Una clave bam\State\UserSettings\<SID> típica tiene este aspecto (datos de ejemplo ficticios del sitio):
| Nombre del valor | Tipo | Datos (hex) |
|---|---|---|
Version | REG_DWORD | 01 00 00 00 |
SequenceNumber | REG_DWORD | 76 00 00 00 |
\Device\HarddiskVolume3\Users\alice\Downloads\Invoice_2026-0914.pdf.exe | REG_BINARY | 80 0d 7c 1d 29 44 dd 01 + 16 bytes |
MSTeams_8wekyb3d8bbwe | REG_BINARY | 24 bytes |
Tres tipos de valor, tres reglas:
- DWORD de control —
VersionySequenceNumber. Ignóralos al enumerar programas. Su semántica no está documentada públicamente; cualquier interpretación (por ejemplo, queSequenceNumbercrece con cada actualización) es una hipótesis que debes probar en tu propio sistema de referencia. - Entradas de ejecutables —
REG_BINARY, el nombre es una ruta y los datos tienen al menos 8 bytes. - Todo lo demás — un valor que no es
REG_BINARYo que mide menos de 8 bytes no es un registro BAM. Un analizador robusto lo ignora en lugar de fallar. El nuestro hace exactamente eso, y notifica los valores ilegibles como avisos en lugar de descartarlos en silencio.
Decodificar el FILETIME
Un FILETIME es un contador de 64 bits de intervalos de 100 nanosegundos desde el 1 de enero de 1601 UTC (Microsoft Learn). Se guarda en little-endian, así que lee los bytes de derecha a izquierda:
bytes 80 0d 7c 1d 29 44 dd 01
as u64 0x01DD44291D7C0D80 = 134338507270000000
seconds 13433850727 (÷ 10,000,000)
minus 11644473600 (1601 → 1970 offset)
unix 1789377127 → 2026-09-14 09:12:07 UTC
Dos cosas que conviene tener presentes:
- Es UTC. El registro no guarda la zona horaria del equipo en el valor. La colmena SYSTEM sí registra la zona configurada (
Control\TimeZoneInformation\TimeZoneKeyName), que nuestra herramienta muestra en la cabecera para razonar sobre la hora local. El botón «Local» de la herramienta convierte a la zona horaria de tu navegador, no a la del equipo investigado. - Precisión. El FILETIME tiene una resolución de 100 ns.
Dateen JavaScript solo llega a milisegundos, así que las herramientas web que convierten conDateredondean. El BAM/DAM Parser conserva los siete decimales en la vista UTC y exporta el FILETIME en bruto como cadena decimal (un entero de 64 bits no cabe sin pérdida en un número JSON).
Qué evento marca la hora
El análisis de bam.sys de Maxim Suhanov muestra que la marca de tiempo se actualiza tanto al crearse el proceso como al terminar (BAM internals). Por tanto, el valor es el más reciente de esos eventos que BAM llegó a guardar. Para programas que estuvieron mucho tiempo abiertos, en los informes es preferible hablar de «última actividad registrada», y recurrir a Prefetch o a los registros de creación de procesos si necesitas la hora de inicio.
Los 16 bytes restantes
En las compilaciones de Windows 10 que examinó Suhanov, los valores BAM miden 24 bytes: el FILETIME y 16 bytes más. Su análisis relaciona uno de los DWORD finales con el estado de moderación (si el usuario dejó que Windows gestionara la actividad en segundo plano o cambió la opción para esa aplicación) y señala que las entradas con un estado distinto del predeterminado no se ven afectadas por la limpieza por antigüedad (fuente). Más allá de eso, la estructura no está documentada públicamente.
Consecuencias prácticas:
- No supongas un tamaño fijo de 24 bytes; lee los 8 primeros y conserva el resto.
- Guarda los bytes en bruto en tu exportación. Nuestra herramienta muestra los datos completos en el panel de detalle («Datos sin procesar») y en la columna CSV
DataHex, para que puedas volver sobre los bytes finales si aparece investigación nueva.
Nombres de valor: rutas de dispositivo y paquetes
Rutas de dispositivo NT
La mayoría de los nombres tienen la forma \Device\HarddiskVolume3\Windows\System32\cmd.exe. Es la ruta de dispositivo NT del kernel: el objeto de volumen y luego la ruta en ese volumen. No hay letra de unidad porque las letras son una asignación del modo usuario (Microsoft Learn: definir un nombre de dispositivo MS-DOS).
Para asociar HarddiskVolumeN a una letra sin conexión:
- Casi siempre, el volumen del sistema es el que contiene las entradas
\Windows\System32\…; todo lo que tenga ese número de volumen está enC:. - Para los demás números, cruza con artefactos que registren ambas formas — por ejemplo los archivos Prefetch, que guardan las rutas de dispositivo y los números de serie de los volúmenes (formato libscca). También ayuda la salida de una recopilación en vivo que haya anotado a la vez la ruta de dispositivo y la letra. (La clave
MountedDevicesde la misma colmena asocia letras con identificadores de volumen, no con númerosHarddiskVolumeN, así que solo ayuda en parte.) - Los números de volumen los asigna el sistema en ejecución y no son un identificador estable entre equipos, ni siquiera necesariamente tras cambios de configuración en el mismo equipo.
Nombres de familia de paquete
Las aplicaciones empaquetadas (Store, MSIX) aparecen por su nombre de familia de paquete: Microsoft.WindowsCalculator_8wekyb3d8bbwe. La parte tras el guion bajo es el hash del identificador del editor y la parte anterior es el nombre del paquete (Microsoft Learn: identidad de paquete). No hay ruta ni nombre de ejecutable. Nuestro analizador muestra el nombre del paquete como programa, marca la fila como aplicación y no le aplica las heurísticas de ruta.
Otras formas
A veces aparece un nombre que no es ni una cosa ni otra — por ejemplo, una ruta sin el prefijo \Device\. No lo descartes: la herramienta lo clasifica como «otro» y decodifica igualmente la marca de tiempo.
La hora de última escritura de la clave SID
Toda clave de registro tiene un FILETIME de última escritura en su nodo de clave (especificación msuhanov/regf). En una clave SID de BAM, esa hora cambia cada vez que cambia cualquier valor que contenga. Te aporta:
- Una comprobación de coherencia: la hora de la clave debe ser igual o posterior a la del valor más reciente de ese usuario. Una hora de clave muy posterior a todos los valores sugiere que después se borró o reescribió una entrada — ver antiforense en BAM.
- Un límite inferior de la última actualización de la colmena para ese usuario.
Nuestra herramienta la muestra como «Última escritura de la clave SID» en el panel de detalle y la exporta como SidKeyLastWriteUtc.
Los campos de la colmena que importan
Algunos campos del bloque base cambian la confianza que merecen los valores (libregf):
| Offset | Campo | Por qué importa para BAM |
|---|---|---|
| 0 | Firma regf | Confirma que es una colmena |
| 4 / 8 | Números de secuencia primario / secundario | Si difieren = colmena dirty: puede haber escrituras BAM recientes en los registros |
| 12 | FILETIME de última escritura | Cuándo se escribió por última vez el archivo principal |
| 48 | Nombre de archivo incrustado | Distingue SYSTEM de SOFTWARE, SAM… cuando los archivos se han renombrado |
Cómo lo traduce el analizador
| Columna de salida | Origen |
|---|---|
LastExecutionUtc | Primeros 8 bytes de los datos, en ISO-8601 con 100 ns |
FileTime | El mismo valor, en decimal bruto |
Program | Nombre del archivo, o nombre del paquete sin el hash del editor |
Path, Volume | Nombre del valor; HarddiskVolumeN cuando existe |
SID, User | Nombre de la clave; cuenta según la ProfileList o etiqueta de SID conocido |
Service, ControlSet, ActiveControlSet, LegacyLayout | Dónde se encontró la clave en la colmena |
SidKeyLastWriteUtc | Marca de tiempo del nodo de clave |
DataHex | Datos completos del valor |
Suelta una colmena en el BAM/DAM Parser y abre el panel de detalle de cualquier fila para ver todos estos campos juntos. Para el mismo ejercicio con otros artefactos del registro, Registry Parser cubre el resto de la colmena.
Fuentes
- Maxim Suhanov, BAM internals.
- Microsoft Learn, FILETIME.
- Maxim Suhanov, Windows registry file format specification; Joachim Metz, documentación de libregf.