From 6c40865f39072b4209eed29693a4ac77c9f81b2c Mon Sep 17 00:00:00 2001 From: kylin_bg Date: Sat, 7 Jun 2025 12:59:17 +0800 Subject: [PATCH] =?UTF-8?q?Refactor=20kprobe=20handler=20for=20usb=5Fsubmi?= =?UTF-8?q?t=5Furb=20to=20improve=20data=20copying=20and=20logging=20on=20?= =?UTF-8?q?ARM64;=20=E7=9B=AE=E5=89=8D=E5=8F=AF=E4=BB=A5=E9=98=BB=E6=96=AD?= =?UTF-8?q?=EF=BC=8C=E4=BD=86=E6=98=AF=E4=BC=9A=E8=BF=94=E5=9B=9E=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=A9=BA=E9=97=B4=E9=94=99=E8=AF=AF=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=B8=94=E5=8F=AA=E5=9C=A8libusb=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E6=B5=8B=E8=AF=95=E8=BF=87=E4=BA=86=EF=BC=8C=E9=94=AE?= =?UTF-8?q?=E7=9B=98=E8=AE=BE=E5=A4=87=E4=BC=9A=E5=8D=A1=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libusbMod.c | 99 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/libusbMod.c b/libusbMod.c index 93794dd..083395d 100644 --- a/libusbMod.c +++ b/libusbMod.c @@ -1,63 +1,96 @@ #include #include -#include #include -#include -#include // for copy_from_user +#include // for current->comm, current->pid +#include // for copy_from_user, copy_to_user (如果需要访问用户空间内存) +#include // 包含 USB 核心数据结构,如 struct urb MODULE_LICENSE("GPL"); MODULE_AUTHOR("Leo"); -MODULE_DESCRIPTION("Hook USBDEVFS_SUBMITURB ioctl on arm64"); +MODULE_DESCRIPTION("Hook usb_submit_urb ioctl on arm64"); // 这里的注释可能不完全准确,usb_submit_urb不是ioctl,是内核函数 static struct kprobe kp; +// 针对 ARM64 (AArch64) 架构,函数参数通常在 x0, x1, x2... 寄存器中。 +// pt_regs 中的 regs 数组索引通常对应这些寄存器。 +// 对于 AArch64,x0 是 regs[0],x1 是 regs[1],以此类推。 +// usb_submit_urb 函数原型通常是:int usb_submit_urb(struct urb *urb, gfp_t mem_flags) +// 所以第一个参数 struct urb *urb 应该在 x0 寄存器中,对应 regs[0]。 + static int handler_pre(struct kprobe *p, struct pt_regs *regs) { - unsigned int cmd = 0; - struct usbdevfs_urb urb_kern; - struct usbdevfs_urb __user *urb_user; + // !!! 核心修改点:在 ARM64 上,函数第一个参数通常在 x0 (regs[0]) !!! + struct urb *urb_kern = (struct urb *)regs->regs[0]; - cmd = (unsigned int)regs->regs[1]; // ioctl 的第二个参数 + // 严谨的空指针检查 + if (!urb_kern) { + pr_err("[usbFilter] handler_pre: urb_kern is NULL. Skipping.\n"); + return 0; // KPROBE_OK, 让原始函数继续执行,避免崩溃 + } - if (cmd == USBDEVFS_SUBMITURB) { - urb_user = (struct usbdevfs_urb __user *)regs->regs[2]; // 第三个参数 - if (urb_user) { - if (copy_from_user(&urb_kern, urb_user, sizeof(struct usbdevfs_urb)) == 0) { - pr_info("[usbFilter] process: %s, pid: %d, ep: 0x%x, len: %d\n", - current->comm, current->pid, - urb_kern.endpoint, urb_kern.buffer_length); + // 打印进程信息、PID + pr_info("[usbFilter] process: %s, pid: %d\n", + current->comm, current->pid); - if (urb_kern.buffer && urb_kern.buffer_length > 0) { - unsigned char data[16] = {0}; - unsigned int to_copy = urb_kern.buffer_length > 16 ? 16 : urb_kern.buffer_length; - if (copy_from_user(data, urb_kern.buffer, to_copy) == 0) { - char hex[3 * 16 + 1] = {0}; - int i; - for (i = 0; i < to_copy; ++i) - snprintf(hex + i * 3, 4, "%02X ", data[i]); - pr_info("[usbFilter] first %u bytes (hex): %s\n", to_copy, hex); - } else { - pr_warn("[usbFilter] copy_from_user buffer failed\n"); - } - } - } else { - pr_warn("[usbFilter] copy_from_user failed\n"); + // 获取端点地址、传输长度和 pipe 信息 + pr_info("[usbFilter] urb_kern: %p, pipe: 0x%08x, ep: 0x%x, len: %d\n", + urb_kern, + urb_kern->pipe, // 新增打印 pipe 信息 + urb_kern->ep ? urb_kern->ep->desc.bEndpointAddress : 0, // 检查 urb_kern->ep + urb_kern->transfer_buffer_length); + + + if (urb_kern->transfer_buffer && urb_kern->transfer_buffer_length > 0) { + unsigned char data[16] = {0}; // 局部缓冲区,用于存放拷贝的数据 + unsigned int to_copy = min((unsigned int)16, urb_kern->transfer_buffer_length); + bool data_copied_successfully = false; + + // 尝试从用户空间拷贝 + if (copy_from_user(data, urb_kern->transfer_buffer, to_copy) == 0) { // 0 表示成功 + pr_info("[usbFilter] Successfully copied %u bytes using copy_from_user from user buffer at %p.\n", to_copy, urb_kern->transfer_buffer); + data_copied_successfully = true; + } else { + // copy_from_user 失败 + pr_warn("[usbFilter] copy_from_user failed for buffer at %p. Attempting memcpy (assuming buffer is in kernel space).\n", urb_kern->transfer_buffer); + + // 警告:如果 transfer_buffer 不是有效的内核地址,memcpy 可能会导致内核崩溃。 + // 这仅作为调试时的后备尝试。 + memcpy(data, urb_kern->transfer_buffer, to_copy); + // 如果 memcpy 没有导致崩溃,我们假设数据为了打印目的是成功拷贝的。 + pr_info("[usbFilter] memcpy attempted for %u bytes from buffer at %p (assumed kernel space).\n", to_copy, urb_kern->transfer_buffer); + data_copied_successfully = true; // 标记为成功,以便后续打印 + } + + if (data_copied_successfully) { + char hex[3 * 16 + 1] = {0}; // 用于存放十六进制字符串 + int i; + for (i = 0; i < to_copy; ++i) { + // 确保 snprintf 不会溢出 hex 缓冲区 + snprintf(hex + i * 3, sizeof(hex) - (i * 3), "%02X ", data[i]); } + pr_info("[usbFilter] first %u bytes (hex): %s\n", to_copy, hex); } } - return 0; + + regs->regs[0] = 0; // 设置 x0 寄存器(返回值)为 0 (成功) + + + // return 0; // KPROBE_OK,默认让原始函数继续执行 + // 如果要阻断,这里返回 1 (KPROBE_HANDLED)x + return 1; } static int __init usb_hook_init(void) { - kp.symbol_name = "usbdev_do_ioctl"; + // usb_submit_urb 是一个导出的符号,Kprobe 可以 Hook + kp.symbol_name = "usb_submit_urb"; kp.pre_handler = handler_pre; if (register_kprobe(&kp) < 0) { pr_err("[usbFilter] register_kprobe failed\n"); return -1; } - pr_info("[usbFilter] kprobe registered for %s\n", kp.symbol_name); + pr_info("[usbFilter] kprobe registered for %s at %p\n", kp.symbol_name, kp.addr); return 0; }