【APP逆向42】unidbg之补环境

  • 简介:当我们使用unidbg调用so文件时,如果so中的c语言调用了java代码,则我们需要补充完整
  • 1.如,在某vip app中,我们在逆向时,找到了gsNav方法,它是在so文件实现的。我们正常按照unidbg操作
package com.nb.demo;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.jni.ProxyDvmObject;
import com.github.unidbg.memory.Memory;

import java.io.File;
import java.util.TreeMap;

public class VIP2 extends AbstractJni {
    public static AndroidEmulator emulator;
    public static Memory memory;
    public static VM vm;
    public static Module module;

    public VIP2() {
        // 1.创建设备(32位或64位模拟器), 具体看so文件在哪个目录。 在armeabi-v7a就选择32位
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.che168.autotradercloud").build();

        // 2.获取内存对象(可以操作内存)
        memory = emulator.getMemory();

        // 3.设置安卓sdk版本(只支持19、23)
        memory.setLibraryResolver(new AndroidResolver(23));

        // 4.创建虚拟机(运行安卓代码需要虚拟机,就想运行py代码需要python解释器一样)
        vm = emulator.createDalvikVM(new File("unidbg-android/apks/vip/v7.83.3.apk"));
        vm.setJni(this);
        //vm.setVerbose(true); //执行日志

        //5.加载so文件
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/apks/vip/libkeyinfo.so"), false);
        dm.callJNI_OnLoad(emulator);

        // 6.dm代表so文件,dm.getModule()得到module对象,基于module对象可以访问so中的成员。
        module = dm.getModule();
    }

    public void getSign() {
        TreeMap<String, String> map = new TreeMap<String, String>();
        map.put("app_name", "achievo_ad");
        map.put("app_version", "7.83.3");
        map.put("channel", "oziq7dxw:::");
        map.put("device", "M2007J17C");
        map.put("device_token", "2bc523e3-b5b9-3ee1-9156-af6bcd9d0f30");
        map.put("manufacturer", "Xiaomi");
        map.put("mf_cid", "HaUTI3uMj5Kamj1KNFU/rDuLk2GTx4yTGrQDuEgDtjmeKVraHn6r7YHRyKgntGhL");
        map.put("mf_regPlat", "1");
        map.put("os_version", "29");
        map.put("regPlat", "1");
        map.put("regid", "HaUTI3uMj5Kamj1KNFU/rDuLk2GTx4yTGrQDuEgDtjmeKVraHn6r7YHRyKgntGhL");
        map.put("rom", "Dalvik/2.1.0 (Linux; U; Android 10; M2007J17C MIUI/V12.0.11.0.QJSCNXM)");
        map.put("skey", "6692c461c3810ab150c9a980d0c275ec");
        map.put("status", "1");
        map.put("vipruid", "");
        map.put("warehouse", "VIP_NH");

        DvmClass ctxClass = vm.resolveClass("android/content/Context");
        DvmObject<?> ctxObject = ctxClass.newObject(null); //创建对象

        //找到类
        DvmClass cls = vm.resolveClass("com/vip/vcsp/KeyInfo");
        String method = "gsNav(Landroid/content/Context;Ljava/util/Map;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";

        // 调用方法
        StringObject obj = cls.callStaticJniMethodObject(
                emulator,
                method,
                ctxObject,
                ProxyDvmObject.createObject(vm, map),
                new StringObject(vm, ""),
                false
        );

        String dataString = obj.getValue();
        System.out.println(dataString);

    }

    public static void main(String[] args) {
        VIP2 obj = new VIP2();
        obj.getSign();
    }
}
  • 2.执行以上代码,我们发现会报错,如下:

  • 3.补环境,根据报错一个一个补充

    • 3.1:补充前
    • 3.2:补充后
  • 4.按照上面的方法,逐一补充完,最终完整代码

package com.nb.demo;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.jni.ProxyDvmObject;
import com.github.unidbg.memory.Memory;

import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class VIP2 extends AbstractJni {
    public static AndroidEmulator emulator;
    public static Memory memory;
    public static VM vm;
    public static Module module;

    public VIP2() {
        // 1.创建设备(32位或64位模拟器), 具体看so文件在哪个目录。 在armeabi-v7a就选择32位
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.che168.autotradercloud").build();

        // 2.获取内存对象(可以操作内存)
        memory = emulator.getMemory();

        // 3.设置安卓sdk版本(只支持19、23)
        memory.setLibraryResolver(new AndroidResolver(23));

        // 4.创建虚拟机(运行安卓代码需要虚拟机,就想运行py代码需要python解释器一样)
        vm = emulator.createDalvikVM(new File("unidbg-android/apks/vip/v7.83.3.apk"));
        vm.setJni(this);
        //vm.setVerbose(true); //执行日志

        //5.加载so文件
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/apks/vip/libkeyinfo.so"), false);
        dm.callJNI_OnLoad(emulator);

        // 6.dm代表so文件,dm.getModule()得到module对象,基于module对象可以访问so中的成员。
        module = dm.getModule();
    }

    public void getSign() {
        TreeMap<String, String> map = new TreeMap<String, String>();
        map.put("app_name", "achievo_ad");
        map.put("app_version", "7.83.3");
        map.put("channel", "oziq7dxw:::");
        map.put("device", "M2007J17C");
        map.put("device_token", "2bc523e3-b5b9-3ee1-9156-af6bcd9d0f30");
        map.put("manufacturer", "Xiaomi");
        map.put("mf_cid", "HaUTI3uMj5Kamj1KNFU/rDuLk2GTx4yTGrQDuEgDtjmeKVraHn6r7YHRyKgntGhL");
        map.put("mf_regPlat", "1");
        map.put("os_version", "29");
        map.put("regPlat", "1");
        map.put("regid", "HaUTI3uMj5Kamj1KNFU/rDuLk2GTx4yTGrQDuEgDtjmeKVraHn6r7YHRyKgntGhL");
        map.put("rom", "Dalvik/2.1.0 (Linux; U; Android 10; M2007J17C MIUI/V12.0.11.0.QJSCNXM)");
        map.put("skey", "6692c461c3810ab150c9a980d0c275ec");
        map.put("status", "1");
        map.put("vipruid", "");
        map.put("warehouse", "VIP_NH");

        DvmClass ctxClass = vm.resolveClass("android/content/Context");
        DvmObject<?> ctxObject = ctxClass.newObject(null); //创建对象

        //找到类
        DvmClass cls = vm.resolveClass("com/vip/vcsp/KeyInfo");
        String method = "gsNav(Landroid/content/Context;Ljava/util/Map;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";

        // 调用方法
        StringObject obj = cls.callStaticJniMethodObject(
                emulator,
                method,
                ctxObject,
                ProxyDvmObject.createObject(vm, map),
                new StringObject(vm, ""),
                false
        );

        String dataString = obj.getValue();
        System.out.println(dataString);

    }

    public static void main(String[] args) {
        VIP2 obj = new VIP2();
        obj.getSign();
    }

    @Override
    public DvmObject<?> callObjectMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {
        //                      类型              方法        签名
        if(signature.equals("java/util/TreeMap->entrySet()Ljava/util/Set;")){
            TreeMap map = (TreeMap) dvmObject.getValue();
            Set set = map.entrySet();
            return vm.resolveClass("java/util/Set").newObject(set);
        }
        if(signature.equals("java/util/Set->iterator()Ljava/util/Iterator;")){
            Set set = (Set) dvmObject.getValue();
            Iterator it = set.iterator();
            return vm.resolveClass("java/util/Iterator").newObject(it);
        }
        if(signature.equals("java/util/Iterator->next()Ljava/lang/Object;")){
            Iterator it = (Iterator) dvmObject.getValue();
            Object obj = it.next();     // Object是泛型,要用ProxyDvmObject.createObject处理下
            return ProxyDvmObject.createObject(vm,obj);
        }
        if(signature.equals("java/util/Map$Entry->getKey()Ljava/lang/Object;")){
            Map.Entry et = (Map.Entry) dvmObject.getValue();
            return ProxyDvmObject.createObject(vm,et.getKey());
        }
        if(signature.equals("java/util/Map$Entry->getValue()Ljava/lang/Object;")){
            Map.Entry v = (Map.Entry) dvmObject.getValue();
            return ProxyDvmObject.createObject(vm,v.getValue());
        }
        return super.callObjectMethod(vm, dvmObject, signature, varArg);
    }

    @Override
    public boolean callBooleanMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {
        if(signature.equals("java/util/Iterator->hasNext()Z")){
            Iterator it = (Iterator) dvmObject.getValue();
            return it.hasNext();    //布尔值,直接返回即可
        }
        return super.callBooleanMethod(vm, dvmObject, signature, varArg);
    }
}
  • 5.至此,环境补充结束,得到结果
posted @ 2025-05-16 21:12  Tony_xiao  阅读(471)  评论(0)    收藏  举报