2012-03-10 1 views
1

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?

Répondre

3

Voir opcode pour JNE ici: http://ref.x86asm.net/coder64.html

Ainsi, il est ce qu'on attend: 0x8d481175 depuis son dword imprimé, et l'architecture est peu endian, vous ayant la séquence suivante d'octets à partir de cette adresse: 75 11 48 8d

et 75 est un code d'opération pour JNE en mode 64 bits avec décalage rel 8 bits.

Vérification: une adresse de saut est calculée à partir de l'adresse de l'instruction suivante + décalage. Ainsi, 0x0000000100000e95 + 0x11 = 0x0000000100000eA6 qui est exactement ce que gdb montre

+0

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

+0

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). –

+0

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. –

Questions connexes