-1
votes

Comprendre la décompilation d'un objet au code source

Tout d'abord, je suis un étudiant, je n'ai pas encore de connaissances étendues sur C, C ++ et Assembleur, alors je fais un effort extrême pour le comprendre.

J'ai ce code de montage de Un processeur Intel X86-32 bit.

Mon objectif est de le transformer en code source. xxx

C'est ce que je comprends à partir du code: < / p>

Il y a 4 variables: xxx

valeurs: xxx

types: < Pré> xxx

C'est ce que j'ai pu créer: xxx

mais je suis coincé. Je ne comprends pas non plus ce que la phrase "CMP al .." se compare à ce que "al"?

Comment fonctionnent ces instructions?

EDIT1:

Cela dit, comme vous commenciez l'assembly semble être faux ou comme des commentaires de quelqu'un, il est fou!

Le code et l'exercice proviennent du livre suivant appelé: "Inverser, ingénierie inverse" à la page 140 (3,8 exercices proposés). Cela ne m'aurait jamais eu pour moi que c'était faux, si tel est le cas, cela rend clairement difficile pour moi d'apprendre ...

Il n'est donc pas possible de faire une inversion pour obtenir le code source parce qu'il n'est pas une bonne assemblée? Peut-être que je ne suis pas opprimé? Est-il possible de l'optimiser?

EDIT2:

HI!

J'ai demandé et enfin, elle dit que cela devrait être le code C: XXX

a-t-il un sens du tout pour vous ?, Quelqu'un pourrait-il s'il vous plaît m'expliquer cela? Est-ce que quelqu'un programmit vraiment comme ça?

Merci beaucoup!


14 commentaires

Long Long (32 bits) = DWORD n'est pas correct. La norme C ++ nécessite long LONG LONG 64 bits. (Eh bien, pas exactement mais la valeur maximale qu'il doit soutenir est telle qu'elle a besoin de 64 bits pour la stocker)


Si vous devez demander ce que al est alors besoin d'une étude plus approfondie du processeur, avant que vous puissiez donner un sentiment d'inscription à démontage ou à assemblage. Le registre al est le moins important 8 bits du registre eAx et hax est le L.S. 16 bits de eAx . Similaire pour BL , cl , dl , bx , CX et dx . Aussi ah est les 8 prochains bits de eAx de sorte que ah et al font ensemble AX .


Vos valeurs sont incorrectes


Voici un lien vers la documentation . Recherchez la section intitulée "Registres d'exécution du programme de base"


Vous avez un code source affiché, c'est dans la langue d'assemblage Intel X86. Quelle langue de haut niveau convertissez-vous en C ou C ++? Ce sont des langues distinctes. Par exemple, C ++ a héritage et std :: string où comme c ne le fait pas. Je recommande de choisir une langue pour faciliter votre projet (ne les mélangez pas, car cela rend votre programme plus compliqué).


Je recommande vivement d'écrire une petite fonction qui reçoit un paramètre de pointeur et indiquez à votre compilateur de sortir la langue d'assemblage. Cela vous montrera comment le compilateur gère la fonction d'appel de fonction. Ensuite, déclarez une variable locale et imprimez la langue d'assemblage. Vous recherchez des modèles. Vous pouvez prendre votre hauteur de haut niveau, imprimer la langue d'assemblage et la comparer à votre langue d'assemblage publiée. Pas une tâche facile, en particulier pour les débutants.


IMHO, le MOV DWORD PTR [EBP-0X8], 0x80484D0 Chargement de l'adresse d'une classe ou d'une structure. Certaines des MOV EAX et MOV EDX peuvent être utilisés pour charger une variable de membre ou une déréférence un pointeur.


@Thomasmatthews: MOV DWORD PTR [EBP-0X8], 0x80484D0 est Stockage une constante immédiate 32 bits à un VAR local sur la pile (car cette ASM est le résultat de Compiler quelque chose avec clang ou gcc -O0 - mode de débogage anti-optimisé qui traite toutes les variables genre de type volatile ). Que 0x80484d0 est probablement un pointeur, et c'est dans la même page que le code, il est donc presque certainement dans la section .rodata . Les premières instructions après Lea EAX, [EBP-0X8] / MOV sont rechargées que le pointeur à pointeur et compensent à partir de celui-ci, pas le code sur .rodata , Sauf si je passe un cerveau pet.


@Petercordes Je ne pense pas que vous ayez un cérébral de péter. Je pense qu'il y a quelque chose de sérieusement bizarre à propos de cette assemblée. En particulier, après 0x80483f2

: MOV EDX, DWORD PTR [EAX + 0XC] , il me semble que l'adresse de retour sera terminée dans edx , qui semble indésirable donné ce que le code continue ensuite à faire avec elle.


À moins que le chapitre porte sur le code obscurci, j'écrirais à l'auteur. Il y a une erreur logique triviale dans le code et le livre ne figure pas sur Google (avez-vous donné le bon nom?) Donc, je suis enclin à croire que le livre a un mazout chapitre sur l'obfuscation du flux de contrôle ou a été écrit par quelqu'un qui ne devrait pas avoir.


Salut! Voici le livre: books.google.es/... Honnêtement, il me rend fou, le livre qu'il n'est pas bien écrit en général et si les exercices sont également faux, je ne sais pas quoi faire ... C'est le matériel qu'ils m'ont donné pour étudier à mon institut.


@conjim: Je suggère de parler à votre instructeur. Ils n'ont peut-être pas compris les graves problèmes avec le livre, ou du moins avec cet exercice en particulier. Ils pourraient commencer à vérifier / corriger les problèmes avant de les assigner à votre classe et, espérons-le, ne pas utiliser ce manuel l'année prochaine.


Le code C que votre professeur vous a donné ne correspond pas à l'assemblée que vous avez posté à l'origine et, en fait, il est plus rentré de bug que l'assemblage.


Merci à tous et à toi monica. Au moins, je suis heureux parce que je pensais que le problème était moi mais je vois que c'est vraiment l'assemblée qu'ils m'ont donné leur réponse. Merci beaucoup


3 Réponses :


1
votes

Le X86 Language de montage suit un long héritage et a principalement maintenu la compatibilité. Nous devons revenir à la puce 8086/8088 où cette histoire commence. Celles-ci étaient des processeurs de 16 bits, ce qui signifie que leur registre avait une taille de mot de 16 bits. Les registres à usage général ont été nommés AX, BX, CX et DX. Les 8086 avaient des instructions pour manipuler les parties supérieure et inférieure 8 bits de ces registres qui ont ensuite été nommés Ah, Al, BH, BL, CH, CL, DH et DL. Cette page Wikipedia le décrit, veuillez jeter un coup d'oeil.

Les versions 32 bits de ces registres ont un E devant: EAX, EBX, ECX, etc.

L'instruction particulière que vous mentionnez, E.g, CMP al, 0x4f comparaisse l'octet inférieur du registre de la hache avec 0x4F. La comparaison est effectivement la même que celle d'une soustraction, mais ne sauvegarde pas le résultat, ne fait que définir les indicateurs.

Pour le jeu d'instructions 8086, Il y a une belle référence ici . Votre programme est de 32 bits de code. Vous aurez donc besoin d'au moins une référence d'instructions 80386.


0 commentaires

1
votes

Vous avez analysé des variables, et c'est un bon endroit pour commencer. Vous devriez essayer d'ajouter des annotations de type, la taille, comme vous avez démarré et, lorsqu'il est utilisé comme des pointeurs (comme B ), des pointeurs sur quel type / taille.

Je pourrais mettre à jour votre graphique de variable comme suit, sachant que [ebp-4] est b : xxx


Une autre chose à analyser est le flux de contrôle. Pour la plupart des instructions, le flux de contrôle est séquentiel, mais certaines instructions modifient délibérément. De manière générale, lorsque le PC est avancé, il passe du code et lorsque le PC est déplacé en arrière, il répète un certain code qu'il a déjà couru. Le code de saut est utilisé pour construire si, alors, si, alors, et des déclarations qui sortent des boucles. Le saut de saut est utilisé pour continuer à boucler.

Certaines instructions, appelées branches conditionnelles, sur une condition dynamique étant vraie: sauter en avant (ou en arrière) et sur une fausse progression séquentielle à la prochaine instruction (parfois appelé branche conditionnelle tombe à travers).

Les séquences de contrôle ici: xxx

Le flux de contrôle atteint cette dernière ligne étiquetée Nous savons que la lettre est la lettre. Soit pas "O" ou ce n'est pas "k".

La construction où l'instruction jne est utilisée pour sauter un autre test est un court-circuit || < / code> opérateur. Ainsi, la construction de contrôle est la suivante: xxx

comme ces deux branches conditionnelles sont les seules modifications de contrôle de flux dans la fonction, il n'y a aucune autre partie du si, et il n'y a pas de boucles ou autres si.


Ce code semble avoir un léger problème.

si la valeur n'est pas "O", la partie alors déclenchera du premier test . Toutefois, si nous atteignons le 2e test, nous savons déjà que la lettre est «O», ce qui le teste pour «k» est idiot et sera vrai («O» n'est pas «K»).

Ainsi, cela if-ensuite tirera toujours.

Il est soit très inefficace, soit un bug que c'est peut-être la prochaine lettre de la chaîne (probablement) doit être testée pour 'K' pas la même lettre exacte.


2 commentaires

[EBP-4] est B - n'est pas B une variable de pointeur, enfoncée l'adresse EBP-8 ? Donc, la compensation de ce [ex + 0xc] est indexation dans la propre image de pile de la fonction, avec MOV EDX, [EXE + 0XC] Chargement de l'adresse de retour de la fonction. (Joseph Satible et I discuté de cela dans les commentaires ; il semble fou pour nous. Je me demande si le code d'origine est indexé en dehors des limites d'un tableau local comme char * arr [1] = {"Hello"}; ?)


Je suis toujours très confus ... mais merci beaucoup pour l'information. Est-il possible de transformer automatiquement le code d'objet en code source, même s'il est similaire à distance ... mais pas tout à fait? Merci



3
votes

Votre montage est totalement fou. Ceci est à peu près équivalent C:

int main() {
    int i = 0x80484d0; // in ebp-8
    int *p = &i; // in ebp-4
    p[3] += (short)p[4]; // add argc to the return address(!)
    if((char)*p != 0x4f || (char)*p != 0x4b) // always true because of || instead of &&
        p[1] = p[3] & 0xf0f0f0f; // note that p[1] is p
    return 0;
}


4 commentaires

0x80484D0 est probablement une adresse dans la section .rodata, donc je pensais char * arr [1] = {"quelque chose"}; . Mais oui, int * p = (int *) arr; et UB d'accéder à l'extérieur des limites de la matrice. Je n'ai pas regardé à quel point le reste est fou.


J'ai demandé à mon professeur mais il dit que c'est parce qu'il n'est pas optimisé ... honnêtement, si vous savez ne pas le comprendre, je doute que je puisse le faire soit ..


@conjim "non optimisé" signifierait que le code fait la bonne chose, mais le fait plus lent que nécessaire. Ce code fait la mauvaise chose.


Merci pour l'information, je suppose que dans ce cas, il n'y a rien d'autre que cela ne peut être fait avec ceci ... Je pensais que je ne l'avais pas bien compris, mais il semble que tout le monde accepte que c'est un mauvais code.