def main(): aparse = argparse.ArgumentParser( description="Connection initiator test script for Sniffle BLE5 sniffer" ) aparse.add_argument("-s", "--serport", default="/dev/ttyACM0", help="Sniffer serial port name") args = aparse.parse_args() global hw hw = SniffleHW(args.serport) # set the advertising channel (and return to ad-sniffing mode) hw.cmd_chan_aa_phy(37, BLE_ADV_AA, 0) # pause after sniffing hw.cmd_pause_done(True) # capture advertisements hw.cmd_endtrim(0x10) # turn off RSSI filter hw.cmd_rssi(-128) # Turn off MAC filter hw.cmd_mac() # initiator doesn't care about this setting, it always accepts aux hw.cmd_auxadv(False) # advertiser needs a MAC address hw.random_addr() # advertise roughly every 200 ms hw.cmd_adv_interval(200) # zero timestamps and flush old packets hw.mark_and_flush() # advertising and scan response data advData = bytes([ 0x02, 0x01, 0x1A, 0x02, 0x0A, 0x0C, 0x11, 0x07, 0x64, 0x14, 0xEA, 0xD7, 0x2F, 0xDB, 0xA3, 0xB0, 0x59, 0x48, 0x16, 0xD4, 0x30, 0x82, 0xCB, 0x27, 0x05, 0x03, 0x0A, 0x18, 0x0D, 0x18 ]) devName = b'NCC Goat' scanRspData = bytes([len(devName) + 1, 0x09]) + devName # now enter advertiser mode hw.cmd_advertise(advData, scanRspData) while True: msg = hw.recv_and_decode() print_message(msg)
def main(): aparse = argparse.ArgumentParser( description="Scanner utility for Sniffle BLE5 sniffer") aparse.add_argument("-s", "--serport", default="/dev/ttyACM0", help="Sniffer serial port name") aparse.add_argument("-c", "--advchan", default=37, choices=[37, 38, 39], type=int, help="Advertising channel to listen on") aparse.add_argument("-r", "--rssi", default=-80, type=int, help="Filter packets by minimum RSSI") aparse.add_argument("-e", "--extadv", action="store_const", default=False, const=True, help="Capture BT5 extended (auxiliary) advertising") aparse.add_argument( "-l", "--longrange", action="store_const", default=False, const=True, help="Use long range (coded) PHY for primary advertising") args = aparse.parse_args() # Sanity check argument combinations if args.longrange and not args.extadv: print("Long-range PHY only supported in extended advertising!", file=sys.stderr) return global hw hw = SniffleHW(args.serport) # set the advertising channel (and return to ad-sniffing mode) hw.cmd_chan_aa_phy(args.advchan, BLE_ADV_AA, 2 if args.longrange else 0) # only sniff advertisements (don't follow connections) hw.cmd_endtrim(0xB0) # configure RSSI filter hw.cmd_rssi(args.rssi) # turn off MAC address filtering hw.cmd_mac() # configure BT5 extended (aux/secondary) advertising hw.cmd_auxadv(args.extadv) # trap Ctrl-C signal.signal(signal.SIGINT, sigint_handler) print("Starting scanner. Press CTRL-C to stop scanning and show results.") while not done_scan: msg = hw.recv_and_decode() if isinstance(msg, DebugMessage): print(msg) elif isinstance(msg, PacketMessage): handle_packet(msg) print("\n\nScan Results:") for a in sorted(advertisers.keys(), key=lambda k: advertisers[k].rssi, reverse=True): print("=" * 80) print("AdvA: %s RSSI: %i Hits: %i" % (a, advertisers[a].rssi, advertisers[a].hits)) if advertisers[a].adv: print("\nAdvertisement:") print(advertisers[a].adv) else: print("\nAdvertisement: None") if advertisers[a].scan_rsp: print("\nScan Response:") print(advertisers[a].scan_rsp) else: print("\nScan Response: None") print("=" * 80, end="\n\n")
def main(): aparse = argparse.ArgumentParser( description="Host-side receiver for Sniffle BLE5 sniffer") aparse.add_argument("-s", "--serport", default="/dev/ttyACM0", help="Sniffer serial port name") aparse.add_argument("-c", "--advchan", default=37, choices=[37, 38, 39], type=int, help="Advertising channel to listen on") aparse.add_argument("-p", "--pause", action="store_const", default=False, const=True, help="Pause sniffer after disconnect") aparse.add_argument("-r", "--rssi", default=-80, type=int, help="Filter packets by minimum RSSI") aparse.add_argument("-m", "--mac", default=None, help="Filter packets by advertiser MAC") aparse.add_argument( "-a", "--advonly", action="store_const", default=False, const=True, help="Sniff only advertisements, don't follow connections") aparse.add_argument("-e", "--extadv", action="store_const", default=False, const=True, help="Capture BT5 extended (auxiliary) advertising") aparse.add_argument( "-H", "--hop", action="store_const", default=False, const=True, help="Hop primary advertising channels in extended mode") aparse.add_argument( "-l", "--longrange", action="store_const", default=False, const=True, help="Use long range (coded) PHY for primary advertising") aparse.add_argument("-o", "--output", default=None, help="PCAP output file name") args = aparse.parse_args() # Sanity check argument combinations if args.hop and args.mac is None: print("Primary adv. channel hop requires a MAC address specified!", file=sys.stderr) return if args.longrange and not args.extadv: print("Long-range PHY only supported in extended advertising!", file=sys.stderr) return if args.longrange and args.hop: # this would be pointless anyway, since long range always uses extended ads print("Primary ad channel hopping unsupported on long range PHY!", file=sys.stderr) return global hw hw = SniffleHW(args.serport) # set the advertising channel (and return to ad-sniffing mode) hw.cmd_chan_aa_phy(args.advchan, BLE_ADV_AA, 2 if args.longrange else 0) # set whether or not to pause after sniffing hw.cmd_pause_done(args.pause) # set up endTrim if args.advonly: hw.cmd_endtrim(0xB0) else: hw.cmd_endtrim(0x10) # configure RSSI filter global _rssi_min _rssi_min = args.rssi hw.cmd_rssi(args.rssi) # disable 37/38/39 hop in extended mode unless overridden global _allow_hop3 if args.extadv and not args.hop: _allow_hop3 = False # configure MAC filter global _delay_top_mac if args.mac is None: hw.cmd_mac() elif args.mac == "top": hw.cmd_mac() _delay_top_mac = True else: try: macBytes = [int(h, 16) for h in reversed(args.mac.split(":"))] if len(macBytes) != 6: raise Exception("Wrong length!") except: print("MAC must be 6 colon-separated hex bytes", file=sys.stderr) return hw.cmd_mac(macBytes, _allow_hop3) # configure BT5 extended (aux/secondary) advertising hw.cmd_auxadv(args.extadv) global pcwriter if not (args.output is None): pcwriter = PcapBleWriter(args.output) while True: msg_type, msg_body = hw.recv_msg() print_message(msg_type, msg_body)
def main(): aparse = argparse.ArgumentParser( description="Connection initiator test script for Sniffle BLE5 sniffer" ) aparse.add_argument("-s", "--serport", default="/dev/ttyACM0", help="Sniffer serial port name") aparse.add_argument("-c", "--advchan", default=37, choices=[37, 38, 39], type=int, help="Advertising channel to listen on") aparse.add_argument("-r", "--rssi", default=-80, type=int, help="Filter packets by minimum RSSI") aparse.add_argument("-m", "--mac", default=None, help="Specify target MAC address") aparse.add_argument("-i", "--irk", default=None, help="Specify target IRK") aparse.add_argument( "-l", "--longrange", action="store_const", default=False, const=True, help="Use long range (coded) PHY for primary advertising") aparse.add_argument("-P", "--public", action="store_const", default=False, const=True, help="Supplied MAC address is public") args = aparse.parse_args() global hw hw = SniffleHW(args.serport) if args.mac is None and args.irk is None: print("Must specify target MAC address or IRK", file=sys.stderr) return if args.mac and args.irk: print("IRK and MAC filters are mutually exclusive!", file=sys.stderr) return if args.public and args.irk: print("IRK only works on RPAs, not public addresses!", file=sys.stderr) return # set the advertising channel (and return to ad-sniffing mode) hw.cmd_chan_aa_phy(args.advchan, BLE_ADV_AA, 2 if args.longrange else 0) # pause after sniffing hw.cmd_pause_done(True) # capture advertisements hw.cmd_endtrim(0x10) # configure RSSI filter hw.cmd_rssi(args.rssi) if args.mac: try: macBytes = [int(h, 16) for h in reversed(args.mac.split(":"))] if len(macBytes) != 6: raise Exception("Wrong length!") except: print("MAC must be 6 colon-separated hex bytes", file=sys.stderr) return hw.cmd_mac(macBytes, False) else: hw.cmd_irk(unhexlify(args.irk), False) # initiator doesn't care about this setting, it always accepts aux hw.cmd_auxadv(False) # initiator needs a MAC address hw.random_addr() if args.irk: macBytes = get_mac_from_irk() # zero timestamps and flush old packets hw.mark_and_flush() # now enter initiator mode global _aa _aa = hw.initiate_conn(macBytes, not args.public) while True: msg = hw.recv_and_decode() print_message(msg)