MFT
La fuente más notable de información valiosa para un analista del sistema de archivos NTFS es la Master File Table (MFT). La ubicación del sector inicial de la MFT se encuentra en el sector de arranque del disco, y cada archivo y directorio del volumen tiene una entrada en la MFT. Cada entrada de la MFT tiene un tamaño de 1024 bytes, lo que hace que la MFT sea muy fácil de analizar. Cada registro o entrada de la MFT comienza con la cadena ASCII «FILE» (si hay un error en la entrada, comenzará con «BAAD») y consta de uno o más atributos (en la mayoría de los casos, más), cada uno con su propio identificador y estructura. La figura 4.1 ilustra una parte de una entrada MFT.
Los primeros 42 bytes de cada entrada MFT comprenden una estructura de cabecera con 12 elementos, y los 982 bytes restantes dependen en gran medida de los valores dentro de la cabecera y de los diversos atributos contenidos en la entrada. No todos los elementos dentro de la cabecera de la entrada MFT son inmediatamente útiles para un analista forense; sin embargo, la Figura 4.2 ilustra cinco de los elementos que son inmediatamente útiles.
Como se ilustra en la Figura 4.2 (que es una parte extraída de la Figura 4.1), vemos la firma «FILE» visible al principio del registro. Luego vemos el número o valor de la secuencia, que se incrementa cuando la entrada es asignada o desasignada. Dado que esta entrada MFT en particular es en realidad el primer registro dentro de la MFT y se refiere al archivo «$MFT», es lógico que el número de secuencia sea 1. A continuación está el recuento de enlaces, que se refiere al número de directorios que tienen entradas para este registro (los enlaces duros hacen que este valor se incremente). A continuación está el desplazamiento con el registro al primer atributo; si miras el desplazamiento 0x38 dentro del registro, verás que el primer atributo tiene un identificador de 0x10, o 16. Por último, vemos el valor de las banderas, que nos indica si la entrada está asignada (si el bit 0x01 está activado) y si la entrada es un directorio (si el bit 0x02 está activado). En resumen, a partir de estos dos valores, podemos determinar si la entrada está asignada o eliminada, y si es para un archivo o un directorio. Cuando se analiza la cabecera, el pseudocódigo para esto puede representarse como sigue:
if ($mft{flags} & 0x0001) – asignado; si no, no asignado/borrado
if ($mft{flags} & 0x0002) – carpeta/directorio; si no, archivo
El valor de flags visible en la Figura 4.2 es «0x01», que indica un archivo asignado. Un valor de 0x00 indicaría un archivo eliminado, y un valor de 0x03 indicaría un directorio asignado.
Consejo
Registros MFT
Los registros MFT no se eliminan una vez creados; se añaden nuevos registros a la MFT según sea necesario, y se reutilizan los registros de los archivos eliminados.
Como se mencionó anteriormente, sólo los primeros 42 bytes están estructurados; después de eso, el resto de la entrada MFT consiste en uno o más campos de atributos. No hay ninguna especificación o declaración formal que diga que tiene que haber atributos específicos dentro de una entrada MFT, pero en su mayor parte, se puede esperar encontrar un atributo $STANDARD_INFORMATION y un atributo $FILE_NAME en la mayoría de las entradas MFT. Esta sección examina estos dos atributos, ya que proporcionan información de marca de tiempo, que es valiosa para los analistas forenses. También echaremos un breve vistazo al atributo $DATA y dejaremos el resto de atributos como ejercicio para el lector interesado y curioso.
La cabecera de cada atributo contiene un encabezado de 16 bytes, que identifica el tipo de atributo, la longitud total del atributo, y si el atributo es residente en la entrada MFT o no, entre otros elementos.
Nota
Archivos de metadatos MFT
Las primeras 16 entradas de la MFT contienen información sobre los archivos de metadatos; sin embargo, puede que no se utilicen todas. Los que no se utilizan se dejan en un estado asignado y sólo contienen información básica.
Usando esta información de cabecera, podemos analizar la entrada MFT y extraer información valiosa de cada atributo. Por ejemplo, el atributo $STANDARD_INFORMATION (que siempre es residente) existe para cada entrada de archivo y directorio y tiene un identificador de 0x10 (es decir, 16). Este atributo contiene los tiempos del archivo para la entrada MFT (bueno, tres de ellos, al menos) que vemos cuando escribimos «dir» en el símbolo del sistema; el tiempo de modificación, el tiempo de último acceso y la fecha de creación (nacimiento) del archivo o directorio, también referidos como tiempos «MAC». El atributo contiene un cuarto valor de tiempo que especifica la última vez que se modificó la entrada MFT. En conjunto, estos tiempos se denominan tiempos «MACE» (con la «E» referida a la hora de modificación de la entrada MFT) o «MACB» (con la «C» referida a la hora de modificación de la entrada MFT).
Atención
Tiempos de los archivos
Los tiempos de los archivos NTFS se registran en formato de tiempo universal coordinado (UTC), que es análogo a la hora media de Greenwich. Esto es cierto para todas las horas; en cada entrada de la MFT, un registro de archivo probablemente tendrá al menos 8 horas asociadas; muchas veces, 12 o más. En el sistema de archivos FAT, las horas de los archivos se mantienen en el formato de la hora del sistema local.
El atributo $FILE_NAME (identificador 0x30, o 48) también se encuentra con la mayoría de las entradas MFT de archivos y directorios; de hecho, muchas entradas MFT tendrán más de un atributo $FILE_NAME. Al igual que el atributo $STANDARD_INFORMATION, este atributo es siempre residente y también contiene cuatro valores de tiempo; sin embargo, estos valores de tiempo se suelen establecer cuando se crea el archivo en el sistema. A diferencia de los tiempos de los archivos en el atributo $STANDARD_INFORMATION, estos tiempos de los archivos no se ven afectados por la actividad normal del sistema o la manipulación maliciosa y, por lo tanto, pueden utilizarse para determinar indicadores de actividad nefasta, y se pueden tomar medidas para ofuscar el momento en que un sistema fue infectado. El siguiente ejemplo de código (función parseSIAttr()) proporciona un ejemplo de cómo se puede analizar el atributo $STANDARD_INFORMATION:
sub parseSIAttr {
my $si = shift;
my %si;
my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)
= unpack(«VVCCvvVv»,substr($si,0,22));
my $content = substr($si,$ofs_content,$sz_content);
my ($t0,$t1) = unpack(«VV»,substr($content,0,8));
$si{c_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(«VV»,substr($content,8,8));
$si{m_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(«VV»,substr($content,16,8));
$si{mft_m_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(«VV»,substr($content,24,8));
$si{a_time} = getTime($t0,$t1);
$si{flags} = unpack(«V»,substr($content,32,4));
return %si;
}
Consejo
GetTime
La función getTime() que se ve dentro del listado de código para el atributo parseSIAttr() que se acaba de dar consiste en un código prestado por Andreas Schuster que traduce las marcas de tiempo del objeto FILETIME de 64 bits a una hora Unix de 32 bits que puede ser traducida a su vez a una hora legible para el ser humano mediante la función gmtime() incorporada en Perl. Ese código aparece como sigue:
sub getTime($$) {
my $lo = shift;
my $hi = shift;
my $t;
if ($lo == 0 && $hi == 0) {
$t = 0;
} else {
$lo -= 0xd53e8000;
$hi -= 0x019db1de;
$t = int($hi*429.4967296 + $lo/1e7);
};
$t = 0 if ($t < 0);
return $t;
}
Este código es muy útil para analizar y traducir cualquier objeto FILETIME, independientemente de dónde se extraiga.
En un sistema normal, muchas entradas MFT pueden tener dos atributos $FILE_NAME: uno para mantener el nombre completo del archivo (o directorio) y otro para mantener el nombre de archivo DOS, 8.3. Por ejemplo, si un archivo se llama «miarchivoalargo.txt», el nombre de archivo 8.3 aparecerá como «mireal~1.txt». Esto se mantiene por compatibilidad con los sistemas de archivos más antiguos y los que no admiten nombres de archivo largos. Así que no es inusual en un sistema Windows normal tener un número de entradas MFT con dos atributos $FILE_NAME con contenidos casi idénticos. El siguiente ejemplo de código (función parseFNAttr()) proporciona un ejemplo de cómo se puede analizar un atributo $FILE_NAME de una entrada MFT y extraer los datos disponibles:
sub parseFNAttr {
my $fn = shift;
my %fn;
my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)
= unpack(«VVCCvvVv»,substr($fn,0,22));
my $content = substr($fn,$ofs_content,$sz_content);
$fn{parent_ref} = unpack(«V»,substr($content,0,4));
$fn{parent_seq} = unpack(«v»,substr($content,6,2));
my ($t0,$t1) = unpack(«VV»,substr($content,8,8));
$fn{c_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(«VV»,substr($content,16,8));
$fn{m_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(«VV»,substr($content,24,8));
$fn{mft_m_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(«VV»,substr($content,32,8));
$fn{a_time} = getTime($t0,$t1);
$fn{flags} = unpack(«V»,substr($content,56,4));
$fn{len_name} = unpack(«C»,substr($content,64,1));
$fn{nombre} = unpack(«C»,substr($content,65,1));
$fn{len_name} = $fn{len_name} * 2 if ($fn{namespace} > 0);
$fn{name} = substr($content,66,$fn{len_name});
$fn{name} = cleanStr($fn{name}) if ($fn{namespace} > 0);
$fn{nombre} =~ s/\x0c/\x2e/g;
$fn{nombre} =~ s///g;
return %fn;
}
El último atributo del que hablamos es el atributo $DATA (identificador 0x80, o 128). Este atributo contiene o hace referencia al contenido real del archivo. Si el indicador de no residente de la cabecera del atributo no está activado, el contenido del archivo reside en el atributo $DATA de la entrada MFT, tras la cabecera y dos estructuras adicionales. Esto es generalmente cierto para archivos de texto cortos, por ejemplo, u otros archivos de menos de 700 bytes. Si los datos no son residentes, entonces los «recorridos de datos», o donde los datos se encuentran en el disco, necesitan ser traducidos.
El código de ejemplo para analizar los recorridos de datos del atributo $DATA es muy complicado y no se presenta aquí. Del mismo modo, el código para extraer información de los atributos $DATA residentes es trivial y consiste en analizar alguna información adicional (tamaño del contenido y desplazamiento hasta el contenido) después de la cabecera del atributo.
Existen algunas herramientas de código abierto para analizar la MFT (concretamente, los atributos $STANDARD_INFORMATION y $FILE_NAME) y poner a disposición del analista los datos con marca de tiempo. Uno de ellos es el script Python analyzemft.py de David Kovar, que se encuentra en la web en http://www.integriography.com/projects/analyzeMFT. Otro es el script Perl mft.pl, del que se extrajeron las funciones parseSIAttr() y parseFNAttr(), que está disponible en el WinForensicAnalysis Google Code projected, ubicado en la Web en http://code.google.com/p/winforensicaanalysis.
Las herramientas «The SleuthKit» (TSK) de Brian Carrier son probablemente las más conocidas para recopilar una amplia gama de información sobre el sistema de archivos y los metadatos del sistema de archivos de las imágenes adquiridas e incluso de los sistemas vivos. Por ejemplo, para recopilar un listado de tiempos de archivo del atributo $STANDARD_INFORMATION de una imagen adquirida, un analista puede utilizar un comando similar al siguiente:
C:\tsk>fls -f ntfs -m C:/ -p -r G:\case\xp.img > G:\case\files\bodyfile.txt
Este comando produce lo que se conoce como «bodyfile», que es un formato de archivo intermedio utilizado para almacenar esta información antes de convertirla en una línea de tiempo de la actividad del sistema de archivos. En algunos casos, el analista puede necesitar añadir el modificador «-o» para identificar el desplazamiento a la partición que apareció en el sistema en vivo como la unidad «C:\»; esta información de desplazamiento se puede determinar manualmente a través de un editor hexadecimal o utilizando mmls.exe.
Un analista también puede recopilar esta misma información de un sistema en vivo y remoto utilizando F-Response. Si el analista se ha conectado correctamente al sistema remoto y ha montado la unidad C:\ como F:\ en su propio sistema, puede utilizar un comando similar al siguiente para recopilar los tiempos de archivo del atributo $STANDARD_INFORMATION para los archivos de la partición C:\:
C:\tsk>fls -f ntfs -m C:/ -p -r \\.\F: > g:\case\files\bodyfile.txt
El conjunto completo de herramientas TSK, junto con la documentación e información de uso, se puede encontrar en la web en el sitio web de SleuthKit, http://www.sleuthkit.org.