增加了回调处理,如果放行控制传输数据,可以查看到返回的数据
This commit is contained in:
parent
7ce2f1d575
commit
3e4d3d9640
178
libusbMod.c
178
libusbMod.c
@ -1,145 +1,139 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/sched.h> // for current->comm, current->pid
|
||||
#include <linux/uaccess.h> // for copy_from_user, copy_to_user (如果需要访问用户空间内存)
|
||||
#include <linux/usb.h> // 包含 USB 核心数据结构,如 struct urb
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
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;
|
||||
|
||||
// 针对 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]。
|
||||
// 自定义回调上下文,保存原始回调和上下文
|
||||
struct urb_context {
|
||||
usb_complete_t original_complete;
|
||||
void *original_context;
|
||||
};
|
||||
|
||||
// 包装回调函数
|
||||
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)
|
||||
{
|
||||
// !!! 核心修改点:在 ARM64 上,函数第一个参数通常在 x0 (regs[0]) !!!
|
||||
struct urb *urb_kern = (struct urb *)regs->regs[0];
|
||||
|
||||
// 严谨的空指针检查
|
||||
if (!urb_kern) {
|
||||
pr_err("[usbFilter] handler_pre: urb_kern is NULL. Skipping.\n");
|
||||
return 0; // KPROBE_OK, 让原始函数继续执行,避免崩溃
|
||||
}
|
||||
if (!urb_kern)
|
||||
return 0;
|
||||
|
||||
// 打印进程信息、PID
|
||||
pr_info("[usbFilter] 进程: %s, pid: %d\n",
|
||||
current->comm, current->pid);
|
||||
pr_info("[usbFilter] 提交 URB 的进程: %s (pid: %d)\n", current->comm, current->pid);
|
||||
|
||||
// 获取并打印 URB 的详细信息
|
||||
pr_info("[usbFilter] URB详情: 地址=%p, pipe=0x%08x, 状态=%d, 传输标志=0x%08x\n",
|
||||
urb_kern,
|
||||
urb_kern->pipe,
|
||||
urb_kern->status,
|
||||
urb_kern->transfer_flags);
|
||||
pr_info("[usbFilter] URB: %p, pipe=0x%x, flags=0x%x\n",
|
||||
urb_kern, urb_kern->pipe, urb_kern->transfer_flags);
|
||||
|
||||
// 打印 pipe 的解析信息
|
||||
pr_info("[usbFilter] Pipe解析: 设备地址=%d, 端点号=%d, 方向=%s, 类型=%s\n",
|
||||
usb_pipedevice(urb_kern->pipe),
|
||||
usb_pipeendpoint(urb_kern->pipe),
|
||||
usb_pipein(urb_kern->pipe) ? "IN(设备到主机)" : "OUT(主机到设备)",
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_CONTROL ? "控制传输" :
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_ISOCHRONOUS ? "等时传输" :
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_BULK ? "批量传输" :
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_INTERRUPT ? "中断传输" : "未知");
|
||||
|
||||
// 端点信息
|
||||
if (urb_kern->ep) {
|
||||
pr_info("[usbFilter] 端点信息: 地址=0x%02x, 属性=0x%02x, 最大包大小=%d, 间隔=%d\n",
|
||||
urb_kern->ep->desc.bEndpointAddress,
|
||||
urb_kern->ep->desc.bmAttributes,
|
||||
urb_kern->ep->desc.wMaxPacketSize,
|
||||
urb_kern->ep->desc.bInterval);
|
||||
} else {
|
||||
pr_info("[usbFilter] 端点信息: urb_kern->ep 为 NULL\n");
|
||||
}
|
||||
|
||||
// 打印设备信息(如果可用)
|
||||
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);
|
||||
;
|
||||
}
|
||||
|
||||
// 传输缓冲区信息
|
||||
pr_info("[usbFilter] 传输缓冲区: buffer=%p, length=%d, actual_length=%d\n",
|
||||
urb_kern->transfer_buffer,
|
||||
urb_kern->transfer_buffer_length,
|
||||
urb_kern->actual_length);
|
||||
// 打印传输方向与类型
|
||||
pr_info("[usbFilter] pipe: 端点=%d, 方向=%s, 类型=%s\n",
|
||||
usb_pipeendpoint(urb_kern->pipe),
|
||||
usb_pipein(urb_kern->pipe) ? "IN" : "OUT",
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_CONTROL ? "CONTROL" :
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_ISOCHRONOUS ? "ISO" :
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_BULK ? "BULK" :
|
||||
usb_pipetype(urb_kern->pipe) == PIPE_INTERRUPT ? "INTERRUPT" : "UNKNOWN");
|
||||
|
||||
|
||||
// 如果是等时传输,打印相关信息
|
||||
if (usb_pipetype(urb_kern->pipe) == PIPE_ISOCHRONOUS) {
|
||||
pr_info("[usbFilter] 等时传输: number_of_packets=%d, start_frame=%d, error_count=%d\n",
|
||||
urb_kern->number_of_packets,
|
||||
urb_kern->start_frame,
|
||||
urb_kern->error_count);
|
||||
}
|
||||
|
||||
// 如果是控制传输,打印setup包
|
||||
if (usb_pipetype(urb_kern->pipe) == PIPE_CONTROL && urb_kern->setup_packet) {
|
||||
struct usb_ctrlrequest *setup = (struct usb_ctrlrequest *)urb_kern->setup_packet;
|
||||
pr_info("[usbFilter] 控制传输Setup包: bRequestType=0x%02x, bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=%u\n",
|
||||
setup->bRequestType, setup->bRequest,
|
||||
le16_to_cpu(setup->wValue), le16_to_cpu(setup->wIndex),
|
||||
le16_to_cpu(setup->wLength));
|
||||
}
|
||||
|
||||
// 传输数据内容打印
|
||||
// 打印前 32 字节传输数据
|
||||
if (urb_kern->transfer_buffer && urb_kern->transfer_buffer_length > 0) {
|
||||
unsigned char data[32] = {0}; // 增加到32字节
|
||||
unsigned int to_copy = min((unsigned int)32, urb_kern->transfer_buffer_length);
|
||||
unsigned char data[32] = {0};
|
||||
unsigned int to_copy = min(32U, (unsigned int)urb_kern->transfer_buffer_length);
|
||||
memcpy(data, urb_kern->transfer_buffer, to_copy);
|
||||
|
||||
// 尝试从用户空间拷贝
|
||||
if (copy_from_user(data, urb_kern->transfer_buffer, to_copy) != 0) { // 0 表示成功
|
||||
memcpy(data, urb_kern->transfer_buffer, to_copy);
|
||||
}
|
||||
|
||||
char hex[3 * 32 + 1] = {0}; // 修改为适应32字节的大小
|
||||
char hex[3 * 32 + 1] = {0};
|
||||
int i;
|
||||
for (i = 0; i < to_copy; ++i) {
|
||||
// 确保 snprintf 不会溢出 hex 缓冲区
|
||||
snprintf(hex + i * 3, sizeof(hex) - (i * 3), "%02X ", data[i]);
|
||||
snprintf(hex + i * 3, sizeof(hex) - i * 3, "%02X ", data[i]);
|
||||
}
|
||||
pr_info("[usbFilter] 数据内容(hex, %u字节): %s\n", to_copy, hex);
|
||||
pr_info("[usbFilter] 数据内容(hex): %s\n", hex);
|
||||
}
|
||||
|
||||
if(urb_kern->dev->descriptor.idVendor == 0x1a86 && urb_kern->dev->descriptor.idProduct == 0x55de) {
|
||||
pr_info("[usbFilter] 发现目标设备,阻断提交URB\n");
|
||||
regs->regs[0] = 0; // 设置 x0 寄存器(返回值)为 0 (成功)
|
||||
return 1;
|
||||
// 是否为目标设备
|
||||
if (urb_kern->dev &&
|
||||
urb_kern->dev->descriptor.idVendor == 0x1a86 &&
|
||||
urb_kern->dev->descriptor.idProduct == 0x55de) {
|
||||
|
||||
pr_info("[usbFilter] 命中目标设备,替换 URB 回调\n");
|
||||
|
||||
struct urb_context *ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
|
||||
if (!ctx) {
|
||||
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)
|
||||
{
|
||||
// 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");
|
||||
pr_err("[usbFilter] 无法注册 kprobe\n");
|
||||
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;
|
||||
}
|
||||
|
||||
static void __exit usb_hook_exit(void)
|
||||
{
|
||||
unregister_kprobe(&kp);
|
||||
pr_info("[usbFilter] kprobe unregistered\n");
|
||||
pr_info("[usbFilter] 已卸载 usb_submit_urb hook\n");
|
||||
}
|
||||
|
||||
module_init(usb_hook_init);
|
||||
module_exit(usb_hook_exit);
|
||||
module_exit(usb_hook_exit);
|
||||
|
||||
Reference in New Issue
Block a user