Xposed框架的另一個功能就是實現應用的簡單脫殼,其實說是Xposed的做用其實也不是,主要是模塊編寫的好就能夠了,主要是利用Xposed的牛逼Hook技術實現的,下面就先來介紹一下這個脫殼模塊工具ZjDroid的原理,由於他是開源的,因此咋們直接分析源碼便可,源碼的下載地址:https://github.com/halfkiss/ZjDroid 不過惋惜的時候他只公開了Java層的代碼,而native層的代碼並無公開,可是分析源碼以後會發現最重要的功能就在native層,不過也不要緊,等分析到那裏的時候我在給你們講解底層的大體實現方案便可。java
下面就來詳細的分析一下ZjDroid工具的源碼吧,他是一個Eclipse工程導入很簡單,基於以前的Xposed模塊編寫的經驗,咱們知道找到入口代碼也很簡單,在assets目錄下有一個xposed_init文件中就記錄了模塊的入口類:git
而後咱們直接進入到這個類查看便可:github
看到了,遵循統一規則,實現了IXposedHookLoadPackage接口,實現handleLoadPackage回調方法便可,下面繼續分析入口方法ModuleContext的initModuleContextshell
發現這開始攔截Application的onCreate方法了,而這個方法通常是每一個應用程序的啓動方法,在這裏作攔截操做也是合情合理的,在看看攔截以後作了什麼,也就是ApplicationOnCreateHook類的實現:設計模式
一個是進程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的核心代碼:
命令用法: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工具的功能了,下面就來總結一下:
一、獲取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框架的強大之處,固然這也只是一部分,後面還能夠利用這個框架編寫遊戲外掛等操做。