Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/tools/hardware/killerbee_msfrelay.py
Views: 11767
#!/usr/bin/env python21# Note: This module explicitly requires Python2 as KillerBee does not yet support Python3:2# https://github.com/riverloopsec/killerbee/tree/cb04e169a635ad4bc0772b631e1b332320f7a8da#killerbee34# KillerBee Metasploit relay server56import re7import os8import sys9import cmd10import time11import json12import base6413import socket14import threading15import pkg_resources # Used to get killerbee version1617from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer18from urlparse import parse_qs, urlparse19from killerbee import *2021last_errors = 022starttime = 023packets_sent = 024last_sent = 025username = None26password = None27kb = None2829class MSFHandler(BaseHTTPRequestHandler):30def status(self):31status = {}32hw_versions = []33fw_version = pkg_resources.get_distribution("killerbee").version34device_names = []35for dev in kbutils.devlist():36hw_versions.append(dev[2])37device_names.append(dev[1])38if len(hw_versions) > 0:39status["operational"] = 140else:41status["operational"] = 042status["hw_specialty"] = { "zigbee": True }43# TODO: We should check firmware before reporting transmit capabilities44status["hw_capabilities"] = { "transmit": True}45status["last_10_errors"] = last_errors46status["api_version"] = "0.0.3"47status["fw_version"] = fw_version48if len(hw_versions) == 1:49status["hw_version"] = hw_versions[0]50status["device_name"] = device_names[0]51elif len(hw_versions) > 1:52status["hw_version"] = ', '.join(hw_versions)53status["device_name"] = ', '.join(device_names)54else:55status["hw_version"] = "Not Supported"56return status5758def statistics(self):59global packets_sent60stats = {}61stats["uptime"] = int(time.time()) - starttime62stats["packet_stats"] = packets_sent63stats["last_request"] = last_sent64stats["voltage"] = "0.0v"65return stats6667def datetime(self):68return { "sytem_datetime": int(time.time()) }6970def timezone(self):71return { "system_timezone": time.strftime("%Z") }7273def set_channel(self, args):74if not "chan" in args:75return self.not_supported()76chan = int(args["chan"][0])77kb.set_channel(chan)78return { "success": True }7980def inject(self, args):81global packets_sent82if not "data" in args:83return self.not_supported()84try:85kb.inject(base64.urlsafe_b64decode(args["data"][0]))86packets_sent+=187except Exception as e:88print("ERROR: Unable to inject packet: {0}".format(e))89return { "success": False }90return { "success": True }9192def recv(self):93pkt = kb.pnext()94if pkt != None and pkt[1]:95return {"data": base64.urlsafe_b64encode(pkt[0]), "valid_crc": pkt[1], "rssi": pkt[2] }96return {}9798def sniffer_off(self):99kb.sniffer_off()100return {"success": True }101102def sniffer_on(self):103kb.sniffer_on()104return {"success": True }105106def supported_devices(self):107devices = []108for dev in kbutils.devlist():109devices.append(dev[0])110return { "devices": devices }111112def not_supported(self):113return { "status": "not supported" }114115def send(self, data, resp=200):116self.send_response(resp)117self.send_header('Content-type', 'application/json')118self.end_headers()119self.wfile.write(json.dumps(data))120return121122def do_AUTHHEAD(self):123self.send_response(401)124self.send_header('WWW-Authenticate', 'Basic realm=\"Killerbee MSF Relay\"')125self.send_header('Content-type', 'text/html')126self.end_headers()127self.wfile.write("Please Authenticate")128129def do_GET(self):130if not password == None:131if self.headers.getheader('Authorization') == None:132print("Did not authenticate")133self.do_AUTHHEAD()134return135if not self.headers.getheader('Authorization') == 'Basic '+base64.b64encode(username + ":" + password):136print("Bad Authentication")137self.do_AUTHHEAD()138return139url = urlparse(self.path)140args = parse_qs(url.query)141if self.path=="/status":142self.send(self.status())143elif self.path=="/statistics":144self.send(self.statistics())145elif self.path=="/settings/datetime":146self.send(self.datetime())147elif self.path=="/settings/timezone":148self.send(self.timezone())149elif self.path=="/zigbee/supported_devices":150self.send(self.supported_devices())151elif self.path.startswith("/zigbee/"):152re_dev = re.compile("/zigbee/([\d\w:]+)/")153m = re_dev.match(self.path)154if m:155dev = m.group(1)156if self.path.find("/set_channel?") > -1:157self.send(self.set_channel(args))158elif self.path.find("/inject?") > -1:159self.send(self.inject(args))160elif self.path.find("/recv") > -1:161self.send(self.recv())162elif self.path.find("/sniffer_off") > -1:163self.send(self.sniffer_off())164elif self.path.find("/sniffer_on") > -1:165self.send(self.sniffer_on())166else:167self.send(self.not_supported(), 404)168else:169self.send(self.not_supported(), 404)170else:171self.send(self.not_supported(), 404)172return173174class Killerbee_MSFRelay(cmd.Cmd):175intro = """176KillerBee Metasploit Relay177"""178179def __init__(self, ip='0.0.0.0', port=8080):180cmd.Cmd.__init__(self)181182self._ip = ip183self._port = port184self._sock = None185self._pause = False186187self.start()188189def start(self):190self._go = True191while self._go:192# serve the NIC port193try:194self._sock = HTTPServer((self._ip, self._port), MSFHandler)195starttime = int(time.time())196print("KillerBee MSFRelay running.")197self._sock.serve_forever()198except KeyboardInterrupt:199self._sock.socket.close()200self._go = False201except:202sys.excepthook(*sys.exc_info())203204if __name__ == "__main__":205import argparse206207parser = argparse.ArgumentParser()208parser.add_argument('-i', '--iface', '--dev', action='store', dest='devstring')209parser.add_argument('-u', '--user', default="msf_relay", help='HTTP Username', type=str)210parser.add_argument('-p', '--password', default="rfcat_relaypass", help='HTTP Password', type=str)211parser.add_argument('-P', '--Port', default=8080, type=int)212parser.add_argument('--noauth', default=False, action="store_true", help='Do not require authentication')213parser.add_argument('--localonly', default=False, action="store_true", help='Listen on localhost only')214215ifo = parser.parse_args()216217try:218kb = KillerBee(device=ifo.devstring)219except KBInterfaceError as e:220print("Interface Error: {0}".format(e))221sys.exit(-1)222223username = ifo.user224password = ifo.password225ip = "0.0.0.0"226port = ifo.Port227if ifo.noauth:228username = None229password = None230if ifo.localonly:231host = "127.0.0.1"232233wait_msg = False234dev_found = False235while not dev_found:236try:237devs = kbutils.devlist()238if len(devs) > 0:239dev_found = True240elif not wait_msg:241print("Insert KillerBee compatible ZigBee device. (You may need to add permissions)")242wait_msg = True243except KeyboardInterrupt:244sys.exit()245except:246if not wait_msg:247print("Insert KillerBee compatible ZigBee device. (You may need to add permissions)")248wait_msg = True249250beerelay = Killerbee_MSFRelay(ip, port)251252import atexit253atexit.register(cleanupInteractiveAtExit)254255256