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

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