python 提供的蓝牙模块
- pybluez: Python code to access the host machine’s Bluetooth resources. 用于经典蓝牙
- bluepy: Python interface to Bluetooth LE on Linux. 用于低功耗蓝牙
强烈推荐官方文档,简单易懂
bluepy
- a Bluetooth LE interface for Python
0x10 快速入门
bluepy 是一个用 python 封装的库,提供了 BLE 的 API,使用起来非常方便。
安装 bluepy
sudo pip3 install bluepy
- 扫描 BLE 设备 - Scanner
scanner = Scanner()
devices = scanner.scan(timeout=3)
print("%-30s %-10s" % ("Name", "Address"))
for dev in devices:
print("%-30s %-20s" % (dev.getValueText(9), dev.addr))
- 建立连接(Just Works 模式)- Peripheral
addr = "7c:ad:8f:db:ba:75"
conn = Peripheral(addr) # Peripheral 构造函数
- 获取 Service
services = conn.getServices() # Service 类的对象
for svc in services:
print(svc.uuid)
- 获取每个 Service 包含的 Characteristic
# 1. 获取所有 Characteristic
characteristics = conn.getCharacteristics()
for charac in characteristics: # Characteristic 类的对象
print(charac.uuid)
# 2. 获取特定 Service 下的 Characteristic
characteristics = svc.getCharacteristics()
- 读/写 Characteristic
data = charac.read() # 得到一个字节数组
print('Get data:',data[0])
charac.write([b'A']) # 写入一个字节数组
0x20 实际案例
0x21 获取当前设备所有服务和特征
# Connect
addr = "7c:ad:8f:xx:xx:xx"
conn = Peripheral(addr)
# Get service & characteristic
services = conn.getServices()
for svc in services:
print("[+] Service: ", svc.uuid)
characteristics = svc.getCharacteristics()
for charac in characteristics:
print(" Characteristic: ", charac.uuid)
print(" Properties: ", charac.propertiesToString())
print("")
结果
┌──(root💀kali)-[/home/lys/Documents]
└─# /bin/python3 /home/lys/Documents/ble_test.py
[+] Service: 00001801-0000-1000-8000-00805f9b34fb
Characteristic: 00002a05-0000-1000-8000-00805f9b34fb
Properties: INDICATE
[+] Service: 00001800-0000-1000-8000-00805f9b34fb
Characteristic: 00002a00-0000-1000-8000-00805f9b34fb
Properties: READ
Characteristic: 00002a01-0000-1000-8000-00805f9b34fb
Properties: READ
Characteristic: 00002a04-0000-1000-8000-00805f9b34fb
Properties: READ
[+] Service: 15f1e600-a277-43fc-a484-dd39ef8a9100
Characteristic: 15f1e601-a277-43fc-a484-dd39ef8a9100
Properties: NOTIFY INDICATE
Characteristic: 15f1e602-a277-43fc-a484-dd39ef8a9100
Properties: WRITE
[+] Service: 15f1e500-a277-43fc-a484-dd39ef8a9100
Characteristic: 15f1e501-a277-43fc-a484-dd39ef8a9100
Properties: WRITE NOTIFY INDICATE
读
charac = conn.getCharacteristics(uuid="00002a00-0000-1000-8000-00805f9b34fb")
response = charac[0].read()
print(response)
结果
b'Hi-VIATON-XXXXX'
写(同步接收反回的确认消息)
charac = conn.getCharacteristics(uuid="15f1e602-a277-43fc-a484-dd39ef8a9100")
data = binascii.unhexlify("00c504000001xxxx")
try:
response = charac[0].write(data, withResponse=True)
print(response)
except BTLEException:
print("No response!")
0x22 异步接收消息
Peripheral.withDelegate(delegate)
, 将一个 delegate 实例关联至此 Perioheral 实例,当异步事件(eg.通知)发生时,调用其中的相关函数
如扫描
from bluepy.btle import Scanner, DefaultDelegate
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
if isNewDev:
print "Discovered device", dev.addr
elif isNewData:
print "Received new data from", dev.addr
scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(10.0)
异步接收
class ReceiveDelegate(DefaultDelegate):
def __init__(self):
super().__init__()
def handleNotification(self, cHandle, data):
print("[<--] ", data)
addr = "xx:xx:xx:xx:aa:9d"
conn = Peripheral(addr)
conn.setDelegate(ReceiveDelegate())
conn.setMTU(500)
charac = conn.getCharacteristics(uuid="xxxx-xxxx-xxxx-xxxx-xxxxxxxx")
conn.writeCharacteristic(charac[0].valHandle + 1, b"\x02\x00")
while True:
if conn.waitForNotifications(1.0):
# handleNotification() 被调用
continue
print("Waiting...")
0x30 Fuzzing
指定长度的随机数据
'''
return \x31\x32\x33 -> 123
'''
def random_data(size):
return binascii.unhexlify("".join(random.choices("0123456789abcdef", k=size*2)))
任意长度的随机数据
data = binascii.unhexlify("00c5040000") + random_data(random.randint(1, 1000))
在进行 fuzzing 的时候,如果被测应用在 GATT 基础之上又封装了自己的协议,这是最容易发现问题的。
参考文献
- https://ianharvey.github.io/bluepy-doc/notifications.html
- https://stackoverflow.com/questions/32807781/ble-subscribe-to-notification-using-gatttool-or-bluepy