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}

Leave a comment

Your email address will not be published. Required fields are marked *