Skip to content

Instantly share code, notes, and snippets.

@fletchto99 fletchto99/badge.py Secret
Last active Jul 7, 2018

Embed
What would you like to do?
NSec badge bluetooth tool
#!/usr/bin/env python
import argparse
import logging
import time
import uuid
import binascii
import Adafruit_BluefruitLE
import sys
import struct
# LED Service
LED_SERVICE_UUID = uuid.UUID('CBCA0000-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_SYNC_KEY_UUID = uuid.UUID('CBCA000B-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_LOCKED_UUID = uuid.UUID('CBCA000A-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_SELECT_UUID = uuid.UUID('CBCA0001-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_START_UUID = uuid.UUID('CBCA0002-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_STOP_UUID = uuid.UUID('CBCA0003-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_MODE_UUID = uuid.UUID('CBCA0004-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_COLORS_UUID = uuid.UUID('CBCA0005-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_SPEED_UUID = uuid.UUID('CBCA0006-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_REVERSE_UUID = uuid.UUID('CBCA0007-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_ACTIVE_UUID = uuid.UUID('CBCA0008-BFBE-BDBC-BBBA-AFAEADACABAA')
LED_BRIGHTNESS_UUID = uuid.UUID('CBCA0009-BFBE-BDBC-BBBA-AFAEADACABAA')
# Name service
NAME_SERVICE_UUID = uuid.UUID('CBCA0100-BFBE-BDBC-BBBA-AFAEADACABAA')
NAME_UUID = uuid.UUID('CBCA0101-BFBE-BDBC-BBBA-AFAEADACABAA')
NAME_SYNC_KEY_UUID = uuid.UUID('CBCA0102-BFBE-BDBC-BBBA-AFAEADACABAA')
NAME_LOCKED_UUID = uuid.UUID('CBCA0103-BFBE-BDBC-BBBA-AFAEADACABAA')
class NSecBadge(object):
def __check_led(self, value):
parsed = int(value)
if parsed < 0 or parsed > 7:
raise argparse.ArgumentTypeError("{0} is an invalid led index".format(value))
return parsed
def __check_mode(self, value):
parsed = int(value)
if parsed < 0x00 or parsed > 0xFF:
raise argparse.ArgumentTypeError("{0} is an invalid mode value".format(value))
return parsed
def __check_color(self, value):
parsed = int(value, 16)
if parsed < 0x00 or parsed > 0xFF:
raise argparse.ArgumentTypeError("{0} is an invalid color value".format(value))
return parsed
def __check_speed1(self, value):
parsed = int(value, 16)
if parsed < 0x00 or parsed > 0xFF:
raise argparse.ArgumentTypeError("{0} is an invalid speed value".format(value))
return parsed
def __check_speed2(self, value):
parsed = int(value, 16)
if parsed < 0xA0 or parsed > 0xFF:
raise argparse.ArgumentTypeError("{0} is an invalid speed value".format(value))
return parsed
def __check_brightness(self, value):
parsed = int(value)
if parsed < 0 or parsed > 100:
raise argparse.ArgumentTypeError("{0} is an invalid brightness value".format(value))
return parsed
def __check_bit(self, value):
parsed = int(value)
if parsed != 0 or parsed != 1:
raise argparse.ArgumentTypeError("{0} is an invalid positive bit value".format(value))
return parsed
def __init__(self):
parser = argparse.ArgumentParser(prog='badge', usage='badge <id> [<args>]')
parser.add_argument('id', help='The device ID, set to "any" if you wish to update any valid device in range')
parser.add_argument('--search_sleep', type=int, default=10, help='The amount of time, in seconds, to sleep when searching for a device')
parser.add_argument('--disconnect_sleep', type=int, default=5, help='The amount of time, in seconds, to sleep when searching for a device')
subparsers = parser.add_subparsers(dest='cmd', help='The action you wish to perfrom')
# Name command parser
parser_name = subparsers.add_parser('name', usage='badge <id> name [<args>]', help='Used to update the name on the device')
parser_name.add_argument('name', help='The new name to set')
# LED command parser
parser_led = subparsers.add_parser('led', help='Used to update the LEDs on the device')
parser_led.add_argument('segment', type=self.__check_led, help='The selected segement')
parser_led.add_argument('start', type=self.__check_led, help='The start LED')
parser_led.add_argument('stop', type=self.__check_led, help='The end LED')
parser_led.add_argument('mode', type=self.__check_mode, help='The mode to use')
parser_led.add_argument('red', type=self.__check_color, help='Red value')
parser_led.add_argument('green', type=self.__check_color, help='Green value')
parser_led.add_argument('blue', type=self.__check_color, help='Blue value')
parser_led.add_argument('--speed1', type=self.__check_speed1, help='The speed (upper byte)')
parser_led.add_argument('--speed2', type=self.__check_speed2, help='The speed (lower byte)')
parser_led.add_argument('--brightness', type=self.__check_brightness, help='The brightness')
parser_led.add_argument('--reverse', type=self.__check_bit, nargs='?', const=1, help='Runs the led cycle in reverse')
self.args = parser.parse_args()
self.ble = Adafruit_BluefruitLE.get_provider()
self.ble.initialize()
self.ble.run_mainloop_with(self.main)
def name(self, device, key):
print('[*] Discovering name service...')
device.discover([NAME_SERVICE_UUID], [NAME_UUID, NAME_SYNC_KEY_UUID, NAME_LOCKED_UUID])
# Known services
service = device.find_service(NAME_SERVICE_UUID)
name_char = service.find_characteristic(NAME_UUID)
sync_key_char = service.find_characteristic(NAME_SYNC_KEY_UUID)
locked_char = service.find_characteristic(NAME_LOCKED_UUID)
print('[+] Unlocking...')
sync_key_char.write_value(key)
print('[+] Updating name to "{0}"'.format(self.args.name))
name_char.write_value(self.args.name) # Write name to device
print('[+] Locking...')
sync_key_char.write_value("1337") # Prevent others from being able to write to the device
print('[+] Locked!')
def led(self, device, key):
print('[*] Discovering name service...')
device.discover([LED_SERVICE_UUID], [LED_SYNC_KEY_UUID, LED_LOCKED_UUID, LED_SELECT_UUID, LED_START_UUID, LED_STOP_UUID, LED_MODE_UUID, LED_COLORS_UUID, LED_SPEED_UUID, LED_REVERSE_UUID, LED_ACTIVE_UUID, LED_BRIGHTNESS_UUID])
# Known services
service = device.find_service(LED_SERVICE_UUID)
sync_key_char = service.find_characteristic(LED_SYNC_KEY_UUID)
locked_char = service.find_characteristic(LED_LOCKED_UUID)
segment_char = service.find_characteristic(LED_SELECT_UUID)
start_char = service.find_characteristic(LED_START_UUID)
stop_char = service.find_characteristic(LED_STOP_UUID)
mode_char = service.find_characteristic(LED_MODE_UUID)
colors_char = service.find_characteristic(LED_COLORS_UUID)
speed_char = service.find_characteristic(LED_SPEED_UUID)
reverse_char = service.find_characteristic(LED_REVERSE_UUID)
active_char = service.find_characteristic(LED_ACTIVE_UUID)
brightness_char = service.find_characteristic(LED_BRIGHTNESS_UUID)
print('[*] Unlocking...')
sync_key_char.write_value(key)
print('[*] Setting segment...')
segment_char.write_value(struct.pack('B', self.args.segment))
print('[*] Setting start/stop values...')
start_char.write_value(struct.pack('B', self.args.start))
stop_char.write_value(struct.pack('B', self.args.stop))
print("[*] Setting mode value")
mode_char.write_value(struct.pack('B', self.args.mode))
colors_char.write_value(struct.pack('BBBBBBBBBBBB', self.args.red, self.args.green, self.args.blue, 0x00, self.args.red, self.args.green, self.args.blue, 0x00, self.args.red, self.args.green, self.args.blue, 0x00))
if self.args.speed1 is not None or self.args.speed2 is not None:
speed_char.write_value(struct.pack('BB', self.args.speed1, self.args.speed2))
if self.args.brightness is not None:
brightness_char.write_value(struct.pack('B', self.args.brightness))
if self.args.reverse is not None:
reverse_char.write_value(struct.pack('B', self.args.reverse))
print("[*] Setting active value")
active_char.write_value(struct.pack('B', 0x01))
print('[*] Locking...')
sync_key_char.write_value("1337") # Prevent others from being able to write to the device
print("[*] Locked")
def main(self):
# Start fresh
self.ble.clear_cached_data()
# Use the proper adapter
adapter = self.ble.get_default_adapter()
adapter.power_on()
print('[+] Using adapter: {0}'.format(adapter.name))
# Disconnect from any devices using the name service
print('[*] Disconnecting any connected devices...')
self.ble.disconnect_devices([NAME_SERVICE_UUID])
self.ble.disconnect_devices([LED_SERVICE_UUID])
print('[*] Searching for NorthSec badge...')
try:
adapter.start_scan()
print('[*] Sleeping {0} seconds while the device list populates...'.format(self.args.search_sleep))
time.sleep(self.args.search_sleep)
devices = self.ble.find_devices([NAME_SERVICE_UUID])
finally:
adapter.stop_scan()
print("[+] Found devices: {0}".format(', '.join(d.name for d in devices)))
for device in devices:
if device.name.upper() != self.args.id.upper() and self.args.id.upper() != "ANY":
continue
print('[*] Connecting to device "{0}"'.format(device.name))
device.connect()
print('[*] Connected!')
print('[*] Device information:')
print('[+] Device name: {0}'.format(device.name))
sync_key = str(hex(int(device.name[4:8], 16) ^ 0xc3c3)).split('x')[1].upper()
print('[+] Device sync key: {0}'.format(sync_key))
print('[*] Performing "{0}" command'.format(self.args.cmd))
getattr(self, self.args.cmd)(device, sync_key)
print('[*] Sleeping {0} seconds while sending data to the device...'.format(self.args.disconnect_sleep))
time.sleep(self.args.disconnect_sleep)
print('[+] Done!')
device.disconnect()
if __name__ == '__main__':
NSecBadge()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.