commit aa13f92e0bfaa4153d252689d2ca12ab9cb2c89d Author: FW_Mumuzi <74121593+Mumuzi7179@users.noreply.github.com> Date: Fri Jun 30 13:27:22 2023 +0800 upload main files diff --git a/KeyboardDecrypt.py b/KeyboardDecrypt.py new file mode 100644 index 0000000..9735fd1 --- /dev/null +++ b/KeyboardDecrypt.py @@ -0,0 +1,106 @@ +from PySide6.QtWidgets import QComboBox,QStackedWidget,QApplication, QMainWindow, QPushButton, QTextEdit, QFileDialog, QVBoxLayout, QWidget, QLabel, QLineEdit, QHBoxLayout, QRadioButton, QButtonGroup, QTabWidget, QMenuBar, QToolBar +from PySide6.QtGui import QAction +from PySide6.QtCore import Qt, Signal +import sys,os +import datetime +from UsbKeyboardExtract import extract_data,process_data + +class KeyboardDecryptWindow(QWidget): + file_name = Signal(str) # 文件名信号 + file_dropped = Signal(str) + + def __init__(self,parent=None): + super(KeyboardDecryptWindow, self).__init__(parent) + + self.layout = QVBoxLayout() + self.setLayout(self.layout) + + # 选择执行的类型 + self.type_layout = QHBoxLayout() + self.type_label = QLabel("选择执行类型:") + self.type_layout.addWidget(self.type_label) + self.button_group = QButtonGroup(self) + self.select_type1 = QRadioButton("capdata") + self.select_type2 = QRadioButton("usbhid") + + self.button_group.addButton(self.select_type1) + self.button_group.addButton(self.select_type2) + self.type_layout.addWidget(self.select_type1) + self.type_layout.addWidget(self.select_type2) + # 确定按钮 + self.run_button = QPushButton("点击执行") + stylesheet = load_stylesheet("./css/style.css") + self.run_button.setStyleSheet(stylesheet) + self.run_button.clicked.connect(self.run_command) + self.type_layout.addWidget(self.run_button) + self.layout.addLayout(self.type_layout) + + # 输出窗口 + self.output = QTextEdit() + self.layout.addWidget(self.output) + self.output.setReadOnly(True) + + self.setAcceptDrops(True) + + # 文件名变量 + self.file = '' + + # 接收文件名信号 + self.file_name.connect(self.set_file) + + def set_file(self, file): + self.file = file + + def dragEnterEvent(self, event): + + if event.mimeData().hasUrls(): + event.accept() + else: + event.ignore() + + def dropEvent(self, event): + urls = event.mimeData().urls() + + url = urls[0] + + filePath = url.toLocalFile() + + self.file_dropped.emit(filePath) + + + + def run_command(self): + self.output.clear() + + current_time = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + self.output.append(f"{current_time}") + + checked_button = self.button_group.checkedButton() + if checked_button: + type = checked_button.text() + else: + type = None + if not self.file: + self.output.append("错误:没有选择文件。") + return + if not type: + self.output.append("错误:没有选择执行类型。") + return + self.output.append(f"执行的类型: {type}") + try: + result,result1 = extract_data(type, self.file) + result2,result_delete = process_data(result1) + except Exception as e: + self.output.append(f"执行出错:{e}") + else: + self.output.append("执行成功。结果如下:") + self.output.append(result) + self.output.append("处理后的结果如下:") + self.output.append(result2) + self.output.append("删除的字符如下:") + self.output.append(result_delete) + + +def load_stylesheet(filename): + with open(filename, "r") as f: + return f.read() \ No newline at end of file diff --git a/MouseDecrypt.py b/MouseDecrypt.py new file mode 100644 index 0000000..c480baf --- /dev/null +++ b/MouseDecrypt.py @@ -0,0 +1,164 @@ +from PySide6.QtWidgets import QSizePolicy,QComboBox,QStackedWidget,QApplication, QMainWindow, QPushButton, QTextEdit, QFileDialog, QVBoxLayout, QWidget, QLabel, QLineEdit, QHBoxLayout, QRadioButton, QButtonGroup, QTabWidget, QMenuBar, QToolBar +from PySide6.QtGui import QAction +from PySide6.QtCore import Qt, Signal +import sys,os,time,datetime +from MouseExtract import extract_data +import matplotlib.pyplot as plt + +class MouseDecryptWindow(QWidget): + file_name = Signal(str) # 文件名信号 + file_dropped = Signal(str) + + def __init__(self): + super(MouseDecryptWindow, self).__init__() + + self.layout = QVBoxLayout(self) + + # 选择执行的类型 + self.type_layout = QHBoxLayout() + self.type_label = QLabel("选择执行类型:") + self.type_layout.addWidget(self.type_label) + self.button_group_type = QButtonGroup(self) + self.select_type1 = QRadioButton("capdata") + self.select_type2 = QRadioButton("usbhid") + self.button_group_type.addButton(self.select_type1) + self.button_group_type.addButton(self.select_type2) + self.type_layout.addWidget(self.select_type1) + self.type_layout.addWidget(self.select_type2) + self.layout.addLayout(self.type_layout) + + # 选择想要查看的鼠标按键 + self.button_layout = QHBoxLayout() + self.button_label = QLabel("选择想要查看的鼠标按键:") + self.button_layout.addWidget(self.button_label) + self.button_group_button = QButtonGroup(self) + self.select_button1 = QRadioButton("左键") + self.select_button2 = QRadioButton("右键") + self.select_button3 = QRadioButton("无按键") + self.select_button4 = QRadioButton("所有") + self.button_group_button.addButton(self.select_button1) + self.button_group_button.addButton(self.select_button2) + self.button_group_button.addButton(self.select_button3) + self.button_group_button.addButton(self.select_button4) + self.button_layout.addWidget(self.select_button1) + self.button_layout.addWidget(self.select_button2) + self.button_layout.addWidget(self.select_button3) + self.button_layout.addWidget(self.select_button4) + self.layout.addLayout(self.button_layout) + + # 执行按钮 + self.button_layout = QHBoxLayout() + stylesheet = load_stylesheet("./css/style.css") + + self.run_button = QPushButton("保存并打开图片") + self.run_button.clicked.connect(self.run_command) + self.run_button.setFixedSize(120, 40) # 设置固定大小 + self.button_layout.addWidget(self.run_button) + self.run_button.setStyleSheet(stylesheet) + + # 保存图片按钮 + self.save_button = QPushButton("仅保存图片") + self.save_button.clicked.connect(self.save_image) + self.save_button.setFixedSize(120, 40) # 设置固定大小 + self.button_layout.addWidget(self.save_button) + self.save_button.setStyleSheet(stylesheet) + + self.layout.addLayout(self.button_layout) + + # 输出窗口 + self.output = QTextEdit() + self.layout.addWidget(self.output) + self.output.setReadOnly(True) + + self.setLayout(self.layout) + + # 文件名变量 + self.file = '' + + # 接收文件名信号 + self.file_name.connect(self.set_file) + + self.setAcceptDrops(True) + + def set_file(self, file): + self.file = file + + def dragEnterEvent(self, event): + # accept the drag only if it contains files + if event.mimeData().hasUrls(): + event.accept() + else: + event.ignore() + + def dropEvent(self, event): + # get the file URLs (a list of QUrls) + urls = event.mimeData().urls() + + # assuming only one file is dropped, get the first URL + url = urls[0] + + # get the file path (a string) + filePath = url.toLocalFile() + + # 发送文件名信号 + self.file_dropped.emit(filePath) + + def save_image(self): + self.run_command(from_save_button=True) + + def run_command(self,from_save_button=False): + self.output.clear() + + # 输出当前时间 + current_time = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + self.output.append(f"{current_time}") + + # 获取当前选中的执行类型和鼠标按键 + checked_button_type = self.button_group_type.checkedButton() + checked_button_key = self.button_group_button.checkedButton() + + # 检查是否选择了执行类型和鼠标按键以及文件 + if checked_button_type: + type = checked_button_type.text() + else: + type = None + + if checked_button_key: + key = checked_button_key.text() + else: + key = None + + if not self.file: + self.output.append("错误:没有选择文件。") + return + + if not type: + self.output.append("错误:没有选择执行类型。") + return + + if not key: + self.output.append("错误:没有选择鼠标按键。") + return + + self.output.append(f"执行的类型: {type}") + self.output.append(f"选择的鼠标按键: {key}") + self.output.append("正在执行,若文件较大可能会出现无响应情况,请稍后……") + + QApplication.processEvents() + + try: + result = extract_data(type, key, self.file) + except Exception as e: + self.output.append(f"执行出错:{e}") + else: + self.output.append("执行成功。") + self.output.append("已将转换后的坐标写入result.txt,如有需要可自行利用") + self.output.append(f"已将图片保存至当前环境运行目录下的{key}.png") + time.sleep(0.5) + result.savefig(f"{key}.png") + if not from_save_button: + os.system(f"{key}.png") + +def load_stylesheet(filename): + with open(filename, "r") as f: + return f.read() \ No newline at end of file diff --git a/MouseExtract.py b/MouseExtract.py new file mode 100644 index 0000000..45d214d --- /dev/null +++ b/MouseExtract.py @@ -0,0 +1,74 @@ +import sys +import os +import numpy as np +import matplotlib.pyplot as plt + +def extract_data(types,choise,filename): + posX, posY = 0, 0 + X, Y = [], [] + type_dicts = {"capdata": "usb.capdata", "usbhid": "usbhid.data"} + mytype = type_dicts[types] + choise_dicts = {"左键": "L", "右键": "R","无按键" : "N" ,"所有" : "ALL"} + mychoise = choise_dicts[choise] + os.system(f'tshark.exe -r "{filename}" -T fields -e {mytype} > usb.dat') + data = [] + + result = open('result.txt', 'w') + + with open('usb.dat', "r") as f: + for line in f: + data.append(line[0:-1]) + + for i in data: + Bytes = bytes.fromhex(i) + if(len(Bytes) == 8): + horizontal = 2 + vertical = 4 + key = 1 + elif(len(Bytes) == 6): + horizontal = 2 + vertical = 3 + key = 1 + elif(len(Bytes) == 4): + horizontal = 1 + vertical = 2 + key = 0 + else: + continue + offsetX = Bytes[horizontal] + offsetY = Bytes[vertical] + if offsetX > 127: + offsetX -= 256 + if offsetY > 127: + offsetY -= 256 + posX += offsetX + posY += offsetY + if Bytes[key] == 1: + if mychoise == "L": + X.append(posX) + Y.append(-posY) + result.write(str(posX) + ' ' + str(-posY) + '\n') + elif Bytes[key] == 2: + if mychoise == "R": + X.append(posX) + Y.append(-posY) + result.write(str(posX) + ' ' + str(-posY) + '\n') + elif Bytes[key] == 0: + if mychoise == "N": + X.append(posX) + Y.append(-posY) + result.write(str(posX) + ' ' + str(-posY) + '\n') + else: + pass + if mychoise == "ALL": + X.append(posX) + Y.append(-posY) + result.write(str(posX) + ' ' + str(-posY) + '\n') + result.close() + + fig = plt.figure() + ax1 = fig.add_subplot(111) + + ax1.scatter(X, Y, c='r', marker='o') + return plt + diff --git a/README.md b/README.md new file mode 100644 index 0000000..1bb6e5b --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# UsbKeyboard&Mouse_Hacker_Gui + +> 本工具作用为对CTF中常见的键盘流量与鼠标流量进行解密,采用GUI的形式方便使用 + + + +## 使用帮助 + +使用python3执行run_GUI.py加载 + +```shell +python3 run_GUI.py +``` + + + +> Note:需安装PySide6、numpy、matplotlib库 +> 若未换源可使用 `pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple执行` + +![image-20230630130402882](README.assets/image-20230630130402882.png) + +> 该工具并不能保证百分百能够提取出想要的内容,如果不符合常见规则可能提取结果为空。 + + + +### 键盘流量 + +加载文件后,选择执行类型后点击执行即可 + +若知道类型,可以直接选择,~~若不知道类型,反正就两种都试一下就行了~~ + +![keyborad](README.assets/keyborad.gif) + + + +### 鼠标流量 + +与键盘一样,加载文件后,选择执行类型后点击执行即可。 + +建议先选择`所有`,确定是否有输出后,再按照鼠标按键进行分类查看。 + +![mouse](README.assets/mouse.gif) \ No newline at end of file diff --git a/UsbKeyboardExtract.py b/UsbKeyboardExtract.py new file mode 100644 index 0000000..477f775 --- /dev/null +++ b/UsbKeyboardExtract.py @@ -0,0 +1,74 @@ +import sys,os + +normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"","29":"","2a":"", "2b":"\t","2c":"","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"","33":";","34":"'","35":"","36":",","37":".","38":"/","39":"","3a":"","3b":"", "3c":"","3d":"","3e":"","3f":"","40":"","41":"","42":"","43":"","44":"","45":"","54":"/","55":"*","56":"-","57":"+","58":"","59":"1","5a":"2","5b":"3","5c":"4","5d":"5","5e":"6","5f":"7","60":"8","61":"9","62":"0","63":"."} +shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"","29":"","2a":"", "2b":"\t","2c":"","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"","33":"\"","34":":","35":"","36":"<","37":">","38":"?","39":"","3a":"","3b":"", "3c":"","3d":"","3e":"","3f":"","40":"","41":"","42":"","43":"","44":"","45":"","54":"/","55":"*","56":"-","57":"+","58":"","59":"1","5a":"2","5b":"3","5c":"4","5d":"5","5e":"6","5f":"7","60":"8","61":"9","62":"0","63":"."} + + +def extract_data(types,filename): + presses = [] + type_dicts = {"capdata": "usb.capdata", "usbhid": "usbhid.data"} + mytype = type_dicts[types] + + os.system(f'tshark.exe -r "{filename}" -T fields -e {mytype} > usb.dat') + with open("usb.dat", "r") as f: + for line in f: + presses.append(line[0:-1]) + result = "" + result_data = [] + for press in presses: + if press == '': + continue + if ':' in press: + Bytes = press.split(":") + else: + Bytes = [press[i:i+2] for i in range(0, len(press), 2)] + if Bytes[0] == "00": + if Bytes[2] != "00" and normalKeys.get(Bytes[2]): + result += normalKeys[Bytes[2]] + result_data.append(normalKeys[Bytes[2]]) + elif int(Bytes[0],16) & 0b10 or int(Bytes[0],16) & 0b100000: + if Bytes[2] != "00" and normalKeys.get(Bytes[2]): + result += shiftKeys[Bytes[2]] + result_data.append(shiftKeys[Bytes[2]]) + else: + pass + + return result,result_data + +#以下是对提取的键盘流量进行加工 +def process_data(res): + datas = [] + delete_data = [] + temp_del = [] + not_last_del = False + CAP = 0 + for data in res: + if(data == ''): + CAP ^= 1 + elif(data == ''): + try: + temp_del.append(datas.pop()) + except: + pass + not_last_del = True + elif(data == ''): + if(not_last_del): + delete_data += temp_del[::-1] + temp_del = [] + datas.append(' ') + not_last_del = False + else: + if(not_last_del): + delete_data += temp_del[::-1] + temp_del = [] + if(CAP == 0 or not data.isalpha()): + datas.append(data) + else: + key = [k for k, v in normalKeys.items() if v == data][0] + corresponding_value_in_shiftKeys = shiftKeys.get(key) + datas.append(corresponding_value_in_shiftKeys) + not_last_del = False + + datas = ''.join(datas) + delete_data = ''.join(delete_data) + return datas,delete_data \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..31569bd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +PySide6 +numpy +matplotlib \ No newline at end of file diff --git a/run_GUI.py b/run_GUI.py new file mode 100644 index 0000000..e84dd08 --- /dev/null +++ b/run_GUI.py @@ -0,0 +1,84 @@ +from PySide6.QtWidgets import QStackedWidget,QApplication, QMainWindow, QFileDialog, QVBoxLayout, QWidget, QLabel, QLineEdit, QToolBar +from PySide6.QtGui import QAction,QIcon +import sys +from KeyboardDecrypt import KeyboardDecryptWindow +from MouseDecrypt import MouseDecryptWindow + + +class MainWindow(QMainWindow): + def __init__(self): + super(MainWindow, self).__init__() + + self.setWindowTitle("键盘流量&鼠标流量 GUI by mumuzi") + self.keyboardDecryptWindow = KeyboardDecryptWindow(self) + self.keyboardDecryptWindow.file_dropped.connect(self.set_file) + self.mouseDecryptWindow = MouseDecryptWindow() + self.mouseDecryptWindow.file_dropped.connect(self.set_file) + + self.stackedWidget = QStackedWidget(self) + self.stackedWidget.addWidget(self.keyboardDecryptWindow) + self.stackedWidget.addWidget(self.mouseDecryptWindow) + + self.typeToolBar = QToolBar(self) + self.keyboardAction = QAction('键盘流量解密', self) + self.mouseAction = QAction('鼠标流量解密', self) + self.keyboardAction.triggered.connect(lambda: self.switch_window(0)) + self.mouseAction.triggered.connect(lambda: self.switch_window(1)) + self.typeToolBar.addAction(self.keyboardAction) + self.typeToolBar.addAction(self.mouseAction) + self.addToolBar(self.typeToolBar) + + # 文件选择功能 + + self.fileToolBar = QToolBar(self) + self.select_file_label = QLabel("选择或拖拽文件") + self.fileToolBar.addWidget(self.select_file_label) + self.file_name = QLineEdit() + self.file_name.setReadOnly(True) + self.fileToolBar.addWidget(self.file_name) + self.select_file_button = QAction("浏览文件", self) + self.select_file_button.triggered.connect(self.select_file) + self.fileToolBar.addAction(self.select_file_button) + self.addToolBar(self.fileToolBar) + + layout = QVBoxLayout() + layout.addWidget(self.stackedWidget) + + self.setWindowIcon(QIcon('./img/myico.ico')) + self.setStyleSheet(""" + MainWindow {background-image: url(img/mybg.jpg)} + QPushButton {background-color: transparent} + QTextEdit {background-color: rgba(255, 255, 255, 200)} + QLineEdit {background-color: rgba(255, 255, 255, 200)} + """) + + centralWidget = QWidget(self) + centralWidget.setLayout(layout) + + self.setCentralWidget(centralWidget) + + # 设置窗口大小 + self.resize(600, 450) + + def switch_window(self, index): + self.stackedWidget.setCurrentIndex(index) + + def select_file(self): + options = QFileDialog.Options() + fileName, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Wireshark pcapng (*.ntar *.ntar.* *.pcapng.gz *.pcapng.zst *.pcapng.lz4 *.pcapng);;tcpdump pcap (*.dmp.* *.dmp *.cap.* *.cap *.pcap.* *.pcap);;other (*.*)", options=options) + if fileName: + self.file_name.setText(fileName) # 更新file_name文本框的文本 + self.keyboardDecryptWindow.set_file(fileName) + self.mouseDecryptWindow.set_file(fileName) + + def set_file(self, file_name): + self.file_name.setText(file_name) + self.keyboardDecryptWindow.set_file(file_name) + self.mouseDecryptWindow.set_file(file_name) + +app = QApplication(sys.argv) + +window = MainWindow() +window.show() + +app.exec_() diff --git a/tshark.exe b/tshark.exe new file mode 100644 index 0000000..0437819 Binary files /dev/null and b/tshark.exe differ