unidbg调用so文件生成xgorgon

目前 App 基本都使用so加密签名算法,如果强行逆向so文件的话可能会消耗大量时间和资源。

之前用 xposed 采用 hook 的方法从程序计算签名,但是需要模拟器或者真机运行这个应用,使用效率不高。
也用过 jtype 启动JVM,然后通过 native 对so文件进行调用,因为每次都需要启动JVM,所以效率也不高。

unidbg 他不需要运行 app,也无需逆向 so 文件,通过在 app 中找到对应的 JNI 接口,然后用 unicorn 引擎直接执行这个 so 文件,所以效率相对要高不少。


unidbg特点

  • 模拟JNI调用API,可以调用JNI_OnLoad
  • 支持JavaVM,JNIEnv
  • 模拟系统调用
  • 支持ARM32和ARM64
  • 内联钩子(Inline Hook)
  • Android import hook
  • iOS 的一些hook工具 fishhook and substrate and whale hook
  • 支持简单的控制台调试器,gdb存根,实验性IDA android调试器服务器,指令跟踪,内存读/写跟踪
  • 支持iOS objc和Swift

unidbg环境配置

unidbg下载链接: https://github.com/zhkl0228/unidbg

IntelliJ IDEA可用于编辑unidbg源
在这里插入图片描述

下载完成之后示导入到 IDEA 中,当然你需要准备好java环境(jdk、maven)

在这里插入图片描述
选择Maven
在这里插入图片描述
等待加载完成之后,运行src/…/encrypt 中的TTEncrypt测试用例
在这里插入图片描述
如果控制台打印相关调用信息,说明已经导入成功。
在这里插入图片描述


加载libcms.so

看过这篇文章的应该已经生成xg的函数位置,所以不具体说了。《抖音xgorgon(0401)

下面准备调用libcms.so文件中的 leviathan 函数

新建一个java文件,编写TTEncryptDy类,我找了一个模版来进行修改

soFilePath :
需要调用的so文件所在路径。可以在 src/test/resources 目录下新建文件夹放入libcms.so
在这里插入图片描述
classPath:
需要调用函数所在的Java类完整路径,比如 a/b/c/d 等等,注意需要用/代替.

String classPath = "com.ss.sys.ces.a";

methodSign: 需要调用函数的函数签名,语法为smali。(在jadx中,直接可以看smali代码)

String methodSign = "leviathan(I[B)[B";

TTEncryptDy文件

package com.bytedance.frameworks.core.encrypt;

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.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;


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("com.dy.lx.lx");
        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       是即将调用的函数需要的参数
     */
    private String myJni(String methodSign, Object ...args) {
        // 使用jni调用传入的函数签名对应的方法() ret存放返回调用结果存放的地址,获得函数执行后返回值
        ByteArray ret = TTEncryptUtils.callStaticJniMethodObject(emulator, methodSign, args);

        //StringObject str = vm.getObject(ret.intValue() & 0xffffffffL);
        System.out.println(ret.toString());
        return ret.toString();
    }




    /**
     * 关闭模拟器
     * @throws IOException
     */
    private void destroy() throws IOException {
        emulator.close();
        System.out.println("emulator destroy...");
    }

    public static void main(String[] args) throws IOException {

        String soFilePath = "/Users/liwei/Desktop/unidbg/unidbg-android/src/test/resources/dylib/libcms.so";
        String classPath = "com.ss.sys.ces.a";

        String methodSign = "leviathan(I[B)[B";
        EncryptUtilsJni encryptUtilsJni = new EncryptUtilsJni(soFilePath, classPath);
        // 输出getGameKey方法调用结果
        System.err.println(encryptUtilsJni.myJni(methodSign));
        encryptUtilsJni.destroy();
    }
}

没写完,过星期了下班回家!下周再写

pass

猜你喜欢

转载自blog.csdn.net/weixin_43582101/article/details/107842928