Wright en las sombras

Esta es una historia sobre una de las tareas que preparamos para la etapa de calificación CTFZone , que se realizó a fines de noviembre. Puede leer sobre el proceso de preparación de calificación aquí .

Comienza con dos archivos: decrypt_flag.py y ntfs_volume.raw. Echemos un vistazo al guión. Abre un archivo llamado key.bin, y luego, usando un bucle, intenta tomar una cadena binaria de 34 bytes de cada desplazamiento dentro del archivo, que luego se usa como entrada para la función PBKDF2. Cada clave devuelta se usa como una clave XOR para descifrar la cadena cifrada cosida en el código. Si su hash MD5 descifrado coincide con el valor predeterminado en una forma descifrada, el script usa los datos recibidos para generar e imprimir la bandera.

Entonces necesita encontrar el archivo key.bin. Es imposible simplemente ordenar todos los desplazamientos dentro del archivo de imagen (ntfs_volume.raw), ya que el proceso de encontrar la clave será demasiado lento. Las reglas no lo prohíben, pero ciertamente no tendrá tiempo antes del final del CTF.

El archivo de imagen contiene una tabla de partición MBR de partición única. Su desplazamiento es 2048 sectores de 512 bytes, y contiene el sistema de archivos NTFS, pero el archivo key.bin no está allí:

$ fls -o 2048 -r -p ntfs_volume.raw | grep -F key.bin | wc –l
0

NTFS almacena nombres de archivos codificados UTF-16LE. ¡Intentemos buscar en él!


Resultados de búsqueda para registros de archivos

Después de estudiar los resultados de búsqueda, nos centramos en los registros de archivos que comienzan con la firma FILE [1]. Aquí está la única entrada de este tipo:


Registro encontrado ¡

El objetivo ya está cerca! Tenemos un registro de archivo, pero necesitamos datos. En NTFS, se almacenan en el atributo $ DATA, que puede ser residente o no residente [2]. Para el registro que encontramos, este atributo comienza en el desplazamiento 0 × 3AADD00 e indica datos no residentes (esto significa que la información se almacena fuera del registro del archivo).

Entonces, ¿dónde están exactamente los datos del archivo deseado? Para responder a esta pregunta, es necesario decodificar los llamados pares de mapeo, o corridas de datos (pares "longitud de bloque - desplazamiento de bloque") [3]. Las ejecuciones de datos del archivo deseado son las siguientes (tenga en cuenta el desplazamiento 0 × 3AADD40): 22 53 01 A0 4E 21 05 31 C1 11 38 30 00. O, si los reorganizamos:

1.	22 53 01 A0 4E
2.	21 05 31 C1
3.	11 38 30 00

El archivo consta de tres fragmentos, el tamaño del primero de los cuales es de 339 grupos, y comienza con el grupo # 20128. Para nuestro código que usa PBKDF2, este fragmento es grande. Como se indica en el encabezado del sistema de archivos, el tamaño de un clúster es de 4096 bytes:

$ fsstat -o 2048 ntfs_volume.raw | grep 'Cluster Size'
Cluster Size: 4096

Echemos un vistazo a los datos para este desplazamiento (en bytes):
2048 * 512 + 20128 * 4096 = 83492864. Extraeremos cualquier cantidad significativa de información (por ejemplo, 128 bytes) desde aquí, insértela en un nuevo archivo, que llamaremos key.bin, ejecute el script ... Nada tuvo éxito.

Quizás el archivo no estaba almacenado en la versión actual, sino en la versión anterior del sistema de archivos (formato anterior); no olvide que no vimos el registro sobre el archivo eliminado con el mismo nombre. ¿Cuál era el tamaño del clúster antes? Busquemos el encabezado del sistema de archivos con la firma NTFS [4]. Tal vez tengamos suerte y realmente encontremos el encabezado del formato anterior.


Resultados de búsqueda para el encabezado del sistema de archivos

Las primeras y últimas posiciones en los resultados de búsqueda se refieren al sistema de archivos actual, pero los encabezados del sistema de archivos ubicados entre ellos parecen pertenecer al formato anterior. ¡Y tienen un tamaño de racimo diferente!


El encabezado del sistema de archivos de la versión anterior.

Tal tamaño de sector se escribe en un desplazamiento de 0 × 4554800B: 00 02 o 512. Pero dicho tamaño de clúster se registra en un desplazamiento de 0 × 0x4554800D: F7 o 247.

Entonces, tenemos el tamaño de clúster (en bytes) 512 * 247 = 126464. ¡Algún tipo de tontería! Si cree que el analizador NTFS [5], dicho valor debe tener un signo y procesarse de manera especial, por lo que el tamaño real del clúster (en sectores) es 1 << - (- 9) = 512. O, si está en bytes, 512 * 512 = 262144 Ahora suena más creíble.

Los datos comienzan aquí en este desplazamiento (en bytes):
2048 * 512 + 20128 * 262144 = 5277483008. Intentemos nuevamente hacer el mismo truco con la información almacenada allí ... ¡De nuevo, un error! ¿Qué está mal? Tenemos CTF aquí, significa "no tan" que cualquier cosa puede ser.

La tarea por la que estamos luchando se llama In the Shadows. Es posible que tenga algo que ver con las instantáneas del volumen. Entonces, tenemos un archivo del sistema de archivos que anteriormente existía en este volumen. Desafortunadamente, simplemente no podemos tomar y montar su instantánea, ¡pero sabemos el desplazamiento exacto en el que comienzan los datos! Esto es 5277483008 o, dentro de la sección, 5277483008 - 2048 * 512 = 5276434432.

De acuerdo con las especificaciones del formato VSS [6], los bloques de datos redirigidos se describen en la estructura del descriptor de bloques que contiene un campo de 64 bits en el que se almacena el desplazamiento original (dentro del volumen), y También un campo de 64 bits que describe el desplazamiento del bloque de destino (dentro del volumen). Busquemos 5276434432 como un pequeño número endian de 64 bits.

Solo hay dos resultados en los resultados, y solo uno de ellos se encuentra en un desplazamiento uniforme.


Descriptor de bloque encontrado

Desplazamiento de bloque de destino: 00 00 9B 03 00 00 00 00, o simplemente 60489728. Desplazamiento final: 60489728 + 2048 * 512 = 61538304. Desde aquí, exporta una cierta cantidad de datos a un nuevo archivo llamado key.bin, y ...

$ ./decrypt_flag.py
ctfzone{my_c0ngr4t5_t0_u,w311_d0n3_31337}

¡Hecho!

Referencias


  1. https://flatcap.org/linux-ntfs/ntfs/concepts/file_record.html
  2. https://flatcap.org/linux-ntfs/ntfs/attributes/data.html
  3. https://flatcap.org/linux-ntfs/ntfs/concepts/data_runs.html
  4. https://flatcap.org/linux-ntfs/ntfs/files/boot.html
  5. https://github.com/msuhanov/dfir_ntfs/blob/94bb46d6600153071b0c3c507ef37c42ad62110d/dfir_ntfs/BootSector.py#L58
  6. https://github.com/libyal/libvshadow/blob/master/documentation/Volume%20Shadow%20Snapshot%20(VSS)%20format.asciidoc#431-block-descriptor

Source: https://habr.com/ru/post/undefined/


All Articles