unidbg实战笔记(1)–基本的SoLoad调用流程

unidbg基本的加载流程

1.创建Android虚拟机

初始化的一个安卓模拟环境 32位或者 64位 ,指定SDK版本和进程
类似代码如下:

AndroidEmulator emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.xhs").build(); // 创建模拟器实例,要模拟32位或者64位,在这里区分
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析
        File file = new File("unidbg-android/src/test/resources/example_binaries/apk/xhs6830.apk");

        vm = emulator.createDalvikVM(file);
        vm.setVerbose(true);

我们在创建时刻 把apk load 进去了,方便后续查找so

2.load so file

基于load apk file,我们可以按需找到我们的libso文件,输入名字即可。

DalvikModule dm = vm.loadLibrary("shield", true); // 加载libttEncrypt.so到unicorn虚拟内存,加载成功以后会默认调用init_array等函数

vm.setJni(this);
module = dm.getModule(); //so的内存空间
System.out.println("call JNIOnLoad");
dm.callJNI_OnLoad(emulator);

找到指定的so文件同时 我们进行jnionload初始化并且开辟一段内存空间记录so文件的内存位置。

3.find Class

DvmClass XhsHttpInterceptor = vm.resolveClass("com/xingin/shield/http/XhsHttpInterceptor");

找到我们的目标调用类

使用resolveClass创建类加载即可 注意路径

4.call method

String methodSign = "initializeNative()V";
        XhsHttpInterceptor.callStaticJniMethod(emulator, methodSign, null);

使用创建的类 直接接调用方法名 注意方法名的类型 是smail风格的

callStaticJniMethod 表示静态方法 最后传入参数就可以了

5.java call implement(非必需)

java层的调用实现,通常so层都会调用java层的方法来完成操作。
虽然一些涉及底层的方法已经由unidbg实现
但是关于程序本身的方法实现还是要手动

举一个例子:

"com/xingin/shield/http/ContextHolder->deviceId:Ljava/lang/String;"

这个方法调用没有实现 很显然是返回string类型的设备id

对应的我们在方法里实现这个调用

@Override
    public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {
        switch (signature) {
            //author
            /**
             * 获取了deviceid
             */
            case "com/xingin/shield/http/ContextHolder->deviceId:Ljava/lang/String;":{
                return new StringObject(vm, DEVICE_ID);
            }
            case "com/xingin/shield/http/ContextHolder->sAppId:I":{
                return DvmInteger.valueOf(vm, (int) 3975851777L);
            }
        }
        return super.getStaticObjectField(vm, dvmClass, signature);
    }

6.代码调试 解决异常((非必需))

如果上面的步骤全部走位 依然没有完成调用。接下来就到了最重要也是最难的部分,代码调试。

关于这点我们放到后面来说。因为需要非常大的篇幅。

总结

unidbg非常实用,对于安全学习,逆向分析非常有意义。