四保护重要进程 进程是操作系统的动态入口内核里有两个特殊进程进程ID (swapd) 和进程ID (init)Init进程是在系统启动的时候所有进程的父进程 不可杀死的进程 就象你可以看到是否有人要夺得root特权一样我们可以很容易的杀死那些该内核发送特别信号的进程为了杀死一个进程你必须得到进程的ID然后用kill命令来杀死它 系统杀死进程的调用是kill是在内核里的sys_kill()命令里的调用 让我们看看LIDS的保护代码 在/usr/src/linux/kernel/signalc里 asmlinkage int sys_kill(int pid int sig) { struct siginfo info; #ifdef CONFIG_LIDS_INIT_CHILDREN_LOCK pid_t this_pid; int i; #ifdef CONFIG_LIDS_ALLOW_KILL_INIT_CHILDREN if (!(current>flags & PF_KILLINITC)) #endif if (lids_load && lids_local_load && LIDS_FISSET(lids_flagsLIDS_FLAGS_LOCK_INIT_CHILDREN)) { this_pid = pid>?pid:pid; for(i=;i if( this_pid == lids_protected_pid[i]) { lids_security_alert(Try to kill pid=%dsig=%dnpidsig); return EPERM; } } } #endif } 你可以在内核里看到两个标签CONFIG_LIDS_INIT_CHILDREN_LOCK 和CONFIG_LIDS_ALLOW_KILL_INIT_CHILDREN 在CONFIG_LIDS_INIT_CHILDREN_LOCK的开启状态LIDS能保护初使的运行程序如如果你在系统里运行inetd程序你可以在隐藏内核前运行它然后你还可以杀死它但是一些人如果telnet到你的机器inetd就会创造子进程来为用户服务这个子进程不会被LIDS保护因为用户在任何时候退出和杀死程序 隐藏进程 另外一个保护进程的方法就是隐藏进程当一个黑客危机你的系统他会登陆然后会看看有没有一些已知的进程在监视它然后他就杀死它如果你隐藏了这个功能的进程黑客就不会知道进程的所有情况并且你可以记录他在你系统上做的任何事情 如何隐藏进程 为了隐藏进程你必须在配置内核的时候提供一个完全的路径名 当内核启动的时候LIDS会访问文件结点到一个叫proc_to_hide[]的结构里 在include/linux/schedh里 #ifdef CONFIG_LIDS_HIDE_PROC #define PF_HIDDEN x /* Hidden process */ #endif /* in fs/lidsc */ #ifdef CONFIG_LIDS_HIDE_PROC struct allowed_ino proc_to_hide[LIDS_MAX_ALLOWED]; int last_hide=; #endif /* in fs/lidsc init_vfs_security() fill up the hidden process in proc_to_hide[] */ #ifdef CONFIG_LIDS_HIDE_PROC lids_fill_table(proc_to_hide&last_hideLIDS_MAX_ALLOWEDCONFIG_LIDS_HIDDEN_PROC_PATH); #endif PF_HIDDEN是否用户可以用显示进程的命令(如ps –a)来显示和检查进程如果一个进程被LIDS隐藏当他执行的时候进程就会得到一个PF_HIDDEN的属性然后当系统输出系统进程信息到用户的时候它就会可以检查当前输出进程是否有PF_HIDDEN标志如果发现了它就不会输出这个进程的信息 在in fs/execc int do_execve(char * filename char ** argv char ** envp struct pt_regs * regs) { if (retval >= ) { #ifdef CONFIG_LIDS_HIDE_PROC if (lids_search_proc_to_hide(dentry>d_inode)) current>flags |= PF_HIDDEN; 因为每一个linux的进程都有一个在/proc文件系统的入口我们为了隐藏进程也需要修改proc的文件入口 在fs/proc/rootc static struct dentry *proc_root_lookup(struct inode * dir struct dentry * dentry) { inode = NULL; #ifdef CONFIG_LIDS_HIDE_PROC if ( pid && p && (! ((p>flags & PF_HIDDEN) && lids_load && lids_local_load)) ) { #else if (pid && p) { #endif unsigned long ino = (pid >> ) + PROC_PID_INO; inode = proc_get_inode(dir>i_sb ino &proc_pid); if (!inode) return ERR_PTR(EINVAL); inode>i_flags|=S_IMMUTABLE; } } 然后如果进程被PF_HIDDEN标记它就不会在proc文件系统里显示 五密封内核 我们需要在系统启动的时候做一些必要的操作但是我们也需要在系统运行的时候保护它们 例如我们需要象内核里插入一些需要的模块但是我们不希望在系统运行的时候插入任何模块因为那样会十分危险如何解决这个问题呢?这里就有一些密封的方法我们可以在系统启动的时候做我们任何想做的事情然后我们就密封内核然后我们就不能做那些以前在没有密封的时候可以做的事情用密封的方法我们可以用模块来解决问题我们可以在密封前向内核里插入我们想要的模块在密封后我们就不可以在内核里插入或是删除任何模块 用LIDS密封内核 为了密封内核我们可以用下面的LIDS命令 #lidsadm –I CAP_xxx… 它们可以放到脚本里让系统启动的时候就执行它具体你们可以看我以前在linuxbyte和chinabyte发表的文章LIDS是通过/proc/sys/lids/locks和内核通讯的 当你密封了内核lidsadm是调用lidsadmc的lids_init()的调用 #define LIDS_LOCKS /proc/sys/lids/locks void lids_init(int optind int argc char *argv[]) { if ((fd=open(LIDS_LOCKSO_RDWR)) == ) { perror(open); exit_error ( can open LIDS_LOCKS); } if (read(fd&lockssizeof(lids_locks_t))==) { perror(read); exit_error ( can read LIDS_LOCKS); } lids_set_caps(optindargcargv&locks); locksmagic=LIDS_MAGIC_; if (write(fd&lockssizeof(lids_locks_t))==) { perror(write); exit_error ( can write LIDS_LOCKS); } } 这个系统调用在LIDS_LOCKS生成新的变量loks内核会通过lids_proc_locks_sysctl()命令来读取它Lids_proc_locks_sysctl也会从用户区完全检查并读取它然后改变密封的变量lids_first_time为 让我们看看lids_proc_locks_sysctl()这个函数会在用户读写/proc/sys/lids/locks的时候调用 int lids_proc_locks_sysctl(ctl_table *table int write struct file *filp void *buffer size_t *lenp int conv int op) { /* first: check the terminal and the program which access the sysctl */ #ifndef CONFIG_LIDS_REMOTE_SWITCH if (current>tty && (current>tty>drivertype != ) ) { lids_security_alert(Try to %s locks sysctl (unauthorized terminal) write ? write : read); return EPERM; } #endif /* second: check wether it is not a timeout period after two many failed attempts */ if (write) { /* Third : check what is submitted (size magics passwd) */ if (*lenp != sizeof(lids_locks_t)) { lids_security_alert(Try to feed locks sysctl with garbage); return EINVAL; } if (copy_from_user(&locksbuffersizeof(lids_locks_t))) return EFAULT; if ((lids_first_time) && (!lockspasswd[])) { number_failed=; if (lids_process_flags(locksflags)) { cap_bset=lockscap_bset; |