使用 Unidbg 调用 APK 中的 SO 文件的原生方法 - 示例
使用 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 参数。如果类或方法不存在,或者参数不匹配,将会导致调用失败。
原文地址: https://www.cveoy.top/t/topic/mP49 著作权归作者所有。请勿转载和采集!