Cracking 101
Ora viva!
O software há dias estava a tentar descobrir como se cracka um simples strncmp(3), então eu fiquei com ideias de criar um breve *curso* de cracking para os iniciantes.
Começamos com o seguinte sores:
#include <stdio.h>
int main() {
char loljews[10];
printf("--> ");
scanf("%s",&loljews);
if(strncmp(loljews,"morte",5)==0) {
printf(" OK ;-)\n");
} else {
printf(" FAiLED!\n");
}
return 1;
}
O código julgo que é auto-explicativo. O que se pretende é, depois de ter o programa compilado alterar o executável de forma a que aceite qualquer palavra sem ser “morte” e diga OK.
Então corri o programa no gdb e fiz “disassemble main”
Dump of assembler code for function main:
0x08048464 <main+0>: push %ebp
0x08048465 <main+1>: mov %esp,%ebp
0x08048467 <main+3>: and $0xfffffff0,%esp
0x0804846a <main+6>: sub $0x20,%esp
0x0804846d <main+9>: mov $0x8048590,%eax
0x08048472 <main+14>: mov %eax,(%esp)
0x08048475 <main+17>: call 0x8048368 <printf@plt> # print "-->"
0x0804847a <main+22>: mov $0x8048595,%eax
0x0804847f <main+27>: lea 0x16(%esp),%edx
0x08048483 <main+31>: mov %edx,0x4(%esp)
0x08048487 <main+35>: mov %eax,(%esp)
0x0804848a <main+38>: call 0x8048378 <__isoc99_scanf@plt>
0x0804848f <main+43>: movl $0x5,0x8(%esp)
0x08048497 <main+51>: movl $0x8048598,0x4(%esp)
0x0804849f <main+59>: lea 0x16(%esp),%eax
0x080484a3 <main+63>: mov %eax,(%esp)
0x080484a6 <main+66>: call 0x8048398 <strncmp@plt> # faz o call ao strncmp
0x080484ab <main+71>: test %eax,%eax
0x080484ad <main+73>: jne 0x80484bd <main+89> # Se não é igual, salta pra bad_boy
0x080484af <main+75>: movl $0x804859e,(%esp) # good_boy
0x080484b6 <main+82>: call 0x8048388 <puts@plt> # print "OK"
0x080484bb <main+87>: jmp 0x80484c9 <main+101> # salta para o fim
0x080484bd <main+89>: movl $0x80485a6,(%esp) # bad_boy
0x080484c4 <main+96>: call 0x8048388 <puts@plt> # print "failed"
0x080484c9 <main+101>: mov $0x1,%eax # fim
0x080484ce <main+106>: leave
0x080484cf <main+107>: ret
Primeiro uma lista de instruções normalmente usadas para o cracking e os seus opcodes em hexadecimal.
JNE - Jump if Not Equal - 75
JE - Jump if Equal - 74
JMP - Jump - EB
NOP - No Operation - 90
JA - Jump if Above - 77
JB - Jump if Below - 72
JNA - Jump if Not Above - 76
JLE - Jump if Less or Equal - 7E
JL - Jump if Less - 7C
O que se pretende então é alterar ali aquele JNE em <main+73>. Mas para o quê? A primeira ideia seria inverter o sentido do jump, em vez de ser JNE passava a ser JE. Mas assim ficávamos com um problema, ao metermos “morte” iamos parar ao “failed”.
Então o que podemos fazer perguntam vocês?
Para explicar primeiro precisei de instalar um hex editor para Linux. O biew pareceu-me bem. Abri o executável nele e andei à procura do naco de código acima (do gdb).
000004A6:E8EDFEFFFF calln file:00000398
000004AB:85C0 test eax,eax
000004AD:750E jne file:000004BD
000004AF:C704249E850408 mov [esp],0804859E
000004B6:E8CDFEFFFF calln file:00000388
000004BB:EB0C jmps file:000004C9
000004BD:C70424A6850408 mov [esp],080485A6
000004C4:E8BFFEFFFF calln file:00000388
000004C9:B801000000 mov eax,00000001
000004CE:C9 leave
O que eu fiz foi alterar os os bytes do JNE e da posição para onde salta “75 0E”, para dois NOPs (No Operation - Não faz nada) “90 90”. Assim ele nunca faz o teste, e segue sempre em frente para o good_guy e depois sai.
Espero que isto tenha alguma utilidade para alguém! Para a próxima talvez haja um com algo mais complexo tipo Username com Serial derivada do Username ou algo do género.
Até la, fiquem bem e crackem muito ;-)
2 comentários a “Cracking 101”
Muito bem!
Algo util! :)
Posta mais disso!