dimanche 27 juillet 2008

Create ur own worldz with virtualization.

Entres deux projets j'ai enfin trouvé le temps pour vous concocter un petit article.

Celui-ci portera sur les machines virtuelles, souvent abrégées "VM" (Virtual Machine) ; c'est une technologie aujourd'hui en pleine expansion, on en trouve dans presque tous les domaines :


Pour le Reverse Engineering, elles servent de sandbox et permettent de mener de nombreux tests "à l'abris".

Pour l’analyse des menaces informatiques, des VMs sont mises en ligne et font office d’honeypot.

Pour l'hébergement web, quelques machines physiques hébergent plusieurs VMs, spécifique à chaque service


En bref on en voit un peu partout :).


L’utilisation qui m'a intéressée ici est celle des protections logicielles, ou encore des crackmes.

Non pas que je sois fan de ce genre de binaire, créés pour faire tourner en bourrique la dite personne, mais ne voyant pas trop comment cette technologie pouvait être utilisée dans ce contexte, j'ai tenté l'expérience :).


I] Un exemple presque inévitable : la machine virtuelle java abrégée JVM.


Bien évidement, je ne pouvais éviter l'exemple de la célèbre JVM. En effet elle illustre un gros avantage de la virtualisation, la possibilité de créer un pseudo-code réalisant les mêmes actions quelque soit la plateforme où il est lancé.

C'est bien évidemment le coeur du fonctionnement de java ; le langage java est "traduit" en bytecode java qui lui est directement interprété par la machine virtuelle.

Il est alors juste nécessaire de développer un interpréteur pour chaque plateforme, celui-ci interprétera ce bytecode java de la même façon.


Cependant comme vous pouviez vous en doutez, cette technologie possède bien évidemment des limites.

Premièrement, cette technologie est finalement une "sur-couche" ; son exécution sera alors plus lente du fait que ce bytecode sera interprété par un autre programme.


Ensuite, il ne faut pas perdre de vue que l’implémentation d'une machine virtuelle complète est un travail harassant ; il suffit de consulter les spécifications du bytecode java pour constater l'ampleur du projet.

Je ne l'ai pas précisé mais la VM doit bien évidemment avoir à disposition tout un environnement où sera interprété notre langage : des registres, une pile etc.


II] Design de notre code.


Comme je l'ai précisé au départ ce qui m'intéressait était de comprendre le fonctionnement et la mise en place d'une protection logicielle par le biais d'une machine virtuelle.

Celle-ci sera on ne peux plus simple ; en effet j'ai choisis de ne pas mettre à disposition en environnement digne de ce nom ; l'envie et le niveau me manque :).


Le code interprété aura donc à sa disposition une pile et des registres classiques ; le minimum pour pouvoir développer une """""protection logicielle""""".

J'ai aussi décidé de créer un petit jeu d’instruction très basique, le minimum vital ; Il suffit en tout cas à comprendre que le développement d’une VM est une tâche longue et fastidieuse…


Pour éviter de coder avec les "bytecode" que nous allons créer, j'ai pensé à mettre en place un système de "traduction".

L'idée est à partir d'une syntaxe asm x86 de convertir celle-ci en notre pseudo-code ; cette espèce de traducteur est codé en perl (celui-ci d'ailleurs est très sale et non optimisé.. mais fonctionnel :)).


Par exemple si je donne à mon script perl :


mov eax,ebx


Il va bien gentiment me donnez l'équivalent en pseudo-code autrement dit:


 "\x14\x00\x01"


Parlons maintenant du squelette de notre interpréteur.

Une variable va donc nous servir de registre EIP, celle-ci pointera sur nos opcodes, ensuite il nous reste juste à les parser et les interpréter ; en gros nous avons le schéma suivant :


while(*eip)
switch *eip
case INSTRU1:
...
sizeOfInstru = 3
case INSTRU2:
...
sizeOfInstru = 5

eip += sizeOfInstru;


Une fois réalisé ce petit schéma tout devrait s'éclaircir pour vous ; ça commence à coder dans la tête normalement :).


Encore une fois pour me faciliter la tâche, les instructions que j'ai implenté sont : MOV, INC, PUSH, POP, CMP, EXIT.

Ces instructions vous ferront évidemment pensées à de l'asm bien sûr, seulement certaines ont été implentées pour pouvoir monter ma petite protection servant d'illustration :).


Concernant mon traducteur, j'ai choisis le language perl ; un language que j'apprecie beaucoup.

Seulement comme dit précedemment, le code se résoud à de piètres conditions (une pour chaque type d'instruction), et ajoutez à cela une petite dose de regex !


Pour ceux qui voudrait s'essayer au reverse de cette protection (en carton vous êtes prévenue :p) ne regardez pas les fichiers « tapz » (celui-ci est à passé au « traducteur » pour avoir la suite d'opcode), vous sortez votre debugguer préféré et vous vous attaquez au binaire « ExempleProtectionLogiciel.exe ».

Afin que vous ayez tous sous la main, je vois est uppé une petite archive contenant binaires/sources ; et pour ceux qui souhaitent observer les sources en lignes, elles sont disponibles en html.


Bon j'esepère que cela pourra apprendre quelques choses à certains, ce petit post m'a pas mal divertit, lorsque qu'on code une « mini-vm » ça reste plutôt sympathique :).


Sinan je vous conseil vivement le dernière article de mon keupin Ivanlef0u ; il illustre un reverse relatif au planificateur de taches, celui-ci aboutira à une technique permettant de dumper les accès avec lesquelles les taches ont été créer.


Alors pour les fichiers consultablent en ligne :


-Le traducteur.

-La dll.

-Le binaire qui implente la protection en carton.


Le petite packetage maintenant :

-Packetage


Je tenais aussi à remercier Deimos pour m'avoir donné l'idée de traiter ce sujet ( Deimos a dit : phear ze vm :)))

Bonne après-midi à vous ;).

PS : Concernant la vm, INVOKE est une instruction pour laquelle j'ai un peu triché, en effet au lieu de déposer les arguments sur la pile virtualisé, je dépose cela sur la pile du binaire qui lance l'interprétation des opcodes.
Seulement parce qu'implémenter un réel call était largement faisable mais ce qui n'etait pas faisable c'est que faire pointer eip dans une api impliquerait d'etre capable d'interpréter le code asm de celle-ci .. :).

"Stay in ur world or get pwnd in mine"

1 commentaire:

Anonyme a dit…

Salut, je suis tomber par hasard sur ton blog (blogger power!), et je le trouve vraiment pas mal ;-) l'humour, les expressions de g33k, le contenu, bref tout y est ! Je débute dans le domaine de la sécurité logicielle, et c'est grâce à des blog comme le tiens qu'on progresse! Bref tout ça pour te souhaiter bonne continuation :-).