
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: