实验环境

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. Codeforces 946 D.Timetable-数据处理+动态规划(分组背包) 处理炸裂

    花了两个晚上来搞这道题. 第一个晚上想思路和写代码,第二个晚上调试. 然而还是菜,一直调不对,我的队友是Debug小能手呀(真的是无敌,哈哈,两个人一会就改好了) D. Timetable   tim ...

  2. RabbitMQ 入门指南——初步使用

    MQ的消息持久化 https://www.rabbitmq.com/tutorials/tutorial-two-java.html When RabbitMQ quits or crashes it ...

  3. 在Linux安装和使用LinuxBrew

    简介 LinuxBrew是流行的Mac OS X的一个Linux叉自制包管理器. LinuxBrew是包管理软件,它能从源(在Debian / Ubuntu的如"易/ DEB",并 ...

  4. Flyway Overview and Installation

    https://flywaydb.org/documentation/ Flyway is an open-source database migration tool. It strongly fa ...

  5. win32汇编(ASM)学习资源

    网站 AoGo汇编小站(MASMPlus作者) Win32Asm教程在线版 Win32Asm教程博客园文件备份版 Masm32补充教程系列 Win32 ASM Tutorial Resource Ki ...

  6. LOJ#2427. 「POI2010」珍珠项链 Beads

    题目地址 题目链接 题解 不会算复杂度真是致命,暴力枚举k每次计算是n/2+n/3+n/4+...+1的,用调和级数算是\(O(nlogn)\)的... 如果写哈希表的话能够\(O(nlogn)\), ...

  7. AndroidStudio Gradle下载速度慢解决方法

    1.在软件里点开工程文件下的 build.gradle 2..在 buildscript 和 allprojects 的 repositories 中分别注释掉 jcenter() 3.在 build ...

  8. 案例1:写一个压缩字符串的方法,例如aaaabbcxxx,则输出a4b2c1x3。

    public static String zipString(String str){ String result = "";//用于拼接新串的变量 char last = str ...

  9. js replace使用及正则表达式使用

    本文为博主原创,未经允许不得转载: js中replace方法与java中的replace方法相同,主要做替换. 表达式:stringObj.replace(rgExp, replaceText) 参数 ...

  10. jquery选择器扩展之样式选择器

    https://github.com/wendux/style-selector-jQuery-plugin http://blog.csdn.net/duwen90/article/details/ ...