成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android Hook技術防范漫談

企業動態
隨著互聯網和數據的思維深入人心,一些灰色產業悄然興起,數據販子、爬蟲、外掛軟件等等也接踵而來,互聯網行業中各公司競爭對手之間不僅業務競爭十分激烈,黑科技的比拼也越發重要。

背景

當下,數據就像水、電、空氣一樣無處不在,說它是“21世紀的生產資料”一點都不夸張,由此帶來的是,各行業對于數據的爭奪熱火朝天。隨著互聯網和數據的思維深入人心,一些灰色產業悄然興起,數據販子、爬蟲、外掛軟件等等也接踵而來,互聯網行業中各公司競爭對手之間不僅業務競爭十分激烈,黑科技的比拼也越發重要。隨著移動互聯網的興起,爬蟲和外掛也從單一的網頁轉向了App,其中利用Android平臺下Dalvik模式中的Xposed Installer和Cydia Substrate框架對App的函數進行Hook這一招,堪稱老牌經典。

[[219767]]

接下來,本文將分別介紹針對這兩種框架的防護技術。

Xposed Installer

原理

Zygote

在Android系統中App進程都是由Zygote進程“孵化”出來的。Zygote進程在啟動時會創建一個虛擬機實例,每當它“孵化”一個新的應用程序進程時,都會將這個Dalvik虛擬機實例復制到新的App進程里面去,從而使每個App進程都有一個獨立的Dalvik虛擬機實例。

Zygote進程在啟動的過程中,除了會創建一個虛擬機實例之外還會將Java Rumtime加載到進程中并注冊一些Android核心類的JNI(Java Native Interface,Java本地接口)方法。一個App進程被Zygote進程孵化出來的時候,不僅會獲得Zygote進程中的虛擬機實例拷貝,還會與Zygote進程一起共享Java Rumtime,也就是可以將XposedBridge.jar這個Jar包加載到每一個Android App進程中去。安裝Xposed Installer之后,系統app_process將被替換,然后利用Java的Reflection機制覆寫內置方法,實現功能劫持。下面我們來看一下細節。

Hook和Replace

Xposed Installer框架中真正起作用的是對方法的Hook和Replace。在Android系統啟動的時候,Zygote進程加載XposedBridge.jar,將所有需要替換的Method通過JNI方法hookMethodNative指向Native方法xposedCallHandler,這個方法再通過調用handleHookedMethod這個Java方法來調用被劫持的方法轉入Hook邏輯。

上面提到的hookMethodNative是XposedBridge.jar中的私有的本地方法,它將一個方法對象作為傳入參數并修改Dalvik虛擬機中對于該方法的定義,把該方法的類型改變為Native并將其實現指向另外一個B方法。

換言之,當調用那個被Hook的A方法時,其實調用的是B方法,調用者是不知道的。在hookMethodNative的實現中,會調用XposedBridge.jar中的handleHookedMethod這個方法來傳遞參數。handleHookedMethod這個方法類似于一個統一調度的Dispatch例程,其對應的底層的C++函數是xposedCallHandler。而handleHookedMethod實現里面會根據一個全局結構hookedMethodCallbacks來選擇相應的Hook函數并調用他們的before和after函數,當多模塊同時Hook一個方法的時候Xposed會自動根據Module的優先級來排序。

調用順序如下:A.before -> B.before -> original method -> B.after -> A.after

檢測

在做Android App的安全防御中檢測點眾多,Xposed Installer檢測是必不可少的一環。對于Xposed框架的防御總體上分為兩層:Java層和Native層。

Java層檢測

需要說明的是,Java層的檢測基本只能檢測出基礎的Xposed Installer框架,而不能防護其對App內方法的Hook,如果框架中帶有反檢測則Java層檢測大多不起作用。

下面列出Java層的檢測點,僅供參考。

① 通過PackageManager查看安裝列表

最簡單的檢測,我們調用Android提供的PackageManager的API來遍歷系統中App的安裝情況來辨別是否有安裝Xposed Installer相關的軟件包。

  1. PackageManager packageManager = context.getPackageManager(); 
  2. List applicationInfoList = packageManager.getInstalledApplications(PackageManager.GET_META_DATA); 
  3. for (ApplicationInfo applicationInfo: applicationInfoList) { 
  4.     if (applicationInfo.packageName.equals("de.robv.android.xposed.installer")) { 
  5.         // is Xposed TODO... } 
  6.     } 

通常情況下使用Xposed Installer框架都會屏蔽對其的檢測,即Hook掉PackageManager的getInstalledApplications方法的返回值,以便過濾掉de.robv.android.xposed.installer來躲避這種檢測。

② 自造異常讀取棧

Xposed Installer框架對每個由Zygote孵化的App進程都會介入,因此在程序方法異常棧中就會出現Xposed相關的“身影”,我們可以通過自造異常Catch來讀取異常堆棧的形式,用以檢查其中是否存在Xposed的調用方法。

  1. try { 
  2.     throw new Exception("blah"); 
  3. } catch(Exception e) { 
  4.     for (StackTraceElement stackTraceElement: e.getStackTrace()) { 
  5.         // stackTraceElement.getClassName() stackTraceElement.getMethodName() 是否存 在Xposed 
  6.     } 
  7. E/GEnvironment: no such table: preference (code 1): while compiling: SELECT keyguard_show_livewallpaper FROM preference 
  8. ... 
  9. at com.meituan.test.extpackage.ExtPackageManager.checkUpdate(ExtPackageManager.java:127) 
  10. at com.meituan.test.MiFGService$1.run(MiFGService.java:41) 
  11. at android.os.Looper.loop(Looper.java:136) 
  12. at android.app.ActivityThread.main(ActivityThread.java:5072) 
  13. at java.lang.reflect.Method.invokeNative(Native Method) 
  14. at java.lang.reflect.Method.invoke(Method.java:515) 
  15. ... 
  16. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
  17. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609) 
  18. at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132) //發現Xposed模塊 
  19. at dalvik.system.NativeStart.main(Native Method) 

③ 檢查關鍵Java方法被變為Native JNI方法

當一個Android App中的Java方法被莫名其妙地變成了Native JNI方法,則非常有可能被Xposed Hook了。由此可得,檢查關鍵方法是不是變成Native JNI方法,也可以檢測是否被Hook。

通過反射調用Modifier.isNative(method.getModifiers())方法可以校驗方法是不是Native JNI方法,Xposed同樣可以篡改isNative這個方法的返回值。

④ 反射讀取XposedHelper類字段

通過反射遍歷XposedHelper類中的fieldCache、methodCache、constructorCache變量,讀取HashMap緩存字段,如字段項的key中包含App中唯一或敏感方法等,即可認為有Xposed注入。

  1. boolean methodCache = CheckHook(clsXposedHelper, "methodCache", keyWord); 
  2.  
  3. private static boolean CheckHook(Object cls, String filedName, String str) { 
  4.     boolean result = false
  5.     String interName; 
  6.     Set keySet; 
  7.     try { 
  8.         Field filed = cls.getClass().getDeclaredField(filedName); 
  9.         filed.setAccessible(true); 
  10.         keySet = filed.get(cls)).keySet(); 
  11.         if (!keySet.isEmpty()) { 
  12.             for (Object aKeySet: keySet) { 
  13.                 interName = aKeySet.toString().toLowerCase(); 
  14.                 if (interName.contains("meituan") || interName.contains("dianping") ) { 
  15.                     result = true
  16.                     break; 
  17.                     }  
  18.                 } 
  19.             } 
  20.         ... 
  21.     return result; 

Native層檢測

由上文可知,無論在Java層做何種檢測,Xposed都可以通過Hook相關的API并返回指定的結果來繞過檢測,只要有方法就可以被Hook。如果僅在Java層檢測就顯得很徒勞,為了有效提搞檢測準確率,就須做到Java和Native層同時檢測。每個App在系統中都有對應的加載庫列表,這些加載庫列表在/proc/下對應的pid/maps文件中描述,在Native層讀取/proc/self/maps文件不失為檢測Xposed Installer的有效辦法之一。由于Xposed Installer通常只能Hook Java層,因此在Native層使用C來解析/proc/self/maps文件,搜檢App自身加載的庫中是否存在XposedBridge.jar、相關的Dex、Jar和So庫等文件。

  1. bool is_xposed() 
  2.    bool rel = false
  3.    FILE *fp = NULL
  4.    char* filepath = "/proc/self/maps"
  5.    ... 
  6.    string xp_name = "XposedBridge.jar"
  7.    fp = fopen(filepath,"r"))  
  8.    while (!feof(fp))                                  
  9.    { 
  10.        fgets(strLine,BUFFER_SIZE,fp);                     
  11.        origin_str = strLine; 
  12.        str = trim(origin_str); 
  13.        if (contain(str,xp_name)) 
  14.        { 
  15.            rel = true; //檢測到Xposed模塊 
  16.            break; 
  17.        } 
  18.    } 
  19.     ... 

Cydia Substrate

原理

Cydia Substrate注入Hook的一個典型流程如下圖所示,在Java層配置注入的關鍵So庫libsubstrate.so和libsubstratedvm.so。考慮到Java層檢測強度太低,Substrate的檢測主要在Native層來實現。

檢測

動態加載式檢測

讀取/proc/self/maps,列出了App中所有加載的文件。

上圖為Cydia Substrate在Android 4.4上注入后的進程maps表,其中libsubstrate.so和libsubstrate-dvm.so兩個文件為Substrate必載入文件。通過IDA Pro分析對其分析。

先來看libsubstrate-dvm.so的導出表,共有9個函數導出。

當進程maps表中出現libsubstrate-dvm.so,可以嘗試去load該so文件并調用MSJavaHookMethod方法,它會返回該方法的地址即判定為惡意模塊(第三方程序)。

  1. void* lookup_symbol(char* libraryname,char* symbolname)   
  2.     void *imagehandle = dlopen(libraryname, RTLD_GLOBAL | RTLD_NOW); 
  3.     if (imagehandle != NULL){ 
  4.         void * sym = dlsym(imagehandle, symbolname); 
  5.         if (sym != NULL){ 
  6.             return sym; //發現Cydia Substrate相關模塊 
  7.             } 
  8.       ... 

該方式基于載入庫文件的文件名或文件路徑和導出函數來判斷是否為惡意模塊,如果完全依賴此方式來判斷可能會誤判,但也不失為檢測方式的一個點。

基于方法特征碼檢測

特征碼即用來判斷某段數據屬于哪個計算機字段。在非Root環境下一般一個正常App在啟動時候,系統會調度相關大小的內存、空間給App使用,此時App的運行環境內產生的數據、內存、存儲等是獨立于其它App的(即獨立運行在沙箱中)。因為處于運行沙箱環境中的進程對沙箱的內存有最高讀寫權限,當我們的App進程被惡意模塊附加或注入時,就可以通過對當前進程的PID所對應的maps中加載的模塊進行合法校驗。這里的模塊校驗我們可以采取對單個模塊內容取樣來判斷是否為惡意模塊,這種方式被定義為“基于方法的特征碼檢測”。

下面對一段程序段中OpcodeSample方法來提取特征碼。

方法原型:

  1. #define  LOGD(fmt, args...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)     
  2. void OpcodeSample(int a ,int b){   
  3.     int c,d,e; 
  4.     c = a + b; 
  5.     d = a * b; 
  6.     e = a / b; 
  7.     LOGD("Hello It's c !%s\n", c);   
  8.     LOGD("Hello It's d !%s\n", d);   
  9.     LOGD("Hello It's e !%s\n", e);   
  10.     return

通過IDA Pro對其分析。

左側紅色方框代表為OpcodeSample方法的操作碼,右邊為操作碼對應ARM平臺的指令集。我們要在左側的操作碼中取出一段作為OpcodeSample的定位特征碼,選用__android_log_print方法調用指令集上下文,來確定特征碼。

第一次取樣:"03 20 31 46 42 46 FF F7 ?? EA"

通過第一次取樣,查找結果有三處相似,再進一步分析。這次我們加入一個常量取樣:

第二次取樣:"7E 44 ?? ?? F8 44 03 20 31 46 42 46 FF F7 ?? EA"

繼而得出唯一特征碼,到此,我們對特征碼方法取樣有了初步的了解。下面來把它轉為實用的技能——動態加載式檢測+特征碼結合。

我們對libsubstrate-dvm.so中導出函數MSJavaHookMethod來精準定位。

IDA PRO導出函數表如圖:

第三次取樣:"55 57 56 53 E8 CC 14 ?? ?? 81 C3 DB ?? ?? ?? 8D 64 ?? ?? 8B 83 F4 ?? ?? ??"

以上即為對Cydia Substrate的注入檢測識別,通過檢測/proc/self/maps下的加載so庫列表得到各個庫文件絕度路徑,通過fopen函數將so庫的內容以16進制讀進來放在內存里面進行規則比對,采用字符串模糊查找來檢測是否命中黑名單中的方法特征碼。

總結

在安全對抗領域,相比攻擊方,防守方歷來處于弱勢的一方。上文所提到的Xposed Installer和Cydia Substrate的檢測也僅僅是保障App安全的手段之一。App安全的防御不應僅僅依賴于此,應該構建起整體的安全防御閉環,盡可能在所有已知的可能攻擊點都追加檢測,再配合代碼加固,將防御代碼隱藏。遺憾的是App防御代碼隱藏再深也終究會被破解,僅僅依賴于客戶端的防御顯然是不足的。移動互聯網領域的整體安全防御應該是走端云結合協作之道,共同防御,方能在攻防對抗中占據優勢地位。

 【本文為51CTO專欄機構“美團點評技術團隊”的原創稿件,轉載請通過微信公眾號聯系機構獲取授權】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2017-03-06 14:44:49

Androidhook技術

2015-09-15 09:20:22

Neutron技術虛擬化

2023-12-25 08:25:42

AndroidHook應用程序

2011-04-21 09:46:41

設計模式

2010-02-04 15:50:28

Android設備

2018-07-02 09:32:36

OceanBase列式存儲

2015-10-30 13:54:55

數據中心防雷SPD

2022-01-08 21:33:39

反入侵安全風險攻擊

2011-07-05 11:06:52

2013-11-15 13:06:52

透明加解密hook技術數據安全

2014-03-06 09:42:25

無線技術802.11ac

2021-08-11 08:41:20

全棧開發技術架構前端

2015-10-15 14:32:58

數據中心網絡融合技術DCB

2015-07-16 11:14:59

Google數據中心網絡技術

2017-01-03 16:57:58

2017-03-23 09:13:56

2022-08-31 15:08:34

家庭網關交互控制智能家居

2011-08-04 14:02:42

2020-07-10 11:12:00

公章技術騰訊

2018-10-08 15:31:30

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日干夜操| 国产高清视频在线播放 | 精品欧美一区二区精品久久久 | 国产精品视频一二三区 | 欧美一区在线视频 | 国产成人精品在线播放 | 亚洲三级在线观看 | 久久精品国产一区二区电影 | 国产激情在线观看视频 | 在线播放中文字幕 | 国产精品午夜电影 | 欧美1级| 日韩精品视频在线观看一区二区三区 | 欧美在线一区二区三区 | 日本网站在线看 | 日韩在线视频免费观看 | 中文字幕高清在线 | 日日噜| 欧美黄色一区 | 国产精品视频一二三区 | 中文字幕一区二区在线观看 | 日日夜夜精品视频 | 国产精品揄拍一区二区 | 国产精品久久久久久久久久免费看 | 国产福利91精品 | 国产高清久久久 | 免费在线看黄 | 久久久久久久国产 | 中文字幕男人的天堂 | 亚洲图片视频一区 | 国产激情毛片 | 精品欧美黑人一区二区三区 | 国产精品18久久久久久久 | 人人鲁人人莫人人爱精品 | 九九热在线观看 | 毛片网站在线观看 | 久久精品亚洲一区 | 一区二区视频在线 | 超碰网址 | 亚洲电影一区二区三区 | 91av在线免费观看 |