逆向工具之unidbg(在pc端模擬執行so文件中的函數)

  昨天在逆向某App的時候,發現有個加密工具類中的native方法是用C語言編寫的,隱藏在so文件中。某大佬推薦逆向工具unidbg,能在pc端直接調用so文件中的函數,最終成功解決了問題。

一、unidbg引入

  逆向某App,反編譯dex得到Java代碼,但是有兩個加密工具類中的方法放到so文件中。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
  方法的實現用的C語言編寫的,放在了so文件中。在Java中,動態加載so文件,使用native方法的形式隱藏了方法的方法體。難道偉大的逆向工程就此放棄?這顯然不符合我們技術人的性格,肯定要想方設法弄出來。

二、unidbg概述

  unidbg 是一個基於 unicorn 的逆向工具,可以直接調用AndroidiOS中的 so 文件。項目的GitHub地址爲https://github.com/zhkl0228/unidbg
  我使用unidbg,直接調用libbaseEncryptLib.solibencryptLib.so中的方法,這樣就不用想破腦袋去逆向so文件了。

:\color{red}備註:so文件是unix系統中的動態連接庫,屬於二進制文件,作用相當於windows系統中的.dll文件。在Android中也可調用動態庫文件(*.so),一般會將加密算法、密碼等重要的方法、信息使用C語言編寫,然後編譯成so文件,增強了軟件的安全性

三、unidbg使用姿勢

1、下載unidbg項目

  下載地址:https://github.com/zhkl0228/unidbg
在這裏插入圖片描述

2、導入到IDEA中

  unidbg項目用Java編寫,並且上面下載的是一個標準的maven項目。我這裏演示導入到IDEA中,如果你熟悉其它的IDE,也可以自己去弄。(順帶一提,如果你之前沒接觸過Java語言,要確保電腦安裝好JDKmaven

①、解壓壓縮包

在這裏插入圖片描述

②、打開IDEA,導入解壓的項目

在這裏插入圖片描述
  瀏覽到剛剛解壓好的文件夾
在這裏插入圖片描述
在這裏插入圖片描述
  後面一路無腦next即可。。。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
  第一次導入此項目會自動下載一些jar包,和網速、maven服務器有關,耐心等待吧。
在這裏插入圖片描述

3、測試unidbg

  項目中的src/test/java/com/xxxx/frameworks/core/encrypt路徑中有一個TTEncrypt測試用例,直接執行其中的main方法。
在這裏插入圖片描述
  控制檯打印相關調用信息,說明項目導入成功。
在這裏插入圖片描述

4、運行自己的so文件

  在前面,我們不是遇到了libbaseEncryptLib.solibencryptLib.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方法中的soFilePathclassPathmethodSign三個參數,它們的作用在main方法中已經註釋過了,這裏再次解釋一下。

soFilePath,填寫你需要調用的so文件路徑
classPath,填寫你需要調用的函數所在Java類的完整類路徑。
在這裏插入圖片描述
methodSign,填寫你要調用的函數簽名,語法爲smali。(在jadx中,直接可以看smali代碼)

在這裏插入圖片描述
:\color{red}備註:如果你要調用的函數還需要傳入參數,直接傳入myJni方法中即可,myJni方法中省略args參數就是供你傳入參數。

③、執行結果

在這裏插入圖片描述

四、分析so文件的IDA工具

  IDA工具是反彙編so文件的強大工具,由於libencryptLib.so文件比較簡單,並且getGameKey函數返回的是一個常量,並沒有複雜的處理過程,所以可以直接查看。

  首先用IDA打開libencryptLib.so文件
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
  查看反彙編得到的代碼。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

五、總結

  unidbg確實很強大,直接在pc端模擬調用so文件,省去了反彙編逆向so文件的麻煩。上面的教程只演示了unidbg項目的導入、封裝自己的調用so文件的API,其實這只是入門了,unidbg還支持斷點調試so文件,也能導入到IDA中進行動態調試,自己去研究下吧,博主我也比較菜。
  \color{red}若是喜歡,可以素質三連一下😂😂😂
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章