在 Ubuntu 20.04 上将 USB 击键的 (Wireshark) LiveCapture 读入 python?

Reading a (Wireshark) LiveCapture of USB keystrokes into python on Ubuntu 20.04?

上下文

我的键盘蓝牙不稳定,这是设备的一个已知问题。制造商表示,micro-USB 不传输按键,仅用于充电。但是,我使用 Wireshark 检查了 USB 数据,发现它确实通过其微型 USB 连接传输击键。所以我试图通过微型 USB 连接让键盘重获新生(并希望能帮助遇到同样问题的人)。

系统

Ubuntu 20.04

方法

我已经在 Wireshark 中识别了我的键盘设备的 USB 端口,并记录了该端口上的数据流。该数据被保存到一个名为 abcd.pcapng 的文件中(我在录制过程中按下了按钮 abcd)。接下来,我编写了一个基本的 python 脚本,该脚本使用 tsharkabcd.pcapng 文件转换为其原始按键 abcd.

代码

这是将 abcd.pcapng 文件转换为字母 abcd:

的 Python 代码
# This script extracts the keypresses from a pcapng file.
import os

pcapng_filename = "abcd.pcapng"
keypress_ids_filename = "keypress_ids.txt"

# create the output for
command_pcapng_to_keypress_ids = (
    f"tshark -r '{pcapng_filename}' -T fields -e usb.capdata > {keypress_ids_filename}"
)
print(
    f"Running the following bash command to convert the pcapng file to 00xx00000 nrs:\n{command_pcapng_to_keypress_ids}"
)
os.system(command_pcapng_to_keypress_ids)

# read keypress id file
switcher = {
    "04": "a",  # or A
    "05": "b",  # or B
    "06": "c",  # or C
    "07": "d",  # or D
    "08": "e",  # or E
    "09": "f",  # or F
    "0A": "g",  # or G
    "0B": "h",  # or H
    "0C": "i",  # or I
    "0D": "j",  # or J
    "0E": "k",  # or K
    "0F": "l",  # or L
    "10": "m",  # or M
    "11": "n",  # or N
    "12": "o",  # or O
    "13": "p",  # or P
    "14": "q",  # or Q
    "15": "r",  # or R
    "16": "s",  # or S
    "17": "t",  # or T
    "18": "u",  # or U
    "19": "v",  # or V
    "1A": "w",  # or W
    "1B": "x",  # or X
    "1C": "y",  # or Y
    "1D": "x",  # or Z
    "1E": "1",  # or !
    "1F": "2",  # or @
    "20": "3",  # or #
    "21": "4",  # or $
    "22": "5",  # or %
    "23": "6",  # or ^
    "24": "7",  # or &
    "25": "8",  # or *
    "26": "9",  # or (
    "27": "0",  # or )
    "2D": "-",  # or _
    "2E": "+",  # or =
    "2F": "[",  # or {
    "30": "]",  # or }
    "31": '"',  # or |
    "33": ";",  # or :
    "34": "'",  # or "
    "35": "`",  # or ~
    "36": ",",  # or <
    "37": ".",  # or >
    "38": "/",  # or ?
}


def readFile(filename):
    fileOpen = open(filename)
    return fileOpen


file = readFile(keypress_ids_filename)
print(f"file={file}")

# parse the 0000050000000000 etc codes and convert them into keystrokes
for line in file:
    if len(line) == 17:
        two_chars = line[4:6]
        try:
            print(
                f"line={line[0:16]}, relevant characters indicating keypress ID: {two_chars} convert keypres ID to letter: {switcher[two_chars]}"
            )
        except:
            pass

输出

指定文件的脚本输出是:

Running the following bash command to convert the pcapng file to 00xx00000 nrs:
tshark -r 'abcd.pcapng' -T fields -e usb.capdata > keypress_ids.txt
file=<_io.TextIOWrapper name='keypress_ids.txt' mode='r' encoding='UTF-8'>
line=0000040000000000, relevant characters indicating keypress ID: 04 convert keypres ID to letter: a
line=0000050000000000, relevant characters indicating keypress ID: 05 convert keypres ID to letter: b
line=0000060000000000, relevant characters indicating keypress ID: 06 convert keypres ID to letter: c
line=0000070000000000, relevant characters indicating keypress ID: 07 convert keypres ID to letter: d

问题

我如何调整代码以直接获取 USB 数据作为连续流,而不是首先必须开始和停止记录 USB 数据,然后必须创建输出 abcd.pcapng 文件?

例如,是否有 Wireshark-api 或 tshark 函数开始侦听直到 the/some 脚本停止?

解决方案

以下名为 live_capture_keystrokes.py 的脚本捕获包含击键信号的 Leftover Capture Data,它们由 Python 代码实时且连续地解析。

我认为每次重新启动计算机时激活 usb 监控很重要(如果您想 运行 此脚本成功)。为此,您可以 运行:

sudo modprobe usbmon

理想情况下,你会 运行 如果没有 sudo,那也将阻止 运行 使用 sudo 的 python 文件,但我还没有弄清楚如何 运行 modprobe usbmon 没有 sudo。

代码

live_capture_keystrokes.py 脚本需要 运行 with sudo 如果 modprobe usbmon 是 运行 with sudo。要 运行 sudo 中的 python 脚本,可以键入:

sudo su
# sudo apt install python3
# pip install pyshark
# python3 live_capture_keystrokes.py

live_capture_keystrokes.py的内容是:

import pyshark
# Get keystrokes data
print("\n----- Capturing keystrokes from usbmon0 --------------------")
capture = pyshark.LiveCapture(interface='usbmon0', output_file='output.pcap')

# Source: https://www.programcreek.com/python/example/92561/pyshark.LiveCapture 
for i, packet in enumerate(capture.sniff_continuously()):
    try:
        data= packet[1].usb_capdata.split(":")
        print(data)
    except:
        pass
capture.clear()
capture.close()
print(f'DONE')

输出

输出尚未解析回击键,稍后我会添加。然而,这就是输出,每次您按下 USB 键盘上的一个键,它都会将随附的列表直接打印到屏幕上。

a['00', '00', '04', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
b['00', '00', '05', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
c['00', '00', '06', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
d['00', '00', '07', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
e['00', '00', '08', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
f['00', '00', '09', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
g['00', '00', '0a', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
h['00', '00', '0b', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
i['00', '00', '0c', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
j['00', '00', '0d', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
k['00', '00', '0e', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
l['00', '00', '0f', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
m['00', '00', '10', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
n['00', '00', '11', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
o['00', '00', '12', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
p['00', '00', '13', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
q['00', '00', '14', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
r['00', '00', '15', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
s['00', '00', '16', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
t['00', '00', '17', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
u['00', '00', '18', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
v['00', '00', '19', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
w['00', '00', '1a', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
x['00', '00', '1b', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
y['00', '00', '1c', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
z['00', '00', '1d', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
0['00', '00', '62', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
1['00', '00', '59', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
2['00', '00', '5a', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
3['00', '00', '5b', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
4['00', '00', '5c', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
5['00', '00', '5d', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
6['00', '00', '5e', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
7['00', '00', '5f', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
8['00', '00', '60', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
9['00', '00', '61', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
1['00', '00', '1e', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
2['00', '00', '1f', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
3['00', '00', '20', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
4['00', '00', '21', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
5['00', '00', '22', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
6['00', '00', '23', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
7['00', '00', '24', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
8['00', '00', '25', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
9['00', '00', '26', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']
0['00', '00', '27', '00', '00', '00', '00', '00']
['00', '00', '00', '00', '00', '00', '00', '00']