昨天在逆向某App
的時候,發現有個加密工具類中的native
方法是用C語言
編寫的,隱藏在so
文件中。某大佬推薦逆向工具unidbg
,能在pc
端直接調用so
文件中的函數,最終成功解決了問題。
逆向工具之unidbg目錄
一、unidbg
引入
逆向某App
,反編譯dex
得到Java
代碼,但是有兩個加密工具類中的方法放到so
文件中。
方法的實現用的C語言
編寫的,放在了so
文件中。在Java
中,動態加載so
文件,使用native
方法的形式隱藏了方法的方法體。難道偉大的逆向工程就此放棄?這顯然不符合我們技術人的性格,肯定要想方設法弄出來。
二、unidbg
概述
unidbg
是一個基於 unicorn
的逆向工具,可以直接調用Android
和iOS
中的 so
文件。項目的GitHub
地址爲https://github.com/zhkl0228/unidbg
我使用unidbg
,直接調用libbaseEncryptLib.so
、libencryptLib.so
中的方法,這樣就不用想破腦袋去逆向so
文件了。
so
文件是unix
系統中的動態連接庫,屬於二進制文件,作用相當於windows
系統中的.dll
文件。在Android
中也可調用動態庫文件(*.so),一般會將加密算法、密碼等重要的方法、信息使用C語言
編寫,然後編譯成so
文件,增強了軟件的安全性
。
三、unidbg
使用姿勢
1、下載unidbg
項目
下載地址:https://github.com/zhkl0228/unidbg
2、導入到IDEA中
unidbg
項目用Java
編寫,並且上面下載的是一個標準的maven
項目。我這裏演示導入到IDEA
中,如果你熟悉其它的IDE
,也可以自己去弄。(順帶一提,如果你之前沒接觸過Java語言,要確保電腦安裝好JDK
、maven
)
①、解壓壓縮包
②、打開IDEA
,導入解壓的項目
瀏覽到剛剛解壓好的文件夾
後面一路無腦next
即可。。。
第一次導入此項目會自動下載一些jar
包,和網速、maven
服務器有關,耐心等待吧。
3、測試unidbg
項目中的src/test/java/com/xxxx/frameworks/core/encrypt
路徑中有一個TTEncrypt
測試用例,直接執行其中的main
方法。
控制檯打印相關調用信息,說明項目導入成功。
4、運行自己的so
文件
在前面,我們不是遇到了libbaseEncryptLib.so
、libencryptLib.so
文件麼,利用unidbg
直接調用so
文件中 的方法。下面演示調用libencryptLib.so
文件中的getGameKey
函數。
①、編寫EncryptUtilsJni
類
package cn.hestyle;
import com.github.unidbg.Module;
import com.github.unidbg.arm.ARMEmulator;
import com.github.unidbg.linux.android.AndroidARMEmulator;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import java.io.File;
import java.io.IOException;
/**
* description: EncryptUtils調用so
*
* @author hestyle
* @version 1.0
* @className unidbg->EncryptUtilsJni
* @date 2020-05-20 22:01
**/
public class EncryptUtilsJni extends AbstractJni {
// ARM模擬器
private final ARMEmulator emulator;
// vm
private final VM vm;
// 載入的模塊
private final Module module;
private final DvmClass TTEncryptUtils;
/**
*
* @param soFilePath 需要執行的so文件路徑
* @param classPath 需要執行的函數所在的Java類路徑
* @throws IOException
*/
public EncryptUtilsJni(String soFilePath, String classPath) throws IOException {
// 創建app進程,包名可任意寫
emulator = new AndroidARMEmulator("cn.hestyle");
Memory memory = emulator.getMemory();
// 作者支持19和23兩個sdk
memory.setLibraryResolver(new AndroidResolver(23));
// 創建DalvikVM,利用apk本身,可以爲null
vm = ((AndroidARMEmulator) emulator).createDalvikVM(null);
// (關鍵處1)加載so,填寫so的文件路徑
DalvikModule dm = vm.loadLibrary(new File(soFilePath), false);
// 調用jni
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
// (關鍵處2)加載so文件中的哪個類,填寫完整的類路徑
TTEncryptUtils = vm.resolveClass(classPath);
}
/**
* 調用so文件中的指定函數
* @param methodSign 傳入你要執行的函數信息,需要完整的smali語法格式的函數簽名
* @param args 是即將調用的函數需要的參數
* @return 函數調用結果
*/
private String myJni(String methodSign, Object ...args) {
// 使用jni調用傳入的函數簽名對應的方法()
Number ret = TTEncryptUtils.callStaticJniMethod(emulator, methodSign, args);
// ret存放返回調用結果存放的地址,獲得函數執行後返回值
StringObject str = vm.getObject(ret.intValue() & 0xffffffffL);
return str.getValue();
}
/**
* 關閉模擬器
* @throws IOException
*/
private void destroy() throws IOException {
emulator.close();
System.out.println("emulator destroy...");
}
public static void main(String[] args) throws IOException {
// 1、需要調用的so文件所在路徑
String soFilePath = "src/test/resources/myso/libencryptLib.so";
// 2、需要調用函數所在的Java類完整路徑,比如a/b/c/d等等,注意需要用/代替.
String classPath = "com/.../EncryptUtils";
// 3、需要調用函數的函數簽名,我這裏調用EncryptUtils中的getGameKey方法,由於此方法沒有參數列表,所以不需要傳入
String methodSign = "getGameKey()Ljava/lang/String;";
EncryptUtilsJni encryptUtilsJni = new EncryptUtilsJni(soFilePath, classPath);
// 輸出getGameKey方法調用結果
System.err.println(encryptUtilsJni.myJni(methodSign));
encryptUtilsJni.destroy();
}
}
②、參數說明
EncryptUtilsJni
類中最重要的設置爲main
方法中的soFilePath
、classPath
、methodSign
三個參數,它們的作用在main方法中已經註釋過了,這裏再次解釋一下。
soFilePath
,填寫你需要調用的so文件路徑
classPath
,填寫你需要調用的函數所在Java類的完整類路徑。
methodSign
,填寫你要調用的函數簽名,語法爲smali。(在jadx
中,直接可以看smali
代碼)
如果你要調用的函數還需要傳入參數,直接傳入myJni
方法中即可,myJni
方法中省略args
參數就是供你傳入參數。
③、執行結果
四、分析so
文件的IDA
工具
IDA
工具是反彙編so
文件的強大工具,由於libencryptLib.so
文件比較簡單,並且getGameKey
函數返回的是一個常量,並沒有複雜的處理過程,所以可以直接查看。
首先用IDA
打開libencryptLib.so
文件
查看反彙編得到的代碼。
五、總結
unidbg
確實很強大,直接在pc
端模擬調用so
文件,省去了反彙編逆向so
文件的麻煩。上面的教程只演示了unidbg
項目的導入、封裝自己的調用so
文件的API
,其實這只是入門了,unidbg
還支持斷點調試so
文件,也能導入到IDA
中進行動態調試,自己去研究下吧,博主我也比較菜。
😂😂😂