#include <stdio.h>
int main(){
char cadena[1024];
printf("Introduce el pass: ");
scanf("%s", cadena);
if(!strcmp(cadena, "esteeselpass")) printf("Correcto\n");
else printf("Incorrecto\n");
}
Si compilamos ese fichero con gcc, obtendremos un ejecutable, yo le he llamado "prueba".
La primera utilidad es objdump, con ella se puede desensamblar ejecutables, bueno, eso y algunas cosas más.
objdump -d prueba > prueba.asm
Ahora en prueba.asm tenemos el fichero con el código desensamblado.
Intentemos averiguar el password del programa anterior, para ello hay que saber algo de ensamblador. Sabemos que en algún momento hay un salto condicional (je, jne, jz, jnz...) que es el que nos lleva a la situación de error, buscando estos saltos podemos ir rápido sobre el código y averiguar la zona en la que se produce la comprobación.
8048472: e8 d9 fe ff ff call 8048350
8048477: 8d 85 f0 fb ff ff lea 0xfffffbf0(%ebp),%eax
804847d: 89 85 e0 fb ff ff mov %eax,0xfffffbe0(%ebp)
8048483: c7 85 dc fb ff ff e3 movl $0x80485e3,0xfffffbdc(%ebp)
804848a: 85 04 08
804848d: c7 85 d8 fb ff ff 0d movl $0xd,0xfffffbd8(%ebp)
8048494: 00 00 00
8048497: fc cld
8048498: 8b b5 e0 fb ff ff mov 0xfffffbe0(%ebp),%esi
804849e: 8b bd dc fb ff ff mov 0xfffffbdc(%ebp),%edi
80484a4: 8b 8d d8 fb ff ff mov 0xfffffbd8(%ebp),%ecx
80484aa: f3 a6 repz cmpsb %es:(%edi),%ds:(%esi)
80484ac: 0f 97 c2 seta %dl
80484af: 0f 92 c0 setb %al
80484b2: 89 d1 mov %edx,%ecx
80484b4: 28 c1 sub %al,%cl
80484b6: 89 c8 mov %ecx,%eax
80484b8: 0f be c0 movsbl %al,%eax
80484bb: 85 c0 test %eax,%eax
80484bd: 75 0e jne 80484cd
80484bf: c7 04 24 f0 85 04 08 movl $0x80485f0,(%esp)
80484c6: e8 b5 fe ff ff call 8048380
80484cb: eb 0c jmp 80484d9
80484cd: c7 04 24 f9 85 04 08 movl $0x80485f9,(%esp)
80484d4: e8 a7 fe ff ff call 8048380
En este código vemos que se hace un scanf, unas operaciones intermedias, luego hay un jne que nos lleva a un puts o a otro (salidas por pantalla diferentes según una condición).
Ahora que ya sabemos por que zona movernos, podemos usar gdb.
gdb es un debugger gnu para linux, ejecutamos:
gdb prueba
En el listado de arriba desensamblado se puede ver que la instrucción que hace la comparación de las cadenas introducida y correcta es la siguiente:
80484aa: f3 a6 repz cmpsb %es:(%edi),%ds:(%esi)
asi que dentro de gdb, ejecutamos:
break *0x80484aa
Con lo que la ejecución se parará justo en esa instrucción, ejecutamos:
run
info registers
Obtenemos el valor de edi y esi, en mi caso 0x80485e3 y 0xbf86a3d8, inspeccionamos lo que hay en esas direcciones de memoria:
x/s 0x80485e3
x/s 0xbf86a3d8
Nos aparecen el pass que hemos introducido, y el ¡correcto!
Hay otra forma de conseguir que el programa nos de "su aprobación":
80484bb: 85 c0 test %eax,%eax
80484bd: 75 0e jne 80484cd
Vamos a la instrucción justo anterior a la del salto, el test (0x80484bb) ponemos un breakpoint ahí, si ejecutamos:
info registers
Vemos que eax vale 1, asi que la condición nos llevará al error, pero vamos ha hacer lo siguiente:
set $eax=0
Después pulsamos la 'c' para continuar...y obtenemos el mensaje que queríamos obtener aún habiendo introducido mal la contraseña.
0 comentarios:
Publicar un comentario