实验环境

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. 软件调用QML的两种方式

    一.两种方式 二.方式1[对窗口的控制权在QML] 三.方式2[对窗口的控制权在C++]

  2. Java lambda例子

    简单数据类型int,跟Integer在lambda中的使用还不一样,有区别 code: package com.qhong.lambda.testDemo; import java.util.Arra ...

  3. (转) Dissecting Reinforcement Learning-Part.2

    Dissecting Reinforcement Learning-Part.2 Jan 15, 2017 • Massimiliano Patacchiola 原文链接:https://mpatac ...

  4. js变量按照存储方式区分,有哪些类型,并表述其特点

    // 值类型 拷贝形式 不像引用类型是指针指向,共用空间 值类型有 undefined string number Boolean var a = 100; var b = a; var a = 20 ...

  5. 用yarn代替cnpm,cnpm漏包有点严重

    npm 的方式  npm  install  -g  yarn   安装完成后,你可以测试下自己的版本 yarn --version 开始使用 单独安装包的方式add 不是install,后面不用加 ...

  6. Vue.extend构造器和$mount实例构造组件后可以用$destroy()进行卸载,$forceUpdate()进行更新,$nextTick()数据修改

    html <div id="app"> </div> <p><button onclick="destroy()"&g ...

  7. Nuget 打包 for .Net Standart project

    Create .NET Standard packages with Visual Studio 2015 Publishing packages nuge.exe 放在项目目录中 nuget spe ...

  8. Docker5之Deploy your app

    Make sure you have published the friendlyhello image you created by pushing it to a registry. We’ll ...

  9. Ambari配置Hive,Hive的使用

    mysql安装,hive环境的搭建 ambari部署hadoop 博客大牛:董的博客 ambari使用 ambari官方文档 hadoop 2.0 详细配置教程 使用Ambari快速部署Hadoop大 ...

  10. HDU 4323 Magic Number(编辑距离DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=4323 题意: 给出n个串和m次询问,每个询问给出一个串和改变次数上限,在不超过这个上限的情况下,n个串中有多少个 ...