系类往期文章:
PyQt5实战------多脚本集合包,前言与环境配置(一)
PyQt5实战------多脚本集合包,UI以及工程布局(二)
PyQt5实战------多脚本集合包,程序入口QMainWindow(三)
PyQt5实战------操作台打印重定向,主界面以及stacklayout使用(四)
PyQt5实战------UTF-8编码器UI页面设计以及按钮连接(五)
PyQt5实战------UTF-8编码器功能的实现(六)
PyQt5实战------翻译器的UI页面设计以及代码实现(七)
PyQt5实战------翻译的实现,第一次爬取微软翻译经验总结(八)
PyQt5实战------翻译的实现,成功爬取微软翻译(可长期使用)经验总结(九)
前言
距离上次更新PyQt实战系列隔了好久,因为现实中比较忙,而且确实是存货已经用完,现在对脚本集合包更新了一些新的内容,包括:JSON数据的处理,ADPCM音频编解码,PCM二进制文件构建以及PCM音频播放功能,此外,还有一个数据加密解密算法,与笔者之前的文章《逆向工程实战,在反汇编工具中理解汇编与伪C》中的算法一致,是笔者在反汇编的学习中无意间发现的一种数据加密算法,简单且有效,当初逆向该算法时花了不少时间,总之,这些内容后续都会讲到!
JSON数据处理UI
本功能的UI设计十分简单,用到的全是PyQt5实战系列提及过的内容,因此本文将不再重复讲解UI界面的代码,但是代码依然会贴出来,如下:
python
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtSvg import *
from component.btnStyle import *
from component.editStyle import *
from component.getPath import *
from tools.wiresharckJsonProcess import *
class WwiresharkJsonProc(QWidget):
def __init__(self):
super().__init__()
self.filePaths = ['']
self.initUI()
def initUI(self):
self.JsonProcesslayout = QVBoxLayout()
self.setLayout(self.JsonProcesslayout)
# 文件选择
self.filelayout = QHBoxLayout()
self.lable = QLabel("请选择文件",self)
self.filelayout.addWidget(self.lable)
self.input = QLineEdit(self)
LineEditStyle(self.input)
self.filelayout.addWidget(self.input)
self.choosebtn = QPushButton("选择文件",self)
btnReleaseStyleA(self.choosebtn)
self.choosebtn.clicked.connect(self.getpath)
self.filelayout.addWidget(self.choosebtn)
self.JsonProcesslayout.addLayout(self.filelayout)
# 开始处理
self.exebtn = QPushButton("开始处理",self)
btnReleaseStyleA(self.exebtn)
self.exebtn.clicked.connect(self.exebtn_press_clicked)
self.JsonProcesslayout.addWidget(self.exebtn)
def getpath(self):
get_path(self)
self.input.setText(self.filePaths[0])
def exebtn_press_clicked(self):
processJson(self.filePaths[0])
界面非常简单,如下所示
可以看到,在这个页面下仅有一个文件选择的组件加上一个处理的按钮。非常简单的一个页面设计,本文的重点并不在这个UI设计上,而是在wireshark的抓包数据转换成JSON格式以及python提取JSON数据。
JSON数据的来源
本文所使用的JSON数据来源于wireshark抓包,wireshark是一个网络封包分析工具,可以截取各种网络数据包,并显示数据包中的各种详细信息,常用于开发测试过程中的问题定位。但笔者并不是用wireshark来处理网络封包,而是处理低功耗蓝牙(BLE)的封包。wireshark本身并没有捕获BLE数据包的能力,但是结合特殊的dongle可以,使用NRF52832 BLE Sniffer
低功耗蓝牙抓包器可以捕捉到到低功耗蓝牙的空中数据,非常实用,感兴趣的同学可以在网上查询相关信息,本文不做赘述。
这里笔者对一个数据包做了筛选,如下图所示,从机通过notify
的形式向主机传递消息,消息通过handle
值为0x97
的特征传递给主机,这里不了解蓝牙的同学可以不用理会,以后笔者会单独出一个蓝牙系列,分享笔者的蓝牙知识。
在下面详细信息中可以看到,所选中的这一条数据,是从机通过handle
为0x97
的特征,向主机发送共计120
个字节的value
数据:3b 18 01 ....... 04 d1 1a
,如果手动一条一条数据中蓝色框框的内容复制出来是非常耗时的,可以采用以下方式获取数据:
文件 → 导出分组解析结果 → As JSON
可以导出JSON格式的数据,我们展示一下JSON数据
json
[
{
"_index": "packets-2024-12-06",
"_type": "doc",
"_score": null,
"_source": {
"layers": {
"frame": {
"frame.section_number": "1",
"frame.interface_id": "0",
"frame.interface_id_tree": {
"frame.interface_name": "COM30-4.0",
"frame.interface_description": "nRF Sniffer for Bluetooth LE COM30"
},
"frame.encap_type": "186",
"frame.time": "Dec 6, 2024 11:19:43.491844000 中国标准时间",
"frame.offset_shift": "0.000000000",
"frame.time_epoch": "1733455183.491844000",
"frame.time_delta": "0.000231000",
"frame.time_delta_displayed": "0.000000000",
"frame.time_relative": "62.812024000",
"frame.number": "12534",
"frame.len": "53",
"frame.cap_len": "53",
"frame.marked": "0",
"frame.ignored": "0",
"frame.protocols": "nordic_ble:btle:btl2cap:btatt"
},
"nordic_ble": {
"nordic_ble.board_id": "30",
"nordic_ble.header": {
"nordic_ble.plen": "46",
"nordic_ble.protover": "3",
"nordic_ble.packet_counter": "36765",
"nordic_ble.packet_id": "6"
},
"nordic_ble.len": "10",
"nordic_ble.flags": "0x0d",
"nordic_ble.flags_tree": {
"nordic_ble.crcok": "1",
"nordic_ble.direction": "0",
"nordic_ble.encrypted": "1",
"nordic_ble.micok": "1",
"nordic_ble.phy": "0",
"nordic_ble.flag_reserved7": "0"
},
"nordic_ble.channel": "29",
"nordic_ble.rssi": "-45",
"nordic_ble.event_counter": "1158",
"nordic_ble.time": "1172995411",
"nordic_ble.packet_time": "296",
"nordic_ble.delta_time": "151",
"nordic_ble.delta_time_ss": "231"
},
"btle": {
"btle.access_address": "0x27353836",
"btle.master_bd_addr": "90:e4:68:a8:41:7c",
"btle.slave_bd_addr": "00:00:00:08:47:2c",
"btle.data_header": {
"btle.data_header.llid": "0x02",
"btle.data_header.next_expected_sequence_number": "1",
"btle.data_header.sequence_number": "0",
"btle.data_header.more_data": "1",
"btle.data_header.cte_info_present": "0",
"btle.data_header.rfu": "0",
"btle.data_header.length": "27"
},
"btle.length": "27",
"btle.l2cap_index": "132",
"btle.connection_parameters_in": "11696",
"btle.crc": "0xe3cc46"
},
"btl2cap": {
"btl2cap.length": "23",
"btl2cap.cid": "0x0004"
},
"btatt": {
"btatt.opcode": "0x1b",
"btatt.opcode_tree": {
"btatt.opcode.authentication_signature": "0",
"btatt.opcode.command": "0",
"btatt.opcode.method": "0x1b"
},
"btatt.handle": "0x0036",
"btatt.handle_tree": {
"btatt.service_uuid16": "0x1812"
},
"btatt.value": "60:d8:4b:d4:62:66:d9:d5:4c:d5:5f:d6:d3:5d:63:da:64:d7:61:d8"
}
}
}
},
这么长的数据,仅仅wireshark中展示的一条数据,而我们需要的数据,仅仅是btatt.value
这一个属性
json
"btatt.value": "60:d8:4b:d4:62:66:d9:d5:4c:d5:5f:d6:d3:5d:63:da:64:d7:61:d8"
而敏锐的同学可以发现,此JSON文件的开头,是[
,也就是说,此JSON文件的框架是[{第一条数据},{第二条数据}....{第n条数据}...]
,这种格式非常适合python
通过list
数据结构进行处理。
JSON数据提取
先来观察我们需要的目标数据,btatt.value
,这是由多层字典嵌套在其中的,因此要依次往上查找不同层级的字典,可以发现:
- __source
- layers
- btatt
- btatt.value
是这样的一个结构。
我们现在来看代码
python
import json
def processJson(filename):
with open(filename, "r", encoding="utf-8") as f:
attvalue = json.load(f)
for i in range(len(attvalue)):
voicevalue = attvalue[i]["_source"]["layers"]["btatt"]["btatt.value"] + "\n"
with open("workspaces/VoiceData.txt", "a", encoding="utf-8") as f:
f.write(voicevalue)
print("line len: ",len(voicevalue))
print("line count: ",len(attvalue))
# print(data)
我们来分析一下代码:
- 从
filename
这个文件中读取数据,以utf-8
编码格式解码 json.load(f)
是指从f
中读取数据JSON
数据,解析并返回对应的Python
对象(例如,字典,列表等,具体取决于JSON的结构),通过我们上面的分析,此json会被解析成python的列表(因为最外层是[]
)。- 循环读取
attvalue
列表对象 - 读取
attvallue
列表中第i
个元素中的layers
字典中的btatt
字典中的btatt.value
所对应的值,并加上一个换行符/n
,最后复制给voicevalue
- 将
voicevalue
写进workspaces/VoiceData.txt
文件的末尾,a
表示在文件末尾写入东西,而不覆盖原来的内容。 - 当将所有的内容都写完时,返回每条数据的数据量以及数据总量
该方法被单独写在wiresharckJsonProcess.py
文件中,存放在tools
目录下,被UI页面通过import
以模块导入的形式使用。
总结
本文的内容并不复杂,主要是如何从wireshark
中导出JSON
数据,以及如何使用python
对数据进行过滤和处理,JSON是非常常用的数据传输和保存格式尤其在网络中非常常用,因此熟练的掌握看懂和处理对程序员来说是值得的,而且并不难不是吗,祝你变得更强!