A. android怎麼實現hook
幾天前,在看雪安卓版塊的論壇上,看到有人發表了一份dalvik hook的實現代碼,這里小弟果斷獻丑下,給提供一份dalvik hook的另外一種實現。
首先解釋下dalvik虛擬機中的Method結構體,Method結構體聲明在源碼目錄樹下的dalvik/vm/oo/Object.h文件內,在dalvik的世界中,每一個java方法都有一個對應的Method對象,
dalvik虛擬機在執行java方法時,就會通過該方法的Method對象調用到方法的具體實現代碼,Method結構體內有個成員,名位insns,該欄位保存著java方法具體的實現代碼。那麼我今天提供的這個dalvik hook的實現原理就是通過修改Method對象中的insns欄位的值來達到hook java的目的。
這里簡短的用文字的形式描述下Hook的實現過程。
現在有一個返回字元串的函數原型聲明為:
public String truth()
{
return "hello from truth";
}
另外聲明一個方法為:
public String fake()
{
return "fake string";
}
之後,該類被載入後,分別獲得truth和fake方法的Method對象,並將fake方法的實現代碼賦值給truth的Method對象,之後,應用程序調用truth方法時,獲得的字元串為"fake string"。
B. 如何Android hook https http
兩種方式
1 靜態織入,aspectJ算是比較成熟的aop方案了,原理是分析class,在要hook的方法前後加入你自己的執行函數。
2 動態注入,native hook。原理是在native中修改需要hook的java方法的修飾符,變為native方法—在native操作—執行原函數。自己懶得搞得話,阿里有Dexposed框架可用
C. Android Binder Hook的實現
Binder Hook可以Hook掉 當前App 用到的系統Service服務。
以LocationManager為例,在獲取一個LocationManager時分為兩步。第一,獲取IBinder對象;第二:IBinder對象通過asInterface()轉化為LocationMangerService對象。最後初始化LocationManager,application層用到的都是LocationManager。
Hook的大致原理是:ServiceManager在獲取某個Binder時,如果本地有緩存的Binder,就不再跨進程請求Binder了。我們可以在緩存中加入自己的Binder,使得ServiceManager查詢本地緩存時得到一個自定義的CustomBinder對象,不再跨進程向系統請求。並且ILocationManager.Stub.asInterface(CustomBinder)方法返回我們自定義的Service對象。
這裡面有兩個地方需要用到自定義的對象。由於我們只Hook其中一部分的功能,其他功能還需要保留,所以用動態代理的方式創建自定義的Binder和自定義的Service。
在理解後面的內容前你需要了解這些知識點:
Activity等類在獲取系統Service時,都是調用getSystemService(serviceName)方法獲取的。
Context 的 getSystemService() 方法調用了 SystemServiceRegistry 的 getSystemService() 方法。
SystemServiceRegistry 中有一個常量 SYSTEM_SERVICE_FETCHERS,這是一個Map。保存了ServiceName和對應的ServiceFetcher。ServicFetcher是用於創建具體Service的類。ServiceFetcher 的關鍵方法是 createService() 方法。
在 ServiceFetcher 的 createService() 方法中,調用了 ServiceManager.getService(name) 方法。以 LocationManager 對應的 ServiceFetcher 為例,它的createService()方法源碼如下:
假如我們要修改 LocationManager 的 getLastKnownLocation() 方法(下文都是)。我們要做的就是讓ServiceManager.getService("location")返回我們自定義的Binder。先看一下這個方法簡化後的源碼:
sCache是一個Map,緩存了已經向系統請求過的Binder。如果我們需要讓這個方法返回我們我們自己的binder,只需要事先往sCache中put一個自定義的Binder就行了。
在put之前,需要先創建出一個自定義的Binder。這個Binder在被 ILocationManager.Stub.asInterface 處理後,可以返回一個自定義的 LocationManagerService。
先看一下Binder的 asInterface() 的實現:
如果把 queryLocalInterface()方法返回一個自定義的Service,使得走if語句內部,不走else,那就算是Hook成功了。
假設我們想讓系統的LocationManager返回的位置信息全是在天安門(116.23, 39.54)。那我們需要使得 LocatitionManagerService 的 getLastLocation() 方法 返回的全是 (116.23, 39.54)。
由於我們不能直接拿到系統的這個Service對象,可以先用反射的方式拿到系統的LocationManagerService。然後攔截getLastLocation()方法。
原生的Binder對象在調用 queryLocalInterface() 方法時會返回原生的Service對象。我們希望返回3.1中的自定義Service。所以這里攔截 queryLocalInterface() 方法。
有了自定義的Binder後,將它注入到ServiceManger的sCache變數中就完成Hook了~
當onClick被調用的時候,Toast和Log都會顯示天安門的坐標(116.23, 39.54)。證明Hook成功!
你甚至可以用Binder Hook的方式Hook掉 ActivityManager 。
D. 如何hook android framework
1.向目標進程注入代碼(注入so,並調用該so里的一個函數)。首先調用ptrace函數,調試com.android.browser進程,在這里我們需要遍歷該進程載入的libc.so,這里有我們需要的dlopen,dlsym等函數的地址,我們先中斷com.android.phone,修改其寄存器...
E. android 怎麼hook主入口
常用hook工具:
Xposed框架;
CydiaSubstrate框架;
ADBI/DDI框架。
這些工具使用流程:配置環境、安裝本地服務、下載使用庫。
Xposed框架:
handleLoadPackage獲取包載入時的回調並拿到其對應的classLoader
findAndLoadHookMethod對指定類的方法進行hook
Cydiasubstrate框架的hook方法:
MS.hookClassLoad 拿到指定class載入時的通知
MS.hookMethod 使用一個Java方法去替換另一個Java方法
MS.moveUnderClassLoader 使用不同的ClassLoader重載對象
F. android插件化(四)Hook載入插件APK(ClassLoader方式)
前面插件化一和二說了下插樁式載入未安裝的APK,主要是重寫了getResource和getClassloader兩個方法來實現的。以及每個組件要實現一個介面,通過介面注入上下文來達到它的生命周期。
那麼插樁式和hook式的實現方式有什麼不同呢?
插樁式是怎麼載入到插件中的class文件呢,是通過將將APK轉化成插件的Classloader,然後想要載入插件的class文件,我們的去拿這個插件的classloader去loadClass。所以是有一個中間者的。
hook式呢是將插件apk融入到了我們的宿主apk,那直接在裡面就可以直接loadClass了,在不用這個插件的ClassLoader了,這樣的話對於插件和宿主就沒什麼區別了,不像插樁式有一個中間者。
那麼要實現hook式 就要知道android中一個class文件式怎樣被載入到內存中去的。其實就是通過PathClassLoader來載入的。
那麼我們先看下ClassLoader
任何一個java程序都是由一個或者多個class組成的,在程序運行時,需要將class文件載入到JVM中才可以使用,負責載入這些class文件的就是java的類載入機制。CLassLoader的作用就是載入class文件提供給程序運行時使用,每個Class對象內部都有一個ClassLoader來標示自己是有那個classLoade載入的。
Android app的所有的java文件都是通過PathClassLoader來載入的,那麼它的父類是BaseDexClassLoader,還有一個兄弟類是DexClassLoader,那麼他們有什麼區別呢。
從上面可以看出這兩個類的構造函數不同。(在26的源碼中DexClassLoader中的optimizedDirectory也廢棄了)
PathClassLoader:用於Android應用程序類載入器。可以載入指定的dex,以及jar、zip、apk中的classes.dex
DexClassLoader:載入指定的dex以及jar、zip、apk中的classes.dex。
可以看到創建ClassLoader的時候需要接收一個CLassLoader parent的參數,這個parent的目的就在於實現類載入的委託。
某個類載入器在接到載入類的請求時,首先將載入任務委託給父類載入器,一次遞歸,如果父載入器可以完成載入任務,那麼就返回,只有當父載入器無法完成載入任務時,才自己去載入。
因此我們自己創建的ClassLoader:newPathClassLoader("/sdcard/xx.dex",getClassLoader()),並不僅僅只能載入我們的xx.dex中的class。
需要注意的是,findBootstrapClassOrNull 這個方法,當parent為null的時候,去這個BootCLassLoader進行載入,
但是在Android當中的實現:
所以new PathClassLoader("/sdcard/xx.dex",null),是不能載入Activity.class的。
上面分析了載入了一個class,是利用了雙親委託機制,那麼要是都找不到那就開始調用自己的findCLass方法
在ClassLoader類中findClass:
任何ClassLoader的子類,都可以重寫loadClass和findClass。如果你不想使用雙親委託,就重寫loadClas修改實現,重寫findClass則表示在雙親委託機制下,父ClassLoader都找不到class的情況下,定義自己去查找一個class。
而我們的PathClassLoader會自己負責載入Activity這樣的類,利用雙親委託父類去載入activity,而我們的PathClassLoader沒有重寫findClass,是在它的父類裡面。因此我們可以看看父類的findClass是如何實現的。
可以看到載入PathClassLoader載入class,轉化為從DexPathList中載入class了,那麼我們看看DexPathList中的findClass
那麼從上面分析得到
到這里我們想要載入一個插件的apk ,其實最終載入的是一個dex文件(先說class文件,載入資源後面說),有沒有辦法吧這個dex文件給轉化成一個 Element 對象,給放到 Elemeng數組 當中,這樣直接就可以載入我們插件中的類了。
1、首先我們肯定是要得到插件APK的的中DexPathList對象中的dexElement數組
2、插件的dexElements數組我們拿到了,那麼是不是要開始拿我們系統裡面的 ,我們反射獲取,和上面的一樣。
3、上面我們獲取到了系統和我們插件的dexElement數組,然後我們將這個數組合並到一個新的數組裡面去,並且給注入到系統裡面
至此,載入插件的一個流程基本就完成了。但是上面只是處理了class文件,沒有處理資源。資源的話我們也是採用hook的方式去實現
在宿主的Application中hook這個方法,然後去重寫getAsserts和getResources兩個方法:
然後在插件的BaseActivity中繼續重寫getAssets和getResources兩個方法
這樣就可以完成hook式載入一個未安裝的APK了。至此基本就完成了插樁式和Hook式插件化的基本實現。(後面幾篇是優化)。
G. 一直不明白 hook 與 注入 有什麼區別,關系
注入跟hook確實有密不可分的聯系,我們通常都是把這兩者放到一起來談,導致很多人認為它們是一回事。
應用安全裡面有一個概念叫完整性,指的是程序或數據不能被攻擊者惡意篡改。根據篡改時刻的不同,我們有兩類方式來破壞應用的完整性:靜態和動態。
在安卓上,靜態的篡改方式是反編譯apk,修改或添加代碼後重打包,用戶只要安裝了這個修改過的apk,運行時攻擊者的代碼就會被載入到進程空間。
動態的篡改方法就是hook。如果我要篡改代碼,那麼我要實現的就是在程序將要執行某段邏輯的時候控制它去執行我的代碼,這個行為就叫hook。
一個運行時的程序表現形式是進程,代碼跟數據都放在自己的進程裡面。那麼問題來了,操作系統隔離了進程,我的代碼在我的進程里,別人的代碼在別人的進程里,別人的進程是不能跳到我的進程來執行我的代碼的,這怎麼辦呢,所以要先想辦法把代碼注入到別人的進程里。之前提到的重打包也算是一種靜態的注入方法,動態的注入方法在安卓上與Linux的共享庫注入是類似的,這種方法網上用的最多的應該是看雪的古河發布的libinject。另外還有Xposed,它採取了一種特殊的注入方法,是動靜結合的。
H. hook是什麼意思
HOOK技術是Windows消息處理機制的一個平台,應用程序可以在上面設置子程序以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達後,在目標窗口處理函數之前處理它。鉤子機制允許應用程序截獲處理window消息或特定事件。
鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得到控制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。
Hook原理
Hook技術無論對安全軟體還是惡意軟體都是十分關鍵的一項技術,其本質就是劫持函數調用。
但是由於處於Linux用戶態,每個進程都有自己獨立的進程空間,所以必須先注入到所要Hook的進程空間,修改其內存中的進程代碼,替換其過程表的符號地址。在Android中一般是通過ptrace函數附加進程,然後向遠程進程注入so庫,從而達到監控以及遠程進程關鍵函數掛鉤。