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.

[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ ls
ATL  CLE  HBG  PGET_A.OUT  RIC
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ file PGET_A.OUT
PGET_A.OUT: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 3.2.29, not stripped
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ cd ATL
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS/ATL]$ file *
10.TRN: data
11.TRN: data
12.TRN: data
13.TRN: data
14.TRN: data
15.TRN: data
1.TRN:  data
2.TRN:  data
3.TRN:  data
4.TRN:  data
5.TRN:  data
6.TRN:  data
7.TRN:  data
8.TRN:  data
9.TRN:  data
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS/ATL]$ cd ..
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ cd CLE
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS/CLE]$ file *
10.TRN: ASCII text
11.TRN: ASCII text
12.TRN: ASCII text
13.TRN: ASCII text
14.TRN: ASCII text
15.TRN: ASCII text
1.TRN:  ASCII text
2.TRN:  ASCII text
3.TRN:  ASCII text
4.TRN:  ASCII text
5.TRN:  ASCII text
6.TRN:  ASCII text
7.TRN:  ASCII text
8.TRN:  ASCII text
9.TRN:  ASCII text
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS/CLE]$ cat 1.TRN
invoice: 21815
order: 8925
customer: 30871
scrip: Percocet
days: 14
addr1: James Monroe
addr2: 6596 Euclid
addr3; Zanesville PA 22112

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.

[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ ./PGET_A.OUT 
Must set options -s (server) -p (password) and -u (username).
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ ./PGET_A.OUT -s 127.0.0.1 -p password -u user

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.

[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ strace ./PGET_A.OUT -s 127.0.0.1 -p password -u user
execve("./PGET_A.OUT", ["./PGET_A.OUT", "-s", "127.0.0.1", "-p", "password", "-u", "user"], [/* 44 vars */]) = 0
[ Process PID=10312 runs in 32 bit mode. ]
uname({sys="Linux", node="vader", ...}) = 0
brk(0)                                  = 0x9f55000
brk(0x9f55d40)                          = 0x9f55d40
set_thread_area({entry_number:-1, base_addr:0x9f55840, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:12)
brk(0x9f76d40)                          = 0x9f76d40
brk(0x9f77000)                          = 0x9f77000
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 4
sendto(4, "user password", 13, 0, {sa_family=AF_INET, sin_port=htons(3000), sin_addr=inet_addr("127.0.0.1")}, 16) = 13
recvfrom(4,
)

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.

#### netcat listener ####
[chiggins@vader ~]$ nc -ulvvp 3000
Listening on any address 3000 (hbci)
Received packet from 127.0.0.1:58075 -> 127.0.0.1:3000 (local)
user passwordJUNKDATA

#### program ####
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ ./PGET_A.OUT -s 127.0.0.1 -p password -u user
bad username or password

#### program with strace ####
[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ strace ./PGET_A.OUT -s 127.0.0.1 -p password -u user
execve("./PGET_A.OUT", ["./PGET_A.OUT", "-s", "127.0.0.1", "-p", "password", "-u", "user"], [/* 44 vars */]) = 0
[ Process PID=10537 runs in 32 bit mode. ]
uname({sys="Linux", node="vader", ...}) = 0
brk(0)                                  = 0x9388000
brk(0x9388d40)                          = 0x9388d40
set_thread_area({entry_number:-1, base_addr:0x9388840, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:12)
brk(0x93a9d40)                          = 0x93a9d40
brk(0x93aa000)                          = 0x93aa000
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 4
sendto(4, "user password", 13, 0, {sa_family=AF_INET, sin_port=htons(3000), sin_addr=inet_addr("127.0.0.1")}, 16) = 13
recvfrom(4, "JUNKDA", 6, 0, {sa_family=AF_INET, sin_port=htons(3000), sin_addr=inet_addr("127.0.0.1")}, [16]) = 6
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff7722000
write(1, "bad username or password\n", 25bad username or password
) = 25
exit_group(0)                           = ?
+++ exited with 0 +++

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.

[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS]$ gdb -q ./PGET_A.OUT
Reading symbols from ./PGET_A.OUT...done.
gdb>set args -s 127.0.0.1 -u username -p password
gdb>disassemble main
Dump of assembler code for function main:
   0x08048c85 <+0>:	push   ebp
   0x08048c86 <+1>:	mov    ebp,esp
   0x08048c88 <+3>:	push   edi
   0x08048c89 <+4>:	push   esi
   0x08048c8a <+5>:	push   ebx
   0x08048c8b <+6>:	and    esp,0xfffffff0
   0x08048c8e <+9>:	sub    esp,0x50
   0x08048c91 <+12>:	mov    DWORD PTR [esp+0x4c],0x0
   0x08048c99 <+20>:	mov    DWORD PTR [esp+0x48],0x0
   0x08048ca1 <+28>:	mov    DWORD PTR [esp+0x44],0x0
   0x08048ca9 <+36>:	lea    eax,[esp+0x13]
   0x08048cad <+40>:	mov    edx,0x80bac20
   0x08048cb2 <+45>:	mov    ebx,0x25
   0x08048cb7 <+50>:	mov    ecx,eax
   0x08048cb9 <+52>:	and    ecx,0x1
   0x08048cbc <+55>:	test   ecx,ecx
   0x08048cbe <+57>:	je     0x8048cc7 <main+66>
   0x08048cc0 <+59>:	mov    cl,BYTE PTR [edx]
   0x08048cc2 <+61>:	mov    BYTE PTR [eax],cl
   0x08048cc4 <+63>:	inc    eax
   0x08048cc5 <+64>:	inc    edx
   0x08048cc6 <+65>:	dec    ebx
   0x08048cc7 <+66>:	mov    ecx,eax
   0x08048cc9 <+68>:	and    ecx,0x2
   0x08048ccc <+71>:	test   ecx,ecx
   0x08048cce <+73>:	je     0x8048cdf <main+90>
   0x08048cd0 <+75>:	mov    cx,WORD PTR [edx]
   0x08048cd3 <+78>:	mov    WORD PTR [eax],cx
   0x08048cd6 <+81>:	add    eax,0x2
   0x08048cd9 <+84>:	add    edx,0x2
   0x08048cdc <+87>:	sub    ebx,0x2
   0x08048cdf <+90>:	mov    ecx,ebx
   0x08048ce1 <+92>:	shr    ecx,0x2
   0x08048ce4 <+95>:	mov    edi,eax
   0x08048ce6 <+97>:	mov    esi,edx
   0x08048ce8 <+99>:	rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi]
   0x08048cea <+101>:	mov    edx,esi
   0x08048cec <+103>:	mov    eax,edi
   0x08048cee <+105>:	mov    ecx,0x0
   0x08048cf3 <+110>:	mov    esi,ebx
   0x08048cf5 <+112>:	and    esi,0x2
   0x08048cf8 <+115>:	test   esi,esi
   0x08048cfa <+117>:	je     0x8048d07 <main+130>
   0x08048cfc <+119>:	mov    si,WORD PTR [edx+ecx*1]
   0x08048d00 <+123>:	mov    WORD PTR [eax+ecx*1],si
   0x08048d04 <+127>:	add    ecx,0x2
   0x08048d07 <+130>:	and    ebx,0x1
   0x08048d0a <+133>:	test   ebx,ebx
   0x08048d0c <+135>:	je     0x8048d14 <main+143>
   0x08048d0e <+137>:	mov    dl,BYTE PTR [edx+ecx*1]
   0x08048d11 <+140>:	mov    BYTE PTR [eax+ecx*1],dl
   0x08048d14 <+143>:	mov    DWORD PTR ds:0x80e4a18,0x0
   0x08048d1e <+153>:	jmp    0x8048d75 <main+240>
   0x08048d20 <+155>:	cmp    DWORD PTR [esp+0x3c],0x75
   0x08048d25 <+160>:	jne    0x8048d32 <main+173>
   0x08048d27 <+162>:	mov    eax,ds:0x80e6218
   0x08048d2c <+167>:	mov    DWORD PTR [esp+0x4c],eax
   0x08048d30 <+171>:	jmp    0x8048d75 <main+240>
   0x08048d32 <+173>:	cmp    DWORD PTR [esp+0x3c],0x70
   0x08048d37 <+178>:	jne    0x8048d44 <main+191>
   0x08048d39 <+180>:	mov    eax,ds:0x80e6218
   0x08048d3e <+185>:	mov    DWORD PTR [esp+0x48],eax
   0x08048d42 <+189>:	jmp    0x8048d75 <main+240>
   0x08048d44 <+191>:	cmp    DWORD PTR [esp+0x3c],0x73
   0x08048d49 <+196>:	jne    0x8048d56 <main+209>
   0x08048d4b <+198>:	mov    eax,ds:0x80e6218
   0x08048d50 <+203>:	mov    DWORD PTR [esp+0x44],eax
   0x08048d54 <+207>:	jmp    0x8048d75 <main+240>
   0x08048d56 <+209>:	mov    edx,DWORD PTR ds:0x80e4a14
   0x08048d5c <+215>:	mov    eax,ds:0x80e453c
   0x08048d61 <+220>:	mov    DWORD PTR [esp+0x8],edx
   0x08048d65 <+224>:	mov    DWORD PTR [esp+0x4],0x80bab4e
   0x08048d6d <+232>:	mov    DWORD PTR [esp],eax
   0x08048d70 <+235>:	call   0x80498a0 <fprintf>
   0x08048d75 <+240>:	mov    DWORD PTR [esp+0x8],0x80bab62
   0x08048d7d <+248>:	mov    eax,DWORD PTR [ebp+0xc]
   0x08048d80 <+251>:	mov    DWORD PTR [esp+0x4],eax
   0x08048d84 <+255>:	mov    eax,DWORD PTR [ebp+0x8]
   0x08048d87 <+258>:	mov    DWORD PTR [esp],eax
   0x08048d8a <+261>:	call   0x8055b10 <getopt>
   0x08048d8f <+266>:	mov    DWORD PTR [esp+0x3c],eax
   0x08048d93 <+270>:	cmp    DWORD PTR [esp+0x3c],0xffffffff
   0x08048d98 <+275>:	jne    0x8048d20 <main+155>
   0x08048d9a <+277>:	cmp    DWORD PTR [esp+0x4c],0x0
   0x08048d9f <+282>:	je     0x8048daf <main+298>
   0x08048da1 <+284>:	cmp    DWORD PTR [esp+0x48],0x0
   0x08048da6 <+289>:	je     0x8048daf <main+298>
   0x08048da8 <+291>:	cmp    DWORD PTR [esp+0x44],0x0
   0x08048dad <+296>:	jne    0x8048dde <main+345>
   0x08048daf <+298>:	mov    eax,ds:0x80e453c
   0x08048db4 <+303>:	mov    DWORD PTR [esp+0xc],eax
   0x08048db8 <+307>:	mov    DWORD PTR [esp+0x8],0x3e
   0x08048dc0 <+315>:	mov    DWORD PTR [esp+0x4],0x1
   0x08048dc8 <+323>:	mov    DWORD PTR [esp],0x80bab6c
   0x08048dcf <+330>:	call   0x8049900 <fwrite>
   0x08048dd4 <+335>:	mov    eax,0x1
   0x08048dd9 <+340>:	jmp    0x8048eed <main+616>
   0x08048dde <+345>:	mov    DWORD PTR [esp+0x8],0x11
   0x08048de6 <+353>:	mov    DWORD PTR [esp+0x4],0x2
   0x08048dee <+361>:	mov    DWORD PTR [esp],0x2
   0x08048df5 <+368>:	call   0x8057100 <socket>
   0x08048dfa <+373>:	mov    DWORD PTR [esp+0x38],eax
   0x08048dfe <+377>:	cmp    DWORD PTR [esp+0x38],0x0
   0x08048e03 <+382>:	jns    0x8048e34 <main+431>
   0x08048e05 <+384>:	mov    eax,ds:0x80e453c
   0x08048e0a <+389>:	mov    DWORD PTR [esp+0xc],eax
   0x08048e0e <+393>:	mov    DWORD PTR [esp+0x8],0x16
   0x08048e16 <+401>:	mov    DWORD PTR [esp+0x4],0x1
   0x08048e1e <+409>:	mov    DWORD PTR [esp],0x80babab
   0x08048e25 <+416>:	call   0x8049900 <fwrite>
   0x08048e2a <+421>:	mov    eax,0x1
   0x08048e2f <+426>:	jmp    0x8048eed <main+616>
   0x08048e34 <+431>:	mov    eax,DWORD PTR [esp+0x38]
   0x08048e38 <+435>:	mov    DWORD PTR [esp+0xc],eax
   0x08048e3c <+439>:	mov    eax,DWORD PTR [esp+0x44]
   0x08048e40 <+443>:	mov    DWORD PTR [esp+0x8],eax
   0x08048e44 <+447>:	mov    eax,DWORD PTR [esp+0x48]
   0x08048e48 <+451>:	mov    DWORD PTR [esp+0x4],eax
   0x08048e4c <+455>:	mov    eax,DWORD PTR [esp+0x4c]
   0x08048e50 <+459>:	mov    DWORD PTR [esp],eax
   0x08048e53 <+462>:	call   0x8048aec <sendAuth>
   0x08048e58 <+467>:	test   eax,eax
   0x08048e5a <+469>:	je     0x8048ec3 <main+574>
   0x08048e5c <+471>:	mov    eax,DWORD PTR [esp+0x38]
   0x08048e60 <+475>:	mov    DWORD PTR [esp],eax
   0x08048e63 <+478>:	call   0x8048bde <recvAuth>
   0x08048e68 <+483>:	test   eax,eax
   0x08048e6a <+485>:	je     0x8048eb5 <main+560>
   0x08048e6c <+487>:	mov    DWORD PTR [esp],0x80babc2
   0x08048e73 <+494>:	call   0x8049a50 <puts>
   0x08048e78 <+499>:	mov    DWORD PTR [esp+0x40],0x0
   0x08048e80 <+507>:	jmp    0x8048ea0 <main+539>
   0x08048e82 <+509>:	lea    edx,[esp+0x13]
   0x08048e86 <+513>:	mov    eax,DWORD PTR [esp+0x40]
   0x08048e8a <+517>:	add    eax,edx
   0x08048e8c <+519>:	mov    al,BYTE PTR [eax]
   0x08048e8e <+521>:	xor    eax,0x17
   0x08048e91 <+524>:	movsx  eax,al
   0x08048e94 <+527>:	mov    DWORD PTR [esp],eax
   0x08048e97 <+530>:	call   0x8049c80 <putchar>
   0x08048e9c <+535>:	inc    DWORD PTR [esp+0x40]
   0x08048ea0 <+539>:	cmp    DWORD PTR [esp+0x40],0x24
   0x08048ea5 <+544>:	jle    0x8048e82 <main+509>
   0x08048ea7 <+546>:	mov    DWORD PTR [esp],0xa
   0x08048eae <+553>:	call   0x8049c80 <putchar>
   0x08048eb3 <+558>:	jmp    0x8048ee8 <main+611>
   0x08048eb5 <+560>:	mov    DWORD PTR [esp],0x80babca
   0x08048ebc <+567>:	call   0x8049a50 <puts>
   0x08048ec1 <+572>:	jmp    0x8048ee8 <main+611>
   0x08048ec3 <+574>:	mov    eax,ds:0x80e453c
   0x08048ec8 <+579>:	mov    DWORD PTR [esp+0xc],eax
   0x08048ecc <+583>:	mov    DWORD PTR [esp+0x8],0x1e
   0x08048ed4 <+591>:	mov    DWORD PTR [esp+0x4],0x1
   0x08048edc <+599>:	mov    DWORD PTR [esp],0x80babe4
   0x08048ee3 <+606>:	call   0x8049900 <fwrite>
   0x08048ee8 <+611>:	mov    eax,0x0
   0x08048eed <+616>:	lea    esp,[ebp-0xc]
   0x08048ef0 <+619>:	pop    ebx
   0x08048ef1 <+620>:	pop    esi
   0x08048ef2 <+621>:	pop    edi
   0x08048ef3 <+622>:	pop    ebp
   0x08048ef4 <+623>:	ret
End of assembler dump.

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.

gdb>break *0x08048e68
Breakpoint 1 at 0x8048e68
gdb>run
Starting program: /home/chiggins/DerbyCon4.0/74/DRIVE_C/TRNDOCS/PGET_A.OUT -s 127.0.0.1 -u username -p password
Got object file from memory but can't read symbols: File truncated.

Breakpoint 1, 0x08048e68 in main ()
gdb>info registers
eax            0x0	0x0
ecx            0xffffd5e8	0xffffd5e8
edx            0xffffd54a	0xffffd54a
ebx            0x0	0x0
esp            0xffffd610	0xffffd610
ebp            0xffffd678	0xffffd678
esi            0x0	0x0
edi            0xffffd648	0xffffd648
eip            0x8048e68	0x8048e68 <main+483>
eflags         0x287	[ CF PF SF IF ]
cs             0x23	0x23
ss             0x2b	0x2b
ds             0x2b	0x2b
es             0x2b	0x2b
fs             0x0	0x0
gs             0x63	0x63
gdb>disassemble main
Dump of assembler code for function main:
[... snip ...]
   0x08048e53 <+462>:	call   0x8048aec <sendAuth>
   0x08048e58 <+467>:	test   eax,eax
   0x08048e5a <+469>:	je     0x8048ec3 <main+574>
   0x08048e5c <+471>:	mov    eax,DWORD PTR [esp+0x38]
   0x08048e60 <+475>:	mov    DWORD PTR [esp],eax
   0x08048e63 <+478>:	call   0x8048bde <recvAuth>
=> 0x08048e68 <+483>:	test   eax,eax
   0x08048e6a <+485>:	je     0x8048eb5 <main+560>
   0x08048e6c <+487>:	mov    DWORD PTR [esp],0x80babc2
   0x08048e73 <+494>:	call   0x8049a50 <puts>
   0x08048e78 <+499>:	mov    DWORD PTR [esp+0x40],0x0
   0x08048e80 <+507>:	jmp    0x8048ea0 <main+539>
   0x08048e82 <+509>:	lea    edx,[esp+0x13]
[... snip ...]
End of assembler dump.
gdb>continue
Continuing.
bad username or password
[Inferior 1 (process 11299) exited normally]

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.

gdb>run
Starting program: /home/chiggins/DerbyCon4.0/74/DRIVE_C/TRNDOCS/PGET_A.OUT -s 127.0.0.1 -u username -p password
Got object file from memory but can't read symbols: File truncated.

Breakpoint 1, 0x08048e68 in main ()
gdb>disassemble main
Dump of assembler code for function main:
[... snip ...]
   0x08048e53 <+462>:   call   0x8048aec <sendAuth>
   0x08048e58 <+467>:   test   eax,eax
   0x08048e5a <+469>:   je     0x8048ec3 <main+574>
   0x08048e5c <+471>:   mov    eax,DWORD PTR [esp+0x38]
   0x08048e60 <+475>:   mov    DWORD PTR [esp],eax
   0x08048e63 <+478>:   call   0x8048bde <recvAuth>
=> 0x08048e68 <+483>:   test   eax,eax
   0x08048e6a <+485>:   je     0x8048eb5 <main+560>
   0x08048e6c <+487>:   mov    DWORD PTR [esp],0x80babc2
   0x08048e73 <+494>:   call   0x8049a50 <puts>
   0x08048e78 <+499>:   mov    DWORD PTR [esp+0x40],0x0
   0x08048e80 <+507>:   jmp    0x8048ea0 <main+539>
   0x08048e82 <+509>:   lea    edx,[esp+0x13]
[... snip ...]
End of assembler dump.
gdb>info registers 
eax            0x0	0x0
ecx            0xffffd5e8	0xffffd5e8
edx            0xffffd54a	0xffffd54a
ebx            0x0	0x0
esp            0xffffd610	0xffffd610
ebp            0xffffd678	0xffffd678
esi            0x0	0x0
edi            0xffffd648	0xffffd648
eip            0x8048e68	0x8048e68 <main+483>
eflags         0x287	[ CF PF SF IF ]
cs             0x23	0x23
ss             0x2b	0x2b
ds             0x2b	0x2b
es             0x2b	0x2b
fs             0x0	0x0
gs             0x63	0x63
gdb>set $eax = 0x1
gdb>info registers
eax            0x1	0x1
ecx            0xffffd5e8	0xffffd5e8
edx            0xffffd54a	0xffffd54a
ebx            0x0	0x0
esp            0xffffd610	0xffffd610
ebp            0xffffd678	0xffffd678
esi            0x0	0x0
edi            0xffffd648	0xffffd648
eip            0x8048e68	0x8048e68 <main+483>
eflags         0x287	[ CF PF SF IF ]
cs             0x23	0x23
ss             0x2b	0x2b
ds             0x2b	0x2b
es             0x2b	0x2b
fs             0x0	0x0
gs             0x63	0x63
gdb>continue
Continuing.
Success
The secret key is EverybodyDoTheLimit
[Inferior 1 (process 11416) exited normally]

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.

[chiggins@vader ~/DerbyCon4.0/74/DRIVE_C/TRNDOCS/ATL]$ openssl des3 -d -salt -in 2.TRN -k EverybodyDoTheLimit
invoice: 19755
order: 11389
customer: 24956
scrip: flag
days: 90
addr1: CountingSheep75
addr2: 8982 Elm
addr3; Henderson LA 13131

Submitted “CountingSheep75” to the scoring engine, and received 450 points. Woo!

Since I’ve really been getting into reverse engineering and debugging lately, this was a really fun challenge for me. Thanks to the DerbyCon CTF crew for creating this one!