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);