Une technique d'obscurcissement : l'overlapping

Mon 03 September 2007 by alex

Je profite de l'étude d'un challenge pour illustrer une technique d'obscurcissement dénommée overlapping.

Motivations

Dans ce billet nous allons parler d'obscurcissement de code, plus connu sous le terme anglais obfuscation. L'obfuscation est un procédé visant à formater le code de manière à entraver d'éventuelles tentatives de rétro-ingénierie. Il existe de nombreuses techniques d'obfuscation (1 et 2) cependant nous nous focaliserons ici sur une technique nommée overlapping.

Présentation de la technique

Une traduction littérale d'overlapping donne une idée simple du procédé employé : la superposition. Cette technique consiste à superposer plusieurs instructions. Une instruction est alors encodée en utilisant une ou plusieurs autres comme support. Pour illustrer ce que nous venons de dire, étudions un exemple extrait d'un challenge proposé dans le cadre de la conférence Chaos Constructions Antique 2007, mettant en œuvre cette technique. Voici un exemple de code tel qu'il apparaît de prime abord dans le debugger Ollydbg. IDA est lui aussi incapable de désassembler correctement cette portion de code :

0040101B    BA EB059068     MOV EDX, 689005EB
00401020  ^ EB FA           JMP SHORT crackmes.0040101C
00401022    68 EB01BDEB     PUSH EBBD01EB
00401027    02EB            ADD CH, BL
00401029    77 64           JA SHORT crackmes.0040108F
0040102B    8925 00000000   MOV DWORD PTR DS:[0], ESP

Le saut situé à l'adresse 401020 fait référence à l'adresse 40101C, cette dernière est pourtant située au milieu de l'instruction précédente. Le moteur de désassemblage est alors mystifié. Il ne peut interpréter correctement la suite du code. Afin d'éclaircir encore le comportement réel de ce code, voici un schéma qui illustre la superposition des différentes instructions exécutées :

overlap.png

Le programme va tout d'abord exécuter le MOV à destination de EDX, puis l'instruction de saut JMP 01 qui pointe vers une adresse située au milieu de l'instruction MOV. La troisième instruction exécutée sera de nouveau un saut : JMP 08. Les octets sur lesquels l'instruction de saut est encodée : EB05, sont partagés avec l'instruction MOV EDX, 689005EB. Ce second saut nous permet finalement de reprendre le flot d'exécution normal du programme.

Le mot de la fin

L'overlapping est une technique très efficace pour mettre en échec un moteur de désassemblage. L'implémentation qui en a été faîte dans ce challenge est efficace mais souffre d'une trop faible variété de schémas, seulement au nombre de 4. C'est une faiblesse inhérente à cette technique, sa complexité la rend difficile à générer. Elle est en particulier très dépendante de l'architecture, c'est à dire du jeu d'instructions, de la plateforme cible. Pour rester sur l'architecture x86. Peu d'instructions se prêtent de façon satisfaisante à cette technique. Les contraintes majeures des instructions candidates sont : longueur des instructions, nombres d'octets partagés. Utilisé seule l'overlapping aura une efficacité limitée et sera mis en échec sans trop de difficultés. En revanche, combinée à d'autres techniques d'obfuscation, elle jouera pleinement son rôle et complexifiera encore un peu plus l'analyse du code.

Pour aller plus loin

  1. F. B. Cohen. Operating system protection through programevolution, 1992. http://all.net/books/IP/evolve.html
  2. C. Linn and S. Debray. Obfuscation of executable code to improve resistance to static disassembly. In Proceedings of the 10th ACM Conference on Computer and Communications Security (CCS), pages 290-299, Washington, DC, October 2003.
  3. Lien vers le challenge : http://www.crackmes.de/users/neon/virt/