Derbycon 4.0 Ctf Trndocs Elf Binary Reverse Engineering and Debugging

So this past weekend I attended DerbyCon 4.0 in Louisville, Kentucky, and was lucky enough to play the CTF along side the @bsjtf team. We were able to place 16th out of the 77 point scoring teams/individuals, which is pretty damn good I’d say. This write-up will be for a reversing challenge I solved, adding 450 points to the teams total.

One of the first things done was a scan for various services on the network. Since FTP is a common place for CTF flags to hide, went searching for any FTP servers in the environment.

nmap 10.10.146.1/24 -p 21 --open -sV

One of the FTP servers that stood out was 10.10.146.74 which has anonymous read access and quite an interesting MOTD when logging in.

230-This is a temporary ftp server, while we finish our migration off DOS
230-platforms. For now transaction documents are still availible at
230-/DRIVE_C/TRNDOCS but these are already being generated by the LINUX
230-backend.
230-
230-DOCS for DCs that have already been upgraded are ciphered with
230-OpenSSL, the utility to obtain the shared password from your
230-credentials is TRNDOCS directory.
230-Use the serer xxx.xxx.xxx.xxx to authenticate, you can manually
230-inspect a TRN document with OpenSSL once you obtain the key.
230-
230-openssl des3 -d -salt -in -k
230-
230 User logged in

Interesting, /DRIVE_C/TRNDOCS/ seems to have a lot of interesting information in it. So I pull everything down and start analyzing the file in there.

So it looks like we have a combination of plaintext data, encrypted data, and an ELF binary, which is very interesting. Running strings on the binary doesn’t show anything of super interest. Lets just run it and see what happens.

The program accepts a server (which I assume it wants to talk to), and a username and password to validate against. Running it with my localhost set as the server just lets it hang, so I’m assuming a socket is being created somewhere. Using strace we’ll be able to see more about this.

I was right, a socket is trying to make a connection and read back some data. If you notice in sendto, the socket is trying to send data “user password” to 127.0.0.1 on port 3000. I figured that this program was meant to talk to a server on the network, but scanning for an open port 3000 turned out no results. Figured to just keep moving on with this binary and see what else it does.

So I decided to set up a natcat listener on port 3000 and try to receive the data and send data back. One thing that tripped me up with this is that I didn’t realize you needed to tell netcat to listen as a UDP port. Before knowing that, whenever I had my netcat listener running on TCP 3000, the program would not connect to it. After finding out how to specify UDP, I was finally able to send data back and forth.

So there’s a bit going on here. The netcat listener gets set up to listen on port 3000 with the -u specifing UDP. Then when the program runs, it sends along the specified arguments “user password”. I send back “JUNKDATA” and the program fails saying bad username and password. I also included the strace output, and you’ll notice that the program only reads 6 bytes, “JUNKDA”.

Here is where we start to do some debugging and reversing. I load up the program in gdb, set the required arguments, and take a look at the main method.

The disassembly for main is pretty crazy, but if you just walk through it, it’s not too bad. It does some argument checking, creates a socket (0x08048df5 <+368>), sends the authentication data (0x08048e53 <+462>), receives the authentication response (0x08048e63 <+478>), and some more nonsense towards the end.

Something interesting that I noticed is that right after we receive the authentication data, a test is done on eax against eax (0x08048e68 <+483>). In assembly, the return value of a function is stored in eax, so this test is looking to verify the return of the recvAuth method. I think it is safe to assume that here is where the program will decide to give us either the “bad username or password” text, or continue on to do something more.

Before I continued, I had to look up what test actually did. From this question on StackOverflow, “TEST sets the Zero Flag if the the result of the AND operation is zero. If two operands are equal, their bitwise AND is zero iff both are zero. It also sets the Sign Flag if the top bit is set in the result, and the Parity Flag if the number of set bits is even.” What this means is that in our program, if eax is set to 0x0, then the program will jump to 0x8048eb5 , which is towards the end of the program. If we put a breakpoint at this location and look at the registers and disassembly, we can see this happen.

So after recvAuth eax was set to 0x0 which caused the result from test to jump to the end of the program and show the bad password message. What happens if we set eax to 0x1, maybe it will bypass the jump and continue onto something more interesting.

Woah! Would you look at that, got something juicy. I tried to submit “EverybodyDoTheLimit” as a flag, but it ended up not being valid. But if you recall back to the FTP MOTD at the beginning of the post, we can now expect the TRN documents via openssl with the newly acquired secret key. After running through the various encrypted files, I finally ran into one with a flag in it.