J'essayais d'apprendre les bases de l'inversion et j'ai essayé de désassembler un petit programme en C. Je travaille sous MacOS 10.7.2 (64 bits - Intel) et en utilisant gcc 4.2.1.Désassemblage C, remplacer le code d'opération
#include <stdio.h>
int main() {
char word[20];
scanf("%s",word);
if (strcmp(word,"password")==0)
printf("Correct\n");
else
printf("Fail\n");
}
Je compilé avec gcc -o test test.c
, puis, en un certain temps avec gdb, je mis un point d'arrêt après l'appel strcmp
(de 100000e8e) et obtenir (ce que je pense est) le code assembleur concerné:
0x0000000100000e40 <main+0>: push %rbp
0x0000000100000e41 <main+1>: mov %rsp,%rbp
0x0000000100000e44 <main+4>: sub $0x30,%rsp
0x0000000100000e48 <main+8>: mov 0x1e9(%rip),%rax # 0x100001038
0x0000000100000e4f <main+15>: mov (%rax),%rax
0x0000000100000e52 <main+18>: mov %rax,-0x8(%rbp)
0x0000000100000e56 <main+22>: lea -0x20(%rbp),%rax
0x0000000100000e5a <main+26>: mov %rax,%rcx
0x0000000100000e5d <main+29>: xor %dl,%dl
0x0000000100000e5f <main+31>: lea 0xda(%rip),%rsi # 0x100000f40
0x0000000100000e66 <main+38>: mov %rsi,%rdi
0x0000000100000e69 <main+41>: mov %rcx,%rsi
0x0000000100000e6c <main+44>: mov %rax,-0x28(%rbp)
0x0000000100000e70 <main+48>: mov %dl,%al
0x0000000100000e72 <main+50>: callq 0x100000eee <dyld_stub_scanf>
0x0000000100000e77 <main+55>: mov -0x28(%rbp),%rcx
0x0000000100000e7b <main+59>: xor %dl,%dl
0x0000000100000e7d <main+61>: lea 0xbf(%rip),%rsi # 0x100000f43
0x0000000100000e84 <main+68>: mov %rcx,%rdi
0x0000000100000e87 <main+71>: mov %dl,%al
0x0000000100000e89 <main+73>: callq 0x100000ef4 <dyld_stub_strcmp>
0x0000000100000e8e <main+78>: mov %eax,%ecx
0x0000000100000e90 <main+80>: cmp $0x0,%ecx
0x0000000100000e93 <main+83>: jne 0x100000ea6 <main+102>
0x0000000100000e95 <main+85>: lea 0xb0(%rip),%rax # 0x100000f4c
0x0000000100000e9c <main+92>: mov %rax,%rdi
0x0000000100000e9f <main+95>: callq 0x100000ee8 <dyld_stub_puts>
0x0000000100000ea4 <main+100>: jmp 0x100000eb5 <main+117>
0x0000000100000ea6 <main+102>: lea 0xa7(%rip),%rax # 0x100000f54
0x0000000100000ead <main+109>: mov %rax,%rdi
0x0000000100000eb0 <main+112>: callq 0x100000ee8 <dyld_stub_puts>
0x0000000100000eb5 <main+117>: mov -0xc(%rbp),%eax
0x0000000100000eb8 <main+120>: mov 0x179(%rip),%rcx # 0x100001038
0x0000000100000ebf <main+127>: mov (%rcx),%rcx
0x0000000100000ec2 <main+130>: mov -0x8(%rbp),%rdx
0x0000000100000ec6 <main+134>: cmp %rdx,%rcx
0x0000000100000ec9 <main+137>: mov %eax,-0x2c(%rbp)
0x0000000100000ecc <main+140>: jne 0x100000ed7 <main+151>
0x0000000100000ece <main+142>: mov -0x2c(%rbp),%eax
0x0000000100000ed1 <main+145>: add $0x30,%rsp
0x0000000100000ed5 <main+149>: pop %rbp
0x0000000100000ed6 <main+150>: retq
0x0000000100000ed7 <main+151>: callq 0x100000edc <dyld_stub___stack_chk_fail>
maintenant, selon ma compréhension de l'assembleur, les choses devraient être faciles: après l'appel strcmp
à 100000e89 la valeur de %ecx
est enregistrée puis comparée à 0.
Si elles ne sont pas égal (jne
) il y a le saut (sinon), sinon il devrait continuer (si).
Très bien, je pensais que modifier jne
dans un je
Je devrais obtenir "Correct" même avec une mauvaise entrée.
En fait, je ne l'ai pas fait. Essayer de comprendre ce que le problème peut être, j'ai essayé d'examiner les codes de fonctionnement et je reçois un étrange (pour moi) sortie:
(gdb) x/8x 0x100000e93
0x100000e93 <main+83>: 0x8d481175 0x0000b005 0xc7894800 0x000044e8
0x100000ea3 <main+99>: 0x480feb00 0x00a7058d 0x89480000 0x0033e8c7
Aucun signe de l'0f85
qui devrait être le code pour jne
.
Je suis un peu confus alors ... Ne devrais-je pas obtenir le code d'opération pour le saut? Quelqu'un peut-il m'expliquer mon erreur?
Merci, cela a fonctionné. En fait, je regardais la même page que vous avez liée, et j'ai pris '0f85' de cette page ... Pouvez-vous s'il vous plaît expliquer" décalage 8 bits rel "et pourquoi' 0f85' est faux? – Saphrosit
Décalage rel 8 bits signifie un décalage relatif, codé en octet unique, de sorte que vous ayez des valeurs comprises entre -128 .. 127 pour le décalage. L'opcode 0f85 en mode 64 bits utilisé pour les décalages rel 16 et 32 bits (en fonction du préfixe d'instruction de taille d'opérande). –
L'utilisation de différentes longueurs de décalage est évidemment effectuée pour conserver la taille du code, c'est-à-dire que vous ne devez pas gaspiller le codage d'espace en entier 32 bits si votre cible de saut est comprise entre 8 et 16 bits. –