Correcciones de relocación inseguras en cargadores de assets

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Por qué importan las relocaciones de assets

Muchos motores de juego heredados (Granny 3D, Gamebryo, etc.) cargan assets complejos mediante:

  1. Analizar un header y la tabla de secciones.
  2. Asignar un heap buffer por sección.
  3. Construir un SectionArray que almacena el puntero base de cada sección.
  4. Aplicar tablas de relocación para que los punteros embebidos dentro de los datos de la sección se parchen al offset + sección objetivo correctos.

Cuando el manejador de relocaciones confía ciegamente en metadata controlada por el atacante, cada relocación se convierte en un potencial primitivo de lectura/escritura arbitraria. En Anno 1404: Venice, granny2.dll incluye la siguiente función auxiliar:

`GrannyGRNFixUp_0` (recortado) ```c int *__cdecl GrannyGRNFixUp_0(DWORD RelocationCount, Relocation *PointerFixupArray, int *SectionArray, char *destination) { while (RelocationCount--) { int target_base = SectionArray[PointerFixupArray->SectionNumber]; // unchecked index int *patch_site = (int *)(destination + PointerFixupArray->SectionOffset); // unchecked offset *patch_site = target_base ; if (target_base) *patch_site = target_base + PointerFixupArray->Offset; ++PointerFixupArray; } return SectionArray; } ```

SectionNumber nunca se comprueba en rango y SectionOffset nunca se valida respecto al tamaño actual de la sección. Crear entradas de relocación con offsets negativos o índices sobredimensionados permite salir de la sección que controlas y pisar metadatos del allocator como el propio arreglo de punteros de sección.

Etapa 1 – Escribir hacia atrás en los metadatos del loader

El objetivo es lograr que la tabla de relocación de sección 0 sobrescriba entradas de SectionContentArray (que refleja a SectionArray y se almacena justo antes del primer buffer de sección). Debido a que el custom allocator de Granny antepone 0x1F bytes y la NT heap añade su propio encabezado de 0x10 bytes más alineamiento, un atacante puede precalcular la distancia entre el inicio de la primera sección (destination) y el arreglo de punteros de sección.

En la build probada, forzar al loader a asignar una estructura GrannyFile de exactamente 0x4000 bytes hace que los arreglos de punteros de sección queden justo antes del primer buffer de sección. Resolviendo

0x20 (header) + 0x20 (section descriptors)
+ n * 1 (section types) + n * 1 (flags)
+ n * 4 (pointer table) = 0x4000

genera n = 2720 secciones. Una entrada de relocación con SectionOffset = -0x3FF0 ( 0x4000 - 0x20 - 0x20 + 0x30 ) ahora resuelve a SectionContentArray[1] aunque la sección destino piense que está parchando punteros internos.

Etapa 2 – Distribución determinista del heap en Windows 10

Windows 10 NT Heap dirige las asignaciones ≤ RtlpLargestLfhBlock (0x4000) al LFH aleatorizado y las mayores al asignador backend determinista. Manteniendo los metadatos de GrannyFile ligeramente por encima de ese umbral (usando el truco de 2720 secciones) y precargando varios .gr2 assets maliciosos, puedes hacer que:

  • La asignación #1 (metadata + section pointer arrays) quede en un chunk backend >0x4000.
  • La asignación #2 (contenido de la sección 0) quede inmediatamente después de la asignación #1.
  • La asignación #3 (contenido de la sección 1) quede justo después de la asignación #2, dándote un objetivo predecible para las relocaciones subsecuentes.

Process Monitor confirmó que los assets se transmiten bajo demanda, por lo que solicitar repetidamente unidades/edificios creados a medida es suficiente para “preparar” la disposición del heap sin tocar la imagen ejecutable.

Etapa 3 – Convertir el primitivo en RCE

  1. Corrompe SectionContentArray[1]. La tabla de relocaciones de la sección 0 la sobrescribe usando el offset -0x3FF0. Apúntala a cualquier región escribible que controles (p.ej., datos de una sección posterior).
  2. Recicla el puntero corrompido. La tabla de relocaciones de la sección 1 ahora trata SectionNumber = 1 como el puntero que inyectaste. El manejador escribe SectionArray[1] + Offset en destination + SectionOffset, otorgándote una escritura arbitraria de 4 bytes por cada entrada de relocación.
  3. Golpea dispatchers fiables. En Anno 1404 el objetivo elegido fueron los allocator callbacks de granny2.dll (sin ASLR, DEP deshabilitado). Sobrescribir el puntero de función que granny2.dll usa para la siguiente llamada a Malloc/Free desvía inmediatamente la ejecución a código controlado por el atacante cargado desde el asset troyanizado.

Como tanto granny2.dll como los buffers .gr2 inyectados residen en direcciones estables cuando ASLR/DEP están deshabilitados, el ataque se reduce a construir una pequeña cadena ROP o shellcode bruto y apuntar el callback hacia ella.

Lista de verificación práctica

  • Busca asset loaders que mantengan SectionArray / relocation tables.
  • Haz diff de los relocation handlers buscando límites faltantes en índices/offsets.
  • Mide los encabezados del allocator añadidos tanto por el wrapper del allocator del juego como por el heap del SO subyacente para calcular con precisión los offsets hacia atrás.
  • Forzar la colocación determinista mediante:
    • inflar los metadatos (muchas secciones vacías) hasta que el tamaño de la asignación > RtlpLargestLfhBlock;
    • cargar repetidamente el asset malicioso para llenar huecos del backend.
  • Usa una tabla de relocación en dos etapas (primero para redirigir SectionArray, segundo para esparcir escrituras) y sobrescribe punteros de función que se ejecuten durante el renderizado normal (allocator callbacks, virtual tables, animation dispatchers, etc.).

Una vez obtengas una escritura arbitraria de archivo (p.ej., vía el path traversal en la transferencia de guardado multijugador), volver a empaquetar los archivos RDA con el .gr2 manipulado te da un vector de entrega limpio que es descomprimido automáticamente por los clientes remotos.

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks