如何用Python或其他方式解析btsnoop日志并提取L2CAP数据?
解析BTSnoop日志提取L2CAP数据的方法
一、用现成工具快速处理(推荐)
直接用Wireshark就能搞定:
- 要是你手里是原始btsnoop格式文件,直接拖进Wireshark,在过滤栏输入
l2cap,就能只显示L2CAP相关数据包,还能直接查看解析后的字段。 - 针对你已转换好的十六进制txt文件:打开Wireshark→菜单栏「文件」→「导入」→选中你的txt文件,在导入向导里选「十六进制转储」,封装格式选「Bluetooth HCI UART」,导入后同样用
l2cap过滤即可提取数据。
二、用Python手动解析(自定义场景)
如果需要针对性处理冗余数据或自定义提取逻辑,按以下步骤操作:
1. 清理冗余十六进制数据
先把txt里的行号、空格、注释等冗余内容去掉,只保留纯十六进制字符:
def clean_hex_file(input_path, output_path): with open(input_path, 'r') as f: content = f.read() # 仅保留合法十六进制字符 clean_hex = ''.join([c for c in content if c.isalnum() and c.lower() in '0123456789abcdef']) with open(output_path, 'w') as f: f.write(clean_hex)
2. 解析BTSnoop格式并提取L2CAP数据
BTSnoop每条记录的标准结构(大端字节序):
- 4字节:记录标识(固定为
0x6274736e,即"btsn") - 4字节:原始数据包长度
- 4字节:实际捕获长度
- 4字节:标志位
- 4字节:累计时间(毫秒)
- 后续为蓝牙HCI数据包
蓝牙HCI ACL数据包的类型标识为0x02,其头部之后的内容就是L2CAP数据,代码实现如下:
import struct def extract_l2cap_from_btsnoop_hex(hex_path): with open(hex_path, 'r') as f: hex_data = f.read() # 将十六进制转为字节流 raw_data = bytes.fromhex(hex_data) offset = 0 l2cap_packets = [] while offset < len(raw_data): # 读取BTSnoop记录头 if len(raw_data) - offset < 20: break magic, orig_len, cap_len, flags, time = struct.unpack('>IIIII', raw_data[offset:offset+20]) offset += 20 # 跳过无效记录 if magic != 0x6274736e: continue # 读取蓝牙数据包内容 packet = raw_data[offset:offset+cap_len] offset += cap_len # 判断是否为HCI ACL数据包 if len(packet) < 1: continue hci_type = packet[0] if hci_type == 0x02: # 普通ACL头长度为4字节,跳过之后即为L2CAP数据 if len(packet) >= 5: l2cap_data = packet[4:] l2cap_packets.append(l2cap_data) print(f"提取到L2CAP数据(十六进制): {l2cap_data.hex()}") return l2cap_packets # 使用示例 clean_hex_file('你的原始hex文件.txt', '清理后的hex文件.txt') l2cap_packets = extract_l2cap_from_btsnoop_hex('清理后的hex文件.txt')
注意事项
- 若你的BTSnoop记录采用小端字节序,把
struct.unpack里的>IIIII改成<IIIII即可。 - 遇到扩展ACL数据包时,需调整ACL头的偏移长度,可参考蓝牙核心规范中HCI ACL数据包的结构定义。
内容的提问来源于stack exchange,提问作者Hemant Jain
相关产品推荐
相关产品推荐

