jeudi 22 octobre 2009

INT 0x2E a la trick

Je m'excuse de la présentation hasardeuse de ce post (notamment la page vide), blogger c'est de la bouse.


Afin de prouver au monde entier que je ne suis pas complètement mort, je me permet de mettre ici une petite analyse d'un trick anti-unpacker qui n'a pas reçu l'attention qu'il mérite à mon humble avis. Il n'est pas compliqué et pas très méchant mais il peut casser los boulos quand on le découvre.


En effet, il n'est pas présent dans la Holy Bible de l'unpacking de notre ami Peter et à ma connaissance la seule référence dans la littérature se trouve dans les slides d'une présentation faite récemment lors de la dernière conférence VB par Kurt Baumgartner. Mais cette analyse, qui décrit le trick comme "Int 0x2e 0xc0000005 location generation trick" est un peu trop rapide, donc j'en profite pour réveiller mon blog.

Comme tu l'a déjà deviné cher lecteur, ce trick utilise l'interruption 0x2E qui permettait de lancer dans « l’ancien temps » les appels systèmes Windows : on plaçait le numéro de l’appel dans le registre EAX, ses arguments dans EDX et hop ! Depuis, l’instruction SYSENTER à remplacé ce bouzin, car plus rapide. Mais bien sur INT 0x2E traine toujours sa ganache dans le coin pour des questions de compatibilité. Finalement, l'instruction n'est pas documentée par Microsoft, ce qui impose une approche "black box" si, comme moi, on est faignant et peu porté dans l'architecture Windows.

I- Utilisation "basique"

Le trick utilisé de la façon la plus simple possible donne :

B8 FFFFFFFF____MOV EAX,-1
CD 2E__________INT 2E
66:817A FE CD2_CMP WORD PTR DS:[EDX-2],2ECD

On appelle donc l’interruption avec comme numéro de syscall "-1" (ce qui est invalide).

Le comportement « normal » dans ce cas là est de faire échouer le syscall en plaçant un code d’erreur dans EAX (0xC000001C) et en faisant pointer EDX vers l’instruction suivant l'interruption. Donc dans notre exemple, EDX-2 pointe sur le début de l'instruction INT 2E dont les opcodes sont bien 2ECD en little-endian.

Par contre sous contrôle d’OllyDbg (v1 ou v2), le registre EDX va être mis à 0xFFFFFFFF si on passe l’interruption en « single-step ». Dans ce cas là un accès mémoire invalide sera réalisé lors de la comparaison, ce qui fera planter le programme.

Remarquons que ce trick devient aussi « anti-VM » dans le cas de VirtualBox de Sun (EDIT: Voir commentaires), puisque même sans être sous le contrôle du débuggeur le registre EDX est mis à 0xFFFFFFFF à tous les coups, sûrement une mauvaise implémentation des interruptions... Une raison de plus (avec la non-implémentation des hardwares breakpoints lorsqu’on n’utilise pas les techniques de virtualization matérielle) pour rester sur VMWare pour l’analyse de malwares.

Finalement, il est utile contre tout émulateur qui n'implémentent pas les interruption de façon rigoureuse.

II- Utilisation "avancée"


Ce qui n'est pas dit dans la littérature et qui est déjà connu des méchants (par exemple ceux qui font le packer de Waledac), c'est que :

  • d'une part, en plaçant autre chose dans EAX que "-1" la valeur de retour va varier et donner divers code d'erreur, tout ceci de façon "stable" (on nike pas tout dude). Pour vérifier cela on se fait un petit programme qui appelle l'interruption sur divers paramètres, voici les premières valeurs qu'on obtient :






















































INT 2E return values
Parameter Return value
0xFFFFFFFF 0xC000001C
0x0-0x1 0xC0000005
0x2 0xC000005C
0x3 0xC0000005
0x4-0x8 0xC000000D
0x9 0xC0000002
0xA-0xC 0xC0000005
0xD 0xC0000008
0xE-0x10 0xC0000005
0x11 0xC00000F1
0x12 0xC0000141
... ...


Il y a donc certaines valeurs particulières, ce qui fait un levier de plus pour détecter un émulateur|débuggeur|VM-pourrie-de-chez-Sun.

  • d'autre part, ECX doit normalement toujours être positionné sur ESP après la levée de l'interruption.

Tout ca peut donner lieu à des utilisations plus rigolote du trick, comme celle-ci vu récemment dans mon malware préféré :

Le code démarre sur ça :

68 CD2EEB08___PUSH 8EB2ECD________________; INT 2E camouflé
58____________POP EAX
2D C42EEB08___SUB EAX,8EB2EC4_____________; EAX = 9
EB F4_________JMP SHORT Waledac_.00401153 ; JMP sur le
INT 2E

Donc on saute sur le INT 2E camouflé au milieu du premier PUSH, ce qui donne à ce moment là le code suivant (les commentaires donnent les valeurs "attendues") :

CD 2E_______INT 2E
EB 08_______JMP SHORT Waledac_.0040115F
58__________POP EAX
2D C42EEB08_SUB EAX,8EB2EC4
EB F4_______JMP SHORT Waledac_.00401153
52__________PUSH EDX____________________; adresse qui suit INT2E (0x401155)
91__________XCHG EAX,ECX________________; EAX=ESP, ECX=0xC0000002
0FC9________BSWAP ECX___________________; ECX=0x020000C0
C1E1 04_____SHL ECX,4___________________; ECX=0x20000C00
8B00________MOV EAX,DWORD PTR DS:[EAX]__; adresse de retour initiale
2B4424 04___SUB EAX,DWORD PTR SS:[ESP+4]; EAX = 0
03C8________ADD ECX,EAX_________________; ECX=
0x20000C00
81E9 FAE5FF_SUB ECX,1FFFE5FA____________; ECX=0x00002606
03CA________ADD ECX,EDX_________________; ECX =
0x401155 + 0x00002606 = 0x40375B
870C24______XCHG DWORD PTR SS:[ESP],ECX
FF1424______CALL DWORD PTR SS:[ESP]_____; CALL
0x40375B -> HERE WE GO 3v1L!


On voit dans ce petit exemple comment sont utilisés les trois leviers possibles de ce trick :
  • la valeur de retour qui doit être le code d'erreur associé à l'appel système (comme on passe pas d'arguments dans EDX, y a peu de risque que l'appel système fonctionne).
  • l'adresse mise dans EDX qui doit normalement être celle de l'instruction qui suit la levée de l'interruption.
  • ECX doit être égal à ESP après la levée de l'interruption.
En jouant avec les valeurs de retours on peut faire beaucoup de tricks différents pour tester l'implémentation de cette interruption, that's not so bad.

Bon allez je retourne dans ma grotte!

lundi 16 février 2009

Oupsx...

Cette semaine j'ai mis le nez dans le code de UPX 3.03, un packer connu pour être très facile à unpacker (ce qui se comprend puisque ce n'est pas pour ça qu'il a été conçu). Mais comme pour FSG, mon but n'était pas de faire de l'unpacking mais plutôt de comprendre comment le loader (le "stub" dans la terminologie UPX) fonctionne et réalise son unpacking. Ces stubs sont programmés en ASM et les commentaires sont plutôt laconiques, donc ça vaut le coup de sortir son débuggeur préféré pour comprendre à la main :-)

Ca ma permit de découvrir une "feature" assez marrante @Microsoft : quand on compile avec Visual Studio C++ un programme qui fait des opérations flottantes, le programme va vérifier dans le header PE que les sections de la mémoire qui ne doivent pas être "écrivables" (typiquement .text et .rdata) le sont bien. Sinon il déclenche un joli message "R6002: floating point not loaded error" et votre programme plante lamentablement. Le "side-effect" c'est que quand un packer lambda (comme FSG) décompresse son exécutable dans une zone mémoire (donc avec les droits d'écritures) il laisse les droits et donc le programme plante.
UPX résoud le problème en changeant les droits juste avant de jumper sur l'OEP mais ça implique un appel à VirtualProtect() pour pouvoir modifier le PE header (+ 1 pour remettre les anciens droits) et d'écrire dans la mémoire, donc une perte de temps.
Voir le post de kpnc sur le sujet.

Ayant une expérience très restreinte je ne sais pas comment les autres packers s'en sortent. Do you have any idea ?

Sur ce, voici le bouzin.



lundi 9 février 2009

De retour...

Pour te jouer un mauvais tour

Je suis toujours vivant, et j'espère avoir de nouveau le temps d'alimenter ce blog :-)

Ces temps-ci je travaille sur les packers et j'essaye de décortiquer leur fonctionnement avec plus ou moins de succès... J'ai commencé petit, donc par les packers les plus simples qui ne font que de la compression. Tout ça pour dire que j'écris des petites keynotes me permettant de me rapeller facilement ce que j'ai compris, il ne s'agit pas du tout d'un travail pédagogique (en gros c'est incompréhensible) mais sait-on jamais, ça peut peut-être dépanner quelqu'un :-)

La première est sur FSG 2.0, un packer très simple dont j'ai étudié le loader sans m'occuper de l'aspect compression qui a déjà été très bien expliqué par Beatrix.

Tu la trouvera ici.

J'ai aussi rajouté mon mail dans la colonne de droite, histoire que si tu est timide et que tu as vu des bourdes dans mon bouzin tu puisses m'insulter.