实验环境

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. 2018年12月7日 字符串格式化2 format与函数1

    tp7="i am \033[44;1m %(name)-25.6s\033[0m"%{"name":"sxj2343333"} print ...

  2. What are the differences between Flyweight and Object Pool patterns?

    What are the differences between Flyweight and Object Pool patterns? They differ in the way they are ...

  3. Tutorial on word2vector using GloVe and Word2Vec

    Tutorial on word2vector using GloVe and Word2Vec 2018-05-04 10:02:53 Some Important Reference Pages ...

  4. NLP--- How to install the tool NLTK in Ubuntu ?

    NLP--- How to install the tool NLTK in Ubuntu ? 1. open the website of NLTK and download it.  https: ...

  5. Face Aging with Conditional Generative Adversarial Network 论文笔记

    Face Aging with Conditional Generative Adversarial Network 论文笔记 2017.02.28  Motivation: 本文是要根据最新的条件产 ...

  6. ZJOI 2015 幻想乡战略游戏(动态点分治)

    题意 https://loj.ac/problem/2135 思路 首先要明确一点,答案分布是有单调性的.什么意思呢?假设我们的答案在 \(u\) 节点,\((u,v)\) 之间有一条边且 \(u\) ...

  7. eclipse创建maven web项目工程步骤示例

    参考链接:https://www.cnblogs.com/noteless/p/5213075.html 需求表均同springmvc案例 此处只是使用maven 注意,以下所有需要建立在你的ecli ...

  8. 【NOIP 2016】Day2 T3 愤怒的小鸟

    Problem Description \(Kiana\) 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 \((0,0)\) 处,每次 \(Kiana\ ...

  9. RN原生调用一:安卓Toast

    首先安卓原生方法:Toast.makeText(getApplicationContext(), "默认的Toast", Toast.LENGTH_SHORT); 在RN中js如何 ...

  10. 蚂蚁金服“定损宝”现身AI顶级会议NeurIPS

    小蚂蚁说: 长期以来,车险定损(通过现场拍摄定损照片确定车辆损失,以作为保险公司理赔的依据)是车险理赔中最为重要的操作环节.以往传统保险公司的车险处理流程,一般为报案.现场查勘.提交理赔材料.审核.最 ...