
Analizador para $LogFile en NTFS
Características Decodificar y volcar registros de $LogFile y entradas de transacción. Decodificar cambios de atributos NTFS. Opcionalmente resolver toda la información de la lista de dataruns disponible en $LogFile. Opción: "Reconstruct data runs". Recuperar transacciones del espacio slack dentro de $LogFile. Elegir reconstruir encabezados faltantes o dañados de transacciones encontradas en slack. Opción: "Rebuild header". Opcionalmente también afinar el resultado con un valor de nivel de error de LSN. Opción: "LSN error level". Registra en csv e importa a base de datos sqlite con varias tablas. Opcionalmente importar la salida csv de mft2csv a la base de datos. Elegir entre 6 formatos de timestamp diferentes. Elegir precisión de timestamp: None, MilliSec y NanoSec. Elegir separador de precisión en milisegundos. Elegir separador de precisión en nanosegundos. Elegir ajuste de región para timestamps. Por defecto se presentan los timestamps en UTC 0.0. Elegir separador de salida. Opción: "Set separator". Salida UNICODE o ANSI configurable. Opción "Unicode". Tamaño de registro MFT configurable (1024 o 4096). Opción "MFT record size". Opcionalmente decodificar transacciones individuales o transacciones parciales (fragmento). Opción de reconstruir RCRD's a partir de una o múltiples transacciones (fragmentos). Opción de configurar $LogFile dañado. Útil con RCRD's carved como entrada. Opción de omitir fixups (para $LogFile dañado, típicamente carved desde memoria). Salida verbose detallada en debug.log. Lista configurable separada por comas de lsn's para activar información ultra verbose sobre transacciones específicas en debug.log. Configuración para SO de 32 bits. Configuración para extracción de datos binarios de actualizaciones de datos residentes. sql autogenerado para importar la salida a base de datos MySql. Opción de omitir todo lo relacionado con sqlite3 para acelerar el parseo total. Modo de línea de comandos opcional. Soporta errorlevel adecuado para scripting por lotes.
Antecedentes NTFS está diseñado como un sistema de archivos recuperable. Esto se logra mediante el registro de todas las transacciones que alteran la estructura del volumen. Así, cualquier cambio a un archivo en el volumen requerirá que algo también se registre en el $LogFile, para que pueda revertirse en caso de fallo del sistema en cualquier momento. Por lo tanto, mucha información se escribe en este archivo, y dado que es circular, significa que las nuevas transacciones sobrescriben registros más antiguos en el archivo. Así, es algo limitado cuánta información histórica puede recuperarse de este archivo. De nuevo, eso dependería del tipo de volumen y del tamaño del $LogFile. En la unidad de sistema de un sistema de uso frecuente, probablemente solo obtendrás unas pocas horas de historial, mientras que un disco externo/secundario con archivos de respaldo probablemente contendría más información histórica. Y un archivo de 2MB contendrá mucho menos historial que uno de 256MB. Entonces, ¿en qué rango de tamaño puede configurarse este archivo? Cualquier cosa desde 256 KB en adelante. Configurar el tamaño a 2 GB puede hacerse así, "chkdsk D: /L:2097152". Cómo un archivo de registro de gran tamaño impacta en el rendimiento está fuera del alcance de este texto. Establecerlo por debajo de 2048 normalmente no es posible. Sin embargo, es posible parcheando untfs.dll: http://code.google.com/p/mft2csv/wiki/Tiny_NTFS
Introducción Este parser decodificará y volcará gran cantidad de información de transacciones del $LogFile en NTFS. Se generan varios csv's así como una base de datos sqlite llamada ntfs.db que contiene toda la información relevante. La salida es extremadamente detallada y de muy bajo nivel, lo que significa que requiere cierto conocimiento decente de NTFS para poder entenderla. Los tipos de transacción Redo actualmente manejados con salida decodificada significativa son:
InitializeFileRecordSegment CreateAttribute DeleteAttribute UpdateResidentValue UpdateNonResidentValue UpdateMappingPairs SetNewAttributeSizes AddindexEntryRoot DeleteindexEntryRoot AddIndexEntryAllocation DeleteIndexEntryAllocation WriteEndOfIndexBuffer SetIndexEntryVcnRoot SetIndexEntryVcnAllocation UpdateFileNameRoot UpdateFileNameAllocation SetBitsInNonresidentBitMap ClearBitsInNonresidentBitMap OpenNonresidentAttribute OpenAttributeTableDump AttributeNamesDump DirtyPageTableDump TransactionTableDump UpdateRecordDataRoot UpdateRecordDataAllocation CompensationlogRecord
La lista de atributos actualmente soportados: $STANDARD_INFORMATION $ATTRIBUTE_LIST $FILE_NAME $OBJECT_ID $SECURITY_DESCRIPTOR $VOLUME_NAME $VOLUME_INFORMATION $DATA $INDEX_ROOT $INDEX_ALLOCATION $REPARSE_POINT $EA_INFORMATION $EA $LOGGED_UTILITY_STREAM
Así que básicamente todos los atributos están soportados.
Explicación de las diferentes salidas generadas:
LogFile.csv: El csv principal generado por el parser.
LogFile_DataRuns.csv La información de entrada necesaria para reconstruir dataruns
LogFile_DataRunsResolved.csv La salida final de dataruns reconstruidos
LogFile_INDX_I30.csv Todos los registros de índice volcados y decodificados (IndexRoot/IndexAllocation)
LogFileJoined.csv Igual que LogFile.csv, pero con información de nombre de archivo unida desde el $UsnJrnl o csv de mft2csv.
MFTRecords.bin $MFT ficticio recreado basado en registros MFT encontrados en transacciones InitializeFileRecordSegment. Se puede usar mft2csv sobre este (recuerda configurar "broken MFT" y "Fixups" correctamente).
LogFile_lfUsnJrnl.csv Registros para el $UsnJrnl que han sido decodificados dentro de $LogFile
LogFile_UndoWipe_INDX_I30.csv Todas las operaciones undo para limpieza de índices de directorio (INDX).
LogFile_AllTransactionHeaders.csv Todos los encabezados de transacciones decodificadas.
LogFile_BitsInNonresidentBitMap.csv Todas las operaciones SetBitsInNonresidentBitMap decodificadas.
LogFile_DirtyPageTable32bit.csv y LogFile_DirtyPageTable64bit.csv Todas las entradas en cada operación DirtyPageTableDump decodificada tanto para SO de 32 bits como de 64 bits.
LogFile_Mft_ObjectId_Entries.csv Atributos $ObjectId decodificados.
LogFile_ObjIdO.csv Todas las decodificaciones del archivo de sistema $ObjId:$O.
LogFile_OpenAttributeTable.csv Todas las entradas en cada operación OpenAttributeTableDump decodificada.
LogFile_QuotaO.csv Todas las decodificaciones del archivo de sistema $Quota:$O.
LogFile_QuotaQ.csv Todas las decodificaciones del archivo de sistema $Quota:$Q.
LogFile_RCRD.csv Todos los encabezados de registros RCRD decodificados.
LogFile_ReparseR.csv Todas las decodificaciones del archivo de sistema $Reparse:$R.
LogFile_SecureSDH.csv Todas las decodificaciones del archivo de sistema $Secure:$SDH.
LogFile_SecureSII.csv Todas las decodificaciones del archivo de sistema $Secure:$SII.
LogFile_SecurityDescriptors.csv Descriptores de seguridad decodificados. La fuente puede ser de $SECURITY_DESCRIPTOR o $Secure:$SDS.
LogFile_SlackAttributeNamesDump.csv Todas las entradas de transacciones AttributeNamesDump decodificadas encontradas en espacio slack.
LogFile_SlackOpenAttributeTable.csv Todas las entradas de transacciones OpenAttributeTableDump decodificadas encontradas en espacio slack.
LogFile_TransactionTable.csv Transacciones TransactionTableDump decodificadas.
LogFile_Filenames.csv Todos los nombres de archivo resueltos con MftRef, MftRefSeqNo y Lsn.
LogFile_TxfData.csv Datos decodificados de $DATA:$TXF_DATA en $LOGGED_UTILITY_STREAM.
LogFile_UpdateFileName_I30.csv Todas las decodificaciones de UpdateFileNameRoot y UpdateFileNameAllocation tanto para operaciones redo como undo.
LogFile_CompensationlogRecord.csv Todas las decodificaciones de CompensationlogRecord. No relevante para nt5.x.
Ntfs.db Un archivo de base de datos sqlite con tablas casi equivalentes a los csv's anteriores. La base de datos contiene 5 tablas: DataRuns IndexEntries LogFile LogFileTmp (tabla temporal usada al recrear dataruns). UsnJrnl
Timestamps Por defecto se presentan en UTC 0.00, y con precisión de nanosegundos. El formato por defecto es YYYY-MM-DD HH:MM:SS:MSMSMS:NSNSNSNS. Estos pueden configurarse. Los diferentes timestamps se refieren a: CTime significa File Create Time. ATime significa File Modified Time. MTime significa MFT Entry modified Time. RTime significa File Last Access Time.
Reconstrucción de dataruns.
Muchas operaciones en el sistema de archivos activarán una transacción en el $LogFile. Aquellas relacionadas con el atributo $DATA, es decir, el contenido de un archivo, hasta ahora se identifican como;
InitializeFileRecordSegment CreateAttribute UpdateMappingPairs SetNewAttributeSizes
Todas dejan información diferente en el $LogFile. Las modificaciones de datos residentes se comportan de manera diferente y no pueden reconstruirse así sin más, al menos en volúmenes NTFS provenientes de versiones modernas de Windows.
InitializeFileRecordSegment es cuando se crea un nuevo archivo. Por lo tanto tendrá el atributo $FILE_NAME, así como el contenido original del atributo $DATA, incluyendo dataruns. Dado que el $LogFile es circular, y los eventos más antiguos son sobrescritos por los más nuevos, el desafío con el $LogFile es obtener información suficientemente atrás en el tiempo. Sin embargo, si InitializeFileRecordSegment está presente, entonces deberíamos poder reconstruir todo, ya que todos los registros escritos después de eso también estarán disponibles. También tendremos información sobre el offset a la lista de dataruns. Este es un offset relativo calculado desde el inicio del atributo $DATA. Esta es información importante para tener al calcular dónde en la lista de dataruns UpdateMappingPairs ha hecho su modificación.
CreateAttribute es el atributo original cuando fue creado por primera vez (si no se escribió como parte de InitializeFileRecordSegment). Con este también deberíamos poder reconstruir dataruns ya que tenemos todas las transacciones disponibles. Sin embargo, este por sí solo no nos proporcionará el nombre del archivo. Aquí también tenemos disponible el offset a la lista de dataruns, lo cual es extremadamente útil al resolver UpdateMappingPairs.
UpdateMappingPairs es una transacción cuando se realizan modificaciones al $DATA/dataruns (el contenido del archivo ha cambiado). La información encontrada en esta transacción no está completa, y contiene solo los nuevos valores añadidos a la lista de dataruns existente. También contiene un offset relativo que nos dice dónde en la lista de dataruns se han escrito los cambios. Este offset se usa en combinación con el offset a datarun como se encuentra en InitializeFileRecordSegment y CreateAttribute.
SetNewAttributeSizes es una transacción que contiene información sobre cualquier modificación relacionada con valores de tamaño hecha al atributo $DATA. Esto está estrechamente conectado con UpdateMappingPairs que solo contiene cambios de dataruns.
Con las 4 operaciones redo anteriores se puede, para un número de referencia dado (archivo distinto), reconstruir parte del historial de cambios del sistema de archivos del archivo. Debido a su circularidad, solo tenemos parte del historial, el más reciente. La extensión del historial que podemos recuperar depende en gran medida del tipo de volumen que sea el objetivo. Si es un volumen de sistema, entonces una semana de historial es probablemente más de lo que podrías esperar, mientras que un disco removible o externo o secundario contendrá mucho más historial. Así, podemos reconstruir el historial completo de un archivo eliminado (habiendo sido sobrescrito su registro $MFT), y a su vez recrear la lista de dataruns para realizar recuperación sobre ella. En otros casos puede que no podamos reconstruir el historial completo, por lo que solo puede reconstruirse una lista de dataruns parcial. El archivo csv final con los dataruns ajustados, LogFile_DatarunsModified.csv, tendrá los dataruns mostrados de manera diferente.
Explicación: Aquellos que comienzan con un "!" indican que la lista completa de dataruns ha sido recreada. Aquellos que comienzan con un "?" indican una recuperación parcial, con el número de "**" representando bytes faltantes de la lista de dataruns original.
Para simplificar la recuperación de un archivo basado en un datarun, se puede usar el PoC adjunto llamado ExtractFromDataRuns. Es bastante autoexplicativo. Solo rellena la lista completa de dataruns, el tamaño real y el tamaño inicial, y un nombre para el archivo de salida. Opcionalmente elige procesar archivos de imagen (disco o partición). También marca si se ha detectado algún flag de comprimido/sparse. ¡Alimentarlo con una lista de dataruns parcialmente reconstruida no funcionará! Ten en cuenta que los flujos de datos alternativos pueden distinguirse por la presencia de un dataname y también por valores OffsetInMft diferentes para un fileref dado.
El paquete de descarga separado "SampleTinyNtfsVolume.zip" tiene una imagen de partición con un pequeño volumen NTFS para probarlo. En el volumen hay 2 archivos no residentes eliminados que ambos tienen su registro MFT sobrescrito por nuevos archivos. Cualquier software de recuperación decente basado en búsqueda de firmas debería poder recuperar el archivo jpg (Tulips.jpg), porque es contiguo. Sin embargo, lo más probable es que no identifiquen su nombre de archivo, ni nada más sobre el archivo. El segundo archivo probablemente no será recuperable usando herramientas estándar, porque está fragmentado (comprimido), y al tener su registro MFT sobrescrito, resolver el archivo sin la lista de dataruns es imposible. Usando el PoC podemos identificar el nombre del archivo (suspicious.zip) y extraerlo en perfecto estado (no te preocupes, solo contiene una de las imágenes de muestra incluidas con Windows). Lee el archivo readme.DataRunsResolved.txt para los detalles sobre la imagen de muestra y cómo interpretar la salida y recuperar los archivos.
Lo que hemos logrado con esto es recuperar archivos fragmentados que tienen su registro MFT sobrescrito. Dado que hemos reconstruido el historial parcial/completo de dataruns, podemos con certeza (al menos si se reconstruye el historial completo) determinar si los datos de slack del archivo han pertenecido al archivo dado o no.
Limitación. La reconstrucción de dataruns está rota con UNICODE (ANSI está bien). La importación de salida de Mft2Csv está rota si el csv es UNICODE (ANSI está bien). Las actualizaciones parciales a IndexRecords (IndexRoot/IndexAllocation) son muy difíciles de interpretar, ya que probablemente no tengamos conocimiento del índice original. Los registros completos sí están bien. La circularidad de un archivo de 65 MB impone una restricción inherente y absoluta sobre cuántas transacciones históricas del FS. Las unidades de sistema tienen así historial limitado en $LogFile, mientras que las unidades externas/secundarias tienen más transacciones históricas almacenadas. Se puede aumentar el tamaño del $LogFile con chkdsk (chkdsk c: /L:262144). Los cambios a los datos de archivos residentes no se almacenan dentro de $LogFile, solo se almacena la información de que se hizo un cambio.
Nota El $UsnJrnl contiene información de una manera más amigable para humanos. Por ejemplo, cada registro contiene fileref, nombre de archivo, timestamp y explicación de lo que ocurrió. También contiene mucha más información histórica que $LogFile, aunque sin muchos detalles. Si $UsnJrnl está activo, entonces todas las transacciones escritas en él durante la vida de reciclaje del $LogFile también están presentes dentro de $LogFile. Esto significa que no hay razón para decodificar el $UsnJrnl con el fin de entender mejor el $LogFile.
Espacio slack En este contexto, espacio slack significa el espacio dentro de un registro RCRD que es el sobrante en el registro más allá de la última transacción. No creo que esto se haya descrito antes, así que déjame explicarlo. El slack de volumen es el espacio no utilizado entre el final del sistema de archivos y el final de la partición donde reside el sistema de archivos. El slack de registro MFT es algo similar, pero se refiere al espacio encontrado después de la firma de fin de registro (0xFFFFFFFF) hasta el final físico del registro (0x400 o 0x1000). Y el espacio slack dentro del $LogFile es así el espacio encontrado más allá de la última transacción y hasta el final del registro RCRD (usualmente 0x1000). Estas transacciones del slack están realmente ahí desde antes de que el $LogFile fuera reciclado (sobrescrito). También hay un algoritmo que identifica transacciones válidas del espacio slack. Además, también pueden existir varias capas de dicho espacio slack. Ejemplo: Digamos que la última transacción en un registro RCRD dado terminó en el offset 0x00007D27. Desde este offset y hasta 0x00007FFF tenemos 0x2D8 bytes de espacio slack. Podría entonces ser que los bytes comenzando en 0x00007D28 no sean un encabezado de transacción válido porque está en medio de una transacción. El programa entonces (si está configurado para ello) intentará reconstruir un pseudo encabezado con valores válidos para poder decodificar la transacción. Si falla al reconstruir cualquier encabezado válido, considera que se ha perdido demasiada información del encabezado original, y considerará estos bytes como perdidos, y continuará escaneando el resto del espacio slack en busca de cualquier encabezado de transacción válido. Los bytes perdidos se registrarán en debug.log para que los investigues. Por otro lado, si pudo reconstruir un encabezado válido, la información sobre esto se encontrará en el campo lf_TextInformation. Digamos que identificó una transacción comenzando en el offset 0x00007D48 y con tamaño 0xB0. Entonces otra transacción buena fue identificada inmediatamente después en el offset 0x00007DF8 con tamaño 0xE0. Sin embargo, en el offset 0x00007ED8 no había ningún encabezado de transacción válido. Esto significa que ahora estamos en la segunda capa de espacio slack dentro de ese registro RCRD. Ahora digamos que el programa, tras reescanear, pudo identificar un encabezado de transacción válido en el offset 0x00007F18. Esta transacción se marcaría en el csv con un valor de 2 en el campo FromRcrdSlack. Sin embargo, considera que el tamaño total de la transacción empuja el offset más allá del tamaño del registro RCRD. En esencia, esta sería una transacción parcialmente recuperada, que podría decodificar bien, pero se encontrará con un valor de 1 en el campo IncompleteTransaction. Recuerda que el debug.log es muy detallado y ayudará a entender la salida decodificada, especialmente lo que proviene del espacio slack.
Configuración de 32 bits vs 64 bits. Esta configuración es importante establecerla correctamente. Significa qué SO ha manejado el volumen objetivo. El punto es que el manejo de OpenAttributeTable difiere de SO de 32 bits a 64 bits. Puede haber por supuesto casos (por ejemplo, disco usb) donde el volumen ha sido manejado por varios SO's diferentes, en cuyo caso podría ser complicado obtener esta configuración 100% correcta. Desde la versión 2.0.0.8 se implementó un mecanismo de autodetección. Sin embargo, todavía se recomienda intentar establecer esta configuración correctamente. En el campo TextEinformation se imprimirá un mensaje "Mixed OS detected" cuando detecte un formato OpenAttributeTableDump que difiera de la configuración o cuando se detecten ambos tipos. En cualquier caso, puede ser útil revisar el LogFile_OpenAttributeTable.csv para evaluar la salida. Si ves entradas con columnas que contienen valores extraños, entonces esta configuración particular podría estar equivocada. Si es así, entonces la mayoría de los valores están muy desviados. Por ejemplo, la mayoría de los campos AttributeType son UNKNOWN, Lsn no está dentro del rango actual, MftRef es demasiado alto y MftRefSeqNo es 0. Ten en cuenta que AttributeType se resuelve como UNKNOWN para entradas no inicializadas en la tabla, pero estas son fáciles de detectar ya que todos los valores después de AllocatedOrNextFree son 0 y son perfectamente válidos. Estos desafíos parecen estar resueltos con la autodetección implementada en la versión 2.0.0.8.Extracción de actualizaciones de atributos residentes (UpdateResidentValue). La operación UpdateResidentValue es para actualizaciones del contenido de atributos residentes. La configuración de "Extract resident updates of min size" le permitirá extraer la modificación binaria del atributo residente. El campo de entrada es para el tamaño mínimo en bytes a extraer. El uso probablemente más interesante de esta característica es con volúmenes gestionados por Nt5.x (XP,2003), donde las actualizaciones completas del atributo $DATA (contenido normal de archivo) se almacenan en los campos redo y undo con UpdateResidentValue. Los archivos con un contenido $DATA residente son archivos de menor tamaño, como máximo 744 bytes (con un tamaño de registro MFT de 1024) pero normalmente menos. Los datos extraídos se escriben en una subcarpeta llamada ResidentExtract. Los archivos de salida se nombran con una lógica como esta; MFT($MFTRef)$OffsetInMft$AttributeOffset_LSN($Lsn)$Operation.bin. Por ejemplo MFT(1643)_0x0098_0x00B8_LSN(1415242628)redo.bin significaría el número de registro MFT 1643, el desplazamiento del atributo objetivo en MFT es 0x98, el desplazamiento de la modificación dentro del atributo objetivo es 0xB8, el LSN de la transacción es 1415242628, y esto fue para una operación redo. Las extracciones para operaciones undo contienen así los datos en ese desplazamiento antes de la modificación. La activación de esta característica provocará alguna salida irrelevante y poco interesante. La mayoría de los falsos positivos se filtran automáticamente, pero algunos son inevitables. Por ejemplo, pueden incluirse actualizaciones de $INDEX_ROOT, $ATTRIBUTE_LIST y $BITMAP. Sin embargo, es posible rastrear manualmente los atributos para filtrar los que no son $DATA comparando el OffsetInMft con lo que se encuentra en el relevante InitializeFileRecordSegment o, si es aplicable, en el propio $MFT. Desde la versión 2.0.0.13 se añadió la extracción de $EA. Véase la nota sobre los atributos $EA.
Filenames csv Desde la versión 2.0.0.6 se implementó una nueva característica para volcar todos los nombres de archivo identificados. El origen de estas entradas proviene de InitializeFileRecordSegment, UpdateNonResidentValue, AddindexEntryRoot, DeleteindexEntryRoot, AddIndexEntryAllocation, DeleteIndexEntryAllocation y WriteEndOfIndexBuffer. El csv con estos nombres de archivo, LogFile_FileNames.csv, contiene así una historia reconstruida de todos los filename, MftRef y MftRefSeqNo durante la duración de la historia del $LogFile. Podrá así ver los diversos nombres de archivo que un registro Mft dado ha tenido durante el intervalo de tiempo que cubrió el $LogFile. Cuando un archivo se renombra, el MftrefSeqNo no se incrementa. Cuando un registro MFT se marca como eliminado y posteriormente se reutiliza, el MftRefSeqNo se incrementa en uno con la nueva inicialización.
$TXF_DATA Con NTFS transaccional (TxF), habrá ocurrencias del flujo con nombre $TXF_DATA en el atributo $LOGGED_UTILITY_STREAM. Siempre es residente, y puede haber varios por archivo. Su uso no está muy extendido, y Microsoft de hecho fomenta métodos alternativos. [quote]Microsoft recomienda encarecidamente a los desarrolladores utilizar medios alternativos para satisfacer las necesidades de sus aplicaciones.[/quote]. Parece que solo unos pocos mecanismos de actualización de software lo utilizan. Cada archivo/carpeta creado con él obtiene un fileref único (no debe confundirse con los números de registro MFT). Este fileref único es el nombre que tendrá el archivo cuando se elimine posteriormente (y se mueva a la carpeta $Extend$RmMetadata$Txf). El atributo $DATA estándar sin nombre del archivo $Tops contiene información sobre dónde en el $TxfLogContainer00000000000000000001 iría la siguiente transacción. El flujo $DATA con nombre $T del $Tops contiene datos reales (de operaciones de archivo transaccionales) que se reciclan. Dentro de $TXF_DATA también hay un campo llamado LsnUserData que es un desplazamiento dentro del $TxfLogContainer00000000000000000001 donde se encuentran muchos más detalles de la transacción. LsnNtfsMetadata también contiene un desplazamiento dentro del mismo archivo $TxfLogContainer00000000000000000001. Tenga en cuenta que estos desplazamientos pueden cambiarse en una etapa posterior, y entonces se hace referencia a ellos en una operación UpdateResidentValue en el $LogFile. El campo MftRef_RM_Root es el número de registro de archivo de la raíz del gestor de recursos responsable de la transacción asociada con este archivo (el valor predeterminado es 5, que es el directorio raíz). Para las actualizaciones de $TXF_DATA mediante UpdateResidentValue, el texto "Partial update" se añade en el campo TextInformation. Por esta razón, también pueden existir valores como 0x0000000000007E-- en LsnUserData. Esto se debe a que un UpdateResidentValue de tamaño 31 bytes significa que faltan los primeros 3 miembros de la estructura completa, y también falta 1 byte de LsnUserData. El byte faltante es el "byte bajo", por lo que 2 caracteres/nibbles de "-" cada uno, como reemplazo para indicar el byte desconocido faltante (en realidad solo el byte existente). Si UpdateResidentValue fuera de 32 bytes, entonces no se necesitarían caracteres/nibbles de reemplazo ya que se proporcionó el LsnUserData completo.
debug.log En este log se escriben mensajes de error e información detallada. Si se encuentran valores extraños o comentarios en la salida, busque el lsn en debug.log. Normalmente se vuelca toda la transacción, lo que puede ayudar a comprender. Para ayudar en las investigaciones de transacciones, puede ser útil rellenar una lista separada por comas de lsn's en el campo de entrada. Entonces se imprimirá información detallada para estos lsn's.
$EA El atributo $EA es un conjunto de pares nombre-valor y se cree que están ahí por compatibilidad con OS/2. Rara vez se ve utilizado, aunque algún malware lo ha usado. Puede haber varios pares por atributo, pero el tamaño máximo de todos ellos es de 65535 bytes. Solo puede haber 1 atributo $EA por archivo. El contenido más grande puede distribuirse entre varios archivos como se muestra en el PoC EaTools; https://github.com/jschicht/EaTools Los atributos $EA existentes no pueden modificarse directamente. Se pueden añadir pares nombre/valor adicionales en cualquier momento siempre que el tamaño de todos los pares esté por debajo de 0xFFFF bytes. El comportamiento extraño de este atributo es que todo el contenido de todo el $EA se escribe en $LogFile para cualquier par nuevo. Esto es tanto para contenido $EA residente como no residente. Eso significa que si se añade un tercer par nombre/valor a un $EA, los 3 pares se escriben en $LogFile ya sea mediante UpdateResidentValue o UpdateNonResidentValue.
Todo Implementar más análisis de los datos presentes en ntfs.db. Actualmente requerirá un cierto nivel de conocimiento de NTFS para comprender la salida. Volcar el contenido de $EA no residente.
Uso desde línea de comandos Si no se proporcionan parámetros, la GUI se iniciará por defecto. Los interruptores válidos son:
Interruptores: /LogFileFile: $LogFile de entrada extraído. Requerido a menos que se use /LogFileFragmentFile:. /LogFileFragmentFile: Opcionalmente, introduzca un fragmento de $LogFile. Puede ser cualquier fragmento roto con al menos 1 transacción. /MftCsvFile: El csv de salida del último Mft2Csv. Opcional. /OutputPath: La ruta de salida de toda la salida del analizador. Por defecto es el directorio del programa. /TimeZone: Un valor de cadena para la zona horaria. Consulte las notas más abajo para los valores válidos. /OutputFormat: El formato de salida del csv. Los valores válidos pueden ser l2t, BodyFile, all. /BrokenMft: Valor booleano para manejar MFT con formato incorrecto. Por defecto es 0. Puede ser 0 o 1. /SkipFixups: Valor booleano para omitir los fixups. Se usa principalmente con volcados de memoria. Por defecto es 0. Puede ser 0 o 1. /Separator: El separador a usar en el csv. Por defecto es | /Unicode: Valor booleano para decodificar cadenas unicode. Por defecto es 0. Puede ser 0 o 1. /TSFormat: Un entero de 1 - 6 para especificar el formato de marca de tiempo. Inicie la gui para ver qué significan. Por defecto es 6. /TSPrecision: Qué precisión usar en la marca de tiempo. Los valores válidos son None, MilliSec y NanoSec. Por defecto es NanoSec. /TSPrecisionSeparator: El separador a colocar en la separación de la precisión. Por defecto es ".". Inicie la gui para ver qué significa. /TSPrecisionSeparator2: El separador a colocar entre MilliSec y NanoSec en la precisión de la marca de tiempo. Por defecto está vacío/nada. Inicie la gui para ver qué significa. /TSErrorVal: Un valor de error personalizado para colocar con errores en la decodificación de marcas de tiempo. El valor por defecto es '0000-00-00 00:00:00', que es compatible con MySql, y representa un valor de marca de tiempo inválido para NTFS. /ReconstructDataruns: Valor booleano para especificar si se debe realizar la reconstrucción de dataruns. Por defecto es 0. Puede ser 0 o 1. /MftRecordSize: El tamaño de los registros MFT. Los valores válidos son 1024 y 4096. Por defecto es 1024. /RebuildHeadersSlack: Valor booleano para especificar si se debe intentar reconstruir el encabezado a partir de transacciones rotas recuperadas del slack. Por defecto es 0. Puede ser 0 o 1. /SectorsPerCluster: Número de sectores por clúster. Por defecto es 8. Puede ser 1,2,4,8,16,32,64 y 128. /LsnErrorLevel: Un valor entre 0 y 1 (100%), como umbral para identificar transacciones válidas/inválidas del slack, basado en el lsn anterior. Por defecto es 0.1 (10%). /SourceIs32bit: Valor booleano para especificar si el volumen proviene de un sistema de 32 bits. Por defecto es 0 (x64). Puede ser 0 o 1. /ExtractDataUpdates: Valor booleano para especificar si se debe realizar la extracción del contenido de datos residentes. Por defecto es 0. Puede ser 0 o 1. /ExtractDataUpdatesSize: Valor para establecer el tamaño mínimo en bytes de lo que se debe extraer. Solo se usa con la configuración ExtractDataUpdates. Por defecto es 2 (bytes) como mínimo. /VerboseLsnList: Una lista separada por comas de lsn's que activarán el modo detallado. La información de registro detallada se encuentra en debug.log. /SkipSqlite3: Valor booleano para especificar si el analizador debe omitir todas las operaciones de sqlite3. Si el ntfs.db generado (reconstrucción de dataruns, importación del csv de mft) no se utiliza, esto puede ignorarse/omitirse sin problema. Por defecto es 0. Puede ser 0 o 1. /VerifyFragment: Valor booleano para activar una validación simple solo en un fragmento, y no en el analizador completo. Puede ser 0 o 1. Por defecto escribirá el fragmento corregido en OutFragment.bin a menos que se especifique lo contrario en /OutFragmentName: /OutFragmentName: El nombre de archivo de salida donde escribir el fragmento corregido, si /VerifyFragment: está establecido en 1. Si se omite, el nombre de archivo por defecto es OutFragment.bin. /SkipFixups: Valor booleano para omitir los fixups. Se usa con fragmentos reconstruidos. Véanse los ejemplos. Por defecto es 0. Puede ser 0 o 1. /BrokenLogFile: Valor booleano para tratar el $LogFile como roto. Se usa con RCRD's reconstruidos y omitirá varias comprobaciones de validación. Por defecto es 0. Puede ser 0 o 1.
Las TimeZone's disponibles para usar son: -12.00 -11.00 -10.00 -9.30 -9.00 -8.00 -7.00 -6.00 -5.00 -4.30 -4.00 -3.30 -3.00 -2.00 -1.00 0.00 1.00 2.00 3.00 3.30 4.00 4.30 5.00 5.30 5.45 6.00 6.30 7.00 8.00 8.45 9.00 9.30 10.00 10.30 11.00 11.30 12.00 12.45 13.00 14.00
Niveles de error Los códigos de salida (error) actuales se han implementado en modo línea de comandos, lo que lo hace más adecuado para scripting por lotes.
Así, si obtiene %ERRORLEVEL% == 1 significa que no se decodificó nada, y si obtiene %ERRORLEVEL% == 2 entonces lo más probable es que el parámetro SectorsPerCluster se estableciera incorrectamente.
Ejemplos: LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:2.00 /MftRecordSize:4096 /ExtractDataUpdates:1 /ExtractDataUpdatesSize:8 /SectorsPerCluster:64 /TSFormat:1 /TSPrecision:NanoSec /Unicode:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:-5.00 /MftRecordSize:1024 /SectorsPerCluster:1 /TSFormat:1 /TSPrecision:MilliSec /Unicode:0 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TSFormat:3 /ReconstructDataruns:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:7.00 /MftRecordSize:1024 /TSFormat:2 /TSPrecision:None /SourceIs32bit:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:7.00 /MftRecordSize:1024 /TSFormat:2 /TSPrecision:None /SourceIs32bit:1 /SkipSqlite3:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /OutputPath:E:\LFP-Output LogFileParser.exe /LogFileFile:c:\temp$LogFile /MftCsvFile:c:\temp$MFT LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output /VerifyFragment:1 LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output /VerifyFragment:1 /OutFragmentName:FragmentsRCRDCollection.bin LogFileParser.exe /LogFileFile:E:\LFP-Output\FragmentsRCRDCollection.bin /OutputPath:E:\LFP-Output /SkipFixups:1 /BrokenLogFile:1
El último ejemplo es un ejemplo básico que usa valores predeterminados comunes que funcionan perfectamente en muchos casos. También es compatible con importaciones de MySql.
Referencias: Windows Internals 6th Edition http://www.opensource.apple.com/source/ntfs/ntfs-80/kext/ntfs_logfile.h https://dl.dropbox.com/s/c0u980a53ipaq7h/CEIC-2012_Anti-Anti_Forensics.pptx?dl=1