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


0. 神器ZjDroid

Xposed框架的另外一個功能就是實現應用的簡單脫殼,其實說是Xposed的作用其實也不是,主要是模塊編寫的好就可以了,主要是利用Xposed的牛逼Hook技術實現的,下面就先來介紹一下這個脫殼模塊工具ZjDroid的原理,因為他是開源的,所以咋們直接分析源碼即可,源碼的下載地址:https://github.com/halfkiss/ZjDroid 不過可惜的時候他只公開了Java層的代碼,而native層的代碼並沒有公開,但是分析源碼之后會發現最重要的功能就在native層,不過也沒關系,等分析到那里的時候我在給大家講解底層的大致實現方案即可。


1. 源碼分析ZjDroid原理(

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

然后我們直接進入到這個類查看即可:

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

 

發現這開始攔截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層的代碼公開,但是通過這里傳遞的參數可以了解到
 

命令用法: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}


3、總結

好了,到這里我們就講解完了基於Xposed框架的脫殼神器ZjDroid的實現原理以及具體用法。而這里也感受到了Xposed框架的強大之處,當然這也只是一部分,后面還可以利用這個框架編寫游戲外掛等操作。


4、源碼







附件列表

     


    免責聲明!

    本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



     
    粵ICP備18138465號   © 2018-2025 CODEPRJ.COM