使用 Unidbg 调用 APK 中的 SO 文件的原生方法 - 示例

本文将介绍如何使用 Unidbg 库调用 Android APK 文件中的 tes.so 库中的 sign 方法,该方法接受 6 个参数,包括应用上下文和 5 个字符串参数。以下是一个示例代码,它使用 Unidbg 调用 tes.so 中的 sign 方法,并传递 6 个参数。

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.DvmObject;
import com.github.unidbg.linux.android.dvm.DvmString;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.linux.android.dvm.jni.JniMethodInfo;
import com.github.unidbg.linux.android.dvm.jni.JniObject;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.utils.Inspector;

import java.io.File;
import java.io.IOException;

public class TesTest {

    public static void main(String[] args) throws IOException {
        File apkFile = new File("a.apk");

        AndroidEmulator emulator = new AndroidEmulator(abi -> {
            LibraryResolver resolver = new AndroidResolver(23);
            resolver.setLibraryPath(apkFile.getParentFile().getAbsolutePath() + File.separatorChar + "lib" + abi);
            return resolver;
        }, apkFile);

        // 加载apk
        DalvikModule bootstrap = emulator.createDalvikBootstrap(apkFile);

        // 加载tes.so
        Module tes = emulator.loadLibrary(new File(apkFile.getParentFile(), "libtes.so"));

        // 获取JNIEnv指针
        VM vm = emulator.createDalvikVM();
        vm.setJni(new TesJni(vm, tes));
        vm.setVerbose(true);
        DvmClass contextClass = vm.resolveClass("android/content/Context");
        DvmObject<?> context = contextClass.newObject(null);
        System.out.println("context=" + context);

        // 调用sign方法
        DvmClass signClass = vm.resolveClass("com/example/tes/Sign");
        DvmObject<?> sign = signClass.newObject(null);
        System.out.println("sign=" + sign);
        DvmObject<?>[] argsArray = new DvmObject[6];
        argsArray[0] = context;
        argsArray[1] = new DvmString(vm, "test");
        argsArray[2] = new DvmString(vm, "123");
        argsArray[3] = new DvmString(vm, "456");
        argsArray[4] = new DvmString(vm, "789");
        argsArray[5] = new DvmString(vm, "abc");
        JniObject result = sign.callJniMethodObject(emulator, "sign", "([Ljava/lang/Object;)Ljava/lang/Object;", argsArray);
        System.out.println("result=" + result.getValue());
    }

    private static class TesJni extends com.github.unidbg.linux.android.dvm.jni.ProxyJni {

        private final Module module;

        private TesJni(VM vm, Module module) {
            super(vm.getJni());
            this.module = module;
        }

        @Override
        public int RegisterNatives(Pointer env, Pointer clazz, JniMethodInfo[] methods, int nMethods) {
            if (methods == null || nMethods != 1) {
                return super.RegisterNatives(env, clazz, methods, nMethods);
            }

            JniMethodInfo method = methods[0];
            if (!"sign".equals(method.methodName)) {
                return super.RegisterNatives(env, clazz, methods, nMethods);
            }

            Memory memory = module.getProcess().getMemory();
            Pointer fnPtr = memory.allocate(4, "jni native function");

            JniObject jniObject = new JniObject(module, clazz);
            jniObject.replace(env);

            Inspector.inspect(methods);

            memory.setPointer(fnPtr, jni(this, "sign", jniObject, method));
            method.accessFlags = 0x100;
            method.nativeFunc = fnPtr;

            return 0;
        }

        private static native Object sign(Object[] args);
    }
}

需要注意的是,这个示例代码中的 com.example.tes.Sign 类必须存在于 tes.so 中,并且必须有一个名为 sign 的方法,接受 6 个 Object 参数。如果类或方法不存在,或者参数不匹配,将会导致调用失败。

使用 Unidbg 调用 APK 中的 SO 文件的原生方法 - 示例

原文地址: https://www.cveoy.top/t/topic/mP49 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录