
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 :