实验环境

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. Guitar Pro怎样可以快速打出三连音?

    相信很多的音乐爱好初学者在使用入门编曲软件Guitar Pro的时候,都会碰到这样一个问题,很多乐谱中都出现了三连音,那么我们使用Guitar Pro的时候,如何能够打出三连音呢? 三连音,就是三等分 ...

  2. Bootstrap3基础 img-thumbnail 给图片加一个圆角的边框

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  3. C# 基于任务的异步模式的创建与使用的简单示例

    对于窗体程序,使用基于任务的异步模式需要用到Task类,下面示例下非常简单的用法. 1.创建一个拥有异步方法的类 该类拥有一个异步方法DoSomthingAsync,根据微软建议的命名规则该方法要带A ...

  4. 160CrackMe练手 002

    首先查壳无壳,输入伪码报错,根据报错od查找字符串,定位到错误代码附近,可以看到有个条件跳转,改掉就可以爆破,接下来分析下注册算法,我们周围看看,从最近几个call看,并没有我们输入的用户名在堆栈中出 ...

  5. Trim Galore用法及参数考量

    Trim Galore是一个非常流行的用于「去接头序列」的软件,用于处理高通量测序得到的原始数据.通常我们从测序公司拿到数据后,第一步就是评估数据的质量以及对raw data去接头处理.公司拿来的数据 ...

  6. The more... the more句型

    百度文库:https://wenku.baidu.com/view/a7f1067f59fb770bf78a6529647d27284a73374b.html the more ... , the m ...

  7. 【ASP.Net】 web api中的media type

    1. 有什么用? 通常用来标识http请求中的内容的类型用来告诉server端如何解析client端发送的message, 或者标识client希望从server端得到的资源是什么样的类型.又被称为M ...

  8. Entity Framework Core导航属性加载问题

    前言 今天下午在开发的时候发现EF Core实体模型中的导航属性为 null,经排查既不是没有加 virtual 关键字,也不是外键关系映射错误. 解决方法 通过查询官网文档,发现,原因在于EF Co ...

  9. echo -n 和echo -e 参数意义

    echo -n 不换行输出 $echo -n "123" $echo "456" 1 2 最终输出 123456 而不是 123 456 1 2 3 4 5 6 ...

  10. Spring重要注解@ControllerAdvice

    @ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMa ...