Bienvenidos sean los crackmes de linux (me estoy iniciando en linux y estos me vendrán muy bien, por lo que tengas o no dudas, te pediría que los fueras subiendo, así todos vamos aprendiendo).
Iré escribiendo el tutorial online (ya no tengo mucho tiempo como solía tenerlo):
Antes que todo verificamos información del archivo:
- Nos muestra que posee librerías dinámicas (estas no están dentro del ejecutable por lo que llama las del sistema).
- Nos dice que el ejecutable es not stripped (posee los símbolos del programa, no ha pasado por el programa strip).
Verificamos las strings y las direcciones de estas:
Ya que el ejecutable está linkeado (enlazado) de forma dinámica, procederemos a la utilización de ltrace, el cual nos mostrará las llamadas a las funciones:
Usamos readelf para obtener el Entry Point:
Generamos un desensamblado del ejecutable:
Recopilamos siguiente información:08048320 <_start>:
Si buscamos información sobre __libc_start_main, obtendremos:
Debido a que se realiza una llamada a una función con convención C, los parámetros son empujados en orden inverso, por lo cual podemos deducir que:
080483fc <main>:
80483fc: 55 push ebp
80483fd: 89 e5 mov ebp,esp
80483ff: 83 e4 f0 and esp,0xfffffff0
8048402: 83 7d 08 03 cmp DWORD PTR [ebp+0x8],0x3
8048406: 75 07 jne 804840f <main+0x13>
8048408: e8 c7 ff ff ff call 80483d4 <win>
804840d: eb 05 jmp 8048414 <main+0x18>
804840f: e8 d4 ff ff ff call 80483e8 <fail>
8048414: b8 00 00 00 00 mov eax,0x0
8048419: c9 leave
804841a: c3 ret
Se compara el segundo parámetro recibido, desde __libc_start_main por main(), si verificamos es un:
El cual contiene la cantidad de argumentos recibidos + 1.
Por lo cual la solución es poner dos argumentos.
PD: No recuerdo por que se contaban como 3, si alguien me puede recordar, se lo agradecería.
EDIT: Es el número de argumentos + 1, debido a:
int main (int argc, char *argv)
donde argc = contador de argumentos
*argv (puntero a un arreglo tipo char)
argv[0]=Nombre del ejecutable.
argv[1]=Parámetro 1.
argv[2]=Parámetro 2.
.....
..
.
Por lo cual argc sin parámetros, contendrá el valor 1, con un parámetro 2, con dos parámetros argc 3
Iré escribiendo el tutorial online (ya no tengo mucho tiempo como solía tenerlo):
Antes que todo verificamos información del archivo:
Citarroot@kali:~/Desktop# file lol
lol: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x05972cc870c77c1b1a71f65e1696b480b725a32e, not stripped
- Nos muestra que posee librerías dinámicas (estas no están dentro del ejecutable por lo que llama las del sistema).
- Nos dice que el ejecutable es not stripped (posee los símbolos del programa, no ha pasado por el programa strip).
Verificamos las strings y las direcciones de estas:
Citarroot@kali:~/Desktop# strings -t x lol
154 /lib/ld-linux.so.2
21d __gmon_start__
22c libc.so.6
236 _IO_stdin_used
245 puts
24a __libc_start_main
25c GLIBC_2.0
328 PTRh
420 UWVS
47c [^_]
4f0 Win!
4f5 Fail...
57b ;*2$"
Ya que el ejecutable está linkeado (enlazado) de forma dinámica, procederemos a la utilización de ltrace, el cual nos mostrará las llamadas a las funciones:
Citarroot@kali:~/Desktop# ltrace -i ./lol
[0x8048341] __libc_start_main(0x80483fc, 1, 0xbfc80fa4, 0x8048420, 0x8048490 <unfinished ...>
[0x80483fa] puts("Fail..."Fail...
) = 8
[0xffffffff] +++ exited (status 0) +++
Usamos readelf para obtener el Entry Point:
Citarroot@kali:~/Desktop# readelf -l lol
Elf file type is EXEC (Executable file)
Entry point 0x8048320
Generamos un desensamblado del ejecutable:
Citarobjdump -M intel -d lol > objdump.txt
Recopilamos siguiente información:08048320 <_start>:
Citar8048320: 31 ed xor ebp,ebp
8048322: 5e pop esi
8048323: 89 e1 mov ecx,esp
8048325: 83 e4 f0 and esp,0xfffffff0
8048328: 50 push eax
8048329: 54 push esp
804832a: 52 push edx
804832b: 68 90 84 04 08 push 0x8048490
8048330: 68 20 84 04 08 push 0x8048420
8048335: 51 push ecx
8048336: 56 push esi
8048337: 68 fc 83 04 08 push 0x80483fc
804833c: e8 cf ff ff ff call 8048310 <__libc_start_main@plt>
Si buscamos información sobre __libc_start_main, obtendremos:
Citarint __libc_start_main(int (*main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));
Debido a que se realiza una llamada a una función con convención C, los parámetros son empujados en orden inverso, por lo cual podemos deducir que:
Citar8048337: 68 fc 83 04 08 push 0x80483fcEs la dirección en donde se encuentra la función main(), la cual es donde generalmente se comienza a escribir código (por parte del programador). Si verificamos su contenido:
080483fc <main>:
80483fc: 55 push ebp
80483fd: 89 e5 mov ebp,esp
80483ff: 83 e4 f0 and esp,0xfffffff0
8048402: 83 7d 08 03 cmp DWORD PTR [ebp+0x8],0x3
8048406: 75 07 jne 804840f <main+0x13>
8048408: e8 c7 ff ff ff call 80483d4 <win>
804840d: eb 05 jmp 8048414 <main+0x18>
804840f: e8 d4 ff ff ff call 80483e8 <fail>
8048414: b8 00 00 00 00 mov eax,0x0
8048419: c9 leave
804841a: c3 ret
Se compara el segundo parámetro recibido, desde __libc_start_main por main(), si verificamos es un:
Citar8048336: 56 push esi
El cual contiene la cantidad de argumentos recibidos + 1.
Por lo cual la solución es poner dos argumentos.
PD: No recuerdo por que se contaban como 3, si alguien me puede recordar, se lo agradecería.
EDIT: Es el número de argumentos + 1, debido a:
int main (int argc, char *argv)
donde argc = contador de argumentos
*argv (puntero a un arreglo tipo char)
argv[0]=Nombre del ejecutable.
argv[1]=Parámetro 1.
argv[2]=Parámetro 2.
.....
..
.
Por lo cual argc sin parámetros, contendrá el valor 1, con un parámetro 2, con dos parámetros argc 3