zhkl0228 / unidbg

Allows you to emulate an Android native library, and an experimental iOS emulation
Apache License 2.0
3.7k stars 938 forks source link

关于unidbg加载so文件,多线程造成的内存不可读问题 #527

Open reachcool opened 1 year ago

reachcool commented 1 year ago

加载某音的metasec_ml.so时, 通过设置

emulator.getBackend().registerEmuCountHook(10000);
emulator.getSyscallHandler().setVerbose(true);
emulator.getSyscallHandler().setEnableThreadDispatcher(true);

来实现多线程加载,但是 当emulator.getBackend().registerEmuCountHook(10000);设置为较大的参数,如1000--10000时 出现如下Fetch memory failed:问题:

`

JNIEnv->GetStaticMethodID(com/bytedance/mobsec/metasec/ml/MS.a()V) => 0x4bfa55cc was called from RWX@0x4023f773[libmetasec_ml.so]0x3f773 stack corruption detected [crash]A/libc: stack corruption detected Exception in thread "main" java.lang.IllegalStateException: Illegal JNI version: 0x1 at com.github.unidbg.linux.android.dvm.BaseVM.checkVersion(BaseVM.java:207) at com.github.unidbg.linux.android.dvm.DalvikModule.callJNI_OnLoad(DalvikModule.java:39) at com.github.unidbg.linux.android.dvm.BaseVM.callJNI_OnLoad(BaseVM.java:343) at com.bytedance.frameworks.core.encrypt.MetaSec.(MetaSec.java:96) at com.bytedance.frameworks.core.encrypt.MetaSec.main(MetaSec.java:108) File closed 'com.github.unidbg.linux.file.LocalAndroidUdpSocket@277c0f21' from RWX@0x4001b314[libc.so]0x1b314 [14:18:52 774] WARN [com.github.unidbg.arm.AbstractARMEmulator] (AbstractARMEmulator$1:64) - Fetch memory failed: address=0x0, size=1, value=0x0, PC=null, LR=unidbg@0xffff0000 [14:18:52 775] WARN [com.github.unidbg.AbstractEmulator] (AbstractEmulator:420) - emulate null exception sp=unidbg@0x403e8000, msg=unicorn.UnicornException: Invalid memory fetch (UC_ERR_FETCH_UNMAPPED), offset=2ms exit with code: 1

Process finished with exit code 1

`

如果设置emulator.getBackend().registerEmuCountHook(10000);的参数为100-200时,出现如下Read memory failed: 问题:

`JNIEnv->GetStaticMethodID(com/bytedance/mobsec/metasec/ml/MS.a()V) => 0x4bfa55cc was called from RWX@0x4023f773[libmetasec_ml.so]0x3f773 [14:23:01 980] WARN [com.github.unidbg.arm.AbstractARMEmulator] (AbstractARMEmulator$1:64) - Read memory failed: address=0x9, size=4, value=0x0, PC=RWX@0x4023f718[libmetasec_ml.so]0x3f718, LR=RWX@0x4023334d[libmetasec_ml.so]0x3334d [14:23:01 982] WARN [com.github.unidbg.AbstractEmulator] (AbstractEmulator:420) - emulate unidbg@0x400f2161 exception sp=unidbg@0xbffff5c0, msg=unicorn.UnicornException: Invalid memory read (UC_ERR_READ_UNMAPPED), offset=2ms Exception in thread "main" java.lang.IllegalStateException: Illegal JNI version: 0xffffffff at com.github.unidbg.linux.android.dvm.BaseVM.checkVersion(BaseVM.java:207) at com.github.unidbg.linux.android.dvm.DalvikModule.callJNI_OnLoad(DalvikModule.java:39) at com.github.unidbg.linux.android.dvm.BaseVM.callJNI_OnLoad(BaseVM.java:343) at com.bytedance.frameworks.core.encrypt.MetaSec.(MetaSec.java:96) at com.bytedance.frameworks.core.encrypt.MetaSec.main(MetaSec.java:108)

Process finished with exit code 1

` 如果不设置emulator.getBackend().registerEmuCountHook(200); 会出现

JNIEnv->GetStaticMethodID(com/bytedance/mobsec/metasec/ml/MS.a()V) => 0x4bfa55cc was called from RWX@0x4023f773[libmetasec_ml.so]0x3f773 bionic_clone fn=RWX@0x4006adbc[libc.so]0x6adbc bionic_clone fn=RWX@0x4006adbc[libc.so]0x6adbc

便卡住停止不动了。 请各位大牛帮忙看看问题出在哪里了。 代码

`public class MetaSec extends AbstractJni implements IOResolver<AndroidFileIO> {

    private final AndroidEmulator emulator;
    private final VM vm;

    private final Module module;

    private final DvmClass TTEncryptUtils;

    private final boolean logging;

    MetaSec(boolean logging) throws IOException {
        this.logging = logging;

        emulator = AndroidEmulatorBuilder.for32Bit()
                .setProcessName("metasec.test")
                .addBackendFactory(new Unicorn2Factory(true))
                .build(); // 创建模拟器实例,要模拟32位或者64位,在这里区分
        //emulator.getBackend().registerEmuCountHook(200);
        emulator.getSyscallHandler().addIOResolver(this);
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析

//        Logger.getLogger("com.github.unidbg.linux.ARM32SyscallHandler").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.unix.UnixSyscallHandler").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.AbstractEmulator").setLevel(Level.ALL);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm.DalvikModule").setLevel(Level.ALL);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm.DalvikVM").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm.BaseVM").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.LinuxModule").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.AndroidElfLoader").setLevel(Level.DEBUG);

        vm = emulator.createDalvikVM( new File("E:\\Douyin\\unidbg-0.9.7\\unidbg-android\\src\\test\\resources\\dylib\\base.apk")); // 创建Android虚拟机

        vm.setJni(this);
        vm.setVerbose(true); // 设置是否打印Jni调用细节

        emulator.getSyscallHandler().setVerbose(true);
        emulator.getSyscallHandler().setEnableThreadDispatcher(true);

        vm.loadLibrary(new File("unidbg-android/src/test/resources/dylib/libc.so"), true);
        DvmClass h = vm.resolveClass("ms/bd/c/k");
        DvmClass a0 = vm.resolveClass("ms/bd/c/a0",h);

        vm.resolveClass("com/bytedance/mobsec/metasec/ml/MS",a0);

        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/dylib/libmetasec_ml.so"), true);

        Pointer jniEnv = vm.getJNIEnv();
        System.out.println("ENV=-===->" + jniEnv);

        //dm.callJNI_OnLoad(emulator); // 手动执行JNI_OnLoad函数
        module = dm.getModule(); //
        vm.callJNI_OnLoad(emulator, module);
        TTEncryptUtils = vm.resolveClass("ms/bd/c/b");
    }

    void destroy() {
        IOUtils.close(emulator);
        if (logging) {
            System.out.println("destroy");
        }
    }

    public static void main(String[] args) throws Exception {
        MetaSec test = new MetaSec(true);

        byte[] data = test.ttEncrypt();
        System.out.println(data);

        test.destroy();
    }

    byte[] ttEncrypt() {

        ByteArray array = TTEncryptUtils.callStaticJniMethodObject(emulator, "a(IILJava/lang/String,LJava/lang/String,[LJava/lang/String)[LJava/lang/String" ); // 执行Jni方法
        return array.getValue();
    }

//    @Override
//    public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
//
//        if (signature.equals("com/bytedance/mobsec/metasec/ml/MS->a()V")){
//            return null;
//        }
//
//        return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);
//    }

    @Override
    public FileResult<AndroidFileIO> resolve(Emulator<AndroidFileIO> emulator, String pathname, int oflags) {
        System.out.println("PATHNAME:" + pathname);
        if (pathname.equals("/system/lib/libc.so")){
            System.out.println("LIBSO");
            File reg = new File("unidbg-android\\src\\main\\resources\\android\\sdk23\\lib\\libc.so");
            return FileResult.<AndroidFileIO>success(new SimpleFileIO(oflags,reg,pathname));
        }
        if (pathname.equals("/proc/self/exe")){
            System.out.println("EXE");
            return FileResult.<AndroidFileIO>success(new SimpleFileIO(oflags, new File("E:\\Douyin\\unidbg-0.9.7\\unidbg-android\\src\\test\\resources\\dylib\\base.apk"), pathname));
        }
        if (pathname.equals("/sys/devices/system/cpu/online")){
            System.out.println("ONLINE");
            return FileResult.<AndroidFileIO>success(new SimpleFileIO(oflags, new File("E:\\Douyin\\unidbg-0.9.7\\unidbg-android\\src\\test\\resources\\dylib\\online"), pathname));
        }

        return null;
    }

    @Override
    public int getStaticIntField(BaseVM vm, DvmClass dvmClass, String signature) {
        if ("com/bytedance/mobsec/metasec/ml/MS->a()V".equals(signature)) {
            return 0x40;
        }
        throw new UnsupportedOperationException(signature);
    }
    @Override
    public void callVoidMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {
        switch (signature) {
            case "com/bytedance/mobsec/metasec/ml/MS->a()V":
                System.out.println("> Patched: com/bytedance/mobsec/metasec/ml/MS->a()V");
                return;
        }
        super.callVoidMethod(vm, dvmObject, signature, varArg);
    }

`

wtx0820 commented 1 year ago

解决了吗

joshuachenn commented 11 months ago

同样的问题,楼主解决了吗?运行起来我打开了traceCode功能,貌似是通过bionic_clone创建了子线程,然后一直循环不停的跑代码,JNI_OnLoad一直没有办法执行完成,初始化环境没有设置好的话跑这个so的其他函数貌似跑不了

reachcool commented 11 months ago

没解决,放弃了

在 2023-09-18 15:08:17,"joshuachenn" @.***> 写道:

同样的问题,楼主解决了吗?运行起来我打开了traceCode功能,貌似是通过bionic_clone创建了子线程,然后一直循环不停的跑代码,JNI_OnLoad一直没有办法执行完成,初始化环境没有设置好的话跑这个so的其他函数貌似跑不了

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

hongri8488 commented 4 months ago

请问有人解决这个问题吗?

Zxqi47 commented 3 months ago

真没人能解决吗