
CVE-2017-8570 Exploit y análisis de muestras de explotación
Causa: al abrir un documento de Office, FLTLDR.EXE se utiliza para procesar el archivo EPS incrustado que contiene la vulnerabilidad. Este archivo está escrito en lenguaje PostScript y puede ser explotado por un atacante mediante la operación "save-restore"; en esencia, se trata de una vulnerabilidad de tipo UAF. Esta vulnerabilidad puede explotarse cuando el usuario abre un archivo que contiene una imagen gráfica con formato incorrecto, o cuando inserta una imagen gráfica con formato incorrecto en un archivo de Office.
Versiones afectadas: Microsoft Office 2010 Service Pack 2, Microsoft Office 2013 Service Pack 1, Microsoft Office 2016
POC: kcufId's Github
El autor buscó durante mucho tiempo en Internet y no encontró ningún paquete de instalación de Office que contuviera EPSIMP32.FLT. Afortunadamente, el experto kcufId proporcionó un LoadEps.exe para cargar archivos EPS. Gracias al experto kcufId.
LoadEps.exe primero carga EPSIMP32.FLT:

Después llama a ImportGr para comenzar a cargar el archivo EPS:

En este punto, pulse F7 directamente para entrar (step into) y así podrá detenerse con éxito en el punto de interrupción establecido dentro de EPSIMP32.FLT.
Antes de entrar en materia, expongamos primero la estructura del objeto PostScript.
// PostScript Object
struct PostScript object
{
dword type;
dword attr;
dword value1;
dword value2; // if array, point to userdict where store the array object
}ps_obj;
Los valores correspondientes a los diferentes type son los siguientes:
0x0 nulltype
0x3 integertype
0x5 realtype
0x8 booleantype
0x10 operatortype
0x20 marktype
0x40 savetype
0x300 nametype
0x500 stringtype
0x900 filetype
0x30000 arraytype
0x0B0000 packedarraytype
0x70000 packedarraytype
0x110000 dicttype
0x210000 gstatetype
Tomando una cadena como ejemplo, se explicará su estructura de almacenamiento. Al establecer un punto de interrupción en la función forall, se puede observar cómo procesa las cadenas (para saber cómo localizar la función forall, consulte https://paper.seebug.org/368/).

La imagen 1 corresponde a ps_obj, cuyo campo value2 apunta al elemento correspondiente en la lista de índices (imagen 2); el elemento de índice apunta a una estructura de tamaño 0x30; en el desplazamiento 0x24 de esta estructura se almacena un puntero a un puntero que apunta a una estructura de tamaño 0x28 (imagen 5), y en el desplazamiento 0x2C se almacena el tamaño de la cadena (imagen 3). En la estructura de la imagen 5, el desplazamiento 0x4 almacena la dirección del elemento correspondiente a esta estructura en la lista de índices (es decir, 0x01DB5E94 de la imagen 4); el desplazamiento 0x20 apunta a la ubicación final de almacenamiento de la cadena (imagen 6); el desplazamiento 0x24 es el tamaño real de memoria ocupada: el tamaño de la cadena + 1.
Estructura de tamaño 0x30:
+0x0 dword
+0x4 dword
+0x8 dword
+0xc dword
+0x10 dword
+0x14 dword
+0x18 dword
+0x1c dword
+0x20 dword
+0x24 dword pp_struct //指向大小为0x28结构的指针的指针
+0x28 dword
+0x2c dword size //字符串实际大小
Estructura de tamaño 0x28 (si se trata de un array, esta estructura tiene un tamaño de 0x2C y el desplazamiento 0x28 apunta a los elementos del array, siendo cada elemento un ps_obj):
+0x0 dword
+0x4 dword //存储该结构于索引列表中对应项的地址
+0x8 dword
+0xc dword
+0x10 dword
+0x14 dword
+0x18 dword
+0x1c dword
+0x20 dword ptr_object //指向字符串最终存储位置
+0x24 dword size //实际所占内存大小,字符串实际大小+1
Primera activación de la vulnerabilidad:

Primero se guarda el estado de la VM en la variable l62; después, para cada carácter de la variable l63, se invoca el proceso de tratamiento l61——>>l59——>>l56; l62 restore restaura el estado anterior. De esta manera, el espacio de memoria solicitado por l63 después de la sentencia /l62 save def es liberado y se convierte en un puntero colgante.

Las variables l95-l99 determinan el flujo posterior y todas tienen un valor de 0 (es decir, 32 bits):

Segunda activación de la vulnerabilidad: primero se solicita un espacio de memoria de tamaño 0x27 (que en realidad ocupará 0x28) para almacenar l63:

Después, l62 restore restaura el estado anterior, lo que provoca que el espacio de memoria solicitado por l63 sea liberado y se convierta en un puntero colgante. A continuación se ejecuta l100, y el espacio de memoria antes ocupado por l63 se utiliza para almacenar la estructura 0x28 de la cadena l102 (es decir, l136) (esto explica por qué l63 solicitó un espacio de memoria de tamaño 0x27):

Se obtienen respectivamente los valores en los desplazamientos 0x4, 0x20 y 0x24 de esta estructura:

Finalmente, se modifica el contenido de la cadena l136 (en la imagen solo se muestran algunas de las modificaciones):

Estas modificaciones están cuidadosamente construidas y se utilizarán en la tercera activación de la vulnerabilidad.
Tercera activación de la vulnerabilidad: se solicita un array que contiene 0x37 elementos; después, cuando el bucle llega al elemento 0x34, se ejecuta l62 restore:

Después de ejecutar restore, la estructura 0x30 del array es sobrescrita por el contenido de la cadena l193:

De esta manera, el objeto ejecutado en el proceso forall final (0x36) pasa a ser la estructura 0x30 de la imagen anterior, y al obtener su elemento 0x36 se llega a la cadena cuidadosamente construida durante la segunda activación de la vulnerabilidad:

El elemento del array obtenido es un array de tamaño 4, cuyo primer elemento es una cadena con dirección de inicio 0 y tamaño 0x7FFFFFFF:

Este array se almacena en la variable l159; su primer elemento —la cadena con dirección de inicio 0 y tamaño 0x7FFFFFFF— se almacena en la variable l201. A partir de entonces, se puede utilizar la variable l201 para obtener el valor de cualquier dirección.
Obtención de la dirección base de kernel32.dll:


De esta manera, la variable l314 almacena la dirección base de EPSIMP32.FLT.

Nota: la sintaxis del comando search es la siguiente:

Búsqueda del gadget especificado:


Construcción de la estructura de tipo file:
l199 l201 get_dword
/l487 exch def
l487 l201 get_dword
/l488 exch def
l488 36 my_add l201 get_dword
/l489 exch def
l489 l201 get_dword
/l490 exch def
l490 32 my_add l201 get_dword
/l491 exch def
l199 l491 l201 put_data_to_array
l199 12 my_sub 2304 l201 put_data_to_array

Escritura de los datos construidos en la dirección l492 (l491+0x32):
l492 0 l201 put_data_to_array %% 0x00 0
l492 4 my_add l375 l201 put_data_to_array %% 0x04 Address of <5E C3>
l492 8 my_add l373 l201 put_data_to_array %% 0x08 Address of <94 00 00 00 00 5E C3>
l492 12 my_add l377 l201 put_data_to_array %% 0x0C Address of <C2 0C 00>
l492 16 my_add l370 l201 put_data_to_array %% 0x10 Address of VirtualProtect()
l492 20 my_add 0 l201 put_data_to_array %% 0x14 0
l492 24 my_add 0 l201 put_data_to_array %% 0x18 0
l492 28 my_add 0 l201 put_data_to_array %% 0x1C 0
l492 32 my_add l368 l201 put_data_to_array %% 0x20 Address of Shellcode
l492 36 my_add l368 l201 put_data_to_array %% 0x24 Address of Shellcode——lpAddress
l492 40 my_add l349 l201 put_data_to_array %% 0x28 Size of Shellcode——dwSize
l492 44 my_add 64 l201 put_data_to_array %% 0x2C PAGE_EXECUTE_READWRITE——flNewProtect
l492 48 my_add l493 l201 put_data_to_array %% 0x30 lpflOldProtect
Finalmente, al ejecutar la instrucción closefile, se salta al Shellcode:

El script de explotación EPS se encuentra en el directorio \word\media; se puede ver después de descomprimir el archivo. Las muestras de explotación de esta vulnerabilidad son básicamente idénticas excepto por la parte del Shellcode, por lo que se toma como ejemplo una muestra de la organización Patchword para su análisis.
Nombre de archivo: Cyber_Secure_Pakistan.docx
MD5: DD89BBB916A2C909630EC78CBB0E13E5
Salto al Shellcode y restauración de la pila:

Solicitud de memoria:

Obtención de las direcciones de llamada de las funciones:

Durante la depuración, posiblemente debido a problemas del entorno, no se pudo obtener correctamente la dirección de llamada de la función CreateToolhelp32Snapshot:

Se rellenó la dirección manualmente y se abrió Word para continuar con el análisis. Enumere los procesos y busque WINWORD.exe:

Se crea un programa llamado MSBuild.exe en el directorio C:\ProgramData\Microsoft\DeviceSync:

Se escribe el contenido del archivo, el cual se almacena en la variable payload_32 del script EPS:


Creación del archivo vmtools.dll:

Se escribe el contenido del archivo, el cual se almacena en la variable payload_32_f2 del script EPS:


Creación del archivo VMwareCplLauncher.exe:

Su contenido se almacena en la variable payload_32_f1 del script EPS:

Este archivo es un archivo legítimo con firma de Vmware:

Se inyecta el siguiente contenido en explorer.exe:

Su función es crear un proceso de VMwareCplLauncher.exe:

El flujo posterior se menciona en este informe de 360; este artículo no abordará por ahora esa parte del análisis:

Los lectores interesados pueden consultar el informe para más detalles.
Nota: las muestras de explotación de esta vulnerabilidad son básicamente similares; la diferencia radica en la carga final de MSBuild.exe, que se almacena en la variable payload_32 del script EPS. Se puede extraer directamente y, después de completar el encabezado del archivo DOS, arrastrarla a IDA para su análisis.