Accediendo a CMD.EXE en un volumen NTFS con solo un editor hexadecimal

Iniciado por Usuario887, 4 Noviembre 2021, 17:01 PM

0 Miembros y 1 Visitante están viendo este tema.

Usuario887

Hola,

Esto fue algo que llevaba buscando desde hace tiempo y de lo cual no encontre respuesta alguna, al menos no con NTFS. Como todo humano que tienda a llenar el vacio, lo hare yo aqui.

Lo que hare concretamente es un basico analisis de un volumen NTFS desde el sector 0 con el objetivo de llegar a un archivo concreto, en este caso "CMD.EXE", al mas bajo nivel, sin utilizar ninguna herramienta mas que un editor hexadecimal y una imagen de disco. cuidando que no se me escape ningun concepto, o al menos buenas referencias a ellos.




PRELIMINARES

Debo mencionar que se asume una lectura al menos superficial del sistema y me gustaria comenzar aclarando lo que se acerca a lo imprescindible saber para entender este pequeño caso de estudio. En pocas palabras, se recomienda conocer el funcionamiento de:


  • Sistemas operativos
  • Sistemas de archivos
  • Nocion clara y recomendable experiencia programando arboles
  • Endianness
  • Estructuras de datos

NTFS

NTFS (New Technology File System) es un sistema de archivos basado en "m-way search trees" (https://en.wikipedia.org/wiki/M-tree) que tiene su peculiaridad de ser muy integro en su definicion: En NTFS, un sistema de archivos, todo es un archivo. Incluso el volumen en si es un archivo como se vera en seguida. Los archivos estan compuestos por un concepto muy inteligente llamado atributo. Los atributos estan compuestos a su vez por una cabecera y un "Data stream". Este ultimo representa los datos que contiene el atributo. Un ejemplo de un pseudo-archivo NTFS podria ser:

CitarATRIBUTO_NOMBRE
"CMD.EXE"

ATRIBUTO_DATOS
MZ...

En NTFS, casi como en FAT (File Allocation Table, https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos, otro sistema de archivos) existe una tabla para descripcion y listado de los archivos. Esta tabla se llama MFT (Master File Table) y en ella se listan todos los archivos presentes en el volumen, incluyendose a si misma (una referencia recursiva). (Esto no es asi en FAT).

Con esto ultimo quiero decir que, para esta tabla, la tabla misma es una entrada en la tabla. Como decir que tenemos una libreta con los nombres de los miembros de este foro, y se nos muestra asi:

Citar"Libreta"
"Pepe"
"Paco"

En el listado, aparecen tanto Pepe, como Paco y la libreta misma. Esto es asi para asegurar la integridad antes mencionada (Todo es un archivo, y esta tabla lista archivos; silogismo: todo esta en la tabla). Hago enfasis en este punto porque se que esta entre los muchos de facil confusion en este sistema de archivos.

Los atributos antes mencionados estan localizados en las entradas de esta tabla, cuyo tamaño cada una suele ser de 400h bytes (1024 bytes).

Notas:


  • A partir de ahora representare todas las cifras en notacion hexadecibal XXh, ya que andar de decimal a hexadecimal y viceversa puede burlar la vista demasiado...
  • No me voy a meter en archivos como $Bitmap, $Volume, $MftMirr... Porque no vienen al caso de esta tarea. Sin embargo, mencionare a algunas. Al final podran verse referencias a estas estructuras
  • Tampoco me metere en temas de analisis forense, para lo que este sistema parece estar muy bien diseñado en comparacion a sus antecesores, por cierto
  • Representare los nomnbres de archivo con mayusculas por costumbre a FAT. Espero no moleste.




CABECERAS DE ATRIBUTOS

Las cabeceras de los atributos, estos que pueden ser: residentes y nombrados, residentes y no nombrados, no residentes y nombrados o no residentes y no nombrados, describen las caracteristicas de los atributos mismos. Esto de nombrados, residentes... Lo explicare en seguida, pero cabe mencionar de inmediato que son un ejemplo de caracteristicas definidas por la cabecera que estoy ahora describiendo.

Tomando el ejemplo anterior, podemos decir que estan estructuradas asi:

Citar
CABECERA_ATRIBUTO ATRIBUTO_NOMBRE
"CMD.EXE"
CABECERA_ATRIBUTO ATRIBUTO_DATOS
MZ...

La cabecera DEFINE el atributo en si. Que tamaño tiene, en donde se encuentra, si tiene nombre, si no tiene nombre, sus correspondientes flags...


RESIDENCIA DE ATRIBUTOS

La residencia es eso... Estar o no estar. La cuestion es en donde: La residencia indica si se encuentra DENTRO del atributo, o en otro cluster (cluster: conjunto de sectores. Sector: Conjunto de bytes minimo para la comunicacion entre el disco y el sistema. Suelen ser 200h bytes por sector. En el caso de este estudio el cluster y el sector son del mismo tamaño, para simplificar) del disco. ¿Por que estaria fuera del mismo atributo al cual ya tienes acceso? ¿POR QUE COMPLICARNOS LA VIDA? Te preguntas... La simpleza es la mayor expresion de sofisticacion, dijo Da Vinci...
Hablando en serio, un atributo contiene datos, y una caracteristica intrinseca de los datos es que tienen tamaño, un tamaño que puede ser mas o menos grande, por lo que puede o no caber en el lugar en el cual lo quieres meter; En este caso: Los 400h bytes disponibles en su correspondiente MFT. En este caso, el atributo se hace "No residente" y se indica su direccion con un concepto que explicare en seguida, llamado "Runs" ("Corridas" xd).


CLUSTER RUNS

Estas "Corridas" representan direcciones relativas de datos en el disco: Quiero decir, direcciones que dependen de algo mas que el numero que representan como desplazamiento en si. Podriamos entonces representarlo con nuestro ejemplo anterior asi:

Citar
CABECERA_ATRIBUTO ATRIBUTO_NOMBRE
"CMD.EXE"
CABECERA_ATRIBUTO:NO_RESIDENTE ATRIBUTO_DATOS
CLUSTER_RUNS:01,02,03

Si el archivo "CMD.EXE" es no residente, segun su cabecera, entonces nos proporcionara sus "Cluster Runs". Efectivamente: 01, 02 y 03. Quisiera que prestes especial atencion a esto:

Creeras que 01, 02 y 03 quieren decir que el contenido del archivo se encuentra en los clusters contiguos 01, 02 y 03, pero recordemos que son RELATIVOS. Es decir: El primer cluster es el 01, el segundo cluster es el 02 (mas el primero, lo que seria 01+02=03, el segundo cluster es el 03) y el tercero es el 03 (mas el anterior, 03+03=06, el tercer cluster en el que se encuentran los datos de "CMD.EXE" es el 06).

Todo esto se hara mas claro cuando veamos el caso real.




CONCEPTOS GENERALES

Hemos cubierto el attribute header (cabecera de atributo). Ahora continuaremos con otros conceptos de esencial importancia. Luego procederemos de inmediato con el ejemplo real, que me extiendo c*ño...

Notas:

Pondre los titulos en ingles. Asi en el caso de que a alguien le interese y quiera continuar investigando, tenga familiaridad con los terminos.


  • Attribute ID
  • B-Trees (Arboles B)
  • File Reference
  • File Record
  • Index Entry
  • Index Node Header
  • Index Record


ATTRIBUTE ID

Cada atributo antes mencionado, tiene un ID asignado dentro de cada entrada MFT. Mantiene la integridad numerando a cada uno.

B TREES

CitarA B-tree is a specialized multiway tree designed especially for use on disk. In a B-tree each node may contain a large number of keys. The number of subtrees of each node, then, may also be large. A B-tree is designed to branch out in this large number of directions and to contain a lot of keys in each node so that the height of the tree is relatively small. This means that only a small number of nodes must be read from disk to retrieve an item. The goal is to get fast access to the data, and with disk drives this means reading a very small number of records. Note that a large node size (with lots of keys in the node) also fits with the fact that with a disk drive one can usually read a fair amount of data at once.
https://cis.stvincent.edu/html/tutorials/swd/btree/btree.html

Seria bueno leer el articulo, aunque no es necesario. Es "Considerable" saber que la forma en la que se conoce la arquitectura en si de NTFS es como arbol B (o milti-way search tree). Puntos de relevancia en el articulo:

CitarIn a B-tree each node may contain a large number of keys.
CitarIn a B+ tree, data records are only stored in the leaves. Internal nodes store just keys.
CitarWhen a B+ tree is implemented on disk, it is likely that the leaves contain key, pointer pairs where the pointer field points to the record of data associated with the key.

Estos tres puntos se cumplen para NTFS.

Cabe mencionar que:


  • Para NTFS, un nodo equivale a un directorio.

Y resaltar que:

Los nodos internos son solo CLAVES (en terminologia de arboles). Los datos se almacenan en las hojas.

No profundizare mucho en arboles porque en este caso NTFS no es siquiera un B tree ideal. Llamemosle una "Implementacion practica".


FILE REFERENCE

Una referencia a un archivo. Tal cual. Como referenciar una estructura en C a traves de un puntero, de la misma forma se referencia a un archivo (que tambien es una estructura) solo que en este caso no con su direccion sino con un identificador asignado previamente por el sistema.


FILE RECORD

La estructura antes mencionada con la que nos referimos al archivo. En este caso, hablamos de cada entrada MFT. ;)


INDEX ENTRY

De la misma forma que en la tabla MFT existen entradas que describen archivos en el volumen, existen entradas que describen archivos en los directorios, estas entradas son llamadas, hablando de NTFS, Index Entry.


INDEX NODE HEADER

Como mencionado anteriormente, un nodo hace referencia a un directorio, por lo que esto seria una cabecera para los directorios. Similar a las cabeceras de los atributos.


INDEX RECORD

En NTFS, las entradas en la MFT de archivos de datos hacen referencia a sus datos; Sin embargo cuando se trata de directorios, hacen referencia a una estructura llamada Index Record, la cual hace descripcion de los ficheros que contiene el directorio en cuestion. Cabe mencionar que este fichero es util en actividades de analisis forense (En este sistema todo parece serlo, pero especialmente esto lo es).


He cubierto hasta ahora todo lo necesario al respecto de NTFS para lograr dar con un archivo. Desde luego, hare especificaciones en el camino. Ahora si, lo divertido:




ACCEDIENDO AL ARCHIVO SIN CreateFile
(Broma)

Ahora seguiremos el rastro de CMD.EXE. Lo primero que tenemos que hacer es leer el sector 0 o, en nomenclatura NTFS, el archivo $Boot con el editor hexadecimal:



De aqui necesitamos tres cosas:


  • La localizacion de la tabla MFT
  • La cantidad de bytes por sector
  • La cantidad de sectores por cluster

Estos datos se encuentran en los offsets 30h, 0bh y 0dh, respectivamente.

Cabe mencionar que este sector es parecido al de los sistemas FAT.



En este caso, la localizacion de la MFT esta representada en clusters (y en little-endian, obviamente). Es decir, nuestra tabla se encuentra en el Cluster @ LCN 0215D3h. (LCN de Logical Cluster Number. Hasta aqui esto es evidente pero por si acaso: A logical cluster number (LCN) describes the offset of a cluster from some arbitrary point within the volume. LCNs should be treated only as ordinal, or relative, numbers. There is no guaranteed mapping of logical clusters to physical hard disk drive sectors. An extent is a run of contiguous clusters.)

La cantidad de bytes por sector es 200h (como dije que era comun, aunque NO siempre es asi).
La cantidad de sectores por cluster es 1. (Facilito ;D)

Si tenemos 200h bytes por sector, y 1 sector por cluster, la MFT se encuentra en el byte 200h*1*0215D3h=42BA600h

Vamos alla...



Mira lo que tenemos aqui. Que belleza, ¿No? Esto fue amor a primera vista para mi...

Volviendo a lo serio: ¿Recuerdas lo que comentaba sobre la residencia de los datos (residente, no residente...)?

Pues la cosa es asi: Si los atributos dejan espacio suficiente en la entrada MFT en cuestion para el contenido del archivo, este queda RESIDENTE dentro de la MFT. Asi no tenemos que hacer calculos y accesos al disco fastidiosos para todos... En este caso CMD.EXE no es residente, BWAHAHAHAHAHAHAHAHAHAHAHAHAHAHA. Pero bueno, los directorios tampoco, asi que doble BWAHAHAHAHAHAHAHAHAHAHA.

Como dije antes, en la MFT esta incluso la propia MFT listada. Podemos leer por ahi $MFT en codigo Unicode. (Nota: NTFS soporta namespaces en Unicode, lo que le permite ser un sistema de archivos portable a todo el mundo).

Vamos a ver que es lo que esconde:



Pido mil disculpas por mi mal pulso.

Lo que pueden ver son los atributos del archivo en cuestion. En este caso $MFT (la tabla).
Lo que necesitamos es dar con SYSTEM32, que es el directorio en el que se encuentra CMD.EXE.

Para esto vamos a recorrer entrada por entrada. Sera facil, ya que esta cerca del directorio raiz (C:\).

Y ojo que a mi me encanta correr antes de caminar, y darme unas cuantas ostias dulces como el azucar, pero tendremos que detenernos aqui para analizar un poco los atributos en profunidad. Si no, no sabremos ni lo que estamos haciendo.
Y yo que queria correr...




ATTRIBUTE HEADER

(Residente, sin nombre)


(Resindente, con nombre)


(No residente, sin nombre)


(No residente, con nombre)


Dejare estas imagenes aqui como referencias rapidas.

$DATA

Este es el atributo que mas nos interesa. Vamos a analizarlo.



Analicemos el header. Podemos ver, segun lo anteriormente mencionado respecto a los attribute headers, este es el atributo con identificador 080h y usa 078h bytes, segun la tabla de la cabecera de atributos (y sabemos que no esta nombrado porque el tamaño del campo "Nombre", desplazamiento 09h, es cero). Bien...

Si vemos el offset 08h que (segun nuestra tabla sobre attributes headers), representa si los datos del atributo (tambien llamado data stream) NO, enfatizo, NO SE ENCUENTRA RESIDENTE, vemos el valor 01. Esto significa que no hay datos, hay data runs; Un indice a los datos.

Segun el attribute header los data runs se encuentran en el offset 040h. Su contenido es:

31 20 D3 15 02 32 72 0F 61 39 02 21 6E FC 12 12 60 01 72 21 40 90 01 12 A0 00 44 22 80 00 A4 00 21 60 84 00 11 20 68 12 E0 00 24 22 00 05 20 02 00

¿Que significa todo esto? Vamos a decodificarlo pero, primero, algo sobre los data runs:

¿Recuerdan que les mencione que en los data runs los clusters estan representados de forma relativa? Pues el formato de un data run es:

<bytes para el LCN (4 bits)> <bytes para la longitud en clusters (4 bits)> <Longitud en clusters> <Logical Cluster Number>

Por ejemplo:

Si los primeros 4 bits son "3" y los segundos 4 bits son "1", significa que los siguientes 1 bytes seran para la longitud en cluster de este data stream y los segundos dos bytes seran para el offset LCN. ¿Por que al reves? Lo mismo me pregunto yo.

Lo que venga despues seguiran siendo data runs siempre que no sea 0. En caso de ser 0, hemos llegado al final (como una cadena ZS).

Cabe mencionar:

No hace falta una calculadora, ya que nuestro divino sistema hexadecimal hace una buena representacion de bits en factores de 4. Recordemos que cada caracter hexadecimal representa 4 bits en una cadena de caracteres hexadecimales, por lo que extraer cuatro bits de 32 no es tan dificil. Me explico:

0A 04 3F 2A

Primeros cuatro bits: 0
Segundos cuatro bits: A
Terceros cuatro bits: 0
Quintos  cuatro bits: 4
Sextos   cuatro bits: 3
Septimos cuatro bits: F
Octavos  cuatro bits: 2
Novenos  cuatro bits: A

Retomando nuestro analisis del atributo $DATA en la entrada (record) de la MFT en la MFT, decodificando:

31 = 3 bytes para el offset, 1 byte para longitud
20 = Longitud es 20 clusters para el actual data run
D3 15 02 = offset del actual data run

20 Clusters @ LCN 0215D3

(Recordemos que la notacion del ordenador en disco (y memoria principal) de los datos es little-endian)

Si hacemos un calculo rapido, y multiplicamos el tamaño en bytes de cada cluster (en este caso 200h) por el LCN del primer data run del archivo $MFT en la MFT obtenemos:

0215D3h*200h=42BA600h

¿Esta no es la misma direccion que vimos de la MFT anteriormente? Si. Como dije, la MFT se lista a si misma como archivo.

Enlace a una descripcion de los atributos:

http://inform.pucp.edu.pe/~inf232/Ntfs/ntfs_doc_v0.5/attributes/index.html




SEAMOS SHERLOCK HOLMES

Ahora toca la fase de busqueda y captura. Antes, tengamos en cuenta la direccion del archivo al cual queremos acceder. Cabe añadir que el sistema en cuestion es Windows NT 4.0. Tomo este sistema porque "Es simple". Ademas de que el tamaño de cluster es el mismo que el de los sectores, por lo que se nos hace facil hacer los calculos, pero es fundamentalmente lo mismo en otros sistemas NTFS. "Pocas" modificaciones se han hecho. Puede comprobarse revisando Windows 10. But anyways...

La direccion del archivo en cuestion en este sistema es:

C:\WINNT\System32\cmd.exe

Entonces, por logica, lo que debemos hacer es:


  • Localizar WINNT en la MFT
  • Buscar la referencia a SYSTEM32 en sus datos
  • Localizar a SYSTEM32 en la MFT
  • Buscar la referencia a CMD.EXE en sus datos
  • Localizar a CMD.EXE en la MFT
  • Calcular la direccion de sus datos
  • Acceder

Se puede apreciar un patron mas o menos ciclico, ¿Verdad?

Comencemos por el principio, equis de.




LOCALIZAR WINNT EN LA MFT

Toca buscar xd. El procedimiento seria buscar en la MFT por el directorio WINNT. Al encontrarlo, se veria algo asi:



Echemosle un vistazo a la cabecera de una entrada MFT:



Podemos ver que el offset 16h de la cabecera indica los flags. Los cuales son:


  • 0x1 este record esta en uso.
  • 0x2 este record es un directorio.

En este caso, en el offset 16h de WINNNT podemos ver que tanto esta en uso como es un directorio:



En el caso de un directorio, no esperamos data runs (ya que no contiene datos, contiene archivos u otros nodos, nodo=directorio).
Esperamos una estructura llamada $INDEX_ALLOCATION, la cual nos indica informacion sobre los sub-nodos respectivos al nodo en cuestion, del arbol del sistema. Este atributo nunca esta residente, y tiene un identificador A0.

Vamos a echarle un vistazo a este atributo en esta MFT particular:



Segun la estructura del atributo $INDEX_ALLOCATION:


(Se pueden ver mas estructuras a las que hare referencia en seguida)

Nos encontramos con un attribute header y los data runs. Facilongo. Vamos a echarle un vistazo a los data runs:

31 04 0A 62 04 - 04 clusters @ LCN 4620A
11 04 20          - 04 clusters @ LCN 20       +4620A=4622A
21 04 F8 01      - 04 clusters @ LCN 1F8     +4620A=46402
00                   - Llegamos al final ;)

Dirijamonos al primer cluster logico (LCN 4620A, addr 8C41400):



Podemos ver varias entradas, con una firma INDX en una especie de cabecera (lo cual es). Esta es la INDX Record. Este registro guarda referencias a los subnodos de un nodo. Echemosle un pequeño vistazo a su estructura:


(Abajo dice: "(b) Has children". Perdonen el recorte)

Falta poco para llegar al archivo...

Necesitamos de esta estructura solo una cosa: El desplazamiento a las index entries, esto es, las referencias a los subnodos que contiene. En este caso, es 38h.

Conviene tomar en cuenta la nota (a) que se aprecia en la imagen: "These values are relative to 18h", "Estos valores son relativos a 18h". Quiere decir que esta vez no vamos a contar a partir del inicio de la estructura, sino a partir de 18h o, lo que seria lo mismo, a partir del inicio de la estructura + 18h.

Vamos alla:



Vemos algunos datos que tienen la siguiente estructura:



De aqui nos interesan dos cosas: El nombre del subnodo, las caracteristicas (tenemos que saber si estamos tratando con una "Hoja" (archivo) o un "Nodo" (directorio) en este arbol) y una referencia a la MFT.

Busquemos la entrada correspondiente a SYSTEM32:



Debo decir que el campo MFT Reference of the file deberia corresponder al campo File Reference to the base MFT record de la entrada respectiva en la MFT, sin embargo, debido a la necesidad de encontrar el archivo y al malentendido de esta referencia, me di la libertad de identificarlo segun ciertos atributos del atributo $FILE_NAME en la MFT: Creation time, Altered time, MFT Changed y Read time, ya que casualmente cada conjunto de estos datos en la respectiva entrada INDX corresponde con tal. Asi pues, vamos a buscar la incidencia de lo que serian del desplazamiento 18h al desplazamiento 18h+20h (20h es el tamaño de esta estructura de fechas completa), es decir, esta estructura de fechas. Nos encontramos con la cadena:

CitarE0 79 98 BC 8F 46 CE 01 C8 57 E8 5C 46 B8 D7 01 C8 57 E8 5C 46 B8 D7 01 C8 57 E8 5C 46 B8 D7 01

Busquemos la incidencia de esta cadena en la MFT en su respectivo campo:



Nos encontramos con su MFT, precisamente. Ahora, ya que este tambien es un directorio, accedamos a su atributo $ALLOCATION_TABLE:



Decodifiquemos sus data runs:

32 2C 01 86 60 04 - 12C  Clusters @ LCN 46086 (addr 8C10C00)
21 04 EC 03          - 4      Clusters @ LCN 2EC
21 04 A4 00           - 4     Clusters @ LCN A4
21 04 10 01           - 4     Clusters @ LCN 110
00                         - Final de los cluster runs

Accedamos:



Busquemos la entrada correspondiente del archivo CMD.EXE:



Bingo. Segun sus campos de fechas, busquemos la incidencia de este archivo en la MFT:



BingoX2. Ahora paseemos por la tabla hasta su $DATA attribute:



Perfecto, ahora estamos solo a un paso de acceder al contenido del archivo. Segun lo que podemos ver, este es un atributo no residente y sin nombre. Segun la tabla de atributos no residentes y sin nombre, mencionada en "ATTRIBUTE HEADER", los data run se encontrarian en el offset 40h; como puede apreciarse en la imagen de la cabecera. Decodifiquemos estos data runs:

32 A0 01 73 1E 04 - 1A0 Clusters @ LCN 41E73 (addr 83CE600)
00
(Facilongo ;)

Ahora podemos, finalmente, acceder a los contenidos del archivo:




NOTAS FINALES

Esta es una muy resumida explicacion del funcionamiento del sistema NTFS y del recorrido hasta un archivo; mas que una lectura educativa, puede ser un divertido primer contacto con el sistema y su funcionamiento, previo a un estudio mas profundo de las catacumbas de los DBMS como lo son, entre los desarrollados por Microsoft y mas populares, NTFS, FAT y sus extensiones, entre otros.

Me gustaria terminar con una sugerencia... Deberia haber un subforo de sistemas operativos en general, en donde se puedan preguntar cosas relacionadas a los diferentes OSs y sus subsistemas, cosas relacionadas a firmware, programacion de sistemas operativos (Ya que no tiene nada que ver con "Programacion en general", no es lo mismo programar para un sistema operativo que programar para una arquitectura de hardware, sea esta estandar o no), gestion de procesos, gestion de memoria... Etc.; en general, temas no solo relacionados sino con una relacion estrecha con los OS y su desarrollo.

En el caso de haberme equivocado, ruego me corrija quien haya reconocido mi error. Y si queda algun hueco, mencioarlo para que asi pueda llenarlo.

Gracias por su atencion, un saludo y

Buenas noches.

Fuentes:

https://bromiley.medium.com/a-journey-into-ntfs-part-1-e2ac6a6367ec
http://inform.pucp.edu.pe/~inf232/Ntfs/ntfs_doc_v0.5/index.html
https://www.youtube.com/watch?v=aZjYr87r1b8
https://cis.stvincent.edu/html/tutorials/swd/btree/btree.html
https://flatcap.org/linux-ntfs/ntfs/index.html
Nota sobre las fuentes: flatcap.org y inform.pucp.edu.pe son paginas similares pero tienen informacion diferente.