Compare commits

..

3 Commits

Author SHA1 Message Date
kylin_bg
3e4d3d9640 增加了回调处理,如果放行控制传输数据,可以查看到返回的数据 2025-06-07 17:00:07 +08:00
kylin_bg
7ce2f1d575 加入更多打印信息,加入设备控制 2025-06-07 16:12:09 +08:00
kylin_bg
4f2d1c0830 默认不阻断状态 2025-06-07 15:04:52 +08:00

View File

@ -1,104 +1,139 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/sched.h> // for current->comm, current->pid #include <linux/sched.h>
#include <linux/uaccess.h> // for copy_from_user, copy_to_user (如果需要访问用户空间内存) #include <linux/uaccess.h>
#include <linux/usb.h> // 包含 USB 核心数据结构,如 struct urb #include <linux/usb.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Leo"); MODULE_AUTHOR("Leo");
MODULE_DESCRIPTION("Hook usb_submit_urb ioctl on arm64"); // 这里的注释可能不完全准确usb_submit_urb不是ioctl是内核函数 MODULE_DESCRIPTION("Hook usb_submit_urb() on ARM64 and replace callback");
static struct kprobe kp; static struct kprobe kp;
// 针对 ARM64 (AArch64) 架构,函数参数通常在 x0, x1, x2... 寄存器中。 // 自定义回调上下文,保存原始回调和上下文
// pt_regs 中的 regs 数组索引通常对应这些寄存器。 struct urb_context {
// 对于 AArch64x0 是 regs[0]x1 是 regs[1],以此类推。 usb_complete_t original_complete;
// usb_submit_urb 函数原型通常是int usb_submit_urb(struct urb *urb, gfp_t mem_flags) void *original_context;
// 所以第一个参数 struct urb *urb 应该在 x0 寄存器中,对应 regs[0]。 };
// 包装回调函数
static void callback_wrapper(struct urb *urb)
{
struct urb_context *ctx = urb->context;
pr_info("[usbFilter] [callback_wrapper] URB 完成: endpoint=0x%x, status=%d, actual_length=%d\n",
usb_pipeendpoint(urb->pipe),
urb->status,
urb->actual_length);
if (urb->transfer_buffer && urb->actual_length > 0) {
char hex[3 * 32 + 1] = {0};
int i, len = min(32, urb->actual_length);
unsigned char *data = (unsigned char *)urb->transfer_buffer;
for (i = 0; i < len; ++i) {
snprintf(hex + i * 3, sizeof(hex) - i * 3, "%02X ", data[i]);
}
pr_info("[usbFilter] [callback_wrapper] 返回数据(hex): %s\n", hex);
}
if (ctx && ctx->original_complete) {
urb->context = ctx->original_context;
ctx->original_complete(urb);
}
kfree(ctx); // 释放上下文
}
static int handler_pre(struct kprobe *p, struct pt_regs *regs) static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{ {
// !!! 核心修改点:在 ARM64 上,函数第一个参数通常在 x0 (regs[0]) !!!
struct urb *urb_kern = (struct urb *)regs->regs[0]; struct urb *urb_kern = (struct urb *)regs->regs[0];
// 严谨的空指针检查 if (!urb_kern)
if (!urb_kern) { return 0;
pr_err("[usbFilter] handler_pre: urb_kern is NULL. Skipping.\n");
return 0; // KPROBE_OK, 让原始函数继续执行,避免崩溃 pr_info("[usbFilter] 提交 URB 的进程: %s (pid: %d)\n", current->comm, current->pid);
pr_info("[usbFilter] URB: %p, pipe=0x%x, flags=0x%x\n",
urb_kern, urb_kern->pipe, urb_kern->transfer_flags);
if (urb_kern->dev) {
pr_info("[usbFilter] USB设备: VID=0x%04x, PID=0x%04x\n",
urb_kern->dev->descriptor.idVendor,
urb_kern->dev->descriptor.idProduct);
} }
// 打印进程信息、PID // 打印传输方向与类型
pr_info("[usbFilter] process: %s, pid: %d\n", pr_info("[usbFilter] pipe: 端点=%d, 方向=%s, 类型=%s\n",
current->comm, current->pid); usb_pipeendpoint(urb_kern->pipe),
usb_pipein(urb_kern->pipe) ? "IN" : "OUT",
// 获取端点地址、传输长度和 pipe 信息 usb_pipetype(urb_kern->pipe) == PIPE_CONTROL ? "CONTROL" :
pr_info("[usbFilter] urb_kern: %p, pipe: 0x%08x, ep: 0x%x, len: %d\n", usb_pipetype(urb_kern->pipe) == PIPE_ISOCHRONOUS ? "ISO" :
urb_kern, usb_pipetype(urb_kern->pipe) == PIPE_BULK ? "BULK" :
urb_kern->pipe, // 新增打印 pipe 信息 usb_pipetype(urb_kern->pipe) == PIPE_INTERRUPT ? "INTERRUPT" : "UNKNOWN");
urb_kern->ep ? urb_kern->ep->desc.bEndpointAddress : 0, // 检查 urb_kern->ep
urb_kern->transfer_buffer_length);
// 打印前 32 字节传输数据
if (urb_kern->transfer_buffer && urb_kern->transfer_buffer_length > 0) { if (urb_kern->transfer_buffer && urb_kern->transfer_buffer_length > 0) {
unsigned char data[16] = {0}; // 局部缓冲区,用于存放拷贝的数据 unsigned char data[32] = {0};
unsigned int to_copy = min((unsigned int)16, urb_kern->transfer_buffer_length); unsigned int to_copy = min(32U, (unsigned int)urb_kern->transfer_buffer_length);
bool data_copied_successfully = false; memcpy(data, urb_kern->transfer_buffer, to_copy);
// 尝试从用户空间拷贝 char hex[3 * 32 + 1] = {0};
if (copy_from_user(data, urb_kern->transfer_buffer, to_copy) == 0) { // 0 表示成功 int i;
pr_info("[usbFilter] Successfully copied %u bytes using copy_from_user from user buffer at %p.\n", to_copy, urb_kern->transfer_buffer); for (i = 0; i < to_copy; ++i) {
data_copied_successfully = true; snprintf(hex + i * 3, sizeof(hex) - i * 3, "%02X ", data[i]);
} 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);
} }
pr_info("[usbFilter] 数据内容(hex): %s\n", hex);
} }
regs->regs[0] = 0; // 设置 x0 寄存器(返回值)为 0 (成功) // 是否为目标设备
if (urb_kern->dev &&
urb_kern->dev->descriptor.idVendor == 0x1a86 &&
urb_kern->dev->descriptor.idProduct == 0x55de) {
pr_info("[usbFilter] 命中目标设备,替换 URB 回调\n");
// return 0; // KPROBE_OK默认让原始函数继续执行 struct urb_context *ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
// 如果要阻断,这里返回 1 (KPROBE_HANDLED)x if (!ctx) {
return 1; pr_err("[usbFilter] 分配回调上下文失败\n");
return 0;
}
ctx->original_complete = urb_kern->complete;
ctx->original_context = urb_kern->context;
urb_kern->complete = callback_wrapper;
urb_kern->context = ctx;
// 可以选择返回 0让 URB 正常提交;也可以选择模拟成功阻断:
// regs->regs[0] = 0;
// return 1;
}
return 0;
} }
static int __init usb_hook_init(void) static int __init usb_hook_init(void)
{ {
// usb_submit_urb 是一个导出的符号Kprobe 可以 Hook
kp.symbol_name = "usb_submit_urb"; kp.symbol_name = "usb_submit_urb";
kp.pre_handler = handler_pre; kp.pre_handler = handler_pre;
if (register_kprobe(&kp) < 0) { if (register_kprobe(&kp) < 0) {
pr_err("[usbFilter] register_kprobe failed\n"); pr_err("[usbFilter] 无法注册 kprobe\n");
return -1; return -1;
} }
pr_info("[usbFilter] kprobe registered for %s at %p\n", kp.symbol_name, kp.addr);
pr_info("[usbFilter] 成功 hook usb_submit_urb()\n");
return 0; return 0;
} }
static void __exit usb_hook_exit(void) static void __exit usb_hook_exit(void)
{ {
unregister_kprobe(&kp); unregister_kprobe(&kp);
pr_info("[usbFilter] kprobe unregistered\n"); pr_info("[usbFilter] 已卸载 usb_submit_urb hook\n");
} }
module_init(usb_hook_init); module_init(usb_hook_init);
module_exit(usb_hook_exit); module_exit(usb_hook_exit);