diff --git a/.gitignore b/.gitignore index 0a95508..5ae7873 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ -.vscode/ \ No newline at end of file +.vscode/ +exFilter/__pycache__/*.pyc \ No newline at end of file diff --git a/exFilter/core.py b/exFilter/core.py index 37c12e5..55633ae 100644 --- a/exFilter/core.py +++ b/exFilter/core.py @@ -1,10 +1,9 @@ import frida import logging -import sys import os import json -import subprocess -import re +import queue + from exFilter.utils import enum_usb_devices, enum_pcie_devices,checkPid logging.basicConfig( @@ -62,7 +61,19 @@ class Filter: return combined_json + def on_message(self, message, data): + self.logger.debug(f"Received message") + if(self.msgQueue.full()): + self.logger.warning("Message queue is full") + self.msgQueue.put(message) + + def rev(self): + message = self.msgQueue.get() + return message + + def open(self,device_path): + self.msgQueue = queue.Queue(maxsize=100) #设置最大消息队列长度为100 self.logger.debug(f"check device at {device_path}") processPid = checkPid(device_path,self.logger) if processPid <0: @@ -80,9 +91,12 @@ class Filter: if "usb" in device_path: try: self.logger.info(f"Loading USB filter script for device: {device_path}") + # 测试脚本和正式脚本切换 with open("scripts/libusbHook.js", "r") as f: + # with open("testScripts/libusb/testSubmit.js", "r") as f: self.script = self.session.create_script(f.read()); self.script.load() + self.script.on("message", self.on_message) self.logger.info(f"Script loaded successfully") return True except Exception as e: @@ -95,6 +109,7 @@ class Filter: self.script = self.session.create_script(f.read()); self.script.load() self.logger.info(f"Script loaded successfully") + self.script.on("message", self.on_message) return True except Exception as e: self.logger.error(f"Failed to load PCIe filter script: {e}") diff --git a/exFilter/utils.py b/exFilter/utils.py index 9e508e8..0fd4645 100644 --- a/exFilter/utils.py +++ b/exFilter/utils.py @@ -98,7 +98,6 @@ def enum_pcie_devices(): return json.dumps(result, indent=2, ensure_ascii=False) - def checkPid(devPath, logger): processPid = -1 # 通过device_path查看当前占用该设备的进程pid号 diff --git a/main.py b/main.py index 1f032b2..2b2982c 100644 --- a/main.py +++ b/main.py @@ -7,10 +7,11 @@ def main(): if filter.start(): # 列举USB和PCIe设备 devices = filter.EnumDriversAndDevices() - filter.open("/dev/bus/usb/002/004") - sleep(10) - filter.stop() - return + filter.open("/dev/bus/usb/002/006") + while True: + msg = filter.rev() + print(f"Received message: {msg}") + if __name__ == "__main__": diff --git a/scripts/libusbHook.js b/scripts/libusbHook.js index e69de29..1a3bf43 100644 --- a/scripts/libusbHook.js +++ b/scripts/libusbHook.js @@ -0,0 +1,88 @@ +console.log("Starting libusb_submit_transfer hook script..."); + +// 传输类型枚举 +const LIBUSB_TRANSFER_TYPE = { + 0: "CONTROL", + 1: "ISOCHRONOUS", + 2: "BULK", + 3: "INTERRUPT" +}; + +// Hook libusb_submit_transfer +const submit_transfer_symbol = DebugSymbol.fromName("libusb_submit_transfer"); +console.log("libusb_submit_transfer symbol info:", submit_transfer_symbol); + +if (submit_transfer_symbol && submit_transfer_symbol.address && !submit_transfer_symbol.address.isNull()) { + Interceptor.attach(submit_transfer_symbol.address, { + onEnter: function(args) { + var transfer = args[0]; + if (!transfer || transfer.isNull()) { + return; + } + + try { + // 检测系统架构 + var ptrSize = Process.pointerSize; + var is64bit = (ptrSize === 8); + + var endpoint, type, length, buffer; + + // 根据架构读取结构体成员 + if (is64bit) { + endpoint = transfer.add(9).readU8(); // 0x09 + type = transfer.add(10).readU8(); // 0x0A + length = transfer.add(20).readU32(); // 0x14 + buffer = transfer.add(48).readPointer(); // 0x30 + } else { + endpoint = transfer.add(5).readU8(); // 0x05 + type = transfer.add(6).readU8(); // 0x06 + length = transfer.add(16).readU32(); // 0x10 + buffer = transfer.add(32).readPointer(); // 0x20 + } + + // 准备发送的数据 + var messageData = { + function: "libusb_submit_transfer", + transferType: LIBUSB_TRANSFER_TYPE[type] || "UNKNOWN", + endpoint: "0x" + endpoint.toString(16), + direction: (endpoint & 0x80) ? "IN" : "OUT", + length: length, + buffer: null + }; + + // 读取缓冲区数据 + if (!buffer.isNull() && length > 0) { + try { + var bufferData = []; + var maxBytes = Math.min(length, 1024); // 最多读取1024字节 + + for (var i = 0; i < maxBytes; i++) { + bufferData.push(buffer.add(i).readU8()); + } + + messageData.buffer = bufferData; + messageData.bufferTruncated = length > maxBytes; + + } catch (readErr) { + messageData.buffer = null; + messageData.error = "Failed to read buffer: " + readErr.message; + } + } + + // 发送数据 + send(messageData); + + } catch (e) { + send({ + function: "libusb_submit_transfer", + error: "Failed to parse transfer structure: " + e.message + }); + } + } + }); + console.log("Successfully hooked libusb_submit_transfer"); +} else { + console.log("libusb_submit_transfer not found"); +} + +console.log("libusb_submit_transfer hook script loaded successfully!"); \ No newline at end of file diff --git a/testScripts/frida_hook_libusb_basic_Version2.js b/testScripts/basic/frida_hook_libusb_basic_Version2.js similarity index 100% rename from testScripts/frida_hook_libusb_basic_Version2.js rename to testScripts/basic/frida_hook_libusb_basic_Version2.js diff --git a/testScripts/frida_hook_libusb_modify_data_Version2.js b/testScripts/basic/frida_hook_libusb_modify_data_Version2.js similarity index 100% rename from testScripts/frida_hook_libusb_modify_data_Version2.js rename to testScripts/basic/frida_hook_libusb_modify_data_Version2.js diff --git a/testScripts/frida_hook_libusb_replay_Version2.js b/testScripts/basic/frida_hook_libusb_replay_Version2.js similarity index 100% rename from testScripts/frida_hook_libusb_replay_Version2.js rename to testScripts/basic/frida_hook_libusb_replay_Version2.js diff --git a/testScripts/libusb/testEn.js b/testScripts/libusb/testEn.js new file mode 100644 index 0000000..e5c5b74 --- /dev/null +++ b/testScripts/libusb/testEn.js @@ -0,0 +1,78 @@ +console.log("Starting libusb hook script..."); + +// Hook libusb_bulk_transfer +const bulk_transfer_symbol = DebugSymbol.fromName("libusb_bulk_transfer"); +console.log("libusb_bulk_transfer symbol info:", bulk_transfer_symbol); + +if (bulk_transfer_symbol && bulk_transfer_symbol.address && !bulk_transfer_symbol.address.isNull()) { + Interceptor.attach(bulk_transfer_symbol.address, { + onEnter: function(args) { + console.log("[LIBUSB] libusb_bulk_transfer called"); + } + }); + console.log("Successfully hooked libusb_bulk_transfer"); +} else { + console.log("libusb_bulk_transfer not found"); +} + +// Hook libusb_control_transfer +const control_transfer_symbol = DebugSymbol.fromName("libusb_control_transfer"); +console.log("libusb_control_transfer symbol info:", control_transfer_symbol); + +if (control_transfer_symbol && control_transfer_symbol.address && !control_transfer_symbol.address.isNull()) { + Interceptor.attach(control_transfer_symbol.address, { + onEnter: function(args) { + console.log("[LIBUSB] libusb_control_transfer called"); + } + }); + console.log("Successfully hooked libusb_control_transfer"); +} else { + console.log("libusb_control_transfer not found"); +} + +// Hook libusb_interrupt_transfer +const interrupt_transfer_symbol = DebugSymbol.fromName("libusb_interrupt_transfer"); +console.log("libusb_interrupt_transfer symbol info:", interrupt_transfer_symbol); + +if (interrupt_transfer_symbol && interrupt_transfer_symbol.address && !interrupt_transfer_symbol.address.isNull()) { + Interceptor.attach(interrupt_transfer_symbol.address, { + onEnter: function(args) { + console.log("[LIBUSB] libusb_interrupt_transfer called"); + } + }); + console.log("Successfully hooked libusb_interrupt_transfer"); +} else { + console.log("libusb_interrupt_transfer not found"); +} + +// Hook libusb_submit_transfer (异步传输) +const submit_transfer_symbol = DebugSymbol.fromName("libusb_submit_transfer"); +console.log("libusb_submit_transfer symbol info:", submit_transfer_symbol); + +if (submit_transfer_symbol && submit_transfer_symbol.address && !submit_transfer_symbol.address.isNull()) { + Interceptor.attach(submit_transfer_symbol.address, { + onEnter: function(args) { + console.log("[LIBUSB] libusb_submit_transfer called"); + } + }); + console.log("Successfully hooked libusb_submit_transfer"); +} else { + console.log("libusb_submit_transfer not found"); +} + +// Hook libusb_cancel_transfer +const cancel_transfer_symbol = DebugSymbol.fromName("libusb_cancel_transfer"); +console.log("libusb_cancel_transfer symbol info:", cancel_transfer_symbol); + +if (cancel_transfer_symbol && cancel_transfer_symbol.address && !cancel_transfer_symbol.address.isNull()) { + Interceptor.attach(cancel_transfer_symbol.address, { + onEnter: function(args) { + console.log("[LIBUSB] libusb_cancel_transfer called"); + } + }); + console.log("Successfully hooked libusb_cancel_transfer"); +} else { + console.log("libusb_cancel_transfer not found"); +} + +console.log("libusb hook script loaded successfully!"); \ No newline at end of file diff --git a/testScripts/libusb/testSubmit.js b/testScripts/libusb/testSubmit.js new file mode 100644 index 0000000..48f21fc --- /dev/null +++ b/testScripts/libusb/testSubmit.js @@ -0,0 +1,211 @@ +console.log("Starting libusb_submit_transfer hook script..."); + +// libusb_transfer结构体定义 (根据libusb源码) +/* +struct libusb_transfer { + libusb_device_handle *dev_handle; // 0x00 + uint8_t flags; // 0x08 (64位) / 0x04 (32位) + unsigned char endpoint; // 0x09 / 0x05 + unsigned char type; // 0x0A / 0x06 + unsigned int timeout; // 0x0C / 0x08 + enum libusb_transfer_status status; // 0x10 / 0x0C + int length; // 0x14 / 0x10 + int actual_length; // 0x18 / 0x14 + libusb_transfer_cb_fn callback; // 0x20 / 0x18 + void *user_data; // 0x28 / 0x1C + unsigned char *buffer; // 0x30 / 0x20 + int num_iso_packets; // 0x38 / 0x24 + struct libusb_iso_packet_descriptor iso_packet_desc[0]; // 0x40 / 0x28 +}; +*/ + +// 传输类型枚举 +const LIBUSB_TRANSFER_TYPE = { + 0: "LIBUSB_TRANSFER_TYPE_CONTROL", + 1: "LIBUSB_TRANSFER_TYPE_ISOCHRONOUS", + 2: "LIBUSB_TRANSFER_TYPE_BULK", + 3: "LIBUSB_TRANSFER_TYPE_INTERRUPT" +}; + +// 传输状态枚举 +const LIBUSB_TRANSFER_STATUS = { + 0: "LIBUSB_TRANSFER_COMPLETED", + 1: "LIBUSB_TRANSFER_ERROR", + 2: "LIBUSB_TRANSFER_TIMED_OUT", + 3: "LIBUSB_TRANSFER_CANCELLED", + 4: "LIBUSB_TRANSFER_STALL", + 5: "LIBUSB_TRANSFER_NO_DEVICE", + 6: "LIBUSB_TRANSFER_OVERFLOW" +}; + +// 传输标志 +const LIBUSB_TRANSFER_FLAGS = { + 1: "LIBUSB_TRANSFER_SHORT_NOT_OK", + 2: "LIBUSB_TRANSFER_FREE_BUFFER", + 4: "LIBUSB_TRANSFER_FREE_TRANSFER", + 8: "LIBUSB_TRANSFER_ADD_ZERO_PACKET" +}; + +function parseTransferFlags(flags) { + var flagStrings = []; + for (var flag in LIBUSB_TRANSFER_FLAGS) { + if (flags & parseInt(flag)) { + flagStrings.push(LIBUSB_TRANSFER_FLAGS[flag]); + } + } + return flagStrings.length > 0 ? flagStrings.join(" | ") : "None"; +} + +function dumpBuffer(buffer, length, maxBytes = 64) { + if (!buffer || buffer.isNull()) { + console.log("Buffer is NULL"); + return; + } + + try { + var nLen = length.toInt32 ? length.toInt32() : parseInt(length); + var bytesToPrint = Math.min(nLen, maxBytes); + + if (buffer && nLen > 0) { + console.log("数据十六进制输出(前" + bytesToPrint + "字节):"); + + // 最原始的读取方法 + var hexOutput = ""; + for (var i = 0; i < bytesToPrint; i++) { + try { + // 尝试使用ptr对象的属性 + var byteValue = buffer.add(i).readU8(); + var hexByte = byteValue.toString(16).padStart(2, "0"); + hexOutput += hexByte + " "; + if ((i + 1) % 16 === 0) { + hexOutput += "\n"; + } + } catch (readErr) { + console.log("读取字节" + i + "时出错:", readErr); + break; + } + } + console.log(hexOutput); + + if (nLen > maxBytes) { + console.log("... (truncated, showing " + bytesToPrint + " of " + nLen + " bytes)"); + } + } else { + console.log('buffer 指针无效 或 length <= 0'); + } + } catch (e) { + console.log('读取buffer时出错:', e); + console.log('错误详情:', e.stack || e.toString()); + } +} + +// Hook libusb_submit_transfer +const submit_transfer_symbol = DebugSymbol.fromName("libusb_submit_transfer"); +console.log("libusb_submit_transfer symbol info:", submit_transfer_symbol); + +if (submit_transfer_symbol && submit_transfer_symbol.address && !submit_transfer_symbol.address.isNull()) { + Interceptor.attach(submit_transfer_symbol.address, { + onEnter: function(args) { + console.log("\n================================"); + console.log("[LIBUSB] libusb_submit_transfer called"); + console.log("================================"); + + var transfer = args[0]; + if (!transfer || transfer.isNull()) { + console.log("Transfer structure is NULL!"); + return; + } + + try { + // 检测系统架构 + var ptrSize = Process.pointerSize; + var is64bit = (ptrSize === 8); + + // 根据实际的libusb_transfer结构体布局调整偏移量 + // 64位系统的正确偏移量 + if (is64bit) { + var dev_handle = transfer.readPointer(); // 0x00 + var flags = transfer.add(8).readU8(); // 0x08 + var endpoint = transfer.add(9).readU8(); // 0x09 + var type = transfer.add(10).readU8(); // 0x0A + var timeout = transfer.add(12).readU32(); // 0x0C + var status = transfer.add(16).readU32(); // 0x10 + var length = transfer.add(20).readU32(); // 0x14 + var actual_length = transfer.add(24).readU32(); // 0x18 + var callback = transfer.add(32).readPointer(); // 0x20 + var user_data = transfer.add(40).readPointer(); // 0x28 + var buffer = transfer.add(48).readPointer(); // 0x30 + var num_iso_packets = transfer.add(56).readU32(); // 0x38 + } else { + // 32位系统的偏移量 + var dev_handle = transfer.readPointer(); // 0x00 + var flags = transfer.add(4).readU8(); // 0x04 + var endpoint = transfer.add(5).readU8(); // 0x05 + var type = transfer.add(6).readU8(); // 0x06 + var timeout = transfer.add(8).readU32(); // 0x08 + var status = transfer.add(12).readU32(); // 0x0C + var length = transfer.add(16).readU32(); // 0x10 + var actual_length = transfer.add(20).readU32(); // 0x14 + var callback = transfer.add(24).readPointer(); // 0x18 + var user_data = transfer.add(28).readPointer(); // 0x1C + var buffer = transfer.add(32).readPointer(); // 0x20 + var num_iso_packets = transfer.add(36).readU32(); // 0x24 + } + + console.log("Transfer Structure Details:"); + console.log(" - Architecture: " + (is64bit ? "64-bit" : "32-bit")); + console.log(" - Transfer Address: " + transfer); + console.log(" - Device Handle: " + dev_handle); + console.log(" - Flags: 0x" + flags.toString(16) + " (" + parseTransferFlags(flags) + ")"); + console.log(" - Endpoint: 0x" + endpoint.toString(16) + " (" + + (endpoint & 0x80 ? "IN" : "OUT") + ", EP" + (endpoint & 0x7F) + ")"); + console.log(" - Type: " + type + " (" + (LIBUSB_TRANSFER_TYPE[type] || "Unknown") + ")"); + console.log(" - Timeout: " + timeout + " ms"); + console.log(" - Status: " + status + " (" + (LIBUSB_TRANSFER_STATUS[status] || "Unknown") + ")"); + console.log(" - Length: " + length + " bytes"); + console.log(" - Actual Length: " + actual_length + " bytes"); + console.log(" - Callback: " + callback); + console.log(" - User Data: " + user_data); + console.log(" - Buffer: " + buffer); + console.log(" - Num ISO Packets: " + num_iso_packets); + + // 调试:打印buffer指针的具体值 + console.log(" - Buffer pointer value: " + buffer.toString()); + console.log(" - Buffer is null: " + buffer.isNull()); + + // 如果有数据缓冲区,打印前64字节 + if (!buffer.isNull() && length > 0) { + console.log("\nBuffer Data:"); + dumpBuffer(buffer, length); + } else { + console.log("\nBuffer is null or length is 0"); + console.log(" - Buffer null check: " + buffer.isNull()); + console.log(" - Length: " + length); + } + + // 对于同步传输,打印更多详细信息 + if (num_iso_packets > 0) { + console.log("\nIsochronous Transfer - Packet Count: " + num_iso_packets); + // 可以进一步解析ISO包描述符 + } + + } catch (e) { + console.log("Error reading transfer structure: " + e.message); + console.log('错误详情:', e.stack || e.toString()); + } + }, + + onLeave: function(retval) { + console.log("\n[LIBUSB] libusb_submit_transfer returned: " + retval); + if (retval.toInt32() !== 0) { + console.log(" - Error occurred during transfer submission"); + } + console.log("================================\n"); + } + }); + console.log("Successfully hooked libusb_submit_transfer"); +} else { + console.log("libusb_submit_transfer not found"); +} + +console.log("libusb_submit_transfer hook script loaded successfully!"); \ No newline at end of file