2017-08-19 1 views
2

J'essaie de comprendre un exemple du livre "Practical Malware Analysis" de Michael Sikorski. Il y a un exemple sur les techniques anti-désassemblage que je ne comprends pas. Il dit qu'une technique courante consiste à créer deux instructions conditionnelles à savoir sauter si zéro (JZ) et sauter sinon zéro (JNZ) qui, considérées ensemble, ne sont en réalité qu'une seule instruction inconditionnelle (c'est clair pour moi). Voici les graphiques des deux résultats possibles créés par le désassembleur.x86 Assembler deux instructions de saut avec la même cible

wrong interpretation

right interpretation

La citation suivante se réfère à la figure 1:

Dans cet exemple, l'instruction qui suit immédiatement les deux instructions de saut conditionnel semble être une instruction d'appel à (appel), en commençant par l'octet 0xE8. Ce n'est pas le cas, cependant, que les deux instructions de saut conditionnel indiquent en fait 1 octet au-delà de l'octet 0xE8

Qu'est-ce que ça veut dire et pourquoi est l'emplacement de saut loc_4011C4 + 1 (où vient le +1 de) ? et dans la figure 2 c'est loc_4011C5? Quelqu'un peut-il fournir une explication plus détaillée?

+1

La cible de saut est de 1 octet dans l'instruction d'appel. Pourquoi? Parce que c'est ainsi que le programmeur l'a écrit, sans doute à des fins d'obscurcissement. La figure 2 montre l'instruction réelle qui sera exécutée. C4 + 1 = C5 – Jester

Répondre

6

Le résultat de la compilation du code d'assemblage est un morceau de code natif, plus précisément une séquence d'octets, où différentes parties de cette séquence correspondent aux instructions de l'assemblage d'origine. Les processeurs Intel x86 ont ce qu'on appelle un jeu d'instructions CISC, ce qui signifie que la longueur des instructions en octets peut varier de 1 à 12, sans tenir compte des extensions d'ensembles d'instructions disponibles de nos jours. La technique présentée utilise ce fait.

Le but est de tromper la personne avec un mal possible dans son esprit. Le code du deuxième exemple (avec pop eax et retn) est ce que nous voulons exécuter et ce qui sera exécuté. Cependant, comme nous avons inséré un faux octet devant l'instruction pop eax, le code désassemblé apparaîtra comme s'il y avait un call en mémoire, car la plupart des désassembleurs moins brillants supposent automatiquement que le code machine d'un binaire n'a pas de lacunes en elle.

Cette technique n'est pas infaillible. Des diassembleurs plus sophistiqués révéleront les véritables intentions de l'auteur. Notez également que si la personne essayant de pénétrer dans le code l'exécute dans un environnement de débogage, cette technique ne sera plus d'aucune utilité.