Hey tout le monde,

ça faisait un moment que je n’avais pas fait un petit tutoriel de coding.

Si vous faites souvent du RE, vous êtes peut-être un jour tombé sur quelque chose ressemblant à ceci :

screenshot_1

Oui ça pique un peut les yeux ! Aujourd’hui, on va apprendre à résoudre la plupart de ces opération comme par exemple 0.65546 + Math.Cos(0.5222). Je sais que votre calculatrice sait le faire mais c’est beaucoup plus simple de coder un tool qui résolvera tout cela en quelques secondes.

Pour ceux qui n’auraient pas lu mon tutoriel pour coder un déobfuscateur basique, je vous invite à aller le lire ici : https://mindlocksite.wordpress.com/2016/12/31/coder-un-simple-string-decryptor/

On va juste changer la méthode de décryption et créer une méthode qui va par exemple résoudre toutes les sommes ou les différences.

Imaginez que vous voulez résoudre : 2 + 2 (oui je sais c’est débile) En code msil, cela donnera ceci :

Ldc.i4.2

Ldc.i4.2

Add

si c’était 15 – 20, cela donnerai ceci :

Ldc.i4.S avec l’operand 0xf

Ldc.i4.S avec l’operand 0x14

Donc pour un int, l’opcode sera toujours un ldc.i4. le nombre 1 est un ldc.i4.1, le nombre 2 est un ldc.i4.2 et ainsi de suite. Mais à un moment, les nombres deviennent trop grand. Et donc on utilise l’opcode ldc.i4.S mais il faudra donner une valeur à S. Si votre nombre est un double (0.56666) ce ne serait plus un ldc.i4 mais un ldc.R8. Tout cela est une question d’habitude. Je vous invite à aller lire l’articles suivant : https://en.wikipedia.org/wiki/List_of_CIL_instructions

Pour ce qui est du type d’opération, il sera toujours placé après le/les arguments. Add = addition, Sub = soustraction, Mul = multiplication, ….

Pour ce qui est par exemple des consinus, ce n’est plus un OpCode spécial mais un Call System.Math

Revenons à notre exemple de départ, résoudre 2+2 et placer à la place 4. Voici la méthode :

http://pastebin.com/XEgBwBUi

Donc on scan d’abord tout les types du modules, ensuite on scan toutes les méthodes du types. On vérifie ensuite si la méthode que l’on va scanner contient des instructions. Après cela, on va scanner chaque opcode un par un. On arrive maintenant à la partie intéressante :

if(method.Body.Instructions[i].OpCode == OpCodes.Ldc_I4 && method.Body.Instructions[i+1].OpCode == OpCodes.Ldc_I4 && method.Body.Instructions[i+2].OpCode == OpCodes.Add)

Cela veut dire, si l’opcode est un ldc.i4, si l’opcode suivant est aussi un ldc.i4 et enfin, si l’opcode encore suivant est un add, dans ce cas là, on a ce qu’on veut.

On save les 2 permières instructions :

firstargument = Convert.ToInt32(method.Body.Instructions[i].Operand);
secondargument = Convert.ToInt32(method.Body.Instructions[i +1].Operand);

On calcule la somme :

result = firstargument + secondargument;

On change l’operand par le résultat :

method.Body.Instructions[i].Operand = result;

Et enfin, on supprime les instructions dont on a plus besoin :

method.Body.Instructions[i + 1].OpCode = OpCodes.Nop;
method.Body.Instructions[i + 2].OpCode = OpCodes.Nop;

On le fait 2 fois car il y a 2 instructions à supprimer.

Voilà ça c’était par exemple pour une addition. A vous d’adapter le code pour résoudre les soustractions, …

Seulement, il n’y a pas que ce genre d’opération !

Maintenant, imaginons que vous vouliez résoudre un cosinus

Voici le code : http://pastebin.com/gEpEmLNM

Donc la méthode est plus ou moins la même sauf à partir du if.

Si j’ai été assez clair, vous devriez comprendre facilement.

if (method.Body.Instructions[i].OpCode == OpCodes.Ldc_R8 && method.Body.Instructions[i + 1].OpCode == OpCodes.Call && method.Body.Instructions[i + 1].ToString().Contains(« Cos »))

On check si la première instruction est un Ldc.R8 (oui car pour un cosinus, on utilise la plupart du temps un double et pas un int). Je voudrais aussi vous faire remarque qu’il existe aussi la fonction. IsLdcI4 qui permet de faciliter les choses !

On check si l’instuction suivante est un call. Si c’est un call, on check si ce call contient Cos (c’est assez de juste vérifier cos et pas Math.Cos)

Dans ce cas, on sauvegarde la variable:

tobemodified = Convert.ToDouble(method.Body.Instructions[i].Operand);

On calcule le résultat :

result = Math.Cos(tobemodified);

Et on remplace l’opérand :

method.Body.Instructions[i].Operand = result;

On supprime ensuite le call est voilà :p

method.Body.Instructions[i+1].OpCode = OpCodes.Nop;

 

Voilà, vous avez les bases pour coder un math resolver.

Petite info, je fais actuellement un tool pour résoudre la majorité de ce genre d’opération. Il devrait sortir bientôt !

Si vous avez des question : mindlockreverser@gmail.com ou Skype : MindSystemm !