转变为仅在内核留下Stub在外部加载KPM
This commit is contained in:
@@ -686,12 +686,6 @@ __maybe_unused int ksu_kprobe_init(void)
|
|||||||
rc = register_kprobe(&renameat_kp);
|
rc = register_kprobe(&renameat_kp);
|
||||||
pr_info("renameat kp: %d\n", rc);
|
pr_info("renameat kp: %d\n", rc);
|
||||||
|
|
||||||
#ifdef CONFIG_KPM
|
|
||||||
// KPM初始化状态
|
|
||||||
kpm_cfi_bypass_init();
|
|
||||||
// kpm_stack_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,11 +693,6 @@ __maybe_unused int ksu_kprobe_exit(void)
|
|||||||
{
|
{
|
||||||
unregister_kprobe(&prctl_kp);
|
unregister_kprobe(&prctl_kp);
|
||||||
unregister_kprobe(&renameat_kp);
|
unregister_kprobe(&renameat_kp);
|
||||||
#ifdef CONFIG_KPM
|
|
||||||
// KPM取消状态
|
|
||||||
kpm_cfi_bypass_exit();
|
|
||||||
// kpm_stack_exit();
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
obj-y += kpm.o
|
obj-y += kpm.o
|
||||||
obj-y += compact.o
|
obj-y += compact.o
|
||||||
obj-y += bypasscfi.o
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
#include <linux/kprobes.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/kallsyms.h>
|
|
||||||
|
|
||||||
/* CFI 检查函数符号 */
|
|
||||||
#define CFI_CHECK_FUNC "__cfi_check"
|
|
||||||
|
|
||||||
/* Kprobe 实例 */
|
|
||||||
static struct kprobe cfi_kp;
|
|
||||||
|
|
||||||
bool kpm_is_allow_address(unsigned long addr);
|
|
||||||
|
|
||||||
/*--------------------- kprobe 处理逻辑 ---------------------*/
|
|
||||||
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
unsigned long target_addr;
|
|
||||||
|
|
||||||
/* 从寄存器获取目标地址(架构相关) */
|
|
||||||
#if defined(__aarch64__)
|
|
||||||
target_addr = regs->regs[1]; // ARM64: 第二个参数在 X1
|
|
||||||
#elif defined(__x86_64__)
|
|
||||||
target_addr = regs->si; // x86_64: 第二个参数在 RSI
|
|
||||||
#else
|
|
||||||
#error "Unsupported architecture"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 根据自定义规则放行 */
|
|
||||||
if (kpm_is_allow_address(target_addr)) {
|
|
||||||
printk(KERN_INFO "CFI bypass at 0x%lx\n", target_addr);
|
|
||||||
#if defined(__aarch64__)
|
|
||||||
regs->regs[0] = 0; // 修改返回值:0 表示校验通过
|
|
||||||
#elif defined(__x86_64__)
|
|
||||||
regs->ax = 0; // x86 返回值在 RAX
|
|
||||||
#endif
|
|
||||||
return 0; // 跳过原始 CFI 检查
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; // 继续执行原始检查
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------- 模块初始化/卸载 ---------------------*/
|
|
||||||
int kpm_cfi_bypass_init(void)
|
|
||||||
{
|
|
||||||
unsigned long cfi_check_addr;
|
|
||||||
|
|
||||||
/* 动态查找 CFI 检查函数 */
|
|
||||||
cfi_check_addr = kallsyms_lookup_name(CFI_CHECK_FUNC);
|
|
||||||
if (!cfi_check_addr) {
|
|
||||||
printk(KERN_ERR "CFI check function not found\n");
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 初始化 kprobe */
|
|
||||||
memset(&cfi_kp, 0, sizeof(cfi_kp));
|
|
||||||
cfi_kp.addr = (kprobe_opcode_t *)cfi_check_addr;
|
|
||||||
cfi_kp.pre_handler = handler_pre;
|
|
||||||
|
|
||||||
/* 注册 kprobe */
|
|
||||||
if (register_kprobe(&cfi_kp) < 0) {
|
|
||||||
printk(KERN_ERR "Register kprobe failed\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_INFO "CFI bypass module loaded\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kpm_cfi_bypass_exit(void)
|
|
||||||
{
|
|
||||||
unregister_kprobe(&cfi_kp);
|
|
||||||
printk(KERN_INFO "CFI bypass module unloaded\n");
|
|
||||||
}
|
|
||||||
@@ -31,62 +31,17 @@ unsigned long sukisu_compact_find_symbol(const char* name);
|
|||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
|
||||||
const char* kpver = "0.10";
|
|
||||||
|
|
||||||
struct CompactAddressSymbol {
|
struct CompactAddressSymbol {
|
||||||
const char* symbol_name;
|
const char* symbol_name;
|
||||||
void* addr;
|
void* addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CompactAliasSymbol {
|
|
||||||
const char* symbol_name;
|
|
||||||
const char* compact_symbol_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CompactProxySymbol {
|
|
||||||
const char* symbol_name;
|
|
||||||
const char* compact_symbol_name;
|
|
||||||
void* cached_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct CompactAddressSymbol address_symbol [] = {
|
static struct CompactAddressSymbol address_symbol [] = {
|
||||||
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
||||||
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
||||||
{ "compat_copy_to_user", ©_to_user },
|
|
||||||
{ "compat_strncpy_from_user", &strncpy_from_user },
|
|
||||||
{ "kpver", &kpver },
|
|
||||||
{ "is_run_in_sukisu_ultra", (void*)1 }
|
{ "is_run_in_sukisu_ultra", (void*)1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct CompactAliasSymbol alias_symbol[] = {
|
|
||||||
{"compat_copy_to_user", "__arch_copy_to_user"}
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct CompactProxySymbol proxy_symbol[] = {
|
|
||||||
{"kf_strncat", "strncat", NULL },
|
|
||||||
{"kf_strlen", "strlen", NULL },
|
|
||||||
{"kf_strcpy", "strcpy", NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned long sukisu_find_proxy_symbol(const char* name) {
|
|
||||||
// 查找proxy符号
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < (sizeof(proxy_symbol) / sizeof(struct CompactProxySymbol)); i++) {
|
|
||||||
struct CompactProxySymbol* symbol = &proxy_symbol[i];
|
|
||||||
if(strcmp(name, symbol->symbol_name) == 0) {
|
|
||||||
if(symbol->cached_address == NULL) {
|
|
||||||
symbol->cached_address = (void*) kallsyms_lookup_name(symbol->compact_symbol_name);
|
|
||||||
}
|
|
||||||
if(symbol->cached_address != NULL) {
|
|
||||||
return (unsigned long) &symbol->cached_address;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long sukisu_compact_find_symbol(const char* name) {
|
unsigned long sukisu_compact_find_symbol(const char* name) {
|
||||||
int i;
|
int i;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
@@ -100,34 +55,13 @@ unsigned long sukisu_compact_find_symbol(const char* name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 如果符号名以 "kf_" 开头,尝试解析去掉前缀的部分 */
|
|
||||||
if (strncmp(name, "kf_", 3) == 0) {
|
|
||||||
addr = sukisu_find_proxy_symbol(name);
|
|
||||||
isFoundedProxy = 1;
|
|
||||||
if(addr != 0) {
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过内核来查
|
// 通过内核来查
|
||||||
addr = kallsyms_lookup_name(name);
|
addr = kallsyms_lookup_name(name);
|
||||||
if(addr) {
|
if(addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查不到就查查兼容的符号
|
|
||||||
for(i = 0; i < (sizeof(alias_symbol) / sizeof(struct CompactAliasSymbol)); i++) {
|
|
||||||
struct CompactAliasSymbol* symbol = &alias_symbol[i];
|
|
||||||
if(strcmp(name, symbol->symbol_name) == 0) {
|
|
||||||
addr = kallsyms_lookup_name(symbol->compact_symbol_name);
|
|
||||||
if(addr)
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isFoundedProxy) {
|
|
||||||
return sukisu_find_proxy_symbol(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(sukisu_compact_find_symbol);
|
||||||
|
|||||||
1296
kernel/kpm/kpm.c
1296
kernel/kpm/kpm.c
File diff suppressed because it is too large
Load Diff
@@ -4,14 +4,9 @@
|
|||||||
int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
int sukisu_handle_kpm(unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
||||||
int sukisu_is_kpm_control_code(unsigned long arg2);
|
int sukisu_is_kpm_control_code(unsigned long arg2);
|
||||||
|
|
||||||
int kpm_cfi_bypass_init(void);
|
|
||||||
void kpm_cfi_bypass_exit(void);
|
|
||||||
int kpm_stack_init(void);
|
|
||||||
void kpm_stack_exit(void);
|
|
||||||
|
|
||||||
// KPM控制代码
|
// KPM控制代码
|
||||||
#define CMD_KPM_CONTROL 28
|
#define CMD_KPM_CONTROL 28
|
||||||
#define CMD_KPM_CONTROL_MAX 34
|
#define CMD_KPM_CONTROL_MAX 35
|
||||||
|
|
||||||
// 控制代码
|
// 控制代码
|
||||||
|
|
||||||
@@ -46,6 +41,8 @@ void kpm_stack_exit(void);
|
|||||||
// error will return -1
|
// error will return -1
|
||||||
#define SUKISU_KPM_PRINT 34
|
#define SUKISU_KPM_PRINT 34
|
||||||
|
|
||||||
|
#define SUKISU_KPM_VERSION 35
|
||||||
|
|
||||||
|
|
||||||
/* A64 instructions are always 32 bits. */
|
/* A64 instructions are always 32 bits. */
|
||||||
#define AARCH64_INSN_SIZE 4
|
#define AARCH64_INSN_SIZE 4
|
||||||
|
|||||||
Reference in New Issue
Block a user