Android Libinject X86平臺EIP-2的分析

在看雪上看到古河大牛的android-LibInject,平臺是arm版的。linux

想測試x86平臺上的android-Libinject,搜索有人已經完成(blog.csdn.net/jinzhuojun/article/details/9900105)。android

 

其中獲取目標進程庫函數地址的代碼以下,特別的,x86平臺的函數地址=實際函數地址+2。windows

 

這個+2的操做讓人蛋疼,起初覺得是ELF在X86平臺上的特性。安全

在GDB中調試,發現函數地址並不須要+2。函數

調試發現,是由於以下的函數ptrace_call設置eip的時候須要把eip加2。源碼分析

 

做以下測試,測試

設置錯誤的eip,Regs->eip=0,目標進程段錯誤,崩潰eip=-2;spa

設置錯誤的eip,regs->eip=10,目標進程段錯誤,崩潰eip=8.net

 

測試代表:X86版本的ptrace_call,確實須要eip=eip+2。調試

根據windows的經驗,怎麼也沒明白爲啥eip-2。

設置目標進程eip=funX,結果目標進程從funX-2開始執行,蛋疼。

 

測試GDB調試,設置目標進程的EIP,目標進程從EIP開始執行,蛋更疼了。

聽說GDB也是用的ptrace接口,爲啥GDP設置EIP就從EIP開始執行,而ptrace_call設置EIP卻從EIP-2的地址開始執行。

 

請教原文做者,答覆「多是ABI的緣由,有的平臺並不須要」。

請教其它大牛,估計是被太多郵件淹沒了。

 

在看雪上看到有文章說,須要在ptrace_attach以後先執行ptrace_syscall

 

測試代表,這篇文章說的沒問題。但做者也沒有爲何必需要先ptrace_syscall。

對比不添加ptrace_syscall和ptrace_syscall,ptrace_getreg得到EIP都是相同的,說明ptrace _attach返回時,目標進程的EIP都是相同的。那添加的ptrace_syscall又作了哪些額外的工做,致使執行結果不同。

 

不明就裏,如鯁在喉!一統搜索,沒有結果!只有去看linux內核相關的書籍了。

在閱讀完《linxu內核源碼分析》的ptrace和signal章節後,找到了最終的緣由。

 

EIP-2內幕

個人目標程序源碼以下:

 

 

個人注入程序代碼以下:

 

注入程序在ptrace_attach目標程序的時候,目標程序由於執行sleep(1)處於休眠狀態。

此時EIP爲系統調用的用戶態返回地址,以下的0xb7fe2424。不管是sysenter方式仍是int 0x80方式,返回EIP都是該地址。

 

 

Ptrace_attach首先向目標進程發送SIGSTOP信號,該信號把原本處於休眠的進程喚醒。而後進入等待目標進程狀態發生改變。

 

目標進程被喚醒後經內核調度開始執行,開始執行實際上是從原來的休眠處開始的,顯然繼續執行將會結束sleep系統調用,而且返回結果不是sleep知足,而是sleep被中斷了。

目標進程準備退出sleep系統調用,在返回到用戶態EIP以前,內核檢測自身是否存在信號量。顯然,赤裸裸的躺着注入程序發送的SIGSTOP信號。因而,轉入執行SIGSTOP信號處理,該信號處理把進程狀態爲STOP,掛起自身,激活注入進程的wait調用。

 

注入進程wait調用返回,ptrace_getregs獲取的EIP是確確實實的目標進程未來返回到用戶態執行的EIP。

 

注入進程ptrace_setreg設置的EIP也確確實實是目標進程未來要返回到用戶態執行的EIP。

 

注入進程ptrace_continue給目標進程發送信號SIGCON,信號發送自己將喚醒掛起的目標進程。

 

目標進程由於收到的SIGCON信號,恢復執行。此時進程的SIGSTOP信號即將處理完畢,系統檢測該到信號來自系統調用,而且該信號處理不是由用戶程序處理,這就意味着該信號致使了本系統調用失敗,須要自動從新執行該系統調用。自動從新本系統調用的方法:恢復用戶態寄存器EAX爲系統調用號,用戶態EIP=EIP-2。而EIP-2剛好就是int 80系統調用指令。

 

目標進程處理完信號後,開始執行系統調用返回到用戶態。此時用戶態的EIP因爲-2的緣由,再也不是原來的pop ebp指令,而是int 80指令。所以返回到用戶態後,自動從新執行本系統調用。

 

所以,EIP-2的本質緣由,在於ptrace_attach的時候目標進程因系統調用進入了休眠,而attach發送的信號致使了目標進程調用中斷返回,系統爲了彌補中斷返回的系統調用,在信號處理中將EIP-2來迫使中斷的系統調用返回後自動重啓本系統調用。

 

爲什麼ptrace_attach+ptrace_syscall就沒有EIP-2的問題?

在ptrace_attach後加入ptrace_syscall後不會致使eip-2,緣由在於ptrace_syscall僅僅是設置目標進程的標誌位,沒有發送任何信號,也沒有中斷目標進程的任何系統調用。目標進程是主動在系統調用以前檢查該標誌位,主動掛起本身。這種條件下,注入進程設置目標進程eip,目標進程的系統調用天然是返回到設置的eip。

 

Ptrace_attach必定會有問題嗎?

NO。attach時刻目標進程若是不是陷入系統調用,就不會觸發自動重啓系統調用致使的EIP-2。

 

ptrace_attach+ptrace_syscall必定安全嗎?

NO。在ptrace_syscall+ptrace_setreg+ptrace_continue後,目標進程開始進行系統調用,若是系統調用是可中斷的阻塞調用,在阻塞等待過程當中若是由於接受到其它信號,致使系統調用中斷返回,那麼系統會由於自動重啓系統調用而設置eip-2,而且系統期待的eip-2處的代碼爲int 80。顯然,注入進程設置的eip爲某個函數,而eip-2就是個不三不四的東西。

 

注:最後兩個問題,沒有實際測試,只是推斷;SIGCON信號對於目標進程只是簡單的忽略。

不知道ARM平臺存不存在由於自動重啓系統調用而致使的EIP-2的問題。

相關文章
相關標籤/搜索