天天看點

Android注入和HOOK

如何了解HOOK?

大家可以想象一下個人電腦防火牆,特别是Linux下的iptables和netfilter。

譬如說一條指令

可以丢棄所有進入的資料包。

為什麼能做到這一點?

資料包從到達網卡一直到傳遞到上層應用有一條完整的路徑,netfilter架構在這條路徑上加入了五個鈎子函數。這些個鈎子函數可以在資料經過自己的時候把它傳遞給挂在鈎子上的處理函數。也即,鈎子是系統提供的,如何處理則是由使用者來控制的。

古河提供的libinject架構的作用也基本是這樣。

1.首先要明白的是,libinject基于ptrace,對給定的程序進行控制。Ptrace本身也類似于鈎子,它将一個程序正常的執行流打斷,讀取這個程序的寄存器和資料,甚至代碼,進而實作控制。

2.為什麼說libinject是一個架構呢?libinject就類似于netfilter,它實作了一種機制,這種機制使得使用者自己提供的.so可以在目标程序中獲得執行,也就類似于在iptables中使用者準備對資料包進行什麼處理,規則是使用者自己定義和提供的,而架構負責執行。

3.libinject是如何使得使用者的.so可以執行呢?使用者的.so要能夠得到執行,就必須在程序的位址空間中,這個需要使用mmap函數将使用者的.so映射到程序的位址空間;然後調用dlopen函數打開.so動态庫,以及使用dlsym函數獲得.so庫中的具體函數,然後開始執行。

4.是以,簡而言之,libinject架構需要完成的工作就是a)停下目标程序正常的執行流,儲存現場,然後調用mmap函數将.so映射到目标程序的位址空間;b)調用dlopen函數和dlsym函數獲得具體要執行的函數;c)執行該函數——這個函數就是使用者希望對被控制程序進行的操作。

5.在具體的實作中,我們知道,程序之是以能夠獲得執行,是因為CPU忠實地從EIP(PC)寄存器所儲存的位址中取出指令,并執行;也即,為了改變程式的執行流,隻要改變該程序的EIP寄存器的值就行了。而這個功能正是ptrace所擅長的。

6.接下來的問題是,如何找到mmap可執行檔案的位址?mmap本身位于libc.so庫中,要先能夠找到libc.so庫的位置,然後定位出來libc.so庫中mmap函數的位置。

(這裡,需要對.so庫的特點有比較深刻的了解。譬如為什麼要有so庫?程式是如何調用.so中的函數的?)

libinject的基本思路是利用了在同一個系統中,多個程序公用的同一個.so庫,這個庫中的某個函數相對于庫基址的偏移對于所有的程序都是一樣的。是以,隻需要在本地程序中計算出mmap函數相對于庫基址的偏移,然後通過讀取/proc/pid(目标程序)/maps檔案得到目标程序中libc.so庫的基址,就可以獲得目标程序中mmap函數的位置。

7.類似的方法,可以獲得linker.so庫中dlopen, dlsym以及dlclose等函數的位址,并強制目标程序執行。

8.在通過dlsym找到使用者注入的.so庫中的函數時,使用者的程式便可以獲得執行,目标達到。

Android神器Xposed也是如此:

pcedu.pconline.com.cn/484/4841077_all.html

Xposed的強大,隻要想一想,基于它,人們已經開發出了衆多的廣受歡迎的子產品,便可見一斑。

有了Xposed,如果想要修改某個apk,隻需要在分析該apk的基礎上,針對它寫一個xposed子產品即可。

相比于libinject, xposed的注入對象是Java層的方法,而這個hook是通過修改Android的啟動程序zygote而來。

關于zygote,可以參考如下連結

http://www.cnblogs.com/samchen2009/p/3294713.html

xposed安裝時修改的正是zygote啟動的第一個可執行檔案app_process,它增強了app_process的功能(具體如何增強的得細讀源碼和其他分析文檔)。Xposed使用自己的app_process替代了系統中的app_process,基本原理是引入了額外的jar包,使用這個jar包,開發者可以實作對java層方法的hook。

Xposed具有一個方法hookmethodnative,顧名思義,這個方法的作用是改變一個方法的類型為native,并且将這個方法的具體實作轉移到xposedbridge中自己實作的native版本。這樣的話,每一次這個方法被調用的時候,真正起作用的是xposed中的實作,而并非系統原有的實作。然後,xposed提供一個方法handlehookedmethod,它可以将被hooked的函數的參數傳遞出去。這樣,開發人員便可以改變、使用該參數,調用其他方法、改變結果等等。

是以,xposed架構使用的基本思路便是首先定位到自己想要進行hook的函數,在xposed架構中進行注冊,然後擷取了該函數的處理權,便可以進行相應的操作。

關于android的hook,更詳細資料可以參考:

http://drops.wooyun.org/tips/9300

http://drops.wooyun.org/papers/10156