Android中Xposed框架篇---基於Xposed的一款脫殼神器ZjDroid工具原理解析
一、前言
在前文中我們介紹了如何使用Xposed框架修改地理位置資訊來進行自身的隱藏功能,本文將繼續介紹Xposed框架的另外一個功能就是實現應用的簡單脫殼,其實說是Xposed的作用其實也不是,主要是模組編寫的好就可以了,主要是利用Xposed的牛逼Hook技術實現的,下面就先來介紹一下這個脫殼模組工具ZjDroid的原理,因為他是開源的,所以咋們直接分析原始碼即可,原始碼的下載地址:https://github.com/halfkiss/ZjDroid 不過可惜的時候他只公開了Java層的程式碼,而native層的程式碼並沒有公開,但是分析原始碼之後會發現最重要的功能就在native層,不過也沒關係,等分析到那裡的時候我在給大家講解底層的大致實現方案即可。
二、ZjDroid原理分析
下面就來詳細的分析一下ZjDroid工具的原始碼吧,他是一個Eclipse工程匯入很簡單,基於之前的Xposed模組編寫的經驗,我們知道找到入口程式碼也很簡單,在assets目錄下有一個xposed_init檔案中就記錄了模組的入口類:
我們直接進入到這個類即可:
看到了,遵循統一規則,實現了IXposedHookLoadPackage介面,實現handleLoadPackage回撥方法即可,下面繼續分析入口方法ModuleContext:
這裡開始攔截Application的onCreate方法了,而這個方法一般是每個應用程式的啟動方法,在這裡做攔截操作也是合情合理的,在看看攔截之後做了什麼,也就是ApplicationOnCreateHook類的實現:
在這裡開始了真正的攔截操作了,主要是新增了一個廣播,也就是說裝置中每個應用在啟動的時候都回去註冊這個廣播,而如果後續傳送一個這樣對應Action的廣播的話,每個應用程式都會收到。所以這裡可以看到,核心工作就在這個廣播的接受之後做了,接下來繼續去看這個廣播的定義:
果然在這裡,可以看到了首先會通過傳送廣播的intent中攜帶一些資料過來,主要是兩個資料:
一個是程式id:這個作用主要是為了過濾其他應用,只處理本應用的邏輯,因為這個廣播傳送之後所有的應用都能接收到,但是我們脫殼有時候肯定只是針對於某一個應用,那麼只需要在這個應用的廣播接收中做處理即可。
一個是命令字串:這個是為了傳送廣播可以支援多種功能,後面分析也可以看到的確有很多功能的。
然後這裡得到命令之後就開始構造一個命令執行器類,這裡用到了設計模式中的命令模式。下面繼續看看有哪幾種命令執行器類:
在這個方法中就開始分析了這裡支援的哪幾種命令類,下面來一一分析一下:
第一個命令:dump_dexinfo
獲取應用執行時記憶體中dex的資訊:DumpDexInfoCommandHandler
進入方法在詳細檢視一下:
看到了,這裡的實現邏輯還是比較簡單的,全部通過反射機制獲取每個應用的dex檔案對應的DexFile型別物件,這裡的工作和我們之前介紹了Android中外掛化開發已經很熟悉了,通過應用的預設類載入PathClassLoader類得到DexPathList類,然後在得到具體的DexFile物件即可。這裡要說的就是這個dex檔案對應的cookie值,這個值非常重要,是後續命令操作的基本資訊,他代表的含義就是底層中每個應用的dex檔案對應的唯一id值,系統會維護一個map結構來儲存這些資料的,系統然後通過這個cookie值來找到對應的dex檔案資訊的。
命令用法:am broadcast -a com.zjdroid.invoke --ei target [pid] --es cmd '{"action":"dump_dexinfo"}'
這裡使用的是命令方式傳送一個廣播,通過--ei攜帶目標程式id是一個int型別,通過--es攜帶命令字串
第二個命令:dump_dexfile
這個命令也是後續脫殼的重要命令,就是dump出應用記憶體中的dex檔案:DumpDexFileCommandHandler
這裡可以看到dump出應用的記憶體資料,首先得需要傳入源應用的dex資料也就是apk檔案,這個一般都是存放在/data/app/xxx.apk目錄下的,然後就是這裡自己構建了一個dump之後的dex檔案路徑,通過原始碼檢視是在/data/data/xxx/files/dexdump.odex中。接下來繼續檢視dump的核心程式碼:
看到這裡有一個核心的方法,但是可惜的是這個方法是native的,而這個工具並沒有把native層的程式碼公開,但是通過這裡傳遞的引數可以瞭解到,底層應該是採用了libdvm.so或者是libart.so庫來得到具體的函式,然後通過dex對應的cookie值獲取資訊。
命令用法:am broadcast -a com.zjdroid.invoke --ei target [pid] --es cmd '{"action":"dump_dexfile","dexpath":"*****"}'
注意這裡的dexpath引數是代表需要脫殼的dex檔案,也就是應用程式檔案。
第三個命令:backsmali
這個命令其實是和上面的命令差不多功能,只是這裡的命令多了一層操作就是把dex檔案轉化成smali檔案,所以這裡不再詳細說明了,咋們可以先得到dex檔案,然後在通過工具得到smali檔案也是可以的。
命令用法:am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"backsmali","dexpath":"*****"}'
注意這裡的dexpath引數是代表需要脫殼的dex檔案,也就是應用程式檔案。而最終生成的smali資料夾是放在/data/data/xxx/smali下面的。
第四個命令:dump_mem
這個命令是用來dump出應用程式執行時記憶體中指定開始位置和長度的記憶體塊資料的:DumpMemCommandHandler
可惜這個方法也是native層的,但是這個操作就比較簡單了,我們知道每個應用執行時的記憶體地址都在 /proc/[pid]/maps 檔案中:
那麼查詢記憶體地址,然後在使用memcpy進行記憶體資料拷貝也是非常簡單的。
命令用法:am broadcast -a com.zjdroid.invoke --ei target [pid] --es cmd '{"action":"dump_mem","start":111,"length":23}'
注意這裡的start和length都是十進位制的,而不是十六進位制的資料格式。
第五個命令:dump_heap
這個命令是可以dump出虛擬機器的堆記憶體資訊的,檔案可以使用java heap工具進行分析,而對於這個命令我們想一下應該也知道實現邏輯應該是也是在native層的,而且這個程式碼邏輯應該和上面的那個命令差不多的,但是對於這個命令我還沒有想到具體的思路,悲哀呀,如果有了解的同學就告知一下哈!
命令用法:am broadcast -a com.zjdroid.invoke --ei target [pid] --es cmd '{"action":"dump_heap"}'
第六個命令:dump_class
這個命令主要是用於dump出dex檔案中的類資訊,這個操作也是非常簡單的,因為在DexFile物件中有一個隱藏的方法可以把dex檔案中的所有類名獲取到:getClassNameList
這裡可以看到這個方法的傳入引數為一個dex檔案對應的cookie值。
命令用法:am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"dump_class","dexpath":"*****"}'
這裡的dexpath是需要得到所有類資訊的dex檔案路徑,也就是應用的apk檔案路徑。
第七個命令:invoke
這個命令是用於執行時動態呼叫Lua指令碼,本人並沒有看懂這個命令的作用,該功能可以通過Lua指令碼動態呼叫java程式碼。使用場景:可以動態呼叫解密函式,完成解密。可以動態觸發特定邏輯。程式碼就不進行分析了,因為我覺得這個命令應該不怎麼會使用
命令用法:am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"invoke","filepath":"****"}'
這裡的filepath是lua指令碼檔案的存放路徑。
到這裡就全部介紹完了ZjDroid的所有命令了,下面還有兩個非常重要的列印日誌的tag:
第一個:adb logcat -s zjdroid-shell-{package name}
這個tag可以檢視上面每個命令執行的結果,便於檢視命令執行的狀態。
第二個:adb logcat -s zjdroid-apimonitor-{package name}
這個tag可以監聽對應包名應用呼叫的哪些api資訊,這個作用有點類似於執行時許可權請求的作用。這個做起來就非常簡單了,可以直接通過Xposed提供的方法進行系統的一些敏感api進行攔截然後新增監控程式碼即可。
三、命令總結
上面就從原始碼的角度完全分析完了ZjDroid工具的功能了,下面就來總結一下:
1、獲取APK當前載入DEX檔案資訊
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"dump_dexinfo"}'
2、獲取指定DEX檔案包含可載入類名
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"dump_class","dexpath":"*****"}'
3、根據Dalvik相關記憶體指標動態反編譯指定DEX,並以檔案形式儲存
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"backsmali","dexpath":"*****"}'
4、Dump指定DEX記憶體中的資料並儲存到檔案(資料為odex格式,可在pc上反編譯)
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"dump_dexfile","dexpath":"*****"}'
5、Dump指定記憶體空間區域資料到檔案
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"dump_mem","start":1234567,"length":123}'
6、Dump Dalvik堆疊資訊到檔案,檔案可以通過java heap分析工具分析處理
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"dump_heap"}'
7、執行時動態呼叫Lua指令碼
該功能可以通過Lua指令碼動態呼叫java程式碼。使用場景:可以動態呼叫解密函式,完成解密。可以動態觸發特定邏輯。
am broadcast -a com.zjdroid.invoke --ei target pid --es cmd '{"action":"invoke","filepath":"****"}'
8、相關命令執行結果檢視
1》、命令執行結果
adb shell logcat -s zjdroid-shell-{package name}
2》、敏感API呼叫監控輸出結果
adb shell logcat -s zjdroid-apimonitor-{package name}
四、案例使用分析
下面咋們就要用一個案例來看看這個工具到底如何使用,有哪些功效,咋們就用一個應用做案例,就是捕魚達人v1.0.1版本,具體的apk檔案可以自行去網上搜尋哈。我們安裝遊戲之後,然後順便把上面的ZjDroid模組工具也安裝上,然後進行重啟生效。
我們最好是單獨開一個CMD視窗用來檢視列印結果,但是從上面的命令可以看到,我們應該需要這遊戲的包名和程式id,那麼這兩個資料怎麼獲取呢?其實我在前面的文章已經介紹了很多次了,用一個命令即可:adb shell dumpsys activity top 但是這時候需要執行起來捕魚達人遊戲:
這裡看到了,就非常簡單的獲取到了遊戲的包名:org.cocos2d.fishingjoy3和程式id=25304,這兩個資料非常重要可以這裡先進行保管,進而後面可以使用。
下面首先來看一下這個應用用了哪些敏感的api資料,使用上面檢視日誌的命令即可:
adb shell logcat -s zjdroid-apimonitor-org.cocos2d.fishingjoy3
看到了,這裡又網路請求資訊,網路切換的廣播等資料的,感覺還是蠻有用的這個工具。
下面在來看一下這個應用的dex檔案資訊,可以使用下面命令即可:
am broadcast -a com.zjdroid.invoke --ei target 25304 --es cmd '{action:dump_dexinfo}'
這裡執行之後的結果:
這時候會發現,執行沒有看到實際效果,原因是因為我們需要通過日誌才能可以看到資料的,因為上面命令執行的結果都是需要通過這個日誌才可以看到的:adb logcat -s zjdroid-shell-org.cocos2d.fishingjoy3
這裡就可以看到了具體的資訊了,看到了有一個filepath這個就是我們後續有些命令需要用到的dex路徑,所以一定要記下來,後面的命令會使用到的。
接下來在看一個關於dump出遊戲中所有的類名的命令:
am broadcast -a com.zjdroid.invoke --ei target 25304 --es cmd '{"action":"dump_class","dexpath":"/data/app/org.cocos2d.fishingjoy3-1.apk"}'
這裡的路徑就是上面獲取到的apk路徑,結果咋們還是需要通過上面的日誌命令才可以看到:
看到了吧,這裡就匯出來了遊戲包含的所有類名了。
最後在來一發,這個是最關鍵的,也是本文的重點也是這個工具最實用的一個功能,就是進行應用的脫殼處理了,而本文的遊戲也是進行加固處理的,我們可以反編譯看看這個遊戲:
你會發現沒幾個類,而且有一個Application類,那麼可以認定了這個遊戲被加固了,本文不介紹是使用哪家的加固平臺操作了,也不再使用IDA等工具去動態除錯脫殼了,這裡直接使用這個工具進行操作即可。咋們為了後續程式碼閱讀方便可以直接獲取他的smali程式碼,也就是使用這個命令:
am broadcast -a com.zjdroid.invoke --ei target 25304 --es cmd '{action:backsmali, "dexpath":"/data/app/org.cocos2d.fishingjoy3-1.apk"}'
這個命令的執行結果咋們通過日誌檢視:
而這個smali資料夾是存放在應用的 /data/data/org.cocos2d.fishingjoy3/smali 中的,咋們可以把他拷貝出來即可:
這裡可以看到咋們就成功的脫殼了,生成了遊戲的所有smali檔案程式碼了。其實這個脫殼操作和我們之前介紹使用IDA工具進行脫殼原理都差不多,因為應用程式不管怎麼加固,最終都會使用一個系統函式將dex檔案載入到記憶體中,而載入之前肯定要進行解密操作,我們只要在載入之前解密之後進行攔截即可。
五、總結
好了,到這裡我們就講解完了基於Xposed框架的脫殼神器ZjDroid的實現原理以及具體用法。而這裡也感受到了Xposed框架的強大之處,當然這也只是一部分,後面還可以利用這個框架編寫遊戲外掛等操作。所以好好膜拜這個框架,也好好拜讀這個框架的原始碼吧,學不完的東東呢!寫的好累好辛苦,記得給小編點贊呢!!
相關文章
- Android Hook框架Xposed原理與原始碼分析AndroidHook框架原始碼
- Xposed原理分析
- Android.Hook框架xposed篇(Http流量監控)AndroidHook框架HTTP
- Xposed框架的安裝框架
- Android Hook 神器——XPosed入門(登陸劫持演示)AndroidHook
- Xposed 常用
- Xposed瞭解以及在Android中的應用Android
- Android.Hook框架Cydia篇(脫殼機制作)AndroidHook框架
- Xposed原理簡介及其精簡化
- 殼的工作原理脫殼
- Xposed模組的開發
- Xposed攔截抽象方法抽象
- Xposed去除抖音Toast教程AST
- Android定製ROM,內嵌su和xposedAndroid
- Android逆向開發 | 小米5刷Xposed過程Android
- 從Android執行時出發,打造我們的脫殼神器Android
- Android流言終結者--xposed生效需要root嗎??不用!!Android
- 獲取Android裝置DeviceId與反Xposed HookAndroiddevHook
- Xposed從入門到棄坑:0x03、XposedHelpers類解析
- Xposed修改硬體資訊總結
- Android逆向之旅---破解某支付軟體防Xposed等框架Hook功能檢測機制Android框架Hook
- Xposed從入門到棄坑:0x02、IXposedHook相關介面解析Hook
- Xposed快速入門例子(一)----- 拉黑好友
- 練習向:Xposed安裝和使用的踩坑
- Android外掛化原理分析(基於Neptune框架)Android框架
- OkHttp原理解析1(框架流程篇)HTTP框架
- 抱歉,Xposed真的可以為所欲為——1.基礎知識儲備
- Android八門神器(一):OkHttp框架原始碼解析AndroidHTTP框架原始碼
- iOS應用程式的脫殼實現原理淺析iOS
- [原創]heXer老兄的telock0.98脫殼機原理
- 如何使用Xposed+JustTrustMe來突破SSL PinningRust
- Xposed快速入門例子(二)----- 調方法的合適時機
- Xposed簡介以及小米去桌面廣告的簡單實現
- 壹次脫殼法――Armadillo 雙程式標準殼 快速脫殼
- 【開源】BlackDex,無需環境,Android新姿勢脫殼工具Android
- (Android機)不要隨意安裝Xposed外掛,不然可能遭受財產損失Android
- Armadillo 2.52加殼原理分析和改進的脫殼方法 (12千字)
- VBExplorer.exe脫殼教程 附脫殼指令碼指令碼