实验环境

Ubuntu 14.04.5 LTS

Linux - 4.15.6

为单个文件进程补丁操作

  1. 在桌面 Desktop 建立文件夹 patch ,作为实验用,然后进入patch 文件夹。建立测试文件 test0test1

    我们的目标:给 test0 打补丁 test1.patch ,使 test0test1 内容一致:

    注:使用 diff 创建补丁 test1.patch ;源文件 test0 ;目标文件 test1 ;因为单个文件,所以不需要 -r 选项。选项顺序没有关系,即可以是 -uN ,也可以是 -Nu

  2. 给源文件 test0 打补丁与恢复:

    注:-pNpatch 文件中列出的文件名有关,N 表示拿掉几个斜线(目录层级);

    -E 选项说明如果发现了空文件,那么就删除它;

    -R 选项说明在补丁文件中的“新”文件和“旧”文件现在要调换过来了(实际上就是给新版本打补丁,让它变成老版本)。

为多个文件进行补丁操作

  1. 在上文中的 /Desktop/patch 文件夹下创建测试文件夹 prj0

    注:在patch文件夹下,创建文件夹prj0,并把test0拷入,再在文件夹prj0下创建文件prj0name;创建文件夹prj1,并把test1拷入,再在文件夹prj1下创建文件prj1name。然后返回patch目录下。

  2. 创建补丁

    diff的功能就是用来比较两个文件的不同,然后记录下来,也就是所谓的diff补丁。语法格式:

    diff 【选项】 源文件(夹) 目的文件(夹)

    就是要给源文件(夹)打个补丁,使之变成目的文件(夹),术语也就是“升级”。下面介绍三个最为常用选项:

    -r 是一个递归选项,设置了这个选项,diff会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,包括子目录文件。

    -N 选项确保补丁文件将正确地处理已经创建或删除文件的情况。

    -u 选项以统一格式创建补丁文件,这种格式比缺省格式更紧凑些。

    注:把所有prj1目录下的文件,打补丁到prj0目录下。

    注:复制 prj1.patch 到 prj0 文件夹下;

    ​ 进入 prj0 目录下,打补丁,-p1 表示 prj0/test0

    下面变通一下,不复制 .patch 文件,执行:

    总结:

    • 单个文件

      diff -uN from_file to_file > to_file.patch

      patch -p0 < to_file.patch

      patch -RE -p0 < to_file.patch

    • 多个文件

      diff -uNr from_docu to_docu > to_docu.patch

      patch -p1 < to_docu.patch

      patch -R -p1 < to_docu.patch

创建显示系统进程信息的 proc 模块

  • tasklist.c与修改后的 tasklist.c(我们下边命名为:tasklist1.c) 生成补丁

    • 首先看一下系统中 proc 目录下是否有 tasklist 这个文件

    • 创建tasklist.ctasklist1.cMakefile 文件:

      tasklist.c 代码:

      //-------------------------------------------------------------------
      //  tasklist.c: 本内核文件创建一个proc伪文件,'/proc/tasklist'
      //  通过如下命令可以显示系统中所有进程的部分信息
      //  注意:Makefile文件必须正确放置在当前目录下。
      //  编译命令: make
      //  内核模块添加:$sudo insmod tasklist.ko
      //  添加内核模块后读取并信息tasklist内核信息: $ cat /proc/tasklist
      //  内核模块删除:$sudo rmmod tasklist
      //  NOTE: Written and tested with Linux kernel version 4.15.6
      //  strace函数可用于追踪系统调用,命令格式如下所示:
      //  $ strace cat /proc/tasklist
      //-------------------------------------------------------------------
      
      #include <linux/module.h>   // for init_module()
      #include <linux/proc_fs.h>  // for create_proc_info_entry()
      #include <linux/sched/task.h>   // for init_task
      #include <linux/seq_file.h> // for sequence files
      #include <linux/slab.h>       // for kzalloc, kfree
      #include <linux/sched/signal.h>   //for next_task
      char modname[] = "tasklist";
      struct task_struct  *task;
      int  taskcounts=0;          // 'global' so value will be retained
      
      static void * my_seq_start(struct seq_file *m, loff_t *pos)
      {
         ///printk(KERN_INFO"Invoke start\n");   //可以输出调试信息
         if ( *pos == 0 )  // 表示遍历开始
         {
             task = &init_task;   //遍历开始的记录地址
             return &task;   //返回一个非零值表示开始遍历
        }
        else //遍历过程中
        {
          if (task == &init_task )    //重新回到初始地址,退出
              return NULL;
          return (void*)pos   ;//否则返回一个非零值
        }
      }
      static int my_seq_show(struct seq_file *m, void *v)
      {//获取进程的相关信息
        //printk(KERN_INFO"Invoke show\n");
        //输出进程序号
        seq_printf( m,  "#%-3d\t ", taskcounts++ );
        //输出进程pid?
        //输出进程state?
        //输出进程名称(comm)?
        seq_puts( m, "\n" );
        return 0;
      }
      
      static void * my_seq_next(struct seq_file *m, void *v, loff_t *pos)
      {
        //printk(KERN_INFO"Invoke next\n");
        (*pos)++;
        //task指向下一个进程?
        return NULL;
      
      }
      static void my_seq_stop(struct seq_file *m, void *v)
      {
          //printk(KERN_INFO"Invoke stop\n");
          // do nothing
      }
      
      static struct seq_operations my_seq_fops = {//序列文件记录操作函数集合
              .start  = my_seq_start,
              .next   = my_seq_next,
              .stop   = my_seq_stop,
              .show   = my_seq_show
      };
      
      static int my_open(struct inode *inode, struct file *file)
      {
          return seq_open(file, &my_seq_fops); //打开序列文件并关联my_seq_fops
      }  
      
      static const struct file_operations my_proc =
      {  //proc文件操作函数集合
          .owner      = THIS_MODULE,
          .open       = my_open,
          .read       = seq_read,
          .llseek     = seq_lseek,
          .release    = seq_release
      }; 
      
      int __init my_init( void )
      {
          struct proc_dir_entry* my_proc_entry;
          printk( "<1>\nInstalling \'%s\' module\n", modname );
          my_proc_entry = proc_create(modname, 0x644, NULL, &my_proc);//生成proc文件
          if (NULL == my_proc_entry)
          {
              return -ENOMEM;
          }
          return  0;  //SUCCESS
      }
      
      void __exit my_exit( void )
      {
          remove_proc_entry( modname, NULL );//删除proc文件
          printk( "<1>Removing \'%s\' module\n", modname );
      }
      
      module_init(my_init);
      module_exit(my_exit);
      MODULE_LICENSE("GPL"); 

      tasklist1.c 代码:

      //-------------------------------------------------------------------
      //  tasklist.c: 本内核文件创建一个proc伪文件,'/proc/tasklist'
      //  通过如下命令可以显示系统中所有进程的部分信息
      //  注意:Makefile文件必须正确放置在当前目录下。
      //  编译命令: make
      //  内核模块添加:$sudo insmod tasklist.ko
      //  添加内核模块后读取并信息tasklist内核信息: $ cat /proc/tasklist
      //  内核模块删除:$sudo rmmod tasklist
      //  NOTE: Written and tested with Linux kernel version 4.15.6
      //  strace函数可用于追踪系统调用,命令格式如下所示:
      //  $ strace cat /proc/tasklist
      //-------------------------------------------------------------------
      
      #include <linux/module.h>   // for init_module()
      #include <linux/proc_fs.h>  // for create_proc_info_entry()
      #include <linux/sched/task.h>   // for init_task
      #include <linux/seq_file.h> // for sequence files
      #include <linux/slab.h>       // for kzalloc, kfree
      #include <linux/sched/signal.h>   //for next_task
      char modname[] = "tasklist";
      struct task_struct  *task;
      int  taskcounts=0;          // 'global' so value will be retained
      
      static void * my_seq_start(struct seq_file *m, loff_t *pos)
      {
         ///printk(KERN_INFO"Invoke start\n");   //可以输出调试信息
         if ( *pos == 0 )  // 表示遍历开始
         {
             task = &init_task;   //遍历开始的记录地址
             return &task;   //返回一个非零值表示开始遍历
        }
        else //遍历过程中
        {
          if (task == &init_task )    //重新回到初始地址,退出
              return NULL;
          return (void*)pos   ;//否则返回一个非零值
        }
      }
      static int my_seq_show(struct seq_file *m, void *v)
      {//获取进程的相关信息
        //printk(KERN_INFO"Invoke show\n");
        //输出进程序号
        seq_printf( m,  "#%-3d\t ", taskcounts++ );
        //输出进程pid?
        seq_printf( m, "%5d\t", task->pid );
        //输出进程state?
        seq_printf( m, "%lu\t", task->state );
        //输出进程名称(comm)?
        seq_printf( m, "%-15s ", task->comm );
        seq_puts( m, "\n" );
        return 0;
      }
      
      static void * my_seq_next(struct seq_file *m, void *v, loff_t *pos)
      {
        //printk(KERN_INFO"Invoke next\n");
        (*pos)++;
        //task指向下一个进程?
        task = next_task(task);
        return NULL;
      
      }
      static void my_seq_stop(struct seq_file *m, void *v)
      {
          //printk(KERN_INFO"Invoke stop\n");
          // do nothing
      }
      
      static struct seq_operations my_seq_fops = {//序列文件记录操作函数集合
              .start  = my_seq_start,
              .next   = my_seq_next,
              .stop   = my_seq_stop,
              .show   = my_seq_show
      };
      
      static int my_open(struct inode *inode, struct file *file)
      {
          return seq_open(file, &my_seq_fops); //打开序列文件并关联my_seq_fops
      }  
      
      static const struct file_operations my_proc =
      {  //proc文件操作函数集合
          .owner      = THIS_MODULE,
          .open       = my_open,
          .read       = seq_read,
          .llseek     = seq_lseek,
          .release    = seq_release
      }; 
      
      int __init my_init( void )
      {
          struct proc_dir_entry* my_proc_entry;
          printk( "<1>\nInstalling \'%s\' module\n", modname );
          my_proc_entry = proc_create(modname, 0x644, NULL, &my_proc);//生成proc文件
          if (NULL == my_proc_entry)
          {
              return -ENOMEM;
          }
          return  0;  //SUCCESS
      }
      
      void __exit my_exit( void )
      {
          remove_proc_entry( modname, NULL );//删除proc文件
          printk( "<1>Removing \'%s\' module\n", modname );
      }
      
      module_init(my_init);
      module_exit(my_exit);
      MODULE_LICENSE("GPL"); 

      Makefile 代码:

      ifneq   ($(KERNELRELEASE),)
      obj-m   := tasklist.o 
      
      else
      KDIR    := /lib/modules/$(shell uname -r)/build
      PWD := $(shell pwd)
      default:
          $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
          rm -r -f .tmp_versions *.mod.c .*.cmd *.o *.symvers 
      
      endif
    • tasklist.c 打补丁 tasklist1.patch

    • ~/Desktop/module_test 文件夹下,编译:

    • 模块 tasklist.ko 已经添加入内核,现在可以查看 tasklist 文件的内核信息了:

  • 通过模块传参,传入进程名隐藏相应进程。

    • 卸载模块 tasklist.ko

    • ~/Desktop/module_test 目录下,新建如下 tasklist2.c 目标文件:

      //-------------------------------------------------------------------
      //  tasklist.c: 本内核文件创建一个proc伪文件,'/proc/tasklist'
      //  通过如下命令可以显示系统中所有进程的部分信息
      //  注意:Makefile文件必须正确放置在当前目录下。
      //  编译命令: make
      //  内核模块添加:$sudo insmod tasklist.ko
      //  添加内核模块后读取并信息tasklist内核信息: $ cat /proc/tasklist
      //  内核模块删除:$sudo rmmod tasklist
      //  NOTE: Written and tested with Linux kernel version 4.15.6
      //  strace函数可用于追踪系统调用,命令格式如下所示:
      //  $ strace cat /proc/tasklist
      //-------------------------------------------------------------------
      
      #include <linux/module.h>   // for init_module()
      #include <linux/proc_fs.h>  // for create_proc_info_entry()
      #include <linux/sched/task.h>   // for init_task
      #include <linux/seq_file.h> // for sequence files
      #include <linux/slab.h>       // for kzalloc, kfree
      #include <linux/sched/signal.h>   //for next_task
      #include <linux/string.h>
      char modname[] = "tasklist";
      struct task_struct  *task;
      int  taskcounts=0;          // 'global' so value will be retained
      
      static char* var;
      module_param(var,charp,0644);
      
      static void * my_seq_start(struct seq_file *m, loff_t *pos)
      {
         ///printk(KERN_INFO"Invoke start\n");   //可以输出调试信息
         if ( *pos == 0 )  // 表示遍历开始
         {
             task = &init_task;   //遍历开始的记录地址
             return &task;   //返回一个非零值表示开始遍历
        }
        else //遍历过程中
        {
          if (task == &init_task )    //重新回到初始地址,退出
              return NULL;
          return (void*)pos   ;//否则返回一个非零值
        }
      }
      static int my_seq_show(struct seq_file *m, void *v)
      {//获取进程的相关信息
        //printk(KERN_INFO"Invoke show\n");
        //输出进程序号
        seq_printf( m,  "#%-3d\t ", taskcounts++ );
        //输出进程pid?
        seq_printf( m, "%5d\t", task->pid );
        //输出进程state?
        seq_printf( m, "%lu\t", task->state );
        //输出进程名称(comm)?
        seq_printf( m, "%-15s ", task->comm );
        seq_puts( m, "\n" );
        return 0;
      }
      
      static void * my_seq_next(struct seq_file *m, void *v, loff_t *pos)
      {
        //printk(KERN_INFO"Invoke next\n");
        (*pos)++;
        //task指向下一个进程?
        task = next_task(task);
        if(!strcmp(task->comm,var))
      {
        task = next_task(task);
      }
        return NULL;
      
      }
      static void my_seq_stop(struct seq_file *m, void *v)
      {
          //printk(KERN_INFO"Invoke stop\n");
          // do nothing
      }
      
      static struct seq_operations my_seq_fops = {//序列文件记录操作函数集合
              .start  = my_seq_start,
              .next   = my_seq_next,
              .stop   = my_seq_stop,
              .show   = my_seq_show
      };
      
      static int my_open(struct inode *inode, struct file *file)
      {
          return seq_open(file, &my_seq_fops); //打开序列文件并关联my_seq_fops
      }  
      
      static const struct file_operations my_proc =
      {  //proc文件操作函数集合
          .owner      = THIS_MODULE,
          .open       = my_open,
          .read       = seq_read,
          .llseek     = seq_lseek,
          .release    = seq_release
      }; 
      
      int __init my_init( void )
      {
          struct proc_dir_entry* my_proc_entry;
          printk( "<1>\nInstalling \'%s\' module\n", modname );
          printk( KERN_INFO"var=%s\n", var );
          my_proc_entry = proc_create(modname, 0x644, NULL, &my_proc);//生成proc文件
          if (NULL == my_proc_entry)
          {
              return -ENOMEM;
          }
          return  0;  //SUCCESS
      }
      
      void __exit my_exit( void )
      {
          remove_proc_entry( modname, NULL );//删除proc文件
          printk( "<1>Removing \'%s\' module\n", modname );
      }
      
      module_init(my_init);
      module_exit(my_exit);
      MODULE_LICENSE("GPL"); 

    • tasklist.c 打补丁 tasklist2.patch

    • ~/Desktop/module_test 文件夹下:

      $ make
      $ sudo insmod tasklist.ko var = "init"
      $ cat /proc/tasklist

      注: init 进程就被隐藏了。

      注意:insmod 命令后一定要给 var 传递参数,否则可能会出现下面问题

      解决办法是重启系统,重新加在模块(执行 insmod 命令)并记得给 var 传递参数。

    • 卸载 tasklist.ko 模块,重新 insmod 进内核,var 赋个空字符串。init 进程就显示了:

    • 上述办法是在执行 insmod 命令时,给变量 var (进程名)赋值。归根结底是 tasklist.c 文件中变量 var 未初始化造成的,另一种办法是初始化 tasklist.c 文件中的变量 var 。比如:

      static char* var; // 将此行替换为下面这行
      static char* var = " "; // 给 var 初始化为空串

      然后:

      $ make
      $ sudo insmod tasklist.ko // 此处可不给var传参,因为代码中已经初始化了
      $ cat /proc/tasklist // 显示全部进程
      $ sudo rmmod tasklist.ko // 卸载tasklist.ko模块
      $ sudo insmod tasklist.ko var = "输入你想隐藏的进程名"
      $ cat /proc/tasklist // 发现指定的进程已被隐藏,显示隐藏的进程请看前一步

Reference

Linux下使用diff和patch制作及打补丁(已经实践可行!)

patch-test-and-proc的更多相关文章

  1. 利用 SysRq 键排除和诊断系统故障

    说白了,SysRq手动触发而不用命令, /proc/sysrq-trigger 这个是通过命令接口 实验:LINUX窗口下 ,CTRL+ALT+F1,切换到TTY1,在文本模式下,按下 ALT+Sys ...

  2. oracle 数据库安装环境,需要大汇总

     Oracle Database (RDBMS) on Unix AIX,HP-UX,Linux,Mac OS X,Solaris,Tru64 Unix Operating Systems Ins ...

  3. 每日一小时linux(1)--sysRq

    参考https://www.ibm.com/developerworks/cn/linux/l-cn-sysrq/index.html SysRq 是什么 你是否遇到服务器不能通过 SSH 登录,也不 ...

  4. 为什么ps中CPU占用率会有超出%100的现象?

    前面的关于ps中的%CPU的含义一文已经介绍了CPU占用率的含义,那么为什么有时会在ps的输出中看到CPU占用率超出%100的现象呢?我们知道在/proc目录下每个进程都会有一个以它的PID以名字的目 ...

  5. Windows X64 Patch Guard

    先简单介绍下PatchGuard ,摘自百度百科 PatchGuard就是Windows Vista的内核保护系统,防止任何非授权软件试图“修改”Windows内核,也就是说,Vista内核的新型金钟 ...

  6. Android内核sys_setresuid() Patch提权(CVE-2012-6422)

    让我们的Android ROOT,多一点套路. 一.简单套路 CVE-2012-6422的漏洞利用代码,展示了另一种提权方法.(见附录) 这也是一个mmap驱动接口校验导致映射任意内核地址的洞.将内核 ...

  7. proc 文件系统学习

    proc.txt翻译 ------------------------------------------------------------------------------Version 1.3 ...

  8. grep,cut,wc,sort,diff,uniq,patch命令

    文本处理工具: Linux上文本处理三剑客: grep,egrep,fgrep: 文本过滤工具(模式: pattern)工具; grep:基本正则表达式,-E,-F egrep:扩展正则表达式,-G, ...

  9. kernel build &amp; preempt-rt patch &amp; xenomai

    提前准备好 linux 内核源代码,假设是 x86 系统.能够去下载原生内核(Vanilla kernel): wget https://www.kernel.org/pub/linux/kernel ...

  10. kubectl 之 patch 命令

    patch命令 kubectl patch — Update field(s) of a resource using strategic merge patch Synopsis kubectl p ...

随机推荐

  1. day 26 元类

    一.isinstance issubclass class Person: passclass Student(Person): passstu1=Student()#判断是不是实例print(isi ...

  2. How to install Maven on Windows

    To install Apache Maven on Windows, you just need to download the Maven’s zip file, and Unzip it to ...

  3. oracle的loop等循环语句的几个用法小例子

    --loop循环用法 (输出1到10) declare v_num number(2) := 0; begin loop v_num := v_num + 1; exit when v_num > ...

  4. 深度学习课程笔记(六)Error

    深度学习课程笔记(六)Error Variance and Bias: 本文主要是讲解方差和偏差: error 主要来自于这两个方面.有可能是: 高方差,低偏差: 高偏差,低方差: 高方差,高偏差: ...

  5. HashMap 和 HashTable 的区别

    1. 存储结构 HashMap HashTable 数组 + 链表/红黑树 数组 + 链表 HashMap的存储规则: 优先使用数组存储, 如果出现Hash冲突, 将在数组的该位置拉伸出链表进行存储( ...

  6. CAS 单点登录4.24版本 登录调用其它系统并且返回客户端用其它的用户信息改造

    1.登录调用其它系统.修改deployerConfigContext.xml <?xml version="1.0" encoding="UTF-8"?& ...

  7. Javascript 高级程序设计(第3版) - 第01章

    2017-05-10 js简介 一个叫“不难登”的人发明的.js的流行是因为 ajax 的关系. js分为三个部分: 核心: ECMAScript 文档对象模型: DOM 浏览器对象模型: BOM 核 ...

  8. HDU 2426 Interesting Housing Problem(二分图最佳匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=2426 题意:每n个学生和m个房间,现在要为每个学生安排一个房间居住,每个学生对于一些房间有一些满意度,如果满意度 ...

  9. C# winform窗体间传值(使用委托或事件)

    窗体间传值 今天得空,刚好看到网上好多人再找winform窗体间传值的问题,由于昨天项目的优化的感觉不错,就写了个C# winform窗体间传值的demo,希望能给需要的人的带来帮助: 工程的源代码地 ...

  10. 使用MVCPager做AJAX分页所需要注意的地方

    1.版本问题,推荐使用2.0以上,对ajax支持才比较的好了 2.当需要使用页索引输入或下拉框以及使用Ajax分页模式时,必须用Html.RegisterMvcPagerScriptResource方 ...