現在很多app都把核心加密放到了so層,如果是Java層主動呼叫ndk的形式運行的話,用unidbg直接呼叫會很方便
unidbg快速入門使用
- 致謝
- 開始
- 代碼部分
- 初始化
- 主動呼叫
- 傳參
- 解決報錯
- 優化
- 最后
致謝
unidbg github地址 https://github.com/zhkl0228/unidbg
蟹蟹成哥的幫助 https://www.cnblogs.com/xbjss/p/12110083.html
還有肉絲姐的星球有好多干貨
開始
下載好后,用idea打開(需要預先配置好maven,這里不多說),最好上個機場,下載配置會快一點
全部搞定之后,到這個路徑
(C:\Users\Administrator\Desktop\unidbg-master\unidbg-android\src\test\java\com\bytedance\frameworks\core\encrypt\TTEncrypt.java)
跑一遍,能跑通就是配置完成了
代碼部分
初始化
直接看代碼
TTEncrypt(boolean logging) {
this.logging = logging;//是否log
emulator = new AndroidARMEmulator("com.qidian.dldl.official"); // 創建模擬器實體,要模擬32位或者64位,在這里區分
final Memory memory = emulator.getMemory(); // 模擬器的記憶體操作介面
memory.setLibraryResolver(new AndroidResolver(23)); // 設定系統類別庫決議
vm = emulator.createDalvikVM(null); // 創建Android虛擬機
vm.setVerbose(logging); // 設定是否列印Jni呼叫細節
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/libttEncrypt.so"), false); // 加載libttEncrypt.so到unicorn虛擬記憶體,加載成功以后會默認呼叫init_array等函式
dm.callJNI_OnLoad(emulator); // 手動執行JNI_OnLoad函式
module = dm.getModule(); // 加載好的libttEncrypt.so對應為一個模塊
TTEncryptUtils = vm.resolveClass("com/bytedance/frameworks/core/encrypt/TTEncryptUtils");//注冊呼叫類
}
- AndroidARMEmulator模擬器名字可以隨便的
- createDalvikVM(File file) 這個函式的file是apk檔案,有些簽名驗證的部分可以通過匯入apk檔案來讓他自動獲取簽名(成哥教的)
- vm.loadLibrary加載類的路徑可以通過idea直接右鍵復制,注意斜杠
- vm.resolveClass呼叫的類需要跟呼叫so的類一模一樣,在jadx中的smail代碼模式可以復制到

初始化完成后就是主動呼叫的部分了.主要是下面這一句話
主動呼叫
ByteArray array = TTEncryptUtils.callStaticJniMethodObject(emulator, "ttEncrypt([BI)[B", new ByteArray(vm, data), data.length); // 執行Jni方法
- ttEncrypt([BI)[B 是so中的方法
- ttEncrypt是方法名
- [BI是引數 byte[] , int
- [B是回傳值
也是可以從jadx中的smail代碼模式可以復制到
傳參
如果全都沒錯,而且是靜態注冊的話,已經可以正常跑起來了.
上面是byte和int 如果傳其它引數的話這邊大概有個參考
- Context
DvmObject context = vm.resolveClass("android/content/Context").newObject(null);
vm.addLocalObject(context);
- String
vm.addLocalObject(new StringObject(vm, "123"));
解決報錯
畢竟第一次使用,肯定會有各種各樣的報錯
- vm.setJni
直接按照上面寫的話有可能會出現這個關鍵詞的報錯
把
vm.setJni(this);
添加到初始化部分的代碼中
- java.lang.UnsupportedOperationException: com.xxx.object->getPackageManager()Landroid/content/pm/PackageManager;
這里的錯誤是我的so進行了簽名驗證,但是我只加載了so檔案,他沒
Landroid/content/pm/PackageManager
這個方法,就報錯了
可以通過重寫部分函式來把環境補齊
public DvmObject callObjectMethodV(BaseVM vm, DvmObject dvmObject, String signature, VaList vaList) {
if (signature.contains("->getPackageManager()Landroid/content/pm/PackageManager;")) {
return vm.resolveClass("Landroid/content/pm/PackageManager;").newObject(null);
}
return dvmObject;
}
因為extends AbstractJni 繼承了AbstractJni,可以看看AbstractJni 中有什么可以重寫的然后把so中需要的環境補齊,有時候可以回傳空物件,有時候可以手動生成一個物件傳過去給他呼叫
可以通過輸出signature來確定走了哪些地方是跟java層有關的
優化
public static void main(String[] args) throws Exception {
// for (int i = 0; i <100 ; i++) {
Long time1 = new Date().getTime();
XXEncrypt test = new XXEncrypt();
test.test();
test.destroy();
System.out.println(new Date().getTime() - time1);
// }
}
呼叫的時候可以創建物件之后多次呼叫,這樣就不用浪費創建物件的時間了,因為要創建個虛擬機所以耗時還是挺大了,至少可以節省100~200ms,實際呼叫的時間就可以降低到20ms左右了
但是,unidbg作者說了,unicron有記憶體泄漏的風險,所以這個物件是需要定期更換的,這個大家自己動動腦子咯
最后
unidbg實在太強大太方便辣
我加了個unidbg-web的服務,把主動呼叫變成可直接呼叫的介面,還能直接打包放到線上服務器上~
可以看下一篇(還沒寫)

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/205013.html
標籤:其他
上一篇:移動應用開發
