April 07, 2020

Capture de la géométrie d’un jeu OpenGL par instrumentation des shaders OpenGL

Ce stage de Master 2 de Bastien Thomasson a porté sur la capture de la géométrie d’un niveau de jeu et ce, au fur et à mesure que l’on joue. Le travail portait sur l’écriture d’un programme permettant :

  • d’intercepter les appels OpenGL pour les dérouter vers des fonctions d’analyse et de capture. Cette fonctionnalité fait essentiellement appel à de la programmation système.

  • d’instrumenter les shaders pour capturer les informations géométriques. Cette fonctionnalité fait appel à l’analyse grammaticale (bison, flex ; nous avons aussi testé du code ANTLR)

  • de reconstituer un univers 3D en inférant la matrice de transformation globale à partir de la matrice de vue, image après image.

  • capture automatique une fois un paramétrage mis en place pendant que le jeu tourne, effectué une seule fois. Et ce, sans altérer le fonctionnement du jeu.

  • programmation de toute l’interface utilisateur nécessaire à cet effet

Un nuage de points est ainsi alimenté au fur et à mesure que le joueur évolue dans son environnement. Nous nous sommes arrêtés là, mais un maillage peut être reconstitué très rapidement avec des méthodes comme Raster2Mesh (video).

Nous avons testé la capture avec deux jeux, IOQuake 3 (dans la vidéo), et SuperTuxCart.

Les appels OpenGL sont d’abord détournés. Sous Windows, cela consiste à appeler CreateProcess(), attendre le chargement des bibliothèques OpenGL (OPENGL32.DLL et éventuellement les bibliothèques spécifiques aux drivers, fonctions récupérables par wglGetProcAddress()), à récupérer les adresses, puis à poker dans l’espace virtuel du process via WriteProcessMemory() pour détourner vers des fonctions typiquement chargées dans une DLL contenant l’implémentation des fonctions détournées. Ces dernières font leur travail puis appellent à leur tour les vraies fonctions OpenGL.

Il existe d’autres manières de détourner des appels, comme par exemple :

  Le programme repose sur l’instrumentation de shaders, dont l’analyse est illustrée de manière basique dans la vidéo ci-dessous.