
CVE-2017-8570 Exp及利用样本分析
save-restore, ce qui constitue une vulnérabilité Use-After-Free (UAF). La vulnérabilité peut être exploitée lorsqu'un utilisateur ouvre un fichier contenant une image graphique mal formatée, ou lorsqu'il insère une image graphique mal formatée dans un fichier Office.L'auteur a cherché longtemps en ligne sans trouver un package Office contenant EPSIMP32.FLT. Heureusement, le camarade kcufId a fourni un
LoadEps.exepour charger les fichiers EPS. Merci au camarade kcufId.
LoadEps.exe charge d'abord :
EPSIMP32.FLT
Ensuite, il appelle ImportGr pour commencer le chargement du fichier EPS :

F7 directement ici, puis on peut réussir à s'arrêter sur le point d'arrêt défini dans EPSIMP32.FLT.
Avant d'entrer dans le vif du sujet, décrivons d'abord la structure des objets PostScript.
// Objet PostScript
struct PostScript object
{
dword type;
dword attr;
dword value1;
dword value2; // si tableau, pointe vers le dictionnaire utilisateur où l'objet tableau est stocké
} ps_obj;
Les valeurs correspondant aux différents type sont les suivantes :
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
Prenons l'exemple d'une chaîne de caractères pour expliquer sa structure de stockage. En définissant un point d'arrêt sur la fonction forall, on peut voir comment elle traite une chaîne (pour savoir comment localiser la fonction forall, voir https://paper.seebug.org/368/).

L'image 1 correspond à ps_obj, dont l'élément value2 pointe vers l'élément correspondant dans la liste d'index (image 2) ; l'élément d'index pointe vers une structure de taille 0x30. À l'offset 0x24 de cette structure se trouve un pointeur vers un pointeur vers une structure de taille 0x28 (image 5). L'offset 0x2C contient la taille de la chaîne (image 3). Dans la structure de l'image 5, l'offset 0x4 stocke l'adresse de l'élément correspondant dans la liste d'index (c'est-à-dire l'adresse 0x01DB5E94 sur l'image 4). L'offset 0x20 pointe vers l'emplacement final de la chaîne (image 6), et l'offset 0x24 contient la taille mémoire réellement occupée — taille de la chaîne + 1.
Structure de taille 0x30 :
+0x0 dword
+0x4 dword
+0x8 dword
+0xc dword
+0x10 dword
+0x14 dword
+0x18 dword
+0x1c dword
+0x20 dword
+0x24 dword pp_struct // pointeur vers un pointeur vers une structure de taille 0x28
+0x28 dword
+0x2c dword size // taille réelle de la chaîne
Structure de taille 0x28 (pour un tableau, cette structure a une taille de 0x2C, et l'offset 0x28 pointe vers les éléments du tableau, chaque élément étant un ps_obj) :
+0x0 dword
+0x4 dword // stocke l'adresse de l'élément correspondant dans la liste d'index
+0x8 dword
+0xc dword
+0x10 dword
+0x14 dword
+0x18 dword
+0x1c dword
+0x20 dword ptr_object // pointe vers l'emplacement final de la chaîne
+0x24 dword size // taille mémoire réellement occupée, taille réelle de la chaîne + 1
Première déclenchement de la vulnérabilité :

Tout d'abord, l'état de la machine virtuelle est sauvegardé dans la variable l62. Ensuite, pour chaque caractère de la variable l63, le processus l61 —>> l59 —>> l56 est appelé ; l62 restore restaure l'état précédent, ce qui libère l'espace mémoire alloué par l63 après l'instruction /l62 save def, créant ainsi un pointeur pendant (dangling pointer).

Les variables l95-l99 déterminent le flux suivant, et leurs valeurs sont toutes égales à 0 (c'est-à-dire 32 bits) :

Deuxième déclenchement de la vulnérabilité. Tout d'abord, un espace mémoire de taille 0x27 (qui en occupe réellement 0x28) est alloué pour stocker l63 :

Ensuite, l62 restore restaure l'état précédent, libérant l'espace mémoire alloué à l63, créant ainsi un pointeur pendant. Puis, l'exécution de l100 utilise l'espace mémoire précédemment occupé par l63 pour stocker la structure 0x28 de la chaîne l102 (c'est-à-dire l136) (ce qui explique pourquoi l63 demandait 0x27 octets) :

On récupère les valeurs aux offsets 0x4, 0x20 et 0x24 de cette structure :

Enfin, on modifie le contenu de la chaîne l136 (l'image ne montre qu'une partie des modifications) :

Ces modifications sont soigneusement construites pour être utilisées lors du troisième déclenchement de la vulnérabilité.
Troisième déclenchement de la vulnérabilité. Un tableau contenant 0x37 éléments est alloué, puis lors du traitement du 0x34e élément, l62 restore est exécuté :

Après l'exécution de restore, la structure 0x30 du tableau est écrasée par le contenu de la chaîne l193 :

Ainsi, l'objet exécuté lors du dernier (0x36) passage de forall devient la structure 0x30 de l'image ci-dessus. L'accès à son 0x36e élément mène à la chaîne soigneusement construite lors du deuxième déclenchement :

L'élément de tableau ainsi obtenu est un tableau de taille 4, dont le premier élément est une chaîne de taille 0x7FFFFFFF commençant à l'adresse 0 :

Ce tableau est stocké dans la variable l159. Son premier élément — la chaîne de taille 0x7FFFFFFF commençant à l'adresse 0 — est stocké dans la variable l201. Ensuite, on peut accéder à n'importe quelle adresse via la variable l201.
Obtention de l'adresse de base de kernel32.dll :


Ainsi, la variable l314 contient l'adresse de base de EPSIMP32.FLT.

Note : la syntaxe de la commande search est la suivante :

Recherche de gadgets spécifiques :


Construction d'une structure de type 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

Écriture des données construites à l'adresse l492 (l491 + 0x32) :
l492 0 l201 put_data_to_array %% 0x00 0
l492 4 my_add l375 l201 put_data_to_array %% 0x04 Adresse de <5E C3>
l492 8 my_add l373 l201 put_data_to_array %% 0x08 Adresse de <94 00 00 00 00 5E C3>
l492 12 my_add l377 l201 put_data_to_array %% 0x0C Adresse de <C2 0C 00>
l492 16 my_add l370 l201 put_data_to_array %% 0x10 Adresse de 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 Adresse de la shellcode
l492 36 my_add l368 l201 put_data_to_array %% 0x24 Adresse de la shellcode — lpAddress
l492 40 my_add l349 l201 put_data_to_array %% 0x28 Taille de la 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
Enfin, l'exécution de l'instruction closefile déclenche le saut vers la shellcode :

Le script d'exploitation EPS se trouve dans le répertoire \word\media ; il suffit de le décompresser pour le voir. Les échantillons d'exploitation de cette vulnérabilité sont fondamentalement identiques, à l'exception de la shellcode. Nous prenons donc un échantillon de l'organisation Patchword comme exemple pour l'analyse.
Nom du fichier : Cyber_Secure_Pakistan.docx
MD5 : DD89BBB916A2C909630EC78CBB0E13E5
Saut vers la shellcode, restauration de la pile :

Allocation de mémoire :

Obtention des adresses des appels de fonctions :

Pendant le débogage, il se peut que l'adresse de la fonction CreateToolhelp32Snapshot n'ait pas été obtenue correctement à cause de l'environnement :

Saisir manuellement l'adresse et ouvrir Word pour continuer l'analyse. Énumération des processus, recherche de WINWORD.exe :

Création d'un programme nommé MSBuild.exe dans le répertoire C:\ProgramData\Microsoft\DeviceSync :

Écriture du contenu du fichier, stocké dans la variable payload_32 du script EPS :


Création du fichier vmtools.dll :

Écriture du contenu du fichier, stocké dans la variable payload_32_f2 du script EPS :


Création du fichier VMwareCplLauncher.exe :

Son contenu est stocké dans la variable payload_32_f1 du script EPS :

Ce fichier est un fichier blanc signé VMware :

Injection du contenu suivant dans explorer.exe :

Sa fonction est de créer un processus VMwareCplLauncher.exe :

La suite du processus est mentionnée dans ce rapport de 360 ; cet article n'aborde pas la partie analyse :

Les lecteurs intéressés peuvent consulter ce rapport.
Note : Les échantillons d'exploitation de cette vulnérabilité sont fondamentalement similaires. La différence réside dans la charge utile finale de MSBuild.exe, stockée dans la variable payload_32 du script EPS. On peut la dumper directement. Après avoir rempli l'en-tête de fichier DOS, on peut l'importer dans IDA pour l'analyse.