1.与不缺少的一致定义内核中要hook的函数的指针
2.写原始函数、备份函数指针(缺少的结构体需要在源码中查找补全)
3.声明并编写替换函数
4.在init中进行hook,exit中进行ubook
整体代码
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2023 bmax121. All Rights Reserved.
* 参数输入 -p:pid 指定进程ID,其他参数为重定向路径对,格式为 原路径:新路径
* 例子: -p:1234 /data/local/tmp/aaa.txt:/data/local/tmp/bbb.txt /data/local/tmp/ccc.txt:/data/local/tmp/ddd.txt
*/
#include <compiler.h>
#include <kpmodule.h>
#include <linux/printk.h>
#include <uapi/asm-generic/unistd.h>
#include <linux/uaccess.h>
#include <syscall.h>
#include <linux/string.h>
#include <kputils.h>
#include <asm/current.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
typedef unsigned long __kernel_ulong_t;
typedef __kernel_ulong_t __u64;
typedef unsigned int __u32;
typedef int __kernel_pid_t;
typedef unsigned int __kernel_uid32_t;
/* basic types for binder (match your target kernel: use __u64 or unsigned long as needed) */
typedef __u64 binder_size_t;
typedef __u64 binder_uintptr_t;
/* minimal binder_transaction_data with only used fields */
struct binder_transaction_data {
union { __u32 handle; binder_uintptr_t ptr; } target;
binder_uintptr_t cookie;
__u32 code;
__u32 flags;
__kernel_pid_t sender_pid;
__kernel_uid32_t sender_euid;
binder_size_t data_size;
binder_size_t offsets_size;
union {
struct { binder_uintptr_t buffer; binder_uintptr_t offsets; } ptr;
__u8 buf[8];
} data;
};
//定义结构体
struct binder_proc;
struct binder_thread;
//内核函数的定义
typedef void (*binder_transaction_func_t)(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr,
int reply,
binder_size_t extra_buffers_size);
KPM_NAME("kpm-syscall-hook-demo");
KPM_VERSION("1.0.0");
KPM_LICENSE("GPL v2");
KPM_AUTHOR("bmax121");
KPM_DESCRIPTION("KernelPatch Module System Call Hook Example");
const char *margs = "function_pointer_hook";
typedef void (*binder_transaction_func_t)(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply,
binder_size_t extra_buffers_size);
//存储原始内核函数指针
static binder_transaction_func_t original_binder_transaction = NULL;
//备份内核函数指针
static binder_transaction_func_t backup_binder_transactionn = NULL;
//替换内核函数指针
static void replace_binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply, binder_size_t extra_buffers_size);
static void replace_binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
struct binder_transaction_data *tr, int reply,
binder_size_t extra_buffers_size) {
// todo 修改并为成功
// 调用原函数,保持 Binder 流程不被阻塞
backup_binder_transactionn(proc, thread, tr, reply, extra_buffers_size);
//这里调用original_binder_transaction会造成自己hook自己无限递归
// original_binder_transaction(proc, thread, tr, reply, extra_buffers_size);
}
static long syscall_hook_demo_init(const char *args, const char *event, void *__user reserved)
{
pr_info("kpm-syscall-hook-demo init ..., args: %s\n", margs);
//初始化 取内核函数指针
// original_do_filp_open = (typeof(do_filp_open_func_t))kallsyms_lookup_name("do_filp_open");
original_binder_transaction = (typeof(binder_transaction_func_t))kallsyms_lookup_name("binder_transaction");
pr_info("[kugua] kernel function original_binder_transaction addr: %llx\n", original_binder_transaction);
if (!margs) {
pr_warn("no args specified, skip hook\n");
return 0;
}
hook_err_t err = HOOK_NO_ERR;
//进行hook 参数: 原始指针 替换指针 备份指针
err = hook((void *)original_binder_transaction,
(void *)replace_binder_transaction,
(void **)&backup_binder_transactionn);
if (err) goto out;
out:
if (err) {
pr_err("hook original_do_filp_open error: %d\n", err);
} else {
pr_info("hook original_do_filp_open success\n");
}
return 0;
}
static long syscall_hook_control0(const char *args, char *__user out_msg, int outlen)
{
pr_info("syscall_hook control, args: %s\n", args);
return 0;
}
static long syscall_hook_demo_exit(void *__user reserved)
{
pr_info("kpm-syscall-hook-demo exit ...\n");
//卸载hook 恢复原始指针
unhook((void *)original_binder_transaction);
return 0;
}
KPM_INIT(syscall_hook_demo_init);
KPM_CTL0(syscall_hook_control0);
KPM_EXIT(syscall_hook_demo_exit);