APatch 中文文档 下载 App

Syscall 表 Hook — 拦截系统调用最直接的方式

什么是 Syscall 表 Hook

Linux 内核里有一个全局数组叫 sys_call_table——每个索引对应一个系统调用号,数组元素指向该 syscall 的内核实现函数。syscall-table-hook 就是修改这个数组的某个条目,让它指向你自己的处理函数。

原 sys_call_table:[read_ptr, write_ptr, open_ptr, close_ptr, ...]

syscall-table-hook open 后:[read_ptr, write_ptr, my_open_ptr, close_ptr, ...]
                                                      ↑ 指向你的函数

当用户态程序执行 open() 系统调用时,CPU 陷入内核态,内核根据 syscall 号查 sys_call_table,找到你装的 hook 函数并执行。

和 Inline-Hook 的区别

维度Syscall-Table-HookInline-Hook
修改位置sys_call_table 数组条目目标函数开头的机器指令
可 hook 的目标只能 hook syscall 处理函数(所有 syscall 都有表项)任何内核函数
实现复杂度简单(替换指针)复杂(处理指令重定位、trampoline)
适用场景拦截用户态程序发起的系统调用拦截任意内核路径

syscall-table-hook 是用户态 → 内核态 边界上最直接的拦截点。所有 App 操作文件、创建进程、访问网络都走 syscall——在这里做 hook 能覆盖所有 App 的行为。

典型用途

隐藏 Root 文件

最常见的用法:hook openat 或 access syscall。任何 App 尝试 open("/sbin/su") 或 access("/data/adb/..."),syscall-table-hook 直接让它返回"文件不存在"。

修改 syscall 返回值

某些 root 检测 App 会检查 syscall 的 errno 或特定返回值——KPM 可以在 hook 里修改这些值。

记录系统调用

调试用途——hook 所有 syscall 然后记录调用者、参数、返回值到内核日志,用于分析 root 检测逻辑。

KernelPatch 的 API

和 inline-hook 一样,KernelPatch 框架也封装了 syscall-table-hook 的 API:

struct kp_syscall_hook *hook = kp_syscall_hook_create(__NR_openat, my_openat_handler);
kp_syscall_hook_install(hook);

__NR_openat 是 syscall 号(ARM64 上 openat 的号是 56)。hook 处理函数签名和原 syscall 一致。

关于 ptrace 和 seccomp

现代 Android root 检测还可能用 ptrace 或 seccomp 来限制系统调用——syscall-table-hook 在这两类场景下都能生效,因为 hook 点在 ptrace/seccomp 之前。

性能影响

syscall 是用户态程序和内核最频繁的交互——每个文件操作、每次进程调度都涉及 syscall。syscall-table-hook 的单次开销很小(只是多一次指针跳转),但如果 hook 里做了复杂逻辑(比如路径匹配、文件 I/O),会显著拖慢系统性能。

建议:hook 里只做简单的判断,复杂逻辑放到异步处理。

局限性

syscall-table-hook 只覆盖用户态发起的 syscall——内核内部的操作(比如内核自己打开文件)不经过 sys_call_table,所以 hook 不到。这时候就需要 inline-hook 了。