修改linux内核达到隐藏进程目的(2.6.28)

要求:

    

高级操作系统与分布式系统作业

pstop命令列出了unix中当前所有进程的相关信息,作业要求在linux中增加两个系统调用,功能如下:

    hide():执行此系统调用后,隐藏当前进程,即当前进程不能够被pstop命令查看到。

    unhide():执行此系统调用后,取消隐藏当前进程,即当前进程恢复正常,能够被pstop命令查看到。

解题思路:

    Ps命令和top命令从/proc文件系统中读取进程信息并显示出来。因此,如果一个进程的进程号没有在/proc文件系统中反映出来,则这个进程被“隐藏”了,“隐藏”进程在pstop命令的输出不出现。

2。修改linux的进程控制块task_struts,在进程控制块中增加一个字段:

    int hide;

    hide的值为1时,表示该进程被隐藏;为0时,表示该进程不被隐藏。

3。修改创建进程的相关代码,在进程创建时,置hide0;即进程在初始创建时(默认)不被隐藏。

4。在系统中增加系统调用hide(),其功能为:

     1)将进程控制块中的hide1

     2)删除/proc文件系统中该进程的相关目录项;

5。在系统中增加系统调用unhide(),其功能为:

     1)将进程控制块中的hide0

     2)增加/proc文件系统中该进程的相关目录项

具体做法:(实验内核版本2.6.28,)

    跟踪内核可知,proc目录下进程号目录是动态生成的,是在每次readdir,getdents时动态生成,所以从某种意义上说增加或删除/proc文件系统中该进程的相关目录项这种说法是不正确的。proc目录内容的填充函数是proc_pid_readdir(fs/proc/base.c)

int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)  //内核源码,修改前
{
 unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
 struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
 struct tgid_iter iter;
 struct pid_namespace *ns;

 if (!reaper)
  goto out_no_task;

 for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) { //这个for,填充self目录
  const struct pid_entry *p = &proc_base_stuff[nr];
  if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
   goto out;
 }

 ns = filp->f_dentry->d_sb->s_fs_info;
 iter.task = NULL;
 iter.tgid = filp->f_pos - TGID_OFFSET;
 for (iter = next_tgid(ns, iter);         
      iter.task;
      iter.tgid += 1, iter = next_tgid(ns, iter)) {  //这个for,根据系统内进程动态添加子进程号目录,也正是我们需要修改的函数
  filp->f_pos = iter.tgid + TGID_OFFSET;
  if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
   put_task_struct(iter.task);
   goto out;
  }
 }
 filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
out:
 put_task_struct(reaper);
out_no_task:
 return 0;
}
将proc_pid_readdir函数中的for循环修改为

 for (iter = next_tgid(ns, iter);         
      iter.task;
      iter.tgid += 1, iter = next_tgid(ns, iter)) {  //这个for,根据系统内进程动态添加子进程号目录,也正是我们需要修改的函数

if(!iter.task->hide){
  filp->f_pos = iter.tgid + TGID_OFFSET;
  if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
   put_task_struct(iter.task);
   goto out;
  }

}
 }

修改task_struct 添加hide字段(include/linux/sched.h)

struct task_struct{

    ...//现有字段

    int hide;//添加hide字段,切忌不要在最开始添加,因为开始的字段的偏移量已固定,内核中其他部分已直接引用,如果在最开始添加,将导致现有代码不能正常工作

}

修改进程创建代码,初始化时置hide字段为0,修改copy_process函数(kernel/fork.c)

p = dup_task_struct(current);
 if (!p)
  goto fork_out;

p->hide=0;//添加

 rt_mutex_init_task(p);

最后一步就是添加系统调用了,

修改kernel/sys.c

添加

asmlinkage long sys_hide()

{

current->hide=1;

return 0;

}

asmlinkage long sys_unhide()

{

current->hide=0;

return 0;

}

修改arch/x86/asm/include/unistd_32.h

#define __NR_inotify_init1 332
#define __NR_hide 333
#define __NR_unhide 334

#ifdef __KERNEL__

修改arch/x86/kernel/syscall_table_32.s

.long sys_dup3   /* 330 */
 .long sys_pipe2
 .long sys_inotify_init1
 .long sys_hide
 .long sys_unhide

 

重新编译内核...OK....

实验验证:

1 test_hide.c

#include <stdio.h>

int main(){
 int pid=getpid();
 char command[80];
 sprintf(command,"ps aux|grep %d\n",pid);
 printf("-------------------------------\n");
 system(command);
 printf("-------------------------------\n");
 asm volatile(\
    "int $0x80"\
    ::"a"(333)); // 执行333号系统调用即sys_hide

 system(command);
 asm volatile(\
    "int $0x80"\
    ::"a"(334));
 printf("-------------------------------\n");
 system(command);
 printf("-------------------------------\n");
 return 0;
}

2 运行,查看实验结果



posted on 2010-12-14 15:21 lstar 阅读(3098) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

常用链接

留言簿

文章档案

搜索

最新评论