源碼分析 脫殼神器ZjDroid工做原理

0. 神器ZjDroid

Xposed框架的另一個功能就是實現應用的簡單脫殼,其實說是Xposed的做用其實也不是,主要是模塊編寫的好就能夠了,主要是利用Xposed的牛逼Hook技術實現的,下面就先來介紹一下這個脫殼模塊工具ZjDroid的原理,由於他是開源的,因此咋們直接分析源碼便可,源碼的下載地址:https://github.com/halfkiss/ZjDroid 不過惋惜的時候他只公開了Java層的代碼,而native層的代碼並無公開,可是分析源碼以後會發現最重要的功能就在native層,不過也不要緊,等分析到那裏的時候我在給你們講解底層的大體實現方案便可。java


1. 源碼分析ZjDroid原理(

下面就來詳細的分析一下ZjDroid工具的源碼吧,他是一個Eclipse工程導入很簡單,基於以前的Xposed模塊編寫的經驗,咱們知道找到入口代碼也很簡單,在assets目錄下有一個xposed_init文件中就記錄了模塊的入口類:git

而後咱們直接進入到這個類查看便可:github

看到了,遵循統一規則,實現了IXposedHookLoadPackage接口,實現handleLoadPackage回調方法便可,下面繼續分析入口方法ModuleContext的initModuleContextshell

 

發現這開始攔截Application的onCreate方法了,而這個方法通常是每一個應用程序的啓動方法,在這裏作攔截操做也是合情合理的,在看看攔截以後作了什麼,也就是ApplicationOnCreateHook類的實現:設計模式

  在這裏開始了真正的攔截操做了,主要是添加了一個廣播,也就是說設備中每一個應用在啓動的時候都回去註冊這個廣播,而若是後續發送一個這樣對應Action的廣播的話,每一個應用程序都會收到。因此這裏能夠看到,核心工做就在這個廣播的接受以後作了,接下來繼續去看這個廣播的定義:

  果真在這裏,能夠看到了首先會經過發送廣播的intent中攜帶一些數據過來,主要是兩個數據:

一個是進程id:api

這個做用主要是爲了過濾其餘應用,只處理本應用的邏輯,由於這個廣播發送以後全部的應用都能接收到,可是咱們脫殼有時候確定只是針對於某一個應用,那麼只須要在這個應用的廣播接收中作處理便可。cookie

一個是命令字符串:這個是爲了發送廣播能夠支持多種功能,後面分析也能夠看到的確有不少功能的。app


而後這裏獲得命令以後就開始構造一個命令執行器類,這裏用到了設計模式中的命令模式。下面繼續看看有哪幾種命令執行器類:框架

 

在這個方法中就開始分析了這裏支持的哪幾種命令類,下面來一一分析一下:函數

第一個命令: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層的代碼公開,可是經過這裏傳遞的參數能夠了解到
 

命令用法: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進行攔截而後添加監控代碼便可。


3、命令總結

上面就從源碼的角度徹底分析完了ZjDroid工具的功能了,下面就來總結一下:

一、獲取APK當前加載DEX文件信息
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」dump_dexinfo」}’

二、獲取指定DEX文件包含可加載類名
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」dump_class」,」dexpath」:」*****」}’

三、根據Dalvik相關內存指針動態反編譯指定DEX,並以文件形式保存
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」backsmali」,」dexpath」:」*****」}’

四、Dump指定DEX內存中的數據並保存到文件(數據爲odex格式,可在pc上反編譯)
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」dump_dexfile」,」dexpath」:」*****」}’

五、Dump指定內存空間區域數據到文件
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」dump_mem」,」start」:1234567,」length」:123}’

六、Dump Dalvik堆棧信息到文件,文件能夠經過java heap分析工具分析處理
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」dump_heap」}’

七、運行時動態調用Lua腳本
該功能能夠經過Lua腳本動態調用java代碼。使用場景:能夠動態調用解密函數,完成解密。能夠動態觸發特定邏輯。
am broadcast -a com.zjdroid.invoke –ei target pid –es cmd ‘{「action」:」invoke」,」filepath」:」****」}’

八、相關命令執行結果查看
一、命令執行結果
adb shell logcat -s zjdroid-shell-{package name}
二、敏感API調用監控輸出結果
adb shell logcat -s zjdroid-apimonitor-{package name}


三、總結

好了,到這裏咱們就講解完了基於Xposed框架的脫殼神器ZjDroid的實現原理以及具體用法。而這裏也感覺到了Xposed框架的強大之處,固然這也只是一部分,後面還能夠利用這個框架編寫遊戲外掛等操做。


四、源碼







附件列表

相關文章
相關標籤/搜索