NSA Codebreaker Challenge 2015: Task 2

This is a continuation of my previous post on the NSA Codebreaker Challenge 2015, and covers the second task in the challenge.

Task 2

Through SIGINT we have collected a new message file - this one appears to
have been sent to a field operative in the terrorist organization that is
of particular interest. A key file for this invidiual was collected
previously and should still be valid. We believe that this message may
contain actionable intelligence, so please report back with the message
contents as soon as possible. This task will require you to figure out how
to bypass the access controls built into the program that limit which
recipient can decode each message.

Running the program with the new message and key produced a new error:

user@host:~/nsa_codebreaker_2015/task_2$ ./secret-messenger --reveal --action tier2_msg.txt --symbol tier2_key.pem
Invalid (failed check 4)

Once again running the program under gdb, it was possible to discover where in the code the error message was being used. First, I used the process memory map to get the starting and ending addresses. Then I used gdb's find command to search for the error message string.

(gdb) info proc map
process 13651
Mapped address spaces:

    Start Addr   End Addr       Size     Offset objfile
     0x8048000  0x81a7000   0x15f000        0x0 /home/user/nsa_codebreaker_2015/task_2/secret-messenger
     0x81a7000  0x81a8000     0x1000   0x15e000 /home/user/nsa_codebreaker_2015/task_2/secret-messenger
     0x81a8000  0x81aa000     0x2000   0x15f000 /home/user/nsa_codebreaker_2015/task_2/secret-messenger
     0x81aa000  0x81ad000     0x3000        0x0 [heap]

     <remaining map removed for brevity>

(gdb) find 0x8048000, 0x81a7000, "Invalid (failed check 4)\n"
1 pattern found.
(gdb) p (char *) 0x814e5e3
$1 = 0x814e5e3 "Invalid (failed check 4)\n"

With the address of the error message string, I could then search the address space for references to it

(gdb) find 0x8048000, 0x81a7000, 0x814e5e3
0x804aad1 <tier2+1233>
1 pattern found.
(gdb) disassemble 0x804aac8, 0x804aaec
Dump of assembler code from 0x804aac8 to 0x804aaec:
   0x0804aac8 <tier2+1224>: call   0x8049700 <exit@plt>
   0x0804aacd <tier2+1229>: mov    DWORD PTR [esp+0x4],0x814e5e3
   0x0804aad5 <tier2+1237>: mov    DWORD PTR [esp],0x1
   0x0804aadc <tier2+1244>: call   0x80498a0 <__printf_chk@plt>
   0x0804aae1 <tier2+1249>: mov    DWORD PTR [esp],0x1
   0x0804aae8 <tier2+1256>: call   0x8049700 <exit@plt>
End of assembler dump.

Searching for references to 0x0804aacd found nothing. If I were using a more advanced tool, such as IDA, I could follow the call graph and see what jumps to that address. Rather than step through the program and watch for the jump manually, I decided to use gdb's ability to step backwards while debugging. This allowed me to set a breakpoint on 0x0804aacd and run the program up to that point, then step backwards to see what led there.

The comparison and jump in gdb

Just prior to the jump was a comparison checking if the value contained in the ax register was equal to 0x6962. Since the goal of this task is to bypass this check, the most straightforward solution is to patch out the jmp so it is never taken. I did this with the hexedit utility, and replaced the 6 bytes that made up the jne instruction with the NOOP value of 0x90.

However, when using the hex editor to edit the binary, the addressing starts at zero. So in order to patch in the correct place, it was necessary to calculate the offset from the beginning of the memory space to the target address (0x804a7c3 - 0x8048000 = 0x27c3), and then modify the binary at that offset in the editor.

The hexeditor program showing the NOOP bytes

After patching the binary, decoding the message worked without errors and showed that the bypass of the check was successful

user@host:~/nsa_codebreaker_2015/task_2$ ./secret-messenger --reveal --action tier2_msg.txt --symbol tier2_key.pem
Message: Our plans have been set into motion - Member number 392 is ready to carry out his tasking, and in 2 weeks time the window of opportunity will be open.  If it is necessary to abort the action, the authentication code to use is hw8qviacbj6xkus6wsel.

A successful decode of the message also meant that Task 2 was complete.