9447 CTF 2015 – Real Flag Finder (70)

Introduction
Hello all, it has been a while and I haven’t published something in a month, so here’s a little something! A had some time to spare and worked on a challenge from 9447 2015!

This was a straightforward reverse engineering task where We’re given the binary and are asked to find a flag, for 70 points!


Approach
A little bit of information about the file to start with:
file

$ flagFinderRedux-e72e7ac9b16b8f40acd337069f94d524
flagFinderRedux-e72e7ac9b16b8f40acd337069f94d524: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=8c0c9c0d5c39ff0cc1954fa8682288b6169b8fff, stripped

As you can imagine, running strings on it is not all that useful in terms of revealing a flag, so let’s open it up in IDA and see what makes this one tick and how we can find the flag! A quick glance at the functions:

Figure 1: Functions in this binary.
Figure 1: Functions in this binary.

So our first order of business would be to locate main. As described here, we see that main is located at 0x40063E! Lucky for us, strings in this application are not obfuscated so we can easily deduce the number of arguments that the product expects, as well as where the check for correctness happens! Location 0x400665 reveals the number of arguments:

.text:000000000040064B                 mov     [rb var_44], edi
.text:000000000040064E                 mov     [rb var_50], rsi
.text:0000000000400652                 mov     rax, rsp
.text:0000000000400655                 mov     r12, rax
.text:0000000000400658                 cmp     [rb var_44], 2
.text:000000000040065C                 jz      short loc_400681
.text:000000000040065E                 mov     rax, [rb var_50]
.text:0000000000400662                 mov     rax, [rax]
.text:0000000000400665                 mov     rsi, rax
.text:0000000000400668                 mov     edi, offset format ; "Usage: %s <password>\n"
.text:000000000040066D                 mov     eax, 0
.text:0000000000400672                 call    _printf
.text:0000000000400677                 mov     eax, 1
.text:000000000040067C                 jmp     loc_4007A0

Next, locating the string “The flag is %s\n” and tracing backwards will lead us to this code block:

.text:00000000004006F2 loc_4006F2:                             ; CODE XREF: main+158j
.text:00000000004006F2                 mov     rax, [rbp+dest]
.text:00000000004006F6                 mov     edx, 4          ; n
.text:00000000004006FB                 mov     esi, offset a9447 ; "9447"
.text:0000000000400700                 mov     rdi, rax        ; s1
.text:0000000000400703                 call    _memcmp
.text:0000000000400708                 test    eax, eax
.text:000000000040070A                 jnz     short loc_40075D
.text:000000000040070C                 mov     eax, cs:n
.text:0000000000400712                 mov     edx, eax        ; n
.text:0000000000400714                 mov     rax, [rbp+var_50]
.text:0000000000400718                 add     rax, 8
.text:000000000040071C                 mov     rcx, [rax]
.text:000000000040071F                 mov     rax, [rbp+dest]
.text:0000000000400723                 mov     rsi, rcx        ; s2
.text:0000000000400726                 mov     rdi, rax        ; s1
.text:0000000000400729                 call    _memcmp
.text:000000000040072E                 test    eax, eax
.text:0000000000400730                 jnz     short loc_400751
.text:0000000000400732                 mov     rax, [rbp+var_50]
.text:0000000000400736                 add     rax, 8
.text:000000000040073A                 mov     rax, [rax]
.text:000000000040073D                 mov     rsi, rax
.text:0000000000400740                 mov     edi, offset aTheFlagIsS ; "The flag is %s\n"
.text:0000000000400745                 mov     eax, 0
.text:000000000040074A                 call    _printf
.text:000000000040074F                 jmp     short loc_40079B

Call me optimistic, but I believe that the memcmp call in location 0x400729 will have the unprotected secret, or flag, in memory for us to read! gdb confirms this:

% gdb -q flagFinderRedux-e72e7ac9b16b8f40acd337069f94d524
Reading symbols from flagFinderRedux-e72e7ac9b16b8f40acd337069f94d524...(no debugging symbols found)...done.
(gdb) br *0x400729
Breakpoint 1 at 0x400729
(gdb) run test
Starting program: ./flagFinderRedux-e72e7ac9b16b8f40acd337069f94d524 test

Breakpoint 1, 0x0000000000400729 in ?? ()
(gdb) x/s $rsp
0x7fffffffe4a0:    "9447{C0ngr47ulaT1ons_p4l_buddy_y0Uv3_solved_the_re4l__H4LT1N6_prObL3M}"

Yay, flags 😀

Conclusion
This was a pretty easy challenge all in all as there were no protections or anything in terms of the code! An interesting side not that I have not seen before in CTFs is that this uses a different calling convention that I traditionally observe. In particular, it doesn’t use the stack to pass arguments like integers (or pointers), but instead they are being passed in the registers – just observe a few of the instructions preceding the call instructions. According to Wikipedia this is the System V AMD64 ABI calling convention (that page is an interesting read with some nice references!).

This was a good warm up!

Advertisements
9447 CTF 2015 – Real Flag Finder (70)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s