Android native创建虚拟机

起因

前段时间看到看雪有篇文章讲百度壳的分析,讲的是native创建虚拟机来自主加载so,代码是基于dvm的。但是我直接改成art,在8.0上并没有成功,当时想着写art的脱壳机的时候再去研究一下原因,结果一拖再拖就没有下文了。最近又看到一个创建虚拟机来加载so的,看了一下代码,是基于art的,并且可以跑成功。于是就打算看看为啥之前的不行。

分析代码

相比于dvm的,art的那个代码多了如下部分:

1
2
3
4
5
6
7
    //1
JavaVMOption opt[4];
opt[0].optionString = "-Djava.class.path=/data/local/tmp/target-app.apk";
opt[1].optionString = "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
opt[2].optionString = "-Djava.library.path=/data/local/tmp";
opt[3].optionString = "-verbose:jni"; // may want to remove this, it's noisy
```
//2

registerNatives_t registerNatives;
registerNatives = (registerNatives_t) dlsym(libandroid_runtime_dso, “Java_com_android_internal_util_WithFramework_registerNatives”);
if (!registerNatives) {
// Attempt non-legacy version
registerNatives = (registerNatives_t) dlsym(libandroid_runtime_dso, “registerFrameworkNatives”);
if(!registerNatives) {
return -3;
}
}

1
2


//3

JNIEXPORT void InitializeSignalChain() {

}

JNIEXPORT void ClaimSignalChain() {

}

JNIEXPORT void UnclaimSignalChain() {

}

JNIEXPORT void InvokeUserSignalHandler() {

}

JNIEXPORT void EnsureFrontOfChain() {

}

JNIEXPORT void AddSpecialSignalHandlerFn() {

}

JNIEXPORT void RemoveSpecialSignalHandlerFn() {

}

```

第一部分主要是加载虚拟机的一些选项,对整个流程影响不大。
第二部分跟注册native函数有关,这里没有仔细分析。
第三部分较为关键,这里直接到导出了这些函数 。也是2个代码区别最大的地方。

如果直接在art下运行之前dvm的代码(需要把libdvm.so改为art)去加载,就会报一个错 > “E/libsigchain(3476): InitializeSignalChain is not exported by the main executable.”
表示主程序没有导出这个函数。 直接查看源码可以看到art确实会用到这些导出函数,另外源码中也在libsigchain中定义了这些函数,但是这些函数是直接调用abort的。
看到这里就有一个疑问,为啥我导出函数的时候会走我的函数,但是我不导出的时候直接调用libsigchain中的dummy函数。我想到的一点可能是函数名称重复导致的问题(其实也不能算问题)。由于我的主程序导出了这个函数,linker在找地址的时候就直接到找了我定义的函数。

引用

https://bbs.pediy.com/thread-216701.htm
https://github.com/rednaga/native-shim