荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: cycker (快过年吧.我想回家), 信区: Linux
标 题: Linux 可卸载内核模块完全指南(十二)(转寄)[转载]
发信站: 荔园晨风BBS站 (Thu Jan 2 18:23:51 2003), 站内信件
【 以下文字转载自 cycker 的信箱 】
【 原文由 xiaofong@bbs.pku.edu.cn 所发表 】
发信人: chenhao (努力学习), 信区: Linux
标 题: Linux 可卸载内核模块完全指南(十二)
发信站: 北大未名站 (2000年11月20日01:21:19 星期一) , 转信
第二部分 渐入佳境
2.9 使我们的LKM不可见,而且不可卸载
现在我们该开始谈谈我们最为重要和有趣的部分了,这个想法起源于plaguez的发表于Phr
ack的LKM(其他的一些人,像Solar Designer,在过去讨论过这些......
到目前为止,我们可以隐藏文件,进程,目录和任何我们想隐藏的.但是我们不能隐藏我们自
己的LKM.加载一个LKM并且看一眼/proc/modules.有很多方法我们可以解决这个问题.第一
个方案我们可以隐藏文件的一部分(见2.4.3).这会很易于实现.但是还有一个更好更安全的
一个方法.使用这个技术你必须截获sys_query_module(...)系统调用.一个关于这个实现的
简单例子可以看A-b.
正如我在1.1中解释的,一个模块最后是通过一个init_module(...)系统调用来开始初始化
函数的.init_module获得一个参数:struct mod_routines *routines.这个结构包含着加载
这个模块的十分重要的信息.我们有可能通过操纵这些信息来使得我们的模块没有名字和引
用记数.在此之后,系统就不会在/proc/modules里面显示我们的LKM了.因为他会忽略没有名
字和引用记数为0的LKMs.下面的代码显示了如何获得mod_routines的部分信息,以及如何隐
藏模块.
/*来自Phrack&AFHRM*/
int init_module()
{
register struct module *mp asm("%ebp");
//或者任何他在的寄存器
*(char*)mp->name=0;
mp->size=0;
mp->ref=0;
...
这段代码代码基于这样的事实:gcc并不控制ebp寄存器.因为我们需要他来找到正确的内存
位置.在找到这个结构以后我们就可以设置结构的名字和引用记数为0.这会使得我们的模块
不可见和不可卸载.因为你只可以卸载kernel知道的LKM.但是我们的模块是kernel不知道的
.
记住这个技巧只有当gcc不改变寄存器的时候才有用.因为你需要他来存取结构.你必须使用
如下的选项:
#gcc -c -O3 -fomit-frame-pointer module.c
fomit-frame-pointer告诉gcc不要为那些不需要的函数保存页面指针.这会使得我们的寄存
器在调用init_module以后保持不变.因此我们可以存取到结构.依我看来这时最重要的技巧
,因为他使得我们可以开发隐藏的和不可卸载的LKMs.
2.10 其他的入侵kerneld进程的方法
在2.8中你看到了一种入侵kerneld的方法.他帮助我们传播了LKM传染者.他也对我们的LKM
后门十分有用.(见2.5.1).假定socketcall载入一个系统模块,而不是打开一个后门或者运
行一个shellscript或者程序.你可以加载一个模块在paswd或者inetd.conf里面加一些入口
.在加载第二个LKM以后你就有很多可能性来改变系统文件.再一次的,只要你有创造力....
2.11 如何检查当前的我们的LKM
我们学习了很多方法来使我们的模块逃避系统的检查.因此假如你自己编程在系统中用LKM
中实现一个漂亮的后门;就像一些pingd,www远程shell,shell,...这样的的东西.当你登陆
到那个系统以后,你自己怎么检查这些东西是否还运行呢?假定你登陆到了这个系统,然而你
的LKM并没有被加载(因此不能隐藏你的进程),系统管理员正等着你呢.因此当你开始在那个
系统中进行你的工作时,(比如说读你自己的纪录,检查一些邮件等等),每一步都会被管理员
监视着.没有什么好的解决方法,我们通过一个简单的检查来确信我们的LKM正在运行。
我觉得下面的方法是一个好的解决方案(尽管也有很多其他的好的方法):
在你的模块中实现一个简单的系统调用
写一个小的用户空间的程序来检查这个系统调用
下面是一个实现了我们的‘检查’的系统调用的模块:
#define MODULE
#define __KERNEL__
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <asm/fcntl.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <sys/mman.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/malloc.h>
#define SYS_CHECK 200
extern void* sys_call_table[];
int sys_check()
{
return 666;
}
int init_module(void)
/*初始化模块*/
{
sys_call_table[SYS_CHECK]=sys_check;
return 0;
}
void cleanup_module(void)
/*卸载模块*/
{}
如果你通过在eax设置200进行一个系统调用,你应该会得到一个返回值666。因此我们的用
户空间的程序可以这样检查:
#include <linux/errno.h>
#include <sys/syscall.h>
#include <errno.h>
extern void *sys_call_table[];
int check()
{
__asm__("movl $200,%eax
int $0x80");
}
main()
{
int ret;
ret = check();
if (ret!=666)
printf("Our module is *not* present !!\n");
else
printf("Our module is present, continue...\n");
}
在我看来,这是最简单的检查我们的LKM的方法之一。不妨试试。
--
※ 来源:.北大未名站 bbs.pku.edu.cn [FROM: 162.105.45.129]
--
※ 转寄:·北大未名站 bbs.pku.edu.cn·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.36.220]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店