Descripción
Find the flag in the program.
Write-Up
El reto consiste en obtener la flag del fichero ejecutable “getflag”, por lo que lo primero que habrá que hacer será obtener información del propio fichero y ejecutarlo. Utilizando el comando “file getflag” podemos ver que el fichero es un binario compilado para Linux de 64 bits:
getflag: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=18a5f1324218e0ec3b49fd89ac3c750dc528dec8, not stripped
Por lo que procedemos a ejecutarlo:
Enter the key to obtain the flag: aaa<br> Bad luck. Try again…
Pongamos lo que pongamos en el programa siempre nos dirá lo mismo: “Bad luck. Try again…” así que tendremos que observar el código y ver el flujo del programa. En este paso utilizaremos la herramienta Radare 2 (comando “r2 -w getflag” para abrir el binario en modo escritura). Analizamos el fichero poniendo varias “a” y buscamos las funciones que hay en el binario mediante el comando “afl”:
[0x004004e0]> aaaa<br> [x] Analyze all flags starting with sym. and entry0 (aa)<br> [x] Analyze len bytes of instructions for references (aar)<br> [x] Analyze function calls (aac)<br> [x] Emulate code to find computed references (aae)<br> [x] Analyze consecutive function (aat)<br> [x] Constructing a function name for fcn.* and sym.func.* functions (aan)<br> [x] Type matching analysis for all functions (afta)<br> [0x004004e0]> afl<br> 0x00400000 2 64 loc.imp.__gmon_start<br> 0x00400041 1 176 fcn.00400041<br> 0x00400460 3 26 sym._init<br> 0x00400490 1 6 sym.imp.puts<br> 0x004004a0 1 6 sym.imp.printf<br> 0x004004b0 1 6 sym.imp.__libc_start_main<br> 0x004004c0 1 6 sym.imp.__isoc99_scanf<br> 0x004004d0 1 6 sub.__gmon_start___248_4d0<br> 0x004004e0 1 41 entry0<br> 0x00400510 4 50 -> 41 sym.deregister_tm_clones<br> 0x00400550 3 53 sym.register_tm_clones<br> 0x00400590 3 28 sym.__do_global_dtors_aux<br> 0x004005b0 4 38 -> 35 entry1.init<br> 0x004005d6 4 185 main<br> 0x00400690 4 101 sym.__libc_csu_init<br> 0x00400700 1 2 sym.__libc_csu_fini<br> 0x00400704 1 9 sym._fini
A simple vista, a parte del “main” no parece haber ninguna función interesante, por lo que nos movemos a su posición de memoria (“s 0x004005d6”) y desensamblamos su código (“pdf”):
[0x004004e0]> s 0x004005d6<br> [0x004005d6]> pdf<br> ;-- main:<br> / (fcn) main 185<br> | main ();<br> | ; var int local_24h @ rbp-0x24<br> | ; var int local_20h @ rbp-0x20<br> | ; var int local_9h @ rbp-0x9<br> | ; var int local_8h @ rbp-0x8<br> | ; DATA XREF from 0x004004fd (entry0)<br> | 0x004005d6 55 push rbp<br> | 0x004005d7 4889e5 mov rbp, rsp<br> | 0x004005da 4883ec30 sub rsp, 0x30 ; '0'<br> | 0x004005de c745dc010000. mov dword [local_24h], 1<br> | 0x004005e5 48c745f81807. mov qword [local_8h], str.hAck11t_Fl4g ; 0x400718 ; "hAck11t_Fl4g"<br> | 0x004005ed bf28074000 mov edi, str.Enter_the_key_to_obtain_the_flag: ; 0x400728 ; "Enter the key to obtain the flag: " ; const char * format<br> | 0x004005f2 b800000000 mov eax, 0<br> | 0x004005f7 e8a4feffff call sym.imp.printf ; int printf(const char *format)<br> | 0x004005fc 488d45e0 lea rax, qword [local_20h]<br> | 0x00400600 4889c6 mov rsi, rax<br> | 0x00400603 bf4b074000 mov edi, 0x40074b<br> | 0x00400608 b800000000 mov eax, 0<br> | 0x0040060d e8aefeffff call sym.imp.__isoc99_scanf<br> | 0x00400612 c645f761 mov byte [local_9h], 0x61 ; 'a' ; 97<br> | 0x00400616 8b45dc mov eax, dword [local_24h]<br> | 0x00400619 85c0 test eax, eax<br> | ,=< 0x0040061b 7561 jne 0x40067e | | 0x0040061d 0fbe45f7 movsx eax, byte [local_9h] | | 0x00400621 448d48e7 lea r9d, dword [rax - 0x19] | | 0x00400625 0fbe45f7 movsx eax, byte [local_9h] | | 0x00400629 448d40ec lea r8d, dword [rax - 0x14] | | 0x0040062d 0fbe45f7 movsx eax, byte [local_9h] | | 0x00400631 0fbe55f7 movsx edx, byte [local_9h] | | 0x00400635 8d7a1e lea edi, dword [rdx + 0x1e] ; 30 | | 0x00400638 0fbe55f7 movsx edx, byte [local_9h] | | 0x0040063c 448d5a03 lea r11d, dword [rdx + 3] ; 3 | | 0x00400640 0fbe55f7 movsx edx, byte [local_9h] | | 0x00400644 448d5213 lea r10d, dword [rdx + 0x13] ; 19 | | 0x00400648 0fbe55f7 movsx edx, byte [local_9h] | | 0x0040064c 8d4a0f lea ecx, dword [rdx + 0xf] ; 15 | | 0x0040064f 0fbe55f7 movsx edx, byte [local_9h] | | 0x00400653 83c214 add edx, 0x14 | | 0x00400656 0fbe75f7 movsx esi, byte [local_9h] | | 0x0040065a 83c601 add esi, 1 | | 0x0040065d 4151 push r9 | | 0x0040065f 4150 push r8 | | 0x00400661 50 push rax | | 0x00400662 57 push rdi | | 0x00400663 4589d9 mov r9d, r11d | | 0x00400666 4589d0 mov r8d, r10d | | 0x00400669 bf50074000 mov edi, str.The_hackiit_flag_is:__c_c_c_c_c_c_c_c_c ; 0x400750 ; "The hackiit_flag is: %c%c%c%c%c%c%c%c%c\n" ; const char * format | | 0x0040066e b800000000 mov eax, 0 | | 0x00400673 e828feffff call sym.imp.printf ; int printf(const char *format) | | 0x00400678 4883c420 add rsp, 0x20 | ,==< 0x0040067c eb0a jmp 0x400688 | || ; JMP XREF from 0x0040061b (main) | |<code>-> 0x0040067e bf79074000 mov edi, str.Bad_luck._Try_again... ; rdi ; 0x400779 ; "Bad luck. Try again..." ; const char * s | | 0x00400683 e808feffff call sym.imp.puts ; int puts(const char *s) | | ; JMP XREF from 0x0040067c (main) |</code>--> 0x00400688 b800000000 mov eax, 0<br> | 0x0040068d c9 leave<br> \ 0x0040068e c3 ret
Observando el código nos damos cuenta de que hay un condicional “jne” (jump short if not equal/not zero) el cual si no se cumple cierta condición realizará un salto a la línea correspondiente al resultado “Bad luck. Try again…”, por lo que deberemos de parchearlo para que el programa continúe ejecutándose por donde podemos ver el string “The hackiit_flag is: %c%c%c%c%c%c%c%c%c\n”. Para ello cambiaremos el “jne” por un “je” (jump short if equal), es decir, si se cumple la condición (que nunca se cumplirá) saltará a la parte “Bad luck. Try again…” y si no se cumple (este es nuestro objetivo) saltará al apartado deseado. Para realizar este parche primero nos movemos a la posición de memoria del “jne” con “s 0x0040061b” y lo sustituimos por el “je” con “wa je 0x40067e”. Una vez sustituido solo nos queda salir de radare con “q” y ejecutar el programa de nuevo, obteniendo así la flag:
root@hackiit:/home/carliquiss/CrackMe# ./getflag<br> Enter the key to obtain the flag: a<br> The hackiit_flag is: buptdaMH<br>
Por lo tanto la flag es:
hackiit_flag{buptdaMH}
Recent Comments