Un byte marca la diferencia: MFT Resident File

Hola, secuaces:

¿Estáis listos para un buen café? ¡Vamos allá!

Hace poco tiempo he retomado un trabajo pendiente. Un trabajo, de muchos, que he ido 'abandonando' por el camino. Concretamente, este trabajo trata sobre la eliminación de un cierto tipo de ficheros para, posteriormente, extraer el contenido de los mismos sin necesidad de recuperar esos ficheros.

Por el camino con este proyecto me he encontrado con dudas, inquietudes y algunas lagunas en la comprensión del cómo y del porqué de las cosas. Lagunas que he sentido la necesidad de cubrir con la curiosidad, la necesidad de saber cómo y porqué funcionan las cosas. Lagunas que he aclarado con esta investigación.

Uno de esos vacíos con los que me he topado tiene relación con una característica de la MFT: 'Fichero residente'.

Me he encontrado con muchos Blogs y artículos que mencionan esta característica de los sistemas de ficheros NTFS, afirmando que se trata de ficheros con un tamaño 'X', (cada publicación varía la cifra de esa 'X'), y con algunos artículos que afirman que los distintos atributos se encuentran siempre en una posición determinada, (cuando este hecho varía según se dé una cierta condición), todo ello sin una prueba fehaciente de ello. No he visto demasiado material documentado sobre ello. Me ha llamado mucho la atención este hecho, dada la importancia que tiene esta característica en este campo de DFIR. Dada la alta importancia, y valor, que tiene el análisis de la MFT en cualquier caso.

Por ello he creído oportuno, e interesante, publicar este material de investigación, dada la carencia documental que existe al respecto, y he decidido realizar mis propias pruebas. 
En este campo de DFIR, todo tiene una explicación. Sólo hay que buscarla. 
Si bien es cierto que esa explicación puede ser muy compleja de encontrar, recuerda que nos movemos entre '0' y '1', (en el caso que nos ocupa, entre bytes y valores hexadecimales).

Estoy de condiciones de arrojar un poco más de luz sobre este atributo de los ficheros residentes en la MFT. Por el camino, en la búsqueda de la información que necesitaba, acudí al Blog de Harlan Carvey, (http://windowsir.blogspot.com), que ha mencionado esta característica en varias ocasiones, en varios de sus artículos. Concretamente, uno de esos artículos de Harlan, publicado el 13 de noviembre de 2013, me llevó a otro artículo, escrito por Hal Pomeranz, bajo el título de "Resident $DATA Residue in NTFS MFT Entries". Y este ha sido mi punto de partida.
Considero interesante leer todo lo que caiga en nuestras manos y prestar atención a las referencias utilizadas porque, en muchas ocasiones, la información que buscamos puede encontrarse en esas referencias que se utilizan.
Recuerdo haber comentado algo, muy de pasada, sobre la MFT en el artículo que escribí en 'Follow the White Rabbit', con el título "¿Qué ha pasado? El ABC del MACB". Al igual que entonces, no voy a desgranar toda la estructura de la MFT y cómo se graban los ficheros en ella. Al final de este artículo te mencionaré algunos enlaces interesantes sobre este tema, por si deseas profundizar más en él.

Introducción


Antes de comenzar... creo conveniente explicar un mínimo sobre el cómo se graban los ficheros en la MFT. Vuelvo a decir que no voy a explicar todos y cada uno de los atributos que podemos encontrar en la MFT porque, para ello, necesitaría de varios extensos artículos. Así, que únicamente mencionaré aquellos que considero de interés para este caso que nos ocupa: Los ficheros residentes y los ficheros no residentes.
Todo en el sistema de ficheros NTFS es un fichero y todo lo que es un fichero se graba en la MFT.
¿Cuándo es un fichero residente? Un fichero es residente cuando toda su información, los datos íntegros del fichero, están alojados únicamente en la MFT. Es decir, que un fichero residente no ocupa espacio en disco, (obviando el propio que usa la MFT para grabar ese registro).

El tamaño asignado en la MFT para cada registro de archivo es de 1024 bytes. Esto quiere decir que si un sector tiene un tamaño de 512 bytes, el registro de un fichero en la MFT ocupará dos sectores. Es indiferente el tamaño de clúster que se le asigne al sistema o al dispositivo de que se trate. No guarda relación. Se trate de un clúster de 512 bytes, o de un clúster de 4096 bytes, la MFT asignará para cada registro 1024 bytes, (dos sectores).

Cosa distinta es si el fichero no es residente en la MFT porque, en ese caso, (donde el fichero sí ocupa un espacio en disco), la información de ese fichero ocupará el espacio asignado al clúster correspondiente. Es decir, si existe un fichero con un tamaño de, por ejemplo, 2000 bytes y el tamaño asignado al clúster es de 512 bytes, entonces ocupará ese clúster, (o clústeres), asignado, (2048 bytes, 4 sectores), mientras que si el tamaño asignado al clúster es de 4096 bytes, entonces ocupará ese clúster asignado, (4096 bytes, 8 sectores).

Tienes a tu disposición toda la explicación relativa a este tema en el sitio oficial de Microsoft.


Los registros grabados en la MFT se representan en valores hexadecimales y cada valor hexadecimal, (cada desplazamiento), representa un byte.

Teniendo en cuenta todo lo anterior, cada registro contendrá un total de 1024 bytes o, lo que es lo mismo, 1024 valores hexadecimales, (aunque no tiene porqué estar todo el espacio ocupado, ni tienen porqué existir en ese registro todos los atributos). Es decir, que, aunque se asigne ese espacio a un registro, un registro grabado en la MFT no tiene porqué abarcar los 1024 bytes, aunque te mostraré ejemplos de ello.

El desplazamiento en bytes comienza desde el byte '0', como primer byte.

Un registro grabado en la MFT presenta una lista de atributos, conforme a lista que puedes consultar en el sitio oficial de Microsoft.

Ten en cuenta que, ni todos los atributos tienen porqué estar presentes en un registro, ni los registros tienen porqué presentar los mismos atributos.

Cada registro comienza con el valor '46494C45', (FILE), que tiene una longitud de 4 bytes. Esta es la cabecera para cada registro alojado en la MFT. Es decir, que el comienzo de cada registro ocupa los cuatro primeros bytes. (Bytes de '0 a 3').

Hasta el byte 151, (donde termina el atributo '$10'), todos los registros presentan el mismo tipo de atributos, (por supuesto, con distintos valores). Las diferencias, en lo relativo a los atributos, comienzan en el byte 152.

La información que nos va a indicar si un fichero es residente o no es residente se encuentra dentro del atributo '$DATA', que comienza con el valor '80000000', cuya ubicación varía, según los casos. Concretamente, se encuentra en el quinto byte, contado desde el final de la cabecera de este atributo. Si se trata de un fichero residente presentará un valor de '00', mientras que si se trata de un fichero no residente presentará un valor de '01'.

La MFT presenta al final de cada registro el valor 'FFFFFFFF', (ÿÿÿÿ), con una longitud de 4 bytes.

Después de esos últimos cuatro bytes que indican el final del registro de archivo, existen otros cuatro bytes.

Las cabeceras de cada uno de los atributos tiene una longitud de 4 bytes.

Mi intención era explicar la situación que se tiene que dar para que un fichero sea residente, o no. Pero en mi investigación me he encontrado con hasta seis situaciones distintas, seis condiciones. Por ello, voy a exponer en primer lugar las pruebas. (Confieso que a partir de este punto me ha dolido la cabeza por pensar en cómo estructurar el contenido). 

Las pruebas


¿Por dónde comenzar las pruebas? Pues, la primera de ellas, por la creación de unos pocos de cientos de ficheros, siendo cada fichero creado de un byte más que el anterior y con nombres correlativos. Para ello, escribí un pequeño fichero batch, teniendo en cuenta que cada carácter alfanumérico representa un byte. Podría haber realizado esta operación con fsutil, asignando directamente el tamaño deseado, pero luego no podría editar esos ficheros generados, cosa que es necesaria para observar el comportamiento de un fichero residente.



El resultado de la ejecución de este pequeño fichero batch...


¡Oh, Dios mío!!Dónde me he metido! 😱😱😱😱😱😱😱😱😱😭 ¡Quiero llorar!

Es hora de tomar mucho café, (grandes dosis de café), hacer mucho trabajo manual y tener mucha paciencia, porque toca comprobar cada uno de los ficheros.

Tras realizar esta primera prueba que he mencionado anteriormente y después de invertir muchas horas para estudiar la situación de todos esos ficheros, he llegado a una conclusión.

¿Quieres saber cuándo un fichero es residente y cuándo no lo es?¿Estás listo para saber el tamaño exacto para que un fichero sea residente, o no lo sea? Pues la respuesta es... Depende 🤪🤪🤪

Depende de si se generan de forma automática o si son creados con un editor 'X'. Depende de si se le asigna un nombre corto o un nombre largo al fichero. Depende de si se encuentra deshabilitada la creación de nombres de archivo 8.3. Depende de varios factores.

Me explico. Lo explico. Porque unas pruebas me han llevado a otras, que me han llevado a otras, que me han llevado a otras, ...


Entorno de pruebas


Las pruebas que he llevado a cabo han sido efectuadas en los siguientes sistemas y dispositivos:
  • Windows 7, (versión 6.1.7601)
  • Windows 7, (versión 6.1.7600)
  • Windows 10, (versión 10.0.17763.404)
  • Windows 10, (versión 10.0.18343.1)
  • Windows 10, (versión versión 10.0.18890.1000)
  • Dispositivo SanDisk Cruzer Blade 32GB, (con formato en NTFS)
Las herramientas que he elegido para determinar si un fichero es residente en la MFT, o no, y para estudiar ese tipo de ficheros, han sido:
He optado por elegir estas herramientas para contrastar datos, para validar resultados entre una y otra, y así evitar errores en la interpretación de los mismos. Considero que Active Disk Editor es una opción muy cómoda para realizar este estudio.

Las pruebas


Fichero residente de 592 bytes; Fichero no residente de 593 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

Esta es la primera prueba que he llevado a cabo, mediante la ejecución de ese fichero batch que he mencionado anteriormente. Ten en cuenta que estos ficheros han sido generados de forma automática, sin pasar por un editor de texto, y asignando un nombre de archivo largo. De todos los ficheros que han sido creados, me he quedado con dos de ellos.


Un fichero con un tamaño de 592 bytes y un fichero con un tamaño de 593 bytes.
El fichero de 592 bytes es un fichero residente en la MFT mientras que el fichero de 593 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 592 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 593 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 593 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 592 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Dos atributos '$30', ($FILE_NAME):
    • El primer atributo '$30', que se corresponde al nombre de archivo corto, comienza en el byte 152 y tiene una longitud de 120 bytes, (hasta el byte 271).
    • El segundo atributo '$30', que se corresponde al nombre de archivo largo, comienza en el byte 272 y tiene una longitud de 128 bytes, (hasta el byte 399).
  3. Un atributo '$80', ($DATA), que comienza en el byte 400 y tiene una longitud de 616 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 408, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 424 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  4. El final del registro del fichero se encuentra en el byte 1016.
  5. Los últimos cuatro bytes del registro presentan el valor '82790200'.

Fichero no residente de 593 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 414.

El atributo '$DATA', que comienza en el byte 400, presenta una longitud de 72 bytes, (hasta el byte 471).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 408), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 465, y el clúster que tiene asignado, que se trata del clúster 3.156.345, en el byte 466.

El final del registro se encuentra en el byte 472.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Si yo no fuera concienzudo y meticuloso, habría dejado aquí el asunto, porque ya tengo una respuesta. Pero me gusta verificar las pruebas que hago porque me gusta hablar sobre seguro, (dentro de lo posible). Así que he seguido ejecutando otro tipo de pruebas. Y he tomado estos ficheros como referencia para las restantes pruebas.

La siguiente prueba que he llevado a cabo ha sido sobre el dispositivo USB. Y es a partir de aquí donde he puesto en marcha mi cerebro a todo lo que da de sí. ¿Por qué? Porque cuando creé esos dos ficheros en ese dispositivo me llevé la sorpresa de que los dos ficheros eran ficheros residentes.

¿Qué he hecho mal?¿Qué ha fallado?¿En qué me he equivocado? En nada. Me he vuelto loco, literalmente, buscando una explicación, mirando todo tipo de configuraciones y estudiando un montón de opciones, hasta que he dado con la clave, (y nunca mejor dicho).

Fichero residente de 712 bytes; Fichero no residente de 713 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

Resulta que el dispositivo USB que he utilizado para efectuar esta otra prueba fue formateado en otro sistema distinto a los que suelo utilizar. Y resulta que ese sistema en cuestión presentaba una modificación que no suelo usar.

¿La respuesta? En la modificación de un valor que se encuentra en la clave de la colmena del Registro:
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation'.

Windows permite habilitar o deshabilitar la creación de nombres de archivo cortos, tanto en el propio volumen del sistema, como en volúmenes externos. Y resulta que la configuración se guarda en el dispositivo. Es decir, que si formateas un dispositivo USB en un sistema que presenta una determinada configuración, esa configuración se aplica a ese dispositivo, para siempre, hasta un nuevo formateo.

Esta configuración, además, no se aplica con carácter retroactivo. Es decir, que los ficheros del sistema que se encuentren grabados en su correspondiente MFT mantendrán toda esa información grabada y no se aplicarán los cambios hasta que no se reinicie el sistema, únicamente para los nuevos registros.

'Descubierto' esto, he procedido a ejecutar, de nuevo, ese fichero batch para crear otros cientos de ficheros dentro de ese dispositivo USB, (y de otro sistema que he modificado para este trabajo). Ten en cuenta que estos ficheros han sido generados de forma automática, sin pasar por un editor de texto, y asignando un nombre de archivo largo. De todos los ficheros que han sido creados, me he quedado con dos de ellos.

Un fichero con un tamaño de 712 bytes y un fichero con un tamaño de 713 bytes.
El fichero de 712 bytes es un fichero residente en la MFT mientras que el fichero de 713 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 712 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 713 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 713 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 712 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Un atributo '$30', ($FILE_NAME), que comienza en el byte 152 y tiene una longitud de 128 bytes, (hasta el byte 279), por lo que se corresponde al de nombre de archivo largo.
  3. Un atributo '$80', ($DATA), que comienza en el byte 280 y tiene una longitud de 736 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 288, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 304 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  4. El final del registro del fichero se encuentra en el byte 1016.
  5. Los últimos cuatro bytes del registro presentan el valor '82790200'.

Fichero no residente de 713 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 294.

El atributo '$DATA', que comienza en el byte 280, presenta una longitud de 72 bytes, (hasta el byte 351).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 288), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 345, y el clúster que tiene asignado, que se trata del clúster 3.150.984, en el byte 346.

El final del registro se encuentra en el byte 352.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Vista esta segunda prueba que he efectuado, la primera conclusión que saco de todo esto es que, cuando un atributo no está presente, en el registro de un fichero, el espacio que debiera ocupar ese atributo ausente es asignado al atributo '$DATA'

¿Cómo he llegado a ese punto? En la prueba efectuada con el fichero residente de 592 bytes, la longitud del atributo '$DATA' es de 616 bytes, mientras que en esta prueba con el fichero residente de 712 bytes, la longitud del atributo '$DATA' es de 736. Así que si restamos '736 - 616' obtenemos un resultado de 120 bytes, que es, casualmente, la longitud del atributo ausente '$30', correspondiente al nombre de archivo corto.

Nuevamente, podría haber dejado esto aquí, porque ya tengo otra respuesta con una cierta lógica. Pero visto esto... me ha dado por pensar un poco más. Por ir un poco más allá. Así que cogí un papel y un lápiz y empecé a tomar notas para ver cómo y en qué condiciones puedo crear ficheros.

Fichero residente de 552 bytes; Fichero no residente de 553 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

Así, he efectuado otra prueba. En esta ocasión he creado unos cuantos ficheros de texto, (muchos), manualmente, con distintos tamaños, asignando, como en los casos anteriores, un nombre de archivo largo, pero la creación ha sido mediante la edición en el bloc de notas de Windows. De todos los ficheros que he creado, me he quedado con dos de ellos.

Un fichero con un tamaño de 552 bytes y un fichero con un tamaño de 553 bytes.
El fichero de 552 bytes es un fichero residente en la MFT mientras que el fichero de 553 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 552 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 553 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 553 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 552 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Dos atributos '$30', ($FILE_NAME):
    • El primer atributo '$30', que se corresponde al nombre de archivo cortocomienza en el byte 152 y tiene una longitud de 120 bytes, (hasta el byte 271).
    • El segundo atributo '$30', que se corresponde al nombre de archivo largocomienza en el byte 272 y tiene una longitud de 128 bytes, (hasta el byte 399).
  3. Un atributo '$40', ($OBJECT_ID), que comienza en el byte 400 y tiene una longitud de 40 bytes, (hasta el byte 439).
  4. Un atributo '$80', ($DATA), que comienza en el byte 440 y tiene una longitud de 676 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 448, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 464 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  5. El final del registro del fichero se encuentra en el byte 1016.
  6. Los últimos cuatro bytes del registro presentan el valor '82790F00'.

Fichero no residente de 553 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 454.

El atributo '$DATA', que comienza en el byte 440, presenta una longitud de 72 bytes, (hasta el byte 411).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 448), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 505, y el clúster que tiene asignado, que se trata del clúster 3.149.052, en el byte 506.

El final del registro se encuentra en el byte 512.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Ha aparecido un nuevo atributo en el campo de juego. Se trata del atributo '$40', que pertenece al '$OBJECT_ID'. Un detalle 'curioso' que aparezca este atributo sólo con la edición del fichero. ¿Por qué no se ha manifestado antes?

Con esta prueba estoy en condiciones de afirmar, sin miedo a equivocarme, que el espacio que debiera ocupar un atributo que se encuentra ausente es asignado al atributo '$DATA'.

Sigo con mis pruebas... Con las opciones que se me ocurren... Y...

Fichero residente de 672 bytes; Fichero no residente de 673 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

Vuelvo a modificar el valor de la clave del Registro:
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation', 
para evitar la creación de los nombres de archivo cortos en los registros de los ficheros en la MFT y creo los mismos ficheros que antes, asignando un nombre de archivo largo y manualmente, mediante el bloc de notas.

Ahora tan sólo creo dos ficheros, porque ya sé cómo jugar a esto.

Si partimos del primero de los ejemplos, como fichero de referencia, donde el fichero de 592 bytes era un fichero residente, que ha sido creado de forma automática y sin deshabilitar la generación de nombres de archivo cortos...

592 bytes del fichero, sumado a los 120 bytes que ocuparía el atributo '$30', (correspondiente al nombre de archivo corto), y restado de 40 bytes, que va a ocupar el atributo '$40'... tenemos un resultado de 672 bytes. Es decir, que si genero dos ficheros de texto, de 672 bytes y de 673 bytes, manualmente, con el bloc de notas, y se encuentra inhabilitada la generación de nombres cortos en el registro de la MFT, el primero de esos ficheros debe ser residente, pero el segundo no debe ser residente.

Así que me quedo con un fichero con un tamaño de 672 bytes y un fichero con un tamaño de 673 bytes.
El fichero de 672 bytes es un fichero residente en la MFT mientras que el fichero de 673 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 672 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 673 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 673 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 672 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Un atributo '$30', ($FILE_NAME), que comienza en el byte 152 y tiene una longitud de 128 bytes, (hasta el byte 279), por lo que se corresponde al de nombre de archivo largo.
  3. Un atributo '$40', ($OBJECT_ID), que comienza en el byte 280 y tiene una longitud de 40 bytes, (hasta el byte 319).
  4. Un atributo '$80', ($DATA), que comienza en el byte 320 y tiene una longitud de 696 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 328, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 344 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  5. El final del registro del fichero se encuentra en el byte 1016.
  6. Los últimos cuatro bytes del registro presentan el valor '82790200'.

Fichero no residente de 673 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 334.

El atributo '$DATA', que comienza en el byte 320, presenta una longitud de 72 bytes, (hasta el byte 391).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 328), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 385, y el clúster que tiene asignado, que se trata del clúster 3.156.283, en el byte 386.

El final del registro se encuentra en el byte 392.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Mmmmm. Me resulta muy curioso cómo funciona la grabación de los ficheros en la MFT. Se me ocurren algunas cosas más para probar...

Fichero residente de 680 bytes; Fichero no residente de 681 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

En esta ocasión, he creado dos nuevos ficheros, con dos tamaños distintos, manualmente, mediante el bloc de notas, pero esta vez asignando un nombre de archivo corto. Concretamente, un nombre de 8 caracteres.

Si volvemos a partir del primero de los ejemplos, como fichero de referencia, donde el fichero de 592 bytes era un fichero residente, que ha sido creado de forma automática y sin deshabilitar la generación de nombres de archivo cortos... y teniendo en cuenta que el atributo '$30', correspondiente al nombre de archivo corto, ocupa 120 bytes, mientras que el atributo '$30', correspondiente al nombre de archivo largo, ocupa 128 bytes, ...

592 bytes del fichero, sumado a los 128 bytes que ocuparía el atributo '$30', (correspondiente al nombre de archivo largo), y restado de 40 bytes, que va a ocupar el atributo '$40'... tenemos un resultado de 680 bytes. Es decir, que si genero dos ficheros de texto, de 680 bytes y de 681 bytesmanualmentecon el bloc de notas, y le asigno un nombre corto de archivo, en el registro de la MFT, el primero de esos ficheros debe ser residente, pero el segundo no debe ser residente.

Así que me quedo con un fichero con un tamaño de 680 bytes y un fichero con un tamaño de 681 bytes.
El fichero de 680 bytes es un fichero residente en la MFT mientras que el fichero de 681 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 680 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 681 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 681 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 680 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Un atributo '$30', ($FILE_NAME), que comienza en el byte 152 y tiene una longitud de 120 bytes, (hasta el byte 271), por lo que se corresponde al de nombre de archivo corto.
  3. Un atributo '$40', ($OBJECT_ID), que comienza en el byte 280 y tiene una longitud de 40 bytes, (hasta el byte 311).
  4. Un atributo '$80', ($DATA), que comienza en el byte 312 y tiene una longitud de 704 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 320, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 336 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  5. El final del registro del fichero se encuentra en el byte 1016.
  6. Los últimos cuatro bytes del registro presentan el valor '82799E00'.

Fichero no residente de 681 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 326.

El atributo '$DATA', que comienza en el byte 312, presenta una longitud de 72 bytes, (hasta el byte 383).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 320), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 377, y el clúster que tiene asignado, que se trata del clúster 3.148.935, en el byte 378.

El final del registro se encuentra en el byte 384.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Tal y como acabamos de comprobar, cuando asignamos un nombre de archivo corto a un fichero, únicamente se va a grabar en el registro correspondiente la información correspondiente al atributo '$30', de nombre de archivo corto. ¿Por qué? Porque el sistema no precisa de más información para completar la información de ese fichero. Por eso prescinde de los 128 bytes que le corresponden al atributo '$30', de nombre de archivo largo.

Ahora... Me pregunto si...

¿Qué ocurre en caso de que le asigne un nombre más corto, aún?

Fichero residente de 696 bytes; Fichero no residente de 697 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

En esta ocasión, he creado dos nuevo ficheros, con dos tamaños distintos, manualmentemediante el bloc de notas, pero esta vez asignando un nombre de archivo corto. Concretamente, un nombre de 1 sólo carácter alfanumérico.

Si volvemos a partir del primero de los ejemplos, como fichero de referencia, donde el fichero de 592 bytes era un fichero residente, que ha sido creado de forma automática y sin deshabilitar la generación de nombres de archivo cortos... y teniendo en cuenta que el atributo '$30', correspondiente al nombre de archivo corto, ocupa 120 bytes, mientras que el atributo '$30', correspondiente al nombre de archivo largo, ocupa 128 bytes, ...

592 bytes del fichero, sumado a los 128 bytes que ocuparía el atributo '$30', (correspondiente al nombre de archivo largo), y restado de 40 bytes, que va a ocupar el atributo '$40'... tenemos un resultado de 680 bytes. Es decir, que en este caso, si genero dos ficheros de texto, de 680 bytes y de 681 bytesmanualmentecon el bloc de notas, y le asigno un nombre corto de archivo, en el registro de la MFT, y teóricamente, el primero de esos ficheros debe ser residente, pero el segundo no debe ser residente.

Pero eso sería teóricamente. Porque el atributo '$30' tiene un tamaño máximo, pero también tiene un tamaño mínimo.

En este caso en particular, en el que sólo he usado un carácter alfanumérico para nombrar un fichero...

Me quedo con un fichero con un tamaño de 696 bytes y un fichero con un tamaño de 697 bytes. (16 bytes más que en el caso anterior).
El fichero de 696 bytes es un fichero residente en la MFT mientras que el fichero de 697 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 696 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 697 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 697 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 696 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Un atributo '$30', ($FILE_NAME), que comienza en el byte 152 y tiene una longitud de 104 bytes, (hasta el byte 255), por lo que se corresponde al de nombre de archivo corto.
  3. Un atributo '$40', ($OBJECT_ID), que comienza en el byte 256 y tiene una longitud de 40 bytes, (hasta el byte 295).
  4. Un atributo '$80', ($DATA), que comienza en el byte 296 y tiene una longitud de 720 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 304, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 320 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  5. El final del registro del fichero se encuentra en el byte 1016.
  6. Los últimos cuatro bytes del registro presentan el valor '82790400'.

Fichero no residente de 697 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 310.

El atributo '$DATA', que comienza en el byte 296, presenta una longitud de 72 bytes, (hasta el byte 367).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 304), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 361, y el clúster que tiene asignado, que se trata del clúster 3.148.938, en el byte 362.

El final del registro se encuentra en el byte 384.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Mmmmm... Muy curioso. Voy a tratar de explicarlo de manera sencilla.

Como decía un poco más arriba, el atributo '$30', correspondiente al nombre de archivo corto, tiene un tamaño máximo de 120 bytes, pero también tiene un tamaño mínimo que, en caso de no estar ocupado, el sistema llena de '00'. Para ver esta diferencia he creado otro fichero idéntico, pero he asignado un nombre de tres dígitos. Así que vamos a comparar tres nombres cortos de fichero: El fichero nombrado como 'File0680.txt', el fichero nombrado como 'A.txt' y el fichero nombrado como '696.txt'.


En la imagen anterior, tal y como puedes apreciar, (espero), se encuentra el atributo '$30', relativo al nombre de archivo corto. Dentro de este atributo se encuentra al final, resaltado, el nombre de archivo corto, que comienza en el byte 92 dentro de este atributo. El nombre de fichero es la última información que se graba en este atributo.

El fichero nombrado como 'File696.txt', que comienza en la misma posición, (byte 92 dentro del propio atributo), está compuesto por 12 caracteres unicode, que pasa a tener 24 caracteres ASCII, porque después de cada carácter se asigna el valor '00', (que corresponde a un '.'). Es decir, que el nombre de este fichero tiene una longitud de 24 bytes. Pero, si te fijas en la imagen, el sistema asigna seis valores hexadecimales más, con valores de '00'. Así que tenemos un total de 30 bytes.

El fichero nombrado como 'A.txt', siguiendo la misma estructura que el fichero anterior, se compone de 5 caracteres unicode, que pasa a tener 10 caracteres ASCII. Pero el sistema marca a '00' los cuatro últimos bytes. Es decir, que el nombre de este fichero tiene una longitud de 14 bytes.

Ocurre exactamente lo mismo con el fichero '696.txt', que se compone de 7 caracteres unicode, que pasa a tener 14 caracteres ASCII, pero en este caso el sistema no marca los últimos bytes a '00'. Así que este fichero tiene también una longitud de 14 bytes.

Así que, si se restan los 30 bytes del fichero nombrado como 'File696' a los 14 bytes de los ficheros nombrados como 'A.txt' y '696.txt', la diferencia es de 16 bytes. La diferencia de tamaño entre el caso anterior y este.

Según estas pruebas, el tamaño mínimo que se reserva para el nombre de archivo corto, dentro del atributo '$30', es de 14 bytes. ¿Por qué ocurre esto? Para verlo de manera gráfica he creado algunos ficheros, nombrados como 'A', 'AA', 'AAA', ... hasta un total de ocho.


La información del nombre de archivo comienza en el byte 92, dentro del propio atributo, que coincide con el tercer byte del primer octeto. El sistema no finaliza la información del atributo hasta que no completa un octeto. Así que el sistema, cuando el nombre de un fichero comienza un octeto, pero no lo termina, asigna valores a '00' hasta el final de ese octeto.

Así que, con la creación de ficheros manualmente y dependiendo de la longitud del nombre de archivo corto, la diferencia entre un fichero residente y otro no va a estar en un byte, si no en ocho bytes. Por ejemplo, mientras que un fichero nombrado como 'A.txt' es residente con un tamaño máximo de 696 bytes, un fichero nombrado como 'AAAA.txt' será residente con un tamaño máximo de 688 bytes.

Para terminar con las posibles formas de crear ficheros y ver sus respectivos tamaños para determinar así en qué momento pueden ser ficheros residentes...

Fichero residente de 728 bytes; Fichero no residente de 729 bytes


El fichero de la izquierda corresponde a un fichero residente. El fichero de la derecha corresponde a un fichero no residente.

Creo que me falta por mostrar qué ocurre con un fichero con un nombre corto asignado y con una creación automática. Para ello, usé el mismo fichero batch que en pruebas anteriores para crear un par de ficheros. Pero en esta ocasión se encuentra deshabilitada la generación de nombres de archivo corto, cambiando el valor de la clave del Registro que he mencionado antes.


Siguiendo con la misma dinámica que en el ejemplo anterior, un fichero nombrado como 'A.txt', podrá ser residente con un tamaño máximo de 720 bytes, mientras que un fichero nombrado como 'File728.txt' podrá ser residente con un tamaño máximo de 728 bytes. Esto ocurre porque tenemos que sumar los 40 bytes correspondientes al atributo '$40' que no nos vamos a encontrar en ese registro.

Así que, para este ejemplo, me quedo con un fichero con un tamaño de 728 bytes y un fichero con un tamaño de 729 bytes.
El fichero de 728 bytes es un fichero residente en la MFT mientras que el fichero de 729 bytes no está residente en la MFT.

Tal y como puedes apreciar en la imagen anterior, el fichero con un tamaño de 728 bytes no ocupa espacio en disco, mientras que el fichero con un tamaño de 729 bytes sí ocupa espacio en disco. Concretamente, el fichero con un tamaño de 729 bytes, ocupa en disco 4096 bytes, que es el tamaño asignado al clúster, (8 sectores).

Fichero residente de 728 bytes


En este caso, encontramos los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Un atributo '$30', ($FILE_NAME), que comienza en el byte 152 y tiene una longitud de 112 bytes, (hasta el byte 263).
  3. Un atributo '$80', ($DATA), que comienza en el byte 264 y tiene una longitud de 752 bytes, (hasta el byte 1015).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 272, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '00', que indica que es residente.
    2. En el byte 2884 se encuentra el comienzo del contenido del fichero, (21 bytes después del final de la cabecera de este atributo).
  4. El final del registro del fichero se encuentra en el byte 1016.
  5. Los últimos cuatro bytes del registro presentan el valor '82790800'.

Fichero no residente de 729 bytes


En este caso nos encontramos con los mismos tipos de atributos que en el caso anterior, con alguna diferencia. Esta diferencia comienza a partir del byte 278.

El atributo '$DATA', que comienza en el byte 264, presenta una longitud de 72 bytes, (hasta el byte 351).

La información que nos indica si un fichero es residente, o no, se encuentra en el mismo byte que en el caso anterior, (byte 272), que presente un valor de '01' y que indica que se trata de un fichero no residente.

Como este fichero sí ocupa espacio en disco, tiene un clúster asignado. Y el registro muestra que el número de clústeres que usa ese fichero es uno, en el byte 329, y el clúster que tiene asignado, que se trata del clúster 3.187.319, en el byte 330.

El final del registro se encuentra en el byte 336.

Los últimos cuatro bytes del registro presentan el valor '82794711'.


Estas son las pruebas que se me han ocurrido llevar a cabo, en cuanto a la creación de ficheros, asignando distintas longitudes de nombres, generándolos de manera distinta y con habilitación y deshabilitación de nombre de archivo corto.

Otra vez, podría haber dejado aquí este asunto, pero necesito saber cómo se comporta un fichero residente, cuando es editado, cuando es modificado.

Comportamiento de un fichero residente


Para llevar a cabo esta prueba he optado por tomar el fichero que usado como referencia para todas las demás, el fichero nombrado como '00Fichero592.txt', y editarlo, añadiendo en él la palabra 'Marcos'. Así, que el fichero pasa de tener un tamaño de 592 bytes, a tener un tamaño de 598 bytes. Por lo que deja de ser un fichero residente.

Tras su edición en Windows 7, el fichero pasa a tener los siguientes atributos::
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Dos atributos '$30', ($FILE_NAME):
    • El primer atributo '$30', que se corresponde al nombre de archivo cortocomienza en el byte 152 y tiene una longitud de 120 bytes, (hasta el byte 271).
    • El segundo atributo '$30', que se corresponde al nombre de archivo largocomienza en el byte 272 y tiene una longitud de 128 bytes, (hasta el byte 399).
  3. Un atributo '$40', ($OBJECT_ID), que comienza en el byte 400 y tiene una longitud de 40 bytes, (hasta el byte 439).
  4. Un atributo '$80', ($DATA), que comienza en el byte 440 y tiene una longitud de 72 bytes, (hasta el byte 511).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 448, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '01', que indica que es un fichero no residente.
    2. El número de clústeres que usa el fichero se encuentra en el byte 505.
    3. El clúster que tiene asignado el fichero se encuentra en el byte 506
  5. El final del registro del fichero se encuentra en el byte 512.
  6. Los últimos cuatro bytes del registro presentan el valor '82794711'.
La sorpresa viene después del supuesto final del registro del fichero, porque el contenido que existía antes en ese registro se puede encontrar de igual manera cuando el fichero deja de ser un fichero residente. 


Además de encontrarse parte de la información del fichero en ese registro, también se encuentra en el clúster asignado, correspondiendo a este caso al clúster 32.664.


Vuelvo a editar ese mismo fichero, eliminando la palabra añadida 'Marcos', para que vuelva a su tamaño original de 592 bytes. El resultado es que ese fichero no vuelve a ser un fichero residente, aunque su contenido se muestra en ese registro.


Y la información, actualizada, también se muestra en el mismo clúster que tenía asignado cuando ha dejado de ser un fichero residente.


Es decir, que en un sistema Windows 7, cuando se modifica un fichero residente para que deje de serlo, la información se grabará a un nuevo clúster, pero también mantendrá parte de esa información en el propio registro del fichero, manteniendo siempre ese clúster asignado.

Realizo la misma operación sobre Windows 10, y tras su edición, con un tamaño de 598 bytes, el fichero pasa a tener los siguientes atributos:
  1. Un atributo '$10', ($TANDARD_INFORMATION), que comienza en el byte 56 y tiene una longitud de 96 bytes, (hasta el byte 151).
  2. Dos atributos '$30', ($FILE_NAME):
    • El primer atributo '$30', que se corresponde al nombre de archivo cortocomienza en el byte 152 y tiene una longitud de 120 bytes, (hasta el byte 271).
    • El segundo atributo '$30', que se corresponde al nombre de archivo largocomienza en el byte 272 y tiene una longitud de 128 bytes, (hasta el byte 399).
  3. Un atributo '$40', ($OBJECT_ID), que comienza en el byte 400 y tiene una longitud de 40 bytes, (hasta el byte 439).
  4. Un atributo '$80', ($DATA), que comienza en el byte 440 y tiene una longitud de 72 bytes, (hasta el byte 511).
    1. La información que nos indica si es un fichero residente, o no, se encuentra en el byte 448, (el quinto byte desde que termina la cabecera de este atributo), y presenta un valor de '01', que indica que es un fichero no residente.
    2. El número de clústeres que usa el fichero se encuentra en el byte 505.
    3. El clúster que tiene asignado el fichero se encuentra en el byte 506
  5. El final del registro del fichero se encuentra en el byte 512.
  6. Los últimos cuatro bytes del registro presentan el valor '82794711'.

Después del final del registro del fichero, la información que se encontraba antes residente, deja de estarlo, porque pasa en su totalidad al clúster asignado en el momento que supera el tamaño máximo para un fichero residente.


Vuelvo a editar ese mismo fichero, eliminando la palabra añadida para que vuelva a tener el tamaño de 592 bytes, y presenta exactamente la misma información, a excepción de un nuevo clúster donde se almacena la información del fichero. Si en el ejemplo anterior el sistema asignaba a ese fichero que había dejado de ser residente el clúster 3.264.719, ahora le ha asignado el clúster 50.179, siguiendo sin ser un fichero residente, a pesar de tener el tamaño adecuado para serlo.


Es decir, que con cada edición de un fichero residente, en un sistema Windows 10, un clúster nuevo va a ser asignado a la información de ese fichero. Y esa información permanecerá ahí hasta que se sobreescriba por otro registro, en caso de encontrarse sin asignar ese clúster.

Ya vamos terminando con este pequeño trabajo...

Conclusiones


¿Existe un tamaño único para que un fichero sea residente en la MFT o no lo sea? No. No existe un tamaño único para que se dé esa condición, porque depende de varios factores.

El espacio que no es usado por atributos que no están presente en el registro del archivo se asigna al atributo '$DATA'. Así que, por ejemplo, si tenemos un registro sin un atributo '$40', que tiene una longitud de 40 bytes, esos 40 bytes son asignados al atributo '$DATA', por lo que el fichero tiene 40 bytes más para que pueda ser un fichero residente.

El primer factor que influye en el tamaño para que un fichero pueda ser residente, o no, es su forma de creación. Si se crea en el sistema o dispositivo un fichero, de forma automática, tendrá más espacio para que se pueda tratar de un fichero residente que si creamos el fichero mediante una edición en el sistema.

Si el sistema se encuentra configurado para que no se generen los nombres de archivo corto, (8.3), en el registro del fichero, ese fichero dispondrá de 120 bytes más, (que son asignados al atributo '$DATA'), para que se pueda tratar de un fichero residente en la MFT.

La deshabilitación o habilitación de nombres de archivo cortos, (8.3), no se aplican con carácter retroactivo. Es decir, que si en la MFT se encuentran grabados 'X' ficheros con 'X' atributos, el sistema mantendrá esa información hasta el reinicio oportuno y aplicará los cambios, únicamente a los nuevos registros.

Si se formatea en NTFS un dispositivo externo, (o cualquier otro volumen), ese dispositivo guardará la misma configuración que ese sistema, hasta un nuevo formateo.

En todas mis pruebas, al final del registro de un archivo no residente en la MFT, después del valor 'FFFFFFFF', he obtenido el mismo valor '82794711', variando los dos últimos valores en caso de tratarse de ficheros residentes.

En el caso de que se asigne un nombre corto a un fichero, (hasta 8 caracteres), el tamaño máximo para que un fichero sea residente, o no, dependerá de los octetos que ocupe la longitud del nombre, porque el sistema, cuando tiene un nombre que comienza un octeto pero no lo termina, lo graba a '00' hasta el final de ese octeto. Un fichero nombrado con un sólo carácter será residente con el mismo tamaño que un fichero nombrado con tres caracteres, por esa razón.

Sé que, seguramente, no habrás leído todo el contenido del texto y sé que te gustan las tablas para una mejor comprensión. Así que te dejo una pequeña tabla con los datos que he obtenido en mis pruebas.

En la tabla,
  • Entiéndase por creación automática, todo fichero creado que no ha sido editado directamente por el usuario.
  • Entiéndase por nombre largo, todo fichero cuyo nombre se compone de más de 8 caracteres.
  • Entiéndase por edición, todo fichero que es creado por el propio usuario, haciendo uso de algún editor.
  • Entiéndase por nombre corto, todo fichero cuyo nombre se compone de 8 caracteres, o menos.
  • Entiéndase por 'Sin 8.3', todo fichero que ha sido creado, teniendo deshabilitada la característica de creación de nombre de archivo corto, desde el Registro.
Primeramente te muestro los resultados de mis pruebas, en los concerniente a los nombres de archivo largo, con el tamaño máximo para que se pueda tratar de un fichero residente y con el tamaño para que deje de tener esa condición.


Ahora te muestro otra tabla más, con los resultados obtenidos de la generación de nombres de archivo corto, puesto que depende de la longitud del nombre del fichero, éste podrá ser residente con un tamaño u otro. Igual que en la tabla anterior, te muestro el tamaño máximo para que un fichero pueda ser residente en la MFT y el tamaño para que deje de ser residente, con la longitud del nombre de archivo, puesto que depende de ello para que se dé una condición u otra.


Para terminar, te dejo a continuación unos enlaces de interés y referencias.

Enlaces de interés y referencias



Si deseas hacer tú mismo algunas pruebas, puedes:
  • Descargar de aquí el fichero para crear archivos de 592 bytes y de 593 bytes, con nombre largo de archivo.
  • Descargar de aquí el fichero para crear archivos de 712 bytes y de 713 bytes, con nombre largo de archivo, teniendo deshabilitada la generación de nombres de archivo corto, (8.3)
  • Descarga de aquí el fichero para crear archivos de 728 bytes y de 729 bytes, con nombre corto de archivo, (7 caracteres).
  • Hacer tus propias pruebas 😉😉



Espero que esta información le resulte útil a alguien. Eso es todo,

spacer

One byte makes the difference: MFT Resident File

Hi, minions:

Are you ready for some good coffee? Let's go!

A short time ago I took up a pending project. A project, of many, that I have been 'abandoning' along the way. Specifically, this project deals with the removal of a certain type of files and then extract the content of those same files, without the need to recover it.

Along the way with this project I have found doubts, worries and some gaps in the understanding of how and why of things. Gaps that I have felt the need to fill with curiosity, the need to know how and why things work. Gaps that I have clarified with this research.

One of those gaps I've come across has to do with a feature of the MFT: 'Resident File'.

I have come across many Blogs and articles that mention this characteristic of NTFS file systems, stating that they are files with a size of 'X' (each publication varies the figure of that 'X'), and with some articles that state that the different attributes are always in a certain position (when this fact varies according to a certain condition), all without reliable proof of it. I have not seen much documented material about it. I have been very struck by this fact, given the importance of this characteristic in this DFIR field. Given the high importance, and value, that has the analysis of the MFT in any case.

That is why I thought it would be appropriate and interesting to publish this research material, given the lack of documentation on the subject, and I have decided to carry out my own tests. 
In this DFIR field, everything has an explanation. Just look for it. 
Although it is true that this explanation can be very complex to find, remember that we move between '0' and '1', (in this case, between bytes and hexadecimal values).

I am in a position to shed a little more light on this attribute of the files resident in the MFT. Along the way, in search of the information I needed, I went to Harlan Carvey's Blog (http://windowsir.blogspot.com), which has mentioned this feature on several occasions, in several of his articles. Specifically, one of those Harlan articles, published on November 13, 2013, led me to another article, written by Hal Pomeranz, under the title "Resident $DATA Residue in NTFS MFT Entries". And this has been my starting point.
I consider it interesting to read everything that falls into our hands and to pay attention to the references used because, on many occasions, the information we are looking for can be found in those references used.
I remember commenting something in passing about MFT in the article I wrote in 'Follow the White Rabbit', entitled "What happened? The ABC of the MACB". Like then, I'm not going to disentangle the whole structure of the MFT and how the files are saved in it. At the end of this article I will mention some interesting links to you on this subject, if you want to delve deeper into it.

Introduction


Before we begin... I think it's convenient to explain a little bit about how files are saved in the MFT. I say again that I am not going to explain each and every one of the attributes that we can find in the MFT because, for it, it would need several extensive articles. So, I will only mention those that I consider of interest for this case: Resident files and non-resident files.
Everything in the NTFS file system is a file and everything that is a file is recorded in the MFT.
When is a resident file? A file is resident when all its information, the complete data of the file, is housed only in the MFT. That is to say, that a resident file does not occupy space in disk, (obviating the own one that uses the MFT to record that record).

The size assigned in the MFT for each file record is 1024 bytes. This means that if a sector has a size of 512 bytes, the record of a file in the MFT will occupy two sectors. The size of the cluster assigned to the system or device is irrelevant. It is not related. Whether it is a cluster of 512 bytes, or a cluster of 4096 bytes, the MFT will assign for each record 1024 bytes, (two sectors).

A different thing is if the file is not resident in the MFT because, in that case (where the file does occupy disk space), the information in that file will occupy the space assigned to the corresponding cluster. That is to say, if there is a file with a size of, for example, 2000 bytes and the size assigned to the cluster is 512 bytes, then it will occupy that cluster, (or clusters), assigned, (2048 bytes, 4 sectors), while if the size assigned to the cluster is 4096 bytes, then it will occupy that assigned cluster, (4096 bytes, 8 sectors).

The full explanation of this topic is available on Microsoft's official website.


The records recorded in the MFT are represented in hexadecimal values and each hexadecimal value, (each shift), represents one byte.

Taking into account all the above, each record will contain a total of 1024 bytes or, which is the same, 1024 hexadecimal values, (although not all the space has to be occupied, nor do all the attributes have to exist in that record). That is to say, that, although that space is assigned to a record, a record recorded in the MFT does not have to cover the 1024 bytes, although I will show you examples of it.

Scrolling in bytes starts from byte '0', as first byte.

A record recorded in the MFT presents a list of attributes, according to a list that you can consult on Microsoft's official site.

Note that not all attributes have to be present in a record, nor do records have to have the same attributes.

Each record starts with the value '46494C45', (FILE), which has a length of 4 bytes. This is the header for each record housed in the MFT. That is, the beginning of each record occupies the first four bytes. (Bytes from '0 to 3').

Up to byte 151, (where the attribute '$10' ends), all records have the same type of attributes, (of course, with different values). The differences, as far as attributes are concerned, start at byte 152.

The information that will indicate whether a file is resident or non-resident is found within the attribute '$DATA', which begins with the value '80000000', whose location varies, depending on the case. Specifically, it is in the fifth byte, counted from the end of the header of this attribute. If it is a resident file it will have a value of '00', while if it is a non-resident file it will have a value of '01'.

The MFT displays at the end of each record the value 'FFFFFFFF', (ÿÿÿÿ), with a length of 4 bytes.

After those last four bytes that indicate the end of the file record, there are another four bytes.

The headers of each attribute have a length of 4 bytes.

My intention was to explain the situation that has to be given for a file to be resident, or not. But in my research I have found up to six different situations, six conditions. (I confess that from this point on, my head has been aching to think about how to structure the content). 

The tests


Where to start testing? Well, the first of them, by the creation of a few hundred files, each file being created one byte more than the previous one and with correlative names. To do this, I wrote a small batch file, taking into account that each alphanumeric character represents a byte. I could have done this with fsutil, directly assigning the desired size, but then I could not edit those generated files, which is necessary to observe the behavior of a resident file.



The result of the execution of this small batch file...


Oh, my God! What have I gotten myself into? 😱😱😱😱😱😱😱😱😱😭 I wanna cry!

It's time to have a lot of coffee, (large doses of coffee), do a lot of manual work and have a lot of patience, because it's time to check each of the files.

After performing this first test that I mentioned earlier and after spending many hours to study the situation of all these files, I have come to a conclusion.

Do you want to know when a file is resident and when it is not? Are you ready to know the exact size for a file to be resident, or not? Well, the answer is... Depends 🤪🤪🤪

It depends on whether they are generated automatically or if they are created with an 'X' editor. It depends on whether the file is given a short name or a long name. It depends on whether the creation of 8.3 file names is disabled. Depends on several factors.

I'll explain. I explain. Because some tests have led me to others, that have led me to others, that have led me to others, ...


Test environment


The tests I have carried out have been carried out on the following systems and devices:
  • Windows 7, (version 6.1.7601)
  • Windows 7, (version 6.1.7600)
  • Windows 10, (version 10.0.17763.404)
  • Windows 10, (version 10.0.18343.1)
  • Windows 10, (version 10.0.18890.1000)
  • SanDisk Cruzer Blade 32GB device, (in NTFS format)
The tools I have chosen to determine if a file is resident in the MFT, or not, and to study that type of files, have been:
I have chosen to choose these tools to contrast data, to validate results between one and the other, and thus avoid errors in the interpretation of the same. I consider that Active Disk Editor is a very comfortable option to carry out this study.

The tests


592 bytes resident file; 593 bytes non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

This is the first test that I have carried out, by means of the execution of that batch file that I have mentioned previously. Note that these files have been generated automatically, without going through a text editor, and assigning a long file name. Of all the files that have been created, I have kept two of them.


A file with a size of 592 bytes and a file with a size of 593 bytes.
The 592 bytes file is a MFT resident file while the 593 bytes file is not MFT resident.

As you can see in the image above, the file with a size of 592 bytes does not occupy disk space, while the file with a size of 593 bytes does occupy disk space. Specifically, the file with a size of 593 bytes, occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

592 bytes resident file


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151)..
  2. Two attributes '$30', ($FILE_NAME):
    • The first attribute '$30', which corresponds to the short filename, starts at byte 152 and has a length of 120 bytes, (up to byte 271).
    • The second attribute '$30', which corresponds to the long filename, starts at byte 272 and has a length of 128 bytes, (up to byte 399).
  3. An attribute '$80', ($DATA), which starts at byte 400 and has a length of 616 bytes, (up to byte 1015).
    1. The information that indicates if it is a resident file, or not, is found in byte 408, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 424 is the beginning of the content of the file, (21 bytes after the end of the header of this attribute).
  4. The end of the file record is in byte 1016.
  5. The last four bytes of the register have the value '82790200'.

593 bytes non-resident file


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 414.

The attribute '$DATA', which starts at byte 400, has a length of 72 bytes, (up to byte 471).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 408), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 465, and the cluster assigned to it, which is cluster 3.156.345, in byte 466.

The end of the record is in byte 472.

The last four bytes of the record have the value '82794711'.



If I were not conscientious and meticulous, I would have left the matter here, because I already have an answer. But I like to check the tests I do because I like to talk about insurance (as much as possible). So I have continued to run other kinds of tests. And I have taken these files as a reference for the remaining tests.

The next test I carried out was on the USB device. And it is from here that I have set my brain in motion to everything it gives of itself. Why? Because when I created those two files on that device I was surprised that the two files were resident files.

What have I done wrong? What has failed? What have I done wrong? Nothing. I've gone crazy, literally, looking for an explanation, looking at all kinds of configurations and studying a lot of options, until I've found the key, (and never better said).

712 byte resident file; 713 byte non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

It turns out that the USB device I used to perform this other test was formatted on a different system than the ones I usually use. And it turns out that the system in question had a modification that I don't usually use.

The answer? In the modification of a value that is in the key of the beehive of the Registry:
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation'.

Windows allows you to enable or disable the creation of short file names, both on the system volume itself and on external volumes. As a result, the settings are saved to the device. That is to say, if you format a USB device in a system that presents a certain configuration, that configuration is applied to that device, forever, until a new formatting.

This setting, moreover, does not apply retroactively. That is to say, the system files that are recorded in their corresponding MFT will keep all that recorded information and the changes will not be applied until the system is restarted, only for the new records.

Discovered' this, I have proceeded to run, again, that batch file to create hundreds of other files inside that USB device, (and another system that I have modified for this job). Note that these files have been generated automatically, without going through a text editor, and assigning a long file name. Of all the files that have been created, I have kept two of them.

A file with a size of 712 bytes and a file with a size of 713 bytes.
The 712-byte file is an MFT resident file while the 713-byte file is not MFT resident.

As you can see in the image above, the file with a size of 712 bytes does not occupy disk space, while the file with a size of 713 bytes does occupy disk space. Specifically, the file with a size of 713 bytes, occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

712 bytes resident file


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. An attribute '$30', ($FILE_NAME), which starts at byte 152 and has a length of 128 bytes, (up to byte 279), so it corresponds to the long filename.
  3. An attribute '$80', ($DATA), which starts at byte 280 and has a length of 736 bytes, (up to byte 1015).
    1. The information that indicates if it is a resident file, or not, is found in byte 288, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 304 is the beginning of the file content, (21 bytes after the end of the header of this attribute).
  4. The end of the file record is in byte 1016.
  5. The last four bytes of the register have the value '82790200'.

Non-resident file of 713 bytes


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 294.

The attribute '$DATA', which starts at byte 280, has a length of 72 bytes, (up to byte 351).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 288), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 345, and the cluster assigned to it, which is cluster 3.150.984, in byte 346.

The end of the record is in byte 352.

The last four bytes of the record have the value '82794711'.


In view of this second test that I have performed, the first conclusion I draw from all this is that, when an attribute is not present, in the record of a file, the space that that absent attribute should occupy is assigned to the attribute '$DATA'

How did I get there? In the test performed with the 592 bytes resident file, the length of the attribute '$DATA' is 616 bytes, while in this test with the 712 bytes resident file, the length of the attribute '$DATA' is 736. So if we subtract '736 - 616' we get a result of 120 bytes, which is, coincidentally, the length of the absent attribute '$30', corresponding to the short file name.

Again, I could have left this here, because I already have another answer with a certain logic. But seeing this... has given me some more thought. To go a little further. So I took a piece of paper and a pencil and started taking notes to see how and under what conditions I can create files.

552 byte resident file; 553 byte non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

So, I've run another test. On this occasion I have created a few text files, (many), manually, with different sizes, assigning, as in the previous cases, a long file name, but the creation has been by editing in the Windows notepad. Of all the files I've created, I've kept two of them.

A file with a size of 552 bytes and a file with a size of 553 bytes.
The 552 byte file is a MFT resident file while the 553 byte file is not MFT resident.

As you can see in the image above, the file with a size of 552 bytes does not occupy disk space, while the file with a size of 553 bytes does occupy disk space. Specifically, the file with a size of 553 bytes, occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

Resident file of 552 bytes


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. Two attributes '$30', ($FILE_NAME):
    • The first attribute '$30', which corresponds to the short filename, starts at byte 152 and has a length of 120 bytes, (up to byte 271).
    • The second attribute '$30', which corresponds to the long filename, starts at byte 272 and has a length of 128 bytes, (up to byte 399).
  3. An attribute '$40', ($OBJECT_ID), which starts at byte 400 and has a length of 40 bytes, (up to byte 439).
  4. An attribute '$80', ($DATA), which starts at byte 440 and has a length of 676 bytes, (up to byte 1015).
    1. The information that indicates if it is a resident file, or not, is found in byte 448, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 464 is the beginning of the content of the file, (21 bytes after the end of the header of this attribute).
  5. The end of the file record is in byte 1016.
  6. The last four bytes of the register have the value '82790F00'.

Non-resident file of 553 bytes


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 454.

The attribute '$DATA', which begins in byte 440, has a length of 72 bytes, (up to byte 411).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 448), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 505, and the cluster assigned to it, which is cluster 3.149.052, in byte 506.

The end of the record is in byte 512.

The last four bytes of the record have the value '82794711'.


A new attribute has appeared on the playing field. This is the attribute '$40', which belongs to the '$OBJECT_ID'. A 'curious' detail that appears this attribute only with the edition of the file. Why hasn't it been manifested before?

With this test I am able to affirm, without fear of making a mistake, that the space that an attribute that is absent should occupy is assigned to the attribute '$DATA'.

I continue with my tests... With the options that occur to me... And...

Translated with www.DeepL.com/Translator

672-byte resident file; 673-byte non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

I am changing the value of the registry key again:
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation', 
to avoid creating short file names in the MFT file records and create the same files as before, assigning a long file name and manually, using the notepad.

Now I only create two files, because I already know how to play this.

If we start from the first of the examples, as a reference file, where the 592 bytes file was a resident file, which has been created automatically and without disabling the generation of short filenames...

592 bytes of the file, added to the 120 bytes that would occupy the attribute '$30', (corresponding to the short file name), and subtracted from 40 bytes, that will occupy the attribute '$40'... we have a result of 672 bytes. That is to say, if I generate two text files, of 672 bytes and 673 bytes, manually, with the notepad, and the generation of short names in the MFT registry is disabled, the first of those files must be resident, but the second must not be resident.

So I keep a file with a size of 672 bytes and a file with a size of 673 bytes.
Así que guardo un archivo con un tamaño de 672 bytes y un archivo con un tamaño de 673 bytes.

As you can see in the image above, the file with a size of 672 bytes does not occupy disk space, while the file with a size of 673 bytes does occupy disk space. Specifically, the file with a size of 673 bytes, occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

Resident file of 672 bytes


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. An attribute '$30', ($FILE_NAME), which starts at byte 152 and has a length of 128 bytes, (up to byte 279), so it corresponds to the long filename.
  3. An attribute '$40', ($OBJECT_ID), which starts at byte 280 and has a length of 40 bytes, (up to byte 319).
  4. An attribute '$80', ($DATA), which starts at byte 320 and has a length of 696 bytes, (up to byte 1015).
    1. The information that indicates if it is a resident file, or not, is found in byte 328, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 344 is the beginning of the content of the file, (21 bytes after the end of the header of this attribute).
  5. The end of the file record is in byte 1016.
  6. The last four bytes of the register have the value '82790200'.

673 bytes non-resident file


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 334.

The attribute '$DATA', which begins in byte 320, has a length of 72 bytes, (up to byte 391).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 328), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 385, and the cluster assigned to it, which is cluster 3.156.283, in byte 386.

The end of the record is in byte 392.

The last four bytes of the record have the value '82794711'.


Mmmmm. I find it very curious how the recording of files in the MFT works. I can think of some more things to try...

680-byte resident file; 681-byte non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

On this occasion, I have created two new files, with two different sizes, manually, using the notepad, but this time assigning a short file name. Specifically, an 8-character name.

If we go back to the first example, as a reference file, where the 592 byte file was a resident file, which has been created automatically and without disabling the generation of short file names... and taking into account that the attribute '$30', corresponding to the short file name, occupies 120 bytes, while the attribute '$30', corresponding to the long file name, occupies 128 bytes, ...

592 bytes of the file, added to the 128 bytes that would occupy the attribute '$30', (corresponding to the long file name), and subtracted from 40 bytes, that will occupy the attribute '$40'... we have a result of 680 bytes. That is to say, if I generate two text files, of 680 bytes and 681 bytes, manually, with the notepad, and I assign it a short file name, in the MFT register, the first of those files must be resident, but the second must not be resident.

So I keep a file with a size of 680 bytes and a file with a size of 681 bytes.
The 680-byte file is a file resident in the MFT while the 681-byte file is not resident in the MFT.

As you can see in the image above, the file with a size of 680 bytes does not occupy disk space, while the file with a size of 681 bytes does occupy disk space. Specifically, the file with a size of 681 bytes, occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

Resident file of 680 bytes


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. An attribute '$30', ($FILE_NAME), which starts at byte 152 and has a length of 120 bytes, (up to byte 271), so it corresponds to the short filename.
  3. An attribute '$40', ($OBJECT_ID), which starts at byte 280 and has a length of 40 bytes, (up to byte 311).
  4. An attribute '$80', ($DATA), which starts at byte 312 and has a length of 704 bytes, (up to byte 1015).
    1. The information that tells us if it is a resident file, or not, is found in byte 320, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 336 is the beginning of the file content, (21 bytes after the end of the header of this attribute).
  5. The end of the file record is in byte 1016.
  6. The last four bytes of the register have the value '82799E00'.

Non-resident file of 681 bytes


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 326.

The attribute '$DATA', which begins in byte 312, has a length of 72 bytes, (up to byte 383).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 320), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 377, and the cluster assigned to it, which is cluster 3.148.935, in byte 378.

The end of the record is in byte 384.

The last four bytes of the record have the value '82794711'.


As we have just seen, when we assign a short file name to a file, only the information corresponding to the short file name attribute '$30' will be recorded in the corresponding record. Why? Because the system does not need more information to complete the information in that file. That's why it dispenses with the 128 bytes that correspond to the attribute '$30', with a long file name.

Now... I wonder if...

What happens if I give it an even shorter name?

696 bytes resident file; 697 bytes non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

On this occasion, I have created two new files, with two different sizes, manually, using the notepad, but this time assigning a short file name. Specifically, a name of only 1 alphanumeric character.

If we go back to the first example, as a reference file, where the 592 byte file was a resident file, which has been created automatically and without disabling the generation of short file names... and taking into account that the attribute '$30', corresponding to the short file name, occupies 120 bytes, while the attribute '$30', corresponding to the long file name, occupies 128 bytes, ...

592 bytes of the file, added to the 128 bytes that would occupy the attribute '$30', (corresponding to the long file name), and subtracted from 40 bytes, that will occupy the attribute '$40'... we have a result of 680 bytes. That is, in this case, if I generate two text files, of 680 bytes and 681 bytes, manually, with the notepad, and I assign it a short file name, in the MFT register, and theoretically, the first of those files should be resident, but the second should not be resident.

But that would be theoretically. Because the '$30' attribute has a maximum size, but it also has a minimum size.

In this particular case, where I have only used an alphanumeric character to name a file...

I keep a file with a size of 696 bytes and a file with a size of 697 bytes. (16 bytes more than in the previous case).
The 696-byte file is an MFT resident file while the 697-byte file is not MFT resident.

As you can see in the image above, the file with a size of 696 bytes does not occupy disk space, while the file with a size of 697 bytes does occupy disk space. Specifically, the file with a size of 697 bytes, occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

Resident file of 696 bytes


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. An attribute '$30', ($FILE_NAME), which starts at byte 152 and has a length of 104 bytes, (up to byte 255), so it corresponds to the short filename.
  3. An attribute '$40', ($OBJECT_ID), which starts at byte 256 and has a length of 40 bytes, (up to byte 295).
  4. An attribute '$80', ($DATA), which starts at byte 296 and has a length of 720 bytes, (up to byte 1015).
    1. The information that indicates if it is a resident file, or not, is found in byte 304, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 320 is the beginning of the content of the file, (21 bytes after the end of the header of this attribute).
  5. The end of the file record is in byte 1016.
  6. The last four bytes of the register have the value '82790400'.

Non-resident file of 697 bytes


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 310.

The attribute '$DATA', which begins in byte 296, has a length of 72 bytes, (up to byte 367).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 304), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 361, and the cluster assigned to it, which is cluster 3.148.938, in byte 362.

The end of the record is in byte 384.

The last four bytes of the record have the value '82794711'.


Mmmmm... Very curious. I'm going to try to explain it in a simple way.

As I said a little above, the attribute '$30', corresponding to the short filename, has a maximum size of 120 bytes, but also has a minimum size that, if not busy, the system fills with '00'. To see this difference I have created another identical file, but I have assigned a three-digit name. So let's compare three short file names: The file named as 'File0680.txt', the file named as 'A.txt' and the file named as '696.txt'.


In the image above, as you can see, (I hope), is the attribute '$30', relative to the short filename. Within this attribute is at the end, highlighted, the short file name, which begins at byte 92 within this attribute. The filename is the last information recorded in this attribute.

The file named as 'File696.txt', which starts at the same position, (byte 92 within the attribute itself), is composed of 12 unicode characters, which happens to have 24 ASCII characters, because after each character is assigned the value '00', (which corresponds to a '.'). That is, the name of this file has a length of 24 bytes. But, if you look at the image, the system assigns six more hexadecimal values, with values of '00'. So we have a total of 30 bytes.

The file named as 'A.txt', following the same structure as the previous file, is composed of 5 unicode characters, which becomes 10 ASCII characters. But the system marks '00' the last four bytes. That is, the name of this file has a length of 14 bytes.

It is exactly the same with the file '696.txt', which is composed of 7 unicode characters, which happens to have 14 ASCII characters, but in this case the system does not mark the last bytes to '00'. So this file also has a length of 14 bytes.

So, if you subtract the 30 bytes of the file named as 'File696' from the 14 bytes of the files named as 'A.txt' and '696.txt', the difference is 16 bytes. The difference in size between the previous case and this one.

According to these tests, the minimum size reserved for the short filename within the '$30' attribute is 14 bytes. Why does this happen? To see it graphically I have created some files, named as 'A', 'AA', 'AAA', ... up to a total of eight.


The filename information begins in byte 92, inside the attribute itself, which coincides with the third byte of the first octet. The system does not terminate the attribute information until it completes an octet. So the system, when a file name starts an octet, but does not end it, assigns values to '00' until the end of that octet.

So, with the creation of files manually and depending on the length of the short filename, the difference between one resident file and another is not going to be in one byte, but in eight bytes. For example, while a file named as 'A.txt' is resident with a maximum size of 696 bytes, a file named as 'AAAA.txt' will be resident with a maximum size of 688 bytes.

To finish with the possible ways to create files and see their respective sizes to determine when they can be resident files...

728 byte resident file; 729 byte non-resident file


The file on the left corresponds to a resident file. The file on the right corresponds to a non-resident file.

I think I have yet to show what happens to a file with an assigned short name and an automatic creation. To do this, I used the same batch file as in previous tests to create a couple of files. But this time the generation of short file names is disabled, changing the value of the registry key I mentioned before.


Following the same dynamics as in the previous example, a file named 'A.txt' can be resident with a maximum size of 720 bytes, while a file named 'File728.txt' can be resident with a maximum size of 728 bytes. This happens because we have to add the 40 bytes corresponding to the attribute '$40' that we are not going to find in that record.

So, for this example, I keep a file with a size of 728 bytes and a file with a size of 729 bytes.
The 728-byte file is a file resident in the MFT while the 729-byte file is not resident in the MFT.

As you can see in the image above, the file with a size of 728 bytes does not occupy disk space, while the file with a size of 729 bytes does occupy disk space. Specifically, the file with a size of 729 bytes occupies 4096 bytes on disk, which is the size assigned to the cluster, (8 sectors).

Resident file of 728 bytes


In this case, we find the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. An attribute '$30', ($FILE_NAME), which starts at byte 152 and has a length of 112 bytes, (up to byte 263).
  3. An attribute '$80', ($DATA), which starts at byte 264 and has a length of 752 bytes, (up to byte 1015).
    1. The information that indicates if it is a resident file, or not, is found in byte 272, (the fifth byte since the end of the header of this attribute), and presents a value of '00', which indicates that it is resident.
    2. In byte 2884 is the beginning of the file content, (21 bytes after the end of the header of this attribute).
  4. The end of the file record is in byte 1016.
  5. The last four bytes of the register have the value '82790800'.

Non-resident file of 729 bytes


In this case we find the same types of attributes as in the previous case, with some difference. This difference starts from byte 278.

The attribute '$DATA', which begins in byte 264, has a length of 72 bytes, (up to byte 351).

The information that indicates if a file is resident, or not, is found in the same byte as in the previous case, (byte 272), that has a value of '01' and that indicates that it is a non-resident file.

As this file does occupy disk space, it has an assigned cluster. And the record shows that the number of clusters used by that file is one, in byte 329, and the cluster assigned to it, which is cluster 3.187.319, in byte 330.

The end of the record is in byte 336.

The last four bytes of the record have the value '82794711'.


These are the tests that have occurred to me to carry out, as for the creation of files, assigning different lengths of names, generating them of different way and with enable and disable of short file name.

Again, I could have left this matter here, but I need to know how a resident file behaves, when it is edited, when it is modified.

Behavior of a resident file


To carry out this test I have chosen to take the file used as reference for all the others, the file named as '00Fichero592.txt', and edit it, adding in it the word 'Marcos'. Thus, the file goes from a size of 592 bytes to a size of 598 bytes. So it ceases to be a resident file.

After its edition in Windows 7, the file has the following attributes::
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. Two attributes '$30', ($FILE_NAME):
    • The first attribute '$30', which corresponds to the short filename, starts at byte 152 and has a length of 120 bytes, (up to byte 271).
    • The second attribute '$30', which corresponds to the long filename, starts at byte 272 and has a length of 128 bytes, (up to byte 399).
  3. An attribute '$40', ($OBJECT_ID), which starts at byte 400 and has a length of 40 bytes, (up to byte 439).
  4. An attribute '$80', ($DATA), which starts at byte 440 and has a length of 72 bytes, (up to byte 511).
    1. The information that indicates if it is a resident file, or not, is found in byte 448, (the fifth byte since the end of the header of this attribute), and presents a value of '01', which indicates that it is a non-resident file.
    2. The number of clusters used by the file is in byte 505.
    3. The cluster assigned to the file is located in byte 506
  5. The end of the file record is in byte 512.
  6. The last four bytes of the register have the value '82794711'.
The surprise comes after the supposed end of the file record, because the content that existed before in that record can be found in the same way when the file ceases to be a resident file. 


In addition to finding part of the file information in that record, it is also found in the assigned cluster, corresponding to cluster 32.664 in this case.


I edit that same file again, deleting the added word 'Frames', to return it to its original size of 592 bytes. The result is that this file is not a resident file again, although its contents are shown in that record.


And the updated information is also shown in the same cluster that was assigned to it when it is no longer a resident file.


That is to say, in a Windows 7 system, when a resident file is modified so that it ceases to be a resident file, the information will be saved to a new cluster, but it will also keep part of that information in the file registry itself, always maintaining that assigned cluster.

I make the same operation on Windows 10, and after its edition, with a size of 598 bytes, the file happens to have the following attributes:
  1. An attribute '$10', ($TANDARD_INFORMATION), which starts at byte 56 and has a length of 96 bytes, (up to byte 151).
  2. Two attributes '$30', ($FILE_NAME):
    • The first attribute '$30', which corresponds to the short filename, starts at byte 152 and has a length of 120 bytes, (up to byte 271).
    • The second attribute '$30', which corresponds to the long filename, starts at byte 272 and has a length of 128 bytes, (up to byte 399).
  3. An attribute '$40', ($OBJECT_ID), which starts at byte 400 and has a length of 40 bytes, (up to byte 439).
  4. An attribute '$80', ($DATA), which starts at byte 440 and has a length of 72 bytes, (up to byte 511).
    1. The information that indicates if it is a resident file, or not, is found in byte 448, (the fifth byte since the end of the header of this attribute), and presents a value of '01', which indicates that it is a non-resident file.
    2. The number of clusters used by the file is in byte 505.
    3. The cluster assigned to the file is located in byte 506.
  5. The end of the file record is in byte 512.
  6. The last four bytes of the register have the value '82794711'.

After the end of the file record, the information that was previously resident is no longer resident, because it passes in its entirety to the assigned cluster at the moment it exceeds the maximum size for a resident file.


I edit that same file again, deleting the added word so that it has the size of 592 bytes again, and it presents exactly the same information, except for a new cluster where the information of the file is stored. If in the previous example the system assigned cluster 3.264.719 to the file that had ceased to be resident, now it has assigned cluster 50.179, still not being a resident file, despite having the right size to be one.


That is to say, with each edition of a resident file, in a Windows 10 system, a new cluster will be assigned to the information of that file. And that information will remain there until it is overwritten by another record, in case it finds itself without assigning that cluster.

We are finishing with this small work...

Conclusions


Is there a single size for a file to be resident in the MFT or not? No. There is no single size for that condition, because it depends on several factors.

Space that is not used by attributes that are not present in the file record is assigned to the '$DATA' attribute. So, for example, if we have a record without an attribute '$40', which has a length of 40 bytes, those 40 bytes are assigned to the attribute '$DATA', so the file has 40 bytes more for it to be a resident file.

The first factor that influences the size for a file to be resident, or not, is how it is created. If a file is automatically created in the system or device, it will have more space for it to be a resident file than if we create the file by editing it in the system.

If the system is configured so that the short file names (8.3) are not generated in the file register, that file will have 120 bytes more (which are assigned to the attribute '$DATA'), so that it can be a file resident in the MFT.

The disabling or enabling of short file names, (8.3), does not apply retroactively. In other words, if 'X' files with 'X' attributes are stored in the MFT, the system will keep that information until the appropriate reboot and will apply the changes only to the new records.

If an external device, (or any other volume) is formatted in NTFS, that device will save the same configuration as that system, until a new formatting.

In all my tests, at the end of the recording of a non-resident file in the MFT, after the value 'FFFFFFFF', I have obtained the same value '82794711', varying the last two values in case of resident files.

In the case that a short name is assigned to a file, (up to 8 characters), the maximum size for a file to be resident, or not, will depend on the octets that occupy the length of the name, because the system, when it has a name that starts an octet but does not end it, records it at '00' until the end of that octet. A file named with only one character will be resident with the same size as a file named with three characters, for that reason.

I know that you probably haven't read all the content of the text and I know that you like tables for a better understanding. So I leave you a small table with the data I have obtained in my tests.

In the table,
  • Automatic creation means any file created that has not been edited directly by the user.
  • A long name is a file with a name of more than 8 characters.
  • An edition is any file that is created by the user himself, using an editor.
  • A short name is any file whose name consists of 8 characters or less.
  • Understand by 'Without 8.3', every file that has been created, having disabled the short filename creation feature, from the Registry.
First of all I show you the results of my tests, concerning the long file names, with the maximum size so that it can be a resident file and with the size so that it no longer has that condition.


Now I show you another table, with the results obtained from the generation of short filenames, since it depends on the length of the filename, it can be resident with one size or another. As in the previous table, I show you the maximum size for a file to be resident in the MFT and the size for it to cease to be resident, with the length of the filename, since it depends on it for one condition or another to occur.


To finish, I leave below some links of interest and references.

Interesting links and references



If you want to do some tests yourself, you can:
  • Download from here the file to create files of 592 bytes and 593 bytes, with long file name.
  • Download from here the file to create files of 712 bytes and 713 bytes, with long file name, having disabled the generation of short file names, (8.3)
  • Download here the file to create files of 728 bytes and 729 bytes, with short file name, (7 characters).
  • Do your own tests 😉😉



I hope this information is useful to someone. That is all,

spacer