2012-03-10 3 views
1

Я пытался изучить основы реверсирования, и я попытался разобрать небольшую программу на C. Я работаю под MacOS 10.7.2 (64 бит - Intel) и с использованием gcc 4.2.1.Демонтаж C, замена кода операции

#include <stdio.h> 

int main() { 

    char word[20]; 

    scanf("%s",word); 
    if (strcmp(word,"password")==0) 
     printf("Correct\n"); 
    else 
     printf("Fail\n"); 
} 

Я скомпилирован с gcc -o test test.c, а затем, работая в то время как с помощью GDB, я поставил точку останова после strcmp вызова (100000e8e) и получить (что я считаю) соответствующий код сборки:

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> 

Теперь, в соответствии с моим пониманием сборщика, все должно быть просто: после strcmp вызова на 100000e89 значение %ecx сохраняется и затем сравнивается с 0.

Если они не являются равно (jne) есть прыжок (else), в противном случае он должен продолжаться (если).

Очень хорошо, я думал, что модифицировать jne в je Я должен получить «Правильно» даже с неправильным вводом.

На самом деле я этого не делал. Пытаясь понять, что проблема может быть, я попытался исследовать коды операции, и я получаю странный (для меня) вывода:

(gdb) x/8x 0x100000e93 
0x100000e93 <main+83>: 0x8d481175 0x0000b005 0xc7894800 0x000044e8 
0x100000ea3 <main+99>: 0x480feb00 0x00a7058d 0x89480000 0x0033e8c7 

Нет знак 0f85, который должен быть кодом для jne.

Я немного растерялся тогда ... Разве я не должен получить код операции для прыжка? Может кто-нибудь объяснить мне мою ошибку?

ответ

3

См опкод для JNE здесь: http://ref.x86asm.net/coder64.html

Итак, это то, что, как ожидается: 0x8d481175 с момента его DWORD печати и архитектура мало младшему, вы имеющий следующую последовательность байтов, начиная с этого адреса: 75 11 48 8d

и 75 - код операции для JNE в 64-битном режиме с 8-разрядным смещением смещения.

Проверка: адрес перехода рассчитывается по адресу следующей инструкции + смещение. Так, 0x0000000100000e95 + 0x11 = 0x0000000100000eA6 это именно то, что GDB показывает

+0

Спасибо, это сработало. Я на самом деле смотрел ту же страницу, с которой вы связались, и я взял «0f85» с этой страницы. Можете ли вы объяснить «8-битное смещение релаксации» и почему «0f85» ошибочен? – Saphrosit

+0

8-битное смещение реверса означает относительное смещение, закодированное в один байт, поэтому у вас есть значения в диапазоне от -128 до 127 для смещения. Код операции 0f85 в 64-битном режиме, используемый для 16-битных и 32-разрядных смещений смещения (в зависимости от префикса инструкций размера операнда). –

+0

Использование различных длин смещения, очевидно, выполняется для сохранения размера кода, то есть вам не нужно отбрасывать смещение пространственного кодирования как 32-разрядное целое, если ваш целевой объект перехода находится в пределах 8 или 16-битного целочисленного диапазона. –

 Смежные вопросы

  • Нет связанных вопросов^_^