zhkl0228 / unidbg

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

DalvikVM64.java _CallObjectMethodV 报错 #238

Closed sepyeight closed 3 years ago

sepyeight commented 3 years ago

log日志

### Trace Instruction [libnative-lib.so] [0x1e074] [ a3 43 01 d1 ] 0x4001e074: sub x3, x29, #0x50>>> x3=0xbffff5f0
### Trace Instruction [libnative-lib.so] [0x1e078] [ e0 03 0a aa ] 0x4001e078: mov x0, x10>>> x0=0xfffe0d30(-127696)
### Trace Instruction [libnative-lib.so] [0x1e07c] [ e9 07 00 f9 ] 0x4001e07c: str x9, [sp, #8]>>> x9=0xbffff778
### Trace Instruction [libnative-lib.so] [0x1e080] [ 60 01 3f d6 ] 0x4001e080: blr x11>>> x11=0xfffe01c0
[17:40:47 227]  WARN [com.github.unidbg.linux.ARM64SyscallHandler] (ARM64SyscallHandler:275) - handleInterrupt intno=2, NR=-1073744360, svcNumber=0x113, PC=unidbg@0xfffe01c4, LR=RX@0x4001e084[libnative-lib.so]0x1e084, syscall=null
com.github.unidbg.arm.backend.BackendException: dvmObject=null, dvmClass=null, jmethodID=unidbg@0xfffffffff6590850
    at com.github.unidbg.linux.android.dvm.DalvikVM64$20.handle(DalvikVM64.java:373)
    at com.github.unidbg.linux.ARM64SyscallHandler.hook(ARM64SyscallHandler.java:82)
    at com.github.unidbg.arm.backend.UnicornBackend$6.hook(UnicornBackend.java:291)
    at unicorn.Unicorn$NewHook.onInterrupt(Unicorn.java:128)
    at unicorn.Unicorn.emu_start(Native Method)
    at com.github.unidbg.arm.backend.UnicornBackend.emu_start(UnicornBackend.java:316)
    at com.github.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:398)
    at com.github.unidbg.AbstractEmulator.eFunc(AbstractEmulator.java:475)
    at com.github.unidbg.arm.AbstractARM64Emulator.eFunc(AbstractARM64Emulator.java:219)
    at com.github.unidbg.Module.emulateFunction(Module.java:154)
    at com.github.unidbg.linux.android.dvm.DvmObject.callJniMethod(DvmObject.java:128)
    at com.github.unidbg.linux.android.dvm.DvmClass.callStaticJniMethodObject(DvmClass.java:297)
    at com.example.nativetest.Test02.start(Test02.java:60)
    at com.example.nativetest.Test02.main(Test02.java:44)
[17:40:47 229]  WARN [com.github.unidbg.AbstractEmulator] (AbstractEmulator:417) - emulate RX@0x4001daa8[libnative-lib.so]0x1daa8 exception sp=unidbg@0xbffff510, msg=dvmObject=null, dvmClass=null, jmethodID=unidbg@0xfffffffff6590850, offset=16397ms
Exception in thread "main" java.lang.NullPointerException
    at com.example.nativetest.Test02.start(Test02.java:61)
    at com.example.nativetest.Test02.main(Test02.java:44)

trace后发现应该是CallObjectMethodV报错了 so文件是一个自己写的demo

#include <jni.h>
#include <string>
#include <android/log.h>

const char *get_packagename(JNIEnv *pEnv, jobject pJobject);

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_nativetest_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */, jobject context) {
    std::string hello = "Hello from C++";

    __android_log_print(ANDROID_LOG_ERROR, "TAG", "Hello from C++ => %s", hello.c_str());
    for (int i = 0; i < hello.length(); i++) {
        hello[i] = hello[i] ^ hello.length();
    }
    __android_log_print(ANDROID_LOG_ERROR, "TAG", "Hello from C++ => %s", hello.c_str());
    const char *pkgname = get_packagename(env, context);

    if (strcmp(pkgname, "com.example.nativetest") != -1) {
        __android_log_print(ANDROID_LOG_ERROR, "TAG", "pkg name => %s", pkgname);
    }
    return env->NewStringUTF(hello.c_str());
}

const char *get_packagename(JNIEnv *env, jobject context) {
    jclass content_class = env->FindClass("android/content/Context");
    if (content_class == nullptr) {
        __android_log_print(ANDROID_LOG_ERROR, "TAG", "find class error");
        return "";
    }
    jmethodID getPackageName_method = env->GetMethodID(content_class, "getPackageName",
                                                       "()Ljava/lang/String;");
    if (getPackageName_method == nullptr) {
        __android_log_print(ANDROID_LOG_ERROR, "TAG", "find method error");
        return "";
    }
    if (env->ExceptionCheck()) {
        return "";
    }
    jstring pkgname_string = (jstring) env->CallObjectMethod(context, getPackageName_method);
    const char *ret = env->GetStringUTFChars(pkgname_string,
                                             JNI_FALSE);
    __android_log_print(ANDROID_LOG_ERROR, "TAG", "pkgname => %s",
                        ret);
    return ret;
}

调试了一下午,不确定具体哪里出了问题,大佬可以看看吗? 调用使用的java脚本

package com.example.nativetest;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.linux.android.AndroidARM64Emulator;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

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

public class Test02 extends AbstractJni {

    private final VM vm;
    private final DvmClass dvmClass;
    private AndroidEmulator emulator;
    private String processName = "com.example.nativetest";
    private String className = "com.example.nativetest";
    private Memory memory;

    public Test02() {
        Logger.getRootLogger().setLevel(Level.DEBUG);
        emulator = createAndroidEmulator();
        memory = emulator.getMemory();
        memory.setLibraryResolver(createLibraryResolver(23));
        vm = createVM(null);
        vm.setJni(this);
        vm.setVerbose(true);

        DalvikModule dalvikModule = vm.loadLibrary(new File("unidbg-android/src/test/resources/example/arm64-v8a/libnative-lib02.so"), false);
        dvmClass = vm.resolveClass(className);
        emulator.traceCode();
    }

    private LibraryResolver createLibraryResolver(int ver) {
        return new AndroidResolver(ver);
    }

    public static void main(String[] args) throws IOException {
        Test02 Test02 = new Test02();
        Test02.start();
        Test02.stop();
    }

    private AndroidEmulator createAndroidEmulator() {
        if (emulator == null) {
            return new AndroidARM64Emulator(processName);
        }
        return emulator;
    }

    private VM createVM(File apk) {
        return emulator.createDalvikVM(apk);
    }

    private void start() {
        DvmObject result = dvmClass.callStaticJniMethodObject(emulator, "Java_com_example_nativetest_MainActivity_stringFromJNI(Landroid/content/Context;)Ljava/lang/String");  //我修改了这里可以直接识别Java_开头的方法
        System.out.println("result = " + result.getValue());
    }

    private void stop() throws IOException {
        emulator.close();
    }

    @Override
    public DvmObject<?> callObjectMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {
        if(signature.equals("android/content/Context->getPackageName()Ljava/lang/String;")){
            System.out.println("getPackageName");
        }
        return super.callObjectMethod(vm, dvmObject, signature, varArg);
    }

    @Override
    public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
        if(signature.equals("android/content/Context->getPackageName()Ljava/lang/String;")){
            System.out.println("getPackageName");
        }
        return super.callObjectMethodV(vm, dvmObject, signature, vaList);
    }
}
zhkl0228 commented 3 years ago

DvmObject result = dvmClass.callStaticJniMethodObject(emulator, "Java_com_example_nativetest_MainActivity_stringFromJNI(Landroid/content/Context;)Ljava/lang/String"); 这一行改成 DvmObject result = dvmClass.callStaticJniMethodObject(emulator, "Java_com_example_nativetest_MainActivity_stringFromJNI(Landroid/content/Context;)Ljava/lang/String", vm.resolveClass("android/content/Context").newObject(null));

zhkl0228 commented 3 years ago

另外: dvmClass = vm.resolveClass(className);这里的className为com/example/nativetest/MainActivity,再调用callStaticJniMethodObject的时候,方法名为stringFromJNI

sepyeight commented 3 years ago

改了代码忘了加参数了,谢谢大佬