Android逆向:在 Unidbg 中解决 native 函数内调用 Java 方法的报错

背景与目标

在使用 Unidbg 对 Android .so 进行离线执行时,常会遇到 native 函数内部调用 Java 方法(JNIEnv 回调) 的情况。若未在 Unidbg 中提供对应的 Java 实现或模拟,通常会报出 "not implemented"、"FindClass 失败"、"GetMethodID 返回 null"、"类型不匹配"等错误。
UnsupportedOperationException
FindClass 失败
GetMethodID 为 null
类型不匹配
native 崩溃
出现错误
错误类型
在 AbstractJni 中实现相应方法
确认类名准确;考虑加载 APK/Dex 或在 findClass 中处理
校验 JNI 签名与方法名
返回正确 Dvm 类型(StringObject、DvmInteger 等)
开启 verbose;用 Inspector 查看寄存器/内存;必要时 patch 或绕过

原理

native 如何调用 Java?

在真实的 Android 环境中,native 获取到 JNIEnv* 后,会使用如下调用:

  • FindClass("com/example/Device")
  • GetStaticMethodID(...) / GetMethodID(...)
  • CallStaticObjectMethod(...) / CallObjectMethod(...)
  • 读取字段:GetStaticFieldID(...) / GetObjectField(...)

这些都属于"native 回调 Java"的过程。只要 native 里有这些调用,Unidbg 默认是"不知道如何返回"的,除非你提供"Java 世界"的实现或 stub。

Unidbg 如何承接 JNI 回调?
  • Unidbg 在创建 VM(Dalvik/ART)后,会通过 vm.setJni(...) 绑定一个 AbstractJni 的子类。
  • 当 native 通过 JNIEnv 调用 Java 方法时,Unidbg 会把这次调用"回调"到你的 AbstractJni 子类中对应的函数,例如:
    • callObjectMethod(...)
    • callStaticObjectMethod(...)
    • getStaticIntField(...) / getStaticObjectField(...)
  • 你需要在这些方法里,根据"类名 + 方法名 + 签名"判断当前调用是谁,并返回合适的 DvmObject<?>(如 StringObjectDvmInteger)。这样 native 就能得到期望值,继续执行。



启动:配置 Emulator + VM
加载 libdemo.so
执行 JNI_OnLoad
调用 JNI 导出函数
native 是否通过 JNIEnv 调用 Java?
路由到 AbstractJni 对应方法
返回模拟的 DvmObject 或基础类型
native 继续执行业务逻辑
将执行结果返回给 Unidbg


常见报错与原因

java.lang.UnsupportedOperationException: callObjectMethod ... not implemented

你的 AbstractJni 子类没有处理该 Java 方法的调用(类/方法/签名没匹配)。

FindClass("xxx") 返回空或抛异常

你的 Jni 没有正确处理 FindClass,或 vm.resolveClass("xxx") 对应的类没有可用(未加载 APK/Dex 或未 stub)。

GetMethodID/GetStaticMethodID 返回空

与上类似;签名不匹配尤为常见(注意 JNI 签名格式)。

返回类型不对导致崩溃

例如 native 期望 String,你却返回了一个非 StringObject;或者签名是 ()I(返回 int),你却返回了 DvmObject。

场景:

  • native 函数 doWork(Context ctx) 需要调用 Java 层获取设备信息(如 packageName、deviceId、Build.MODEL 等),再拼接返回一个签名字符串。
  • 在 Unidbg 中,我们用自定义 Jni 拦截这些调用并返回"伪造数据",让函数跑通。
native 中的伪代码示例:
c 复制代码
jstring Java_com_example_NativeBridge_doWork(JNIEnv* env, jclass clazz, jobject ctx) {
    jclass devCls = env->FindClass("com/example/Device");
    jmethodID getId = env->GetStaticMethodID(devCls, "getDeviceId", "(Landroid/content/Context;)Ljava/lang/String;");
    jstring deviceId = (jstring) env->CallStaticObjectMethod(devCls, getId, ctx);

    jclass ctxCls = env->FindClass("android/content/Context");
    jmethodID pkg = env->GetMethodID(ctxCls, "getPackageName", "()Ljava/lang/String;");
    jstring pkgName = (jstring) env->CallObjectMethod(ctx, pkg);

    jclass buildCls = env->FindClass("android/os/Build");
    jfieldID modelField = env->GetStaticFieldID(buildCls, "MODEL", "Ljava/lang/String;");
    jstring model = (jstring) env->GetStaticObjectField(buildCls, modelField);

    // 拼接签名(伪)
    // return "sign:" + deviceId + "|" + pkgName + "|" + model;
}

解决方案

方案一、用 AbstractJni 自定义方法返回值(最常用)
  • 优点:简单直接,适合没有完整 APK 的场景
  • 做法:匹配类名/方法名/签名,返回合理的 DvmObject 或基础类型,让 native 满足条件分支即可
unidbg 调用流程
java 复制代码
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.Module;

import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.utils.Inspector;

public class UnidbgJniDemo {

    private AndroidEmulator emulator;
    private VM vm;
    private Module module;

    public UnidbgJniDemo() {
        // 1) 构建 32 位 Emulator(如需 64 位:for64Bit)
        emulator = AndroidEmulatorBuilder.for32Bit().build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23)); // 指定 API Level

        // 2) 创建 VM(不加载 APK,亦可传 APK 文件以更真实)
        vm = emulator.createDalvikVM(null);
        vm.setVerbose(true); // 打开详细日志

        // 3) 设置自定义 Jni
        vm.setJni(new MyJni(vm));

        // 4) 加载目标 so 并执行 JNI_OnLoad
        // 确保 libdemo.so 可被找到(工作目录或搜索路径)
        DalvikModule dm = vm.loadLibrary("demo", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);
    }

    // 调用导出 JNI 函数:Java_com_example_NativeBridge_doWork
    public void callDoWork() {
        DvmClass bridge = vm.resolveClass("com/example/NativeBridge");
        // 构造一个假的 Context 对象(native 内部可能调用其方法)
        DvmObject<?> context = vm.resolveClass("android/content/Context").newObject(null);

        DvmObject<?> result = bridge.callStaticJniMethodObject(
                emulator,
                "doWork(Landroid/content/Context;)Ljava/lang/String;",
                context
        );

        System.out.println("doWork result = " + result.getValue());
    }

    public static void main(String[] args) {
        UnidbgJniDemo demo = new UnidbgJniDemo();
        demo.callDoWork();
    }

    // 自定义 Jni:模拟 Java 层方法
    static class MyJni extends AbstractJni {
        private final VM vm;

        public MyJni(VM vm) { this.vm = vm; }

        @Override
        public DvmClass findClass(VM vm, String className) {
            // 允许常用类被 resolve;若返回 null 则 FindClass 会失败
            return vm.resolveClass(className);
        }

        @Override
        public DvmObject<?> callStaticObjectMethod(
                VM vm, DvmClass dvmClass, String methodName, String signature, VarArgs varArgs) {

            String className = dvmClass.getName();
            // com/example/Device.getDeviceId(Landroid/content/Context;)Ljava/lang/String;
            if ("com/example/Device".equals(className)
                    && "getDeviceId".equals(methodName)
                    && "(Landroid/content/Context;)Ljava/lang/String;".equals(signature)) {
                DvmObject<?> context = varArgs.getObjectArg(0);
                return new StringObject(vm, "FAKE-DEVICE-ID-123456");
            }

            throw new UnsupportedOperationException("callStaticObjectMethod not implemented: "
                    + className + "." + methodName + signature);
        }

        @Override
        public DvmObject<?> callObjectMethod(
                VM vm, DvmObject<?> dvmObject, String methodName, String signature, VarArgs varArgs) {

            String className = dvmObject.getObjectType().getName();

            // android/content/Context.getPackageName()Ljava/lang/String;
            if ("android/content/Context".equals(className)
                    && "getPackageName".equals(methodName)
                    && "()Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "com.example.app");
            }

            throw new UnsupportedOperationException("callObjectMethod not implemented: "
                    + className + "." + methodName + signature);
        }

        @Override
        public DvmObject<?> getStaticObjectField(VM vm, DvmClass dvmClass, String fieldName, String signature) {
            String className = dvmClass.getName();

            // android/os/Build.MODEL:Ljava/lang/String;
            if ("android/os/Build".equals(className)
                    && "MODEL".equals(fieldName)
                    && "Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "Pixel-FAKE-Model");
            }

            // android/os/Build.MANUFACTURER:Ljava/lang/String;
            if ("android/os/Build".equals(className)
                    && "MANUFACTURER".equals(fieldName)
                    && "Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "Google");
            }

            return super.getStaticObjectField(vm, dvmClass, fieldName, signature);
        }

        @Override
        public int getStaticIntField(VM vm, DvmClass dvmClass, String fieldName) {
            String className = dvmClass.getName();
            // android/os/Build$VERSION.SDK_INT
            if ("android/os/Build$VERSION".equals(className) && "SDK_INT".equals(fieldName)) {
                return 23;
            }
            return super.getStaticIntField(vm, dvmClass, fieldName);
        }

        @Override
        public void registerNativeMethods(VM vm, DvmClass dvmClass, String className, DvmNativeMethod[] methods) {
            System.out.println("RegisterNatives for " + className + ", methods count=" + methods.length);
            super.registerNativeMethods(vm, dvmClass, className, methods);
        }
    }
}

方案二、加载 APK

配置说明:

将真实APK文件放在指定路径(修改new File("path/to/your/app.apk"))

确保APK中包含com.example.NativeBridge类

将目标SO库(如libnative-lib.so)放在工作目录或指定路径

只需在JNI中补充APK中缺少的Android系统方法

java 复制代码
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.Module;
import java.io.File;

public class ApkLoadedDemo {

    private AndroidEmulator emulator;
    private VM vm;
    private Module module;

    public ApkLoadedDemo() {
        // 1. 创建模拟器
        emulator = AndroidEmulatorBuilder.for32Bit().build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23)); // API Level 23

        // 2. 加载真实APK文件
        File apkFile = new File("path/to/your/app.apk");
        vm = emulator.createDalvikVM(apkFile);
        vm.setVerbose(true); // 启用详细日志

        // 3. 设置自定义Jni实现
        vm.setJni(new ApkJni(vm));

        // 4. 加载目标SO库
        DalvikModule dm = vm.loadLibrary("native-lib", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);
    }

    public void executeNativeMethod() {
        // 获取NativeBridge类
        DvmClass bridge = vm.resolveClass("com/example/NativeBridge");
        
        // 创建Context对象(实际应用中可能从APK中获取真实Context)
        DvmObject<?> context = vm.resolveClass("android/content/Context").newObject(null);
        
        // 调用doWork方法
        DvmObject<?> result = bridge.callStaticJniMethodObject(
            emulator,
            "doWork(Landroid/content/Context;)Ljava/lang/String;",
            context
        );
        
        System.out.println("Native method result: " + result.getValue());
    }

    public static void main(String[] args) {
        ApkLoadedDemo demo = new ApkLoadedDemo();
        demo.executeNativeMethod();
    }

    // 自定义JNI实现 - 仅需补充APK中缺少的方法
    static class ApkJni extends AbstractJni {
        private final VM vm;

        public ApkJni(VM vm) { this.vm = vm; }

        @Override
        public DvmObject<?> getStaticObjectField(VM vm, DvmClass dvmClass, String fieldName, String signature) {
            // 补充Build.MODEL字段
            if ("android/os/Build".equals(dvmClass.getName()) && 
                "MODEL".equals(fieldName) && 
                "Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "Pixel-5");
            }
            return super.getStaticObjectField(vm, dvmClass, fieldName, signature);
        }

        @Override
        public int getStaticIntField(VM vm, DvmClass dvmClass, String fieldName) {
            // 补充SDK版本
            if ("android/os/Build$VERSION".equals(dvmClass.getName()) && 
                "SDK_INT".equals(fieldName)) {
                return 30;
            }
            return super.getStaticIntField(vm, dvmClass, fieldName);
        }
    }
}

方案三、轻量Dex实现

java 复制代码
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.Module;
import com.github.unidbg.utils.Inspector;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

public class LightDexImplementation {

    private AndroidEmulator emulator;
    private VM vm;
    private Module module;

    public LightDexImplementation() {
        // 创建模拟器
        emulator = AndroidEmulatorBuilder.for32Bit().build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23)); // API Level 23

        // 创建虚拟机
        vm = emulator.createDalvikVM(null);
        vm.setVerbose(true); // 启用详细日志

        // 加载轻量Dex
        byte[] dexBytes = generateLightDex();
        DalvikModule dm = vm.load(dexBytes);
        dm.callJNI_OnLoad(emulator);

        // 设置Jni实现
        vm.setJni(new LightJni(vm));

        // 加载目标SO库
        dm = vm.loadLibrary("demo", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);
    }

    // 生成轻量Dex文件
    private byte[] generateLightDex() {
        DexBuilder dexBuilder = new DexBuilder();
        
        // 添加NativeBridge类
        dexBuilder.addClass("com/example/NativeBridge",
            "public class NativeBridge {\n" +
            "    public static native String doWork(android.content.Context ctx);\n" +
            "}");
        
        // 添加Device类
        dexBuilder.addClass("com/example/Device",
            "public class Device {\n" +
            "    public static String getDeviceId(android.content.Context ctx) {\n" +
            "        return \"LIGHT-DEX-DEVICE-ID\";\n" +
            "    }\n" +
            "}");
        
        return dexBuilder.build();
    }

    // 可选:生成轻量APK
    private void generateLightApk() throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        JarOutputStream jar = new JarOutputStream(baos);
        
        // 添加Dex文件
        jar.putNextEntry(new JarEntry("classes.dex"));
        jar.write(generateLightDex());
        jar.closeEntry();
        
        // 添加AndroidManifest.xml
        jar.putNextEntry(new JarEntry("AndroidManifest.xml"));
        jar.write((
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
            "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
            "    package=\"com.example.lightapp\">\n" +
            "    <application android:label=\"LightApp\">\n" +
            "    </application>\n" +
            "</manifest>"
        ).getBytes());
        jar.closeEntry();
        
        jar.close();
        
        // 保存APK文件
        try (FileOutputStream fos = new FileOutputStream("light-app.apk")) {
            fos.write(baos.toByteArray());
        }
    }

    public void executeDoWork() {
        // 从Dex中获取NativeBridge类
        DvmClass bridge = vm.resolveClass("com/example/NativeBridge");
        
        // 创建Context对象
        DvmObject<?> context = vm.resolveClass("android/content/Context").newObject(null);
        
        // 调用doWork方法
        DvmObject<?> result = bridge.callStaticJniMethodObject(
            emulator,
            "doWork(Landroid/content/Context;)Ljava/lang/String;",
            context
        );
        
        System.out.println("doWork result: " + result.getValue());
    }

    public static void main(String[] args) {
        LightDexImplementation demo = new LightDexImplementation();
        demo.executeDoWork();
    }

    // 轻量Jni实现
    static class LightJni extends AbstractJni {
        private final VM vm;

        public LightJni(VM vm) {
            this.vm = vm;
        }

        @Override
        public DvmObject<?> callObjectMethod(
                VM vm, DvmObject<?> dvmObject, String methodName, String signature, VarArgs varArgs) {
            
            // Context.getPackageName()
            if ("android/content/Context".equals(dvmObject.getObjectType().getName()) &&
                "getPackageName".equals(methodName) &&
                "()Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "com.example.lightapp");
            }
            
            return super.callObjectMethod(vm, dvmObject, methodName, signature, varArgs);
        }

        @Override
        public DvmObject<?> getStaticObjectField(VM vm, DvmClass dvmClass, String fieldName, String signature) {
            // Build.MODEL
            if ("android/os/Build".equals(dvmClass.getName()) &&
                "MODEL".equals(fieldName) &&
                "Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "LightDex-Device");
            }
            return super.getStaticObjectField(vm, dvmClass, fieldName, signature);
        }
    }
}
/*Dex 生成
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import com.android.dx.dex.DexOptions;
import com.android.dx.dex.file.DexFile;
import com.android.dx.dex.cf.CfTranslator;
import com.android.dx.cf.direct.DirectClassFile;
import com.android.dx.cf.direct.StdAttributeFactory;

public class DexGenerator {

    public static byte[] generateClass(String className, String code) throws IOException {
        // 使用ASM生成类字节码
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        
        // 类头
        cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, 
                 className.replace('.', '/'), 
                 null, "java/lang/Object", null);
        
        // 添加方法
        if (code.contains("getDeviceId")) {
            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, 
                    "getDeviceId", "()Ljava/lang/String;", null, null);
            mv.visitCode();
            mv.visitLdcInsn("ASM-GENERATED-ID");
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(1, 0);
            mv.visitEnd();
        }
        
        // 其他方法生成...
        
        cw.visitEnd();
        return cw.toByteArray();
    }

    public static byte[] createDexFile(byte[][] classBytes) throws IOException {
        DexOptions options = new DexOptions();
        DexFile dexFile = new DexFile(options);
        
        for (byte[] classByte : classBytes) {
            DirectClassFile cf = new DirectClassFile(classByte, null, null, false);
            cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
            
            dexFile.add(CfTranslator.translate(
                cf, 
                classByte, 
                new CfOptions(), 
                options
            ));
        }
        
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        dexFile.writeTo(out, null, false);
        return out.toByteArray();
    }
}
*/

方案四、RegisterNatives 监控与分析

一些 .so 通过 RegisterNatives 动态注册 JNI 方法,Unidbg 会回调到 registerNativeMethods,便于记录与分析。

  • 添加 RegisterNatives 钩子监控
  • 捕获并解析所有动态注册的 JNI 方法
  • 输出方法名、签名和函数指针
  • 适用于逆向分析和安全审计
  • 不影响正常功能执行
java 复制代码
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Backend;

public class RegisterNativesMonitor {

    private AndroidEmulator emulator;
    private VM vm;
    private Module module;

    public RegisterNativesMonitor() {
        // 创建模拟器
        emulator = AndroidEmulatorBuilder.for32Bit().build();
        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23)); // API Level 23

        // 创建虚拟机
        vm = emulator.createDalvikVM(null);
        vm.setVerbose(true); // 启用详细日志

        // 设置Jni实现
        vm.setJni(new MonitorJni(vm));

        // 加载目标SO库
        DalvikModule dm = vm.loadLibrary("demo", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);

        // 设置RegisterNatives钩子
        setupRegisterNativesHook();
    }

    private void setupRegisterNativesHook() {
        // 查找RegisterNatives函数地址
        long registerNativesAddr = module.findSymbol("RegisterNatives");
        if (registerNativesAddr == 0) {
            System.out.println("RegisterNatives symbol not found");
            return;
        }

        // 添加钩子
        emulator.getBackend().addHook(new RegisterNativesHook(), registerNativesAddr);
    }

    public void executeDoWork() {
        // 解析NativeBridge类
        DvmClass bridge = vm.resolveClass("com/example/NativeBridge");
        
        // 创建Context对象
        DvmObject<?> context = vm.resolveClass("android/content/Context").newObject(null);
        
        // 调用doWork方法
        DvmObject<?> result = bridge.callStaticJniMethodObject(
            emulator,
            "doWork(Landroid/content/Context;)Ljava/lang/String;",
            context
        );
        
        System.out.println("doWork result: " + result.getValue());
    }

    public static void main(String[] args) {
        RegisterNativesMonitor demo = new RegisterNativesMonitor();
        demo.executeDoWork();
    }

    // RegisterNatives钩子实现
    class RegisterNativesHook extends BlockHook {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            // 获取参数
            long envPtr = backend.getRegisters()[0]; // JNIEnv*
            long clazz = backend.getRegisters()[1];  // jclass
            long methodsPtr = backend.getRegisters()[2]; // JNINativeMethod*
            int methodCount = backend.getRegisters()[3]; // jint

            // 解析类名
            String className = vm.findClassByAddress(clazz).getName();
            
            System.out.println("RegisterNatives called for class: " + className);
            System.out.println("Method count: " + methodCount);

            // 解析JNINativeMethod数组
            long currentPtr = methodsPtr;
            for (int i = 0; i < methodCount; i++) {
                // 读取方法名指针
                long namePtr = backend.readPointer(currentPtr);
                String name = backend.readCString(namePtr);
                
                // 读取方法签名指针
                long sigPtr = backend.readPointer(currentPtr + emulator.getPointerSize());
                String signature = backend.readCString(sigPtr);
                
                // 读取函数指针
                long fnPtr = backend.readPointer(currentPtr + emulator.getPointerSize() * 2);
                
                System.out.printf("|-- Method %d: %s%s @ 0x%x%n", i + 1, name, signature, fnPtr);
                
                // 移动到下一个方法结构
                currentPtr += emulator.getPointerSize() * 3;
            }
        }
    }

    // 监控专用Jni实现
    static class MonitorJni extends AbstractJni {
        private final VM vm;

        public MonitorJni(VM vm) {
            this.vm = vm;
        }

        @Override
        public DvmObject<?> callStaticObjectMethod(
                VM vm, DvmClass dvmClass, String methodName, String signature, VarArgs varArgs) {

            // Device.getDeviceId()
            if ("com/example/Device".equals(dvmClass.getName()) &&
                "getDeviceId".equals(methodName) &&
                "(Landroid/content/Context;)Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "MONITOR-DEVICE-ID");
            }

            return super.callStaticObjectMethod(vm, dvmClass, methodName, signature, varArgs);
        }

        @Override
        public DvmObject<?> callObjectMethod(
                VM vm, DvmObject<?> dvmObject, String methodName, String signature, VarArgs varArgs) {

            // Context.getPackageName()
            if ("android/content/Context".equals(dvmObject.getObjectType().getName()) &&
                "getPackageName".equals(methodName) &&
                "()Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "com.example.monitor");
            }

            return super.callObjectMethod(vm, dvmObject, methodName, signature, varArgs);
        }

        @Override
        public DvmObject<?> getStaticObjectField(VM vm, DvmClass dvmClass, String fieldName, String signature) {
            // Build.MODEL
            if ("android/os/Build".equals(dvmClass.getName()) &&
                "MODEL".equals(fieldName) &&
                "Ljava/lang/String;".equals(signature)) {
                return new StringObject(vm, "Monitor-Device");
            }
            return super.getStaticObjectField(vm, dvmClass, fieldName, signature);
        }
    }
}
相关推荐
devnullcoffee2 小时前
2026年Amazon Listing优化完全指南:COSMO算法与Rufus AI技术解析
人工智能·python·算法·亚马逊运营·amazon listing·cosmo算法·rufus ai技术
输出输入2 小时前
IJ IDEA 目录结构
java
Kratzdisteln2 小时前
【1902】预先生成完整的树状PPT结构
java·前端·powerpoint
python机器学习ML2 小时前
机器学习——16种模型(基础+集成学习)+多角度SHAP高级可视化+Streamlit交互式应用+RFE特征选择+Optuna+完整项目
人工智能·python·机器学习·分类·数据挖掘·scikit-learn·集成学习
Kratzdisteln2 小时前
【1902】优化后的三路径学习系统
android·学习
Sylvia-girl2 小时前
Lambda表达式
java·开发语言
Pluchon2 小时前
硅基计划4.0 算法 动态规划入门
java·数据结构·算法·动态规划
Java程序员威哥2 小时前
Java应用容器化最佳实践:Docker镜像构建+K8s滚动更新(生产级完整模板+避坑指南)
java·开发语言·后端·python·docker·kubernetes·c#
shjita2 小时前
mr-----topn的用法
java