linux热补丁(进程中的函数替换)

原文链接:https://blog.csdn.net/windy_huarj/article/details/88537006

https://blog.csdn.net/windy_huarj/article/details/88537006

背景知识
本文介绍Linux环境下正在运行进程的函数替换,不改变该进程的可执行文件内容。通过使用汇编指令JMP完成运行中进程的函数替换。为了更好地理解本文所述内容,我们需要了解以下几个知识点:

1) 了解汇编JMP指令实现无条件跳转,远跳转,近跳转;

     -- E9:本文所用

     -- EA:

     -- EB:

2) 汇编指令JMP与call的区别;为什么不能使用call来实现本文所述功能?

     -- call指令跳转前会将下一条语句入栈,与ret指令结合完成函数调用

     -- jmp指令直接修改指令寄存器IP的值

3) 如何控制一个正在运行的进程,并修改该进程代码空间的内容?

     -- 想想Linux中的GDB;

     -- 系统调用ptrace;

4) 补码的表示,负数的补码是多少?正数的补码是多少?

     -- 正数的补码与本值相同;

     -- 负数的补码是取反再加1,且最高位置1;

5) 

效果展示
            

                                                             <mytest.c>

如上图所示,将<mytest.c>编译成可执行程序mytest,并运行,结果如下:

            

           打完补丁之后,进程运行如下:

            

           mytest进程不间断,while循环中的myprint替换成new_myprint函数,完成功能。下面来看看具体实现~~~

打补丁的工具
                     

            

                                                                                <jmp.c>

如上图所示,将jmp.c编译成可执行文件jmp(就是打补丁的工具)。

实现原理是:

1) 计算jmp指令的偏移量:记为offset

    > jmp的偏移量:目标地址与下一条指令地址的差值

    > 下一条指令地址:即是待替换函数地址+jmp跳转指令长度

    > offset:占用4字节,表示可跳转空间达4G,如果进程的跳转超过4G,则失败;

2) 构造JMP指令(共5字节):E9 XX XX XX XX

    > LINUX有大小端之分,GDB内存查看时要注意;

2) 使用ptrace系统调用控制mytest进程(PTRACE_ATTACH);

3) 使用ptrace系统调用修改进程空间的代码段内容;

    > PTRACE_POKEDATA:将E9 XX XX XX XX写入到进程的myprint函数地址处,完成函数替换;

4) 使用ptrace系统调用放弃进程控制(PTRACE_DETACH)

过程分析
1) 首先,我们要获取myprint函数地址,和new_myprint函数地址

            > 本文源码很简单,可直接使用Linux自带的命令objdump就可查看:

               myprint函数地址:0x400580(4195712)

                  

                 new_myprint函数地址:0x400591(4195729)

                  

                > 实际使用中,新函数往往是动态库,只能通过dlopen、dlsym等函数查询;

           2) 运行mytest程序,获取进程号:pid = 45151

                   

           3) gdb调用mytest,查看myprint函数的汇编代码(0x400580)

               

          4) 退出gdb, 且执行jmp进行补丁

               

           5) 再次gdb查看myprint函数的汇编代码

               > 0x400580地址处的push %rbp变成了jmpq 0x400591,实现无条件跳转到new_myprint

               > 注意,为了不破坏整个函数调用栈桢的顺序,只能在push %rbp进行跳转 

               

          6) 函数替换成功

               

  
--------------------- 
版权声明:本文为CSDN博主「huarj_echo」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/windy_huarj/article/details/88537006

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章