
Exploit de preuve de concept pour CVE-2022-37969, une élévation de privilèges locale du pilote Windows Common Log File System. Démontre le heap spray, le vol de jeton et l'écriture arbitraire dans le noyau pour obtenir les privilèges SYSTEM.
auteurs : Ricardo Narvaja & Daniel Kazimirow (Solid)
À des fins de démonstration uniquement. L'exploit complet fonctionne sur les systèmes vulnérables Windows 11 21H2.
PoC fonctionnel basé sur les informations précédemment publiées par Zscaler
Consultez l'article Understanding the CVE-2022-37969 Windows Common Log File System Driver Local Privilege Escalation.
Présentation de l'exploitation :
Le scénario utilisé ici était Windows 11 21H2 (OS Build 22000.918) clfs.sys v10.0.22000.918
La première étape consiste à créer un fichier nommé MyLog.blf dans le dossier public (%public%), en utilisant la fonction CreateLogFile() :



Ensuite, il crée plusieurs fichiers journaux avec des noms aléatoires en utilisant une boucle.
Et dans la boucle, il appelle notre fonction getBigPoolInfo() :

Elle appelle NtQuerySystemInformation(), avec 0x42 (66 décimal) comme premier argument, cela retournera dans v5 les informations sur les allocations faites dans le bigpool, dont la structure est de type SYSTEM_BIGPOOL_INFORMATION.

Nous devons appeler cette fonction deux fois. La première retournera une erreur, mais nous donnera la taille correcte du tampon pour appeler la seconde fois et obtenir les informations souhaitées.

v5 recevra les informations de la structure SYSTEM_BIG_POOL_INFORMATION.

Le nombre d'allocations dans le bigpool est stocké dans le premier champ appelé Count, dans le second champ se trouve un tableau de structures SYSTEM_BIGPOOL_ENTRY.

Ensuite, nous recherchons dans toutes les structures la balise "Clfs" et la taille 0x7a00.

Il stocke dans un tableau appelé kernelAddrArray l'adresse virtuelle qui est le premier champ de chaque structure ayant la balise CLFS et la taille 0x7a00. Désormais, les pools qui remplissent ces deux conditions seront appelés : "pools corrects".

En plus de stocker chaque pool correct dans le tableau, il stocke le dernier pool correct trouvé dans le contenu de la variable a2, qui est utilisée comme argument de la fonction.

Ainsi, a2 pointe toujours vers le dernier pool correct créé avec la balise CLFS et la taille 0x7a00.
La variable v26 stocke toujours le pool correct précédent trouvé car elle est égale à v24 (v26=v24), avant d'appeler getBigPoolinfo(), mais v24 est mise à jour en sortant de cet appel avec le dernier pool correct trouvé, et v26 reste avec le pool correct précédent trouvé.

Ensuite, il soustrait les deux directions, et si le résultat est négatif, il inverse les opérandes pour qu'il soit toujours positif.

Ainsi, dans v32 sera stockée la différence entre l'adresse virtuelle des deux derniers pools corrects trouvés.
Ensuite, il fait quelque chose de similaire. Dans ce cas, v23 est initialement nul, donc il fait v23 = v32 la première fois.

La prochaine fois dans la boucle, v23 a toujours la même valeur et n'est pas nul, donc il s'arrête et va ici.

V32 a la dernière différence et v23 la précédente, si elles sont égales, il sort et incrémente de un, mais remet le compteur à zéro.
L'idée est de trouver 6 comparaisons consécutives de balises CLFS et de taille 0x7a00 dont les différences sont égales, et cette différence sera 0x11000. Nous verrons lors de l'exécution que lorsqu'il trouve 6 (car il repart de zéro) consécutives avec des distances égales, il donnera cette valeur de différence entre elles.


Là, nous voyons qu'il a trouvé 6 consécutives et a quitté la boucle de création de fichiers journaux.
Dans le dossier "public", nous pouvons voir les fichiers créés
