Y por aquí seguimos... parece que me lo vuelvo a tomar en serio... ya veremos cuánto me dura.
Mi amiguete d4ni, me dijo que cuándo iba a empezar a hablar un poco de los cracks, desemsamblar programas y tal...
Es que a mi colega le encanta trastear con los porgramas, siempre me anda picando para que haga no se qué, para que intente crackear el programita 'X', mil cosas. Así que hoy vamos a empezar con lo básico.
Primero una herramienta básica de muy bajo nivel (por decirlo de alguna manera): strace - system trace-. Básicamente muestra en el terminal las llamadas del sitema que realiza el programas que ejecutéis.
Tan fácil de probar como hacer:
-$ strace ls
Podréis ver todas las llamadas al sistema que hace - mmap2(..., access(... -, los ficheros que abre - open(... - y más o menos todo lo que hace un ls. Podéis probar con cualquier ejecutable o programa, y veréis a que va llamando.
También tenemos en linux una herramienta de depuración, para mí bastante decente, que es el gdb, normalmente viene instalada en Ubuntu por defecto. Es un programa que funciona por línea de comandos, existe su versión gráfica -gdb-, pero de esa hablaré en el próximo post dedicado a este tema. Voy a hablar un poco de cómo usarlo y las cuatro cosillas un poco básica que yo creo que son necesarias para empezar. Como con todo, lo ideal es empezar con algún tutorial y/o con ayuda de google y esas cosillas.
Bueno, pues vamos a hacer un pequeño ejemplillo que me he currado, es una tontería muy gorda, pero para empezar está muy bien. Os debo aclarar que para todo esto de los cracks y de "debuggear" hay que saber un poco de lenguaje ensamblador y algo del funcionamiento de los programas, con su pila y sus cosillas. Yo no sé mucho, un poquillo, lo justo - y ni eso - para poder trastear, así que a poquito que sepáis o seáis espabilaillos esto lo pillaréis más o menos rápido.
Lo dicho, aquí tenéis un ejecutable para Linux. Os diría que os lo descarguéis y lo ejecutárais, pero a lo mejor sois muy excépticos y no queréis jugároslo a correr un programa de a saber quién. Aquí tenéis el código fuente, lo suyo sería no mirarlo, y empezar con el ejecutable para que no veáis lo que hace ni como lo hace el programa y aprendáis más sobre la depuración de programas. Pero, bueno si lo que hacéis es bajaros el fuente, y echándole un vistazo rápido, para ver que no hay nada malo, pero tampoco viendo lo que hace, que si no no tiene gracia. Que me lío, ahora hacéis:
$ gcc -o crack crack.c
Y ya tenéis el ejcutable. Ahora ya tengáis el ejecutable mío descargado, o el vuestro compilado, lo ejecutamos, y veremos que es un progrmas tonto que nos pide una clave, si la introducimos bien nos da un "OK", sino un "FALLASTE".
Una vez visto el ejecutable, continuamos haciendo:
$ file crack
Y os dirá:
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), not stripped
Lo importante de aquí es el "not stripped", que significa que el ejecutable tiene los símbolos incluídos, que más o menos quiere decirque mantiene los nombres (los importantes) del código fuente. Esto quiere decir que mantiene el "main", que es donde empieza el programa, por que si el ejecutable fuera "stripped", el ejecutable empezaría en "_start".
Ahora hacemos:
$ objdump -D crack >> crack.asm
$ gedit crack.asm
Y veremos todas las funciones del ejecutable en ensamblador.
Empezemos ahora con nuestro gdb:
$ gdb crack
Con esto cargamos nuestro ejecutablesi ahora escribimos
(gdb) run
nuestro porgrama correrá más o menos igual que si lo ejecutáramos normalmente, aunque éste nos avisa del motivo de como termina.
Para poner puntos de ruptura se hace con 'b' o 'break' y donde queremos ponerlo.
(gdb) b 1 -> pone un punto de ruptura en la línea 1
(gdb) b main -> pone un punto de ruptura en la función main
Hemos podido poner un breakpoint en la función main por que esta existe y se llama igual, por que si la buscáis en crack.asm está:
080483d4 <main>:
sino también podemos hacer:
(gdb) b *0x080483d4
que es lo mismo, pero si otro ejecutable no tiene la función main, o lo que quieres es poner el punto de ruptura en otor sitio, con poner la dirección es suficiente (OJO!, no os olvidéis del '*').
Ahora vayamos al grano. Si buscamos en crack.asm el main, veremos lo que viene a ser el meollo del programa:
080483d4 <main>:
80483d4: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483d8: 83 e4 f0 and $0xfffffff0,%esp
80483db: ff 71 fc pushl -0x4(%ecx)
80483de: 55 push %ebp
80483df: 89 e5 mov %esp,%ebp
80483e1: 51 push %ecx
80483e2: 83 ec 24 sub $0x24,%esp
80483e5: c7 04 24 0c 85 04 08 movl $0x804850c,(%esp)
80483ec: e8 3f ff ff ff call 8048330 <printf@plt>
80483f1: 8d 45 f8 lea -0x8(%ebp),%eax
80483f4: 89 44 24 04 mov %eax,0x4(%esp)
80483f8: c7 04 24 34 85 04 08 movl $0x8048534,(%esp)
80483ff: e8 1c ff ff ff call 8048320 <scanf@plt>
8048404: 8b 45 f8 mov -0x8(%ebp),%eax
8048407: 3d 31 d4 00 00 cmp $0xd431,%eax
804840c: 75 15 jne 8048423 <main+0x4f>
804840e: c7 04 24 37 85 04 08 movl $0x8048537,(%esp)
8048415: e8 26 ff ff ff call 8048340 <puts@plt>
804841a: c7 45 e8 01 00 00 00 movl $0x1,-0x18(%ebp)
8048421: eb 13 jmp 8048436 <main+0x62>
8048423: c7 04 24 3b 85 04 08 movl $0x804853b,(%esp)
804842a: e8 11 ff ff ff call 8048340 <puts@plt>
804842f: c7 45 e8 ff ff ff ff movl $0xffffffff,-0x18(%ebp)
8048436: 8b 45 e8 mov -0x18(%ebp),%eax
8048439: 83 c4 24 add $0x24,%esp
804843c: 59 pop %ecx
804843d: 5d pop %ebp
804843e: 8d 61 fc lea -0x4(%ecx),%esp
8048441: c3 ret
Vemos que hay un scanf:
80483ff: e8 1c ff ff ff call 8048320 <scanf@plt>
que es donde recoge lo que introducimos por teclado. Pues vayamos ahí:
$ gdb crack
(gdb) b 0x80483ff
(gdb) run
Se nos parará en el breakpoint
Si hacemos
(gdb) x/10i $eip
nos mostrará en hexadecimal las 10 instrucciones siguientes desde donde estamos (desde el contador de programa, que es el 'eip', pero hay que indicarlo con el '$'):
0x80483ff <main+43>: call 0x8048320 <scanf@plt>
0x8048404 <main+48>: mov 0xfffffff8(%ebp),%eax
0x8048407 <main+51>: cmp $0xd431,%eax
0x804840c <main+56>: jne 0x8048423 <main+79>
0x804840e <main+58>: movl $0x8048537,(%esp)
0x8048415 <main+65>: call 0x8048340 <puts@plt>
0x804841a <main+70>: movl $0x1,0xffffffe8(%ebp)
0x8048421 <main+77>: jmp 0x8048436 <main+98>
0x8048423 <main+79>: movl $0x804853b,(%esp)
0x804842a <main+86>: call 0x8048340 <puts@plt>
Como podéis ver es bastante parecido al crack.asm. Ahora hay varias formas de ir avanzando por el programa:
(gdb) n -> o next sigue ejecutando el programa. Lo que ocurre que no se parará hasta que éste termine o llegue a otro breakpoint.
(gdb) nexti -> basicamente avanza hasta la siguiente instrucción. Pero si entrar en la instrucción que ejecuta.
(gdb) stepi -> muy parecido a nexti, lo único que en este caso si que se introduce en la instrocción que ejecutamos. Por ejemplo, si la instrucción a ejecutar es una llamada a una función, stepi entraría en ella, y nexti ejecutaría toda la función pero no veríamos nada de ésta.
Total que si miramos las instrucciones nos damos cuentas de que primero se llama a la función 'scanf':
0x80483ff <main+43>: call 0x8048320 <scanf@plt>
Después recoge lo tecleado y lo mueve a eax
0x8048404 <main+48>: mov 0xfffffff8(%ebp),%eax
Si una vez ejecuta esta instrucción, hacemos:
(gdb)p $eax
veremos que en 'eax' está guardada la contraseña que nosotros hemos introducido.
Y después vemos.... ¡¡¡OHHHH!!!, vaya, hace una comparación de 'eax' con un número decimal. Uhhhmmmm, y si no coincide salta a la dirección 0x8048423, e imprime algo y termina:
0x8048423 <main+79>: movl $0x804853b,(%esp)
0x804842a <main+86>: call 0x8048340 <puts@plt>
y si no continúa e imprime otra cosa diferente y termina:
0x804840e <main+58>: movl $0x8048537,(%esp)
0x8048415 <main+65>: call 0x8048340 <puts@plt>
0x804841a <main+70>: movl $0x1,0xffffffe8(%ebp)
0x8048421 <main+77>: jmp 0x8048436 <main+98>
Pues ya está, hemos depurado y crakeado un programa MUUUUUUYYYYY estúpido, pero por algo hay que empezar.
Dentro de poco, vendrá la segunda parte de este post, y empezaremos con cositas un poco más serias, no demasiado, que si no, no podré enseñaros, jejejeje.
Espero que os sirva de algo, y os entretenga si tenéis tiempo suficiente como para "desperdiciar con esto", ;).
Un saludo.