Exemplo n.º 1
0
def main():
    aparse = argparse.ArgumentParser(
        description="Firmware reset utility for Sniffle BLE5 sniffer")
    aparse.add_argument("-s",
                        "--serport",
                        default="/dev/ttyACM0",
                        help="Sniffer serial port name")
    args = aparse.parse_args()

    hw = SniffleHW(args.serport)

    # 5 resets seems to work more reliably than fewer
    print("Sending reset commands...")
    for i in range(5):
        hw.ser.write(b'@@@@@@@@\r\n')  # command sync
        hw.cmd_reset()
        sleep(0.02)

    # try a flush, see if we get a marker back to prove firmware liveness
    hw.ser.write(b'@@@@@@@@\r\n')  # command sync
    print("Trying a mark and flush to get things flowing...")
    hw.mark_and_flush()
    print("Reset success.")
Exemplo n.º 2
0
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")
Exemplo n.º 3
0
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)

    # Accept/follow connections
    hw.cmd_follow(True)

    # 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)

    # reset preloaded encrypted connection interval changes
    hw.cmd_interval_preload()

    # 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)
Exemplo n.º 4
0
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 only
    hw.cmd_follow(False)

    # 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)
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
def main():
    aparse = argparse.ArgumentParser(
        description="Scanner utility for Sniffle BLE5 sniffer")
    aparse.add_argument("-s",
                        "--serport",
                        default=None,
                        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=-128,
                        type=int,
                        help="Filter packets by minimum RSSI")
    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()

    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_follow(False)

    # configure RSSI filter
    hw.cmd_rssi(args.rssi)

    # turn off MAC address filtering
    hw.cmd_mac()

    # set a MAC address for ourselves
    hw.random_addr()

    # switch to active scanner mode
    hw.cmd_scan()

    # zero timestamps and flush old packets
    hw.mark_and_flush()

    # 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")
Exemplo n.º 7
0
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=40, 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("-i", "--irk", default=None, help="Filter packets by advertiser IRK")
    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("-q", "--quiet", action="store_const", default=False, const=True,
            help="Don't display empty packets")
    aparse.add_argument("-Q", "--preload", default=None, help="Preload expected encrypted "
            "connection parameter changes")
    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 and args.irk is None:
        print("Primary adv. channel hop requires a MAC address or IRK 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
    if args.mac and args.irk:
        print("IRK and MAC filters are mutually exclusive!", file=sys.stderr)
        return
    if args.advchan != 40 and args.hop:
        print("Don't specify an advertising channel if you want advertising channel hopping!", file=sys.stderr)
        return

    global hw
    hw = SniffleHW(args.serport)

    # if a channel was explicitly specified, don't hop
    global _allow_hop3
    if args.advchan == 40:
        args.advchan = 37
    else:
        _allow_hop3 = False

    # 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 whether or not to follow connections
    hw.cmd_follow(not args.advonly)

    if args.preload:
        # expect colon separated triplets, separated by commas
        triplets = []
        for tstr in args.preload.split(','):
            tsplit = tstr.split(':')
            tup = (int(tsplit[0]), int(tsplit[1]), int(tsplit[2]))
            triplets.append(tup)
        hw.cmd_interval_preload(triplets)
    else:
        # reset preloaded encrypted connection interval changes
        hw.cmd_interval_preload()

    # 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
    if args.extadv and not args.hop:
        _allow_hop3 = False

    # configure MAC filter
    global _delay_top_mac
    if args.mac is None and args.irk is None:
        hw.cmd_mac()
    elif args.irk:
        hw.cmd_irk(unhexlify(args.irk), _allow_hop3)
    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)

    # zero timestamps and flush old packets
    hw.mark_and_flush()

    global pcwriter
    if not (args.output is None):
        pcwriter = PcapBleWriter(args.output)

    while True:
        msg = hw.recv_and_decode()
        print_message(msg, args.quiet)