本帖最后由 L剑仙 于 2020-3-1 18:53 编辑
看雪发一遍了,在52再发一次
菜鸟最近初学脱壳,必须得先搞明白dex的加载流程,才能搞懂哪里到了脱壳的时机。n6装的8.1,最近跟了一遍8.1源码,记录笔记,理解一下类似opencommon的脱壳点
网上的文章大都比较老了,参考这篇6.0的加载https://www.jianshu.com/p/20dcfcf27004
新版本多走了 oat_file_manager.cc ,oat_file_assistant.cc这2个重要的类,
而没有去走linker,需要重新跟一次,在调试一遍才能搞明白整个流程。java层肯定走classloader,最终调用了dalvik_system_DexFile.cc的opeDexFileNative,进入so层,从这里开始分析
先放个简要流程,源码分别在dalvik_system_DexFile.cc ,oat_file_manager.cc ,oat_file_assistant.cc,oat_file.cc,dex_file.cc里,大致就是先得到Oat,通过Oat得到 OatDexFile,在通过 OatDexFile得到 DexFile
[C++] 纯文本查看 复制代码opeDexFileNative dalvik_system_DexFile.cc
{
OpenDexFilesFromOat oat_file_manager.cc
{
GetBestOatFile oat_file_assistant.cc
{
OatFile::Open oat_file.cc
}
LoadDexFiles oat_file_assistant.cc
{
GetOatDexFile(得到上面open的OatFile的OatDexFile)oat_file.cc
OpenDexFile oat_file.cc
{
DexFile::Open dex_file.cc
}
}
}
}
下面开始一步一步分析
1.首先是dalvik_system_DexFile.cc的opeDexFileNative
关键是这一句
dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),class_loader,dex_elements,/*out*/ &oat_file,/*out*/ &error_msgs);
与之前如6.0不同,OpenDexFilesFromOat这个函数放在了oat_file_manager.cc而不是class_linker.cc
[C++] 纯文本查看 复制代码static jobject DexFile_openDexFileNative(JNIEnv* env,
jclass,
jstring javaSourceName,
jstring javaOutputName ATTRIBUTE_UNUSED,
jint flags ATTRIBUTE_UNUSED,
jobject class_loader,
jobjectArray dex_elements) {
ScopedUtfChars sourceName(env, javaSourceName);
if (sourceName.c_str() == nullptr) {
return 0;
}
Runtime* const runtime = Runtime::Current();
ClassLinker* linker = runtime->GetClassLinker(); //获得linker
std::vector<:unique_ptr dexfile>> dex_files;
std::vector<:string> error_msgs;
const OatFile* oat_file = nullptr;
dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
class_loader,
dex_elements,
/*out*/ &oat_file,
/*out*/ &error_msgs);//这句调用OpenDexFilesFromOat获得dex_files
if (!dex_files.empty()) {
jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files);//这句把DexFiles转化为JavaArray,方便java层使用
if (array == nullptr) {
ScopedObjectAccess soa(env);
for (auto& dex_file : dex_files) {
if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) { //这里linker只用来判断dex_file是不是已经存在,跟以前版本不同,需要注意一下
dex_file.release();
}
}
}
return array;
} else {
ScopedObjectAccess soa(env);
CHECK(!error_msgs.empty());
// The most important message is at the end. So set up nesting by going forward, which will
// wrap the existing exception as a cause for the following one.
auto it = error_msgs.begin();
auto itEnd = error_msgs.end();
for ( ; it != itEnd; ++it) {
ThrowWrappedIOException("%s", it->c_str());
}
return nullptr;
}
}
2.进入oat_file_manager.cc的 OpenDexFilesFromOat
2.1,先通过:std::unique_ptr oat_file(oat_file_assistant.GetBestOatFile().release())这句获得了oat_file,
2.2然后通过:dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location)这里通过加载source_oat_file获得dex_files2.3如果上面2.1与2.2不成立:DexFile::Open(dex_location, dex_location, kVerifyChecksum, /*out*/ &error_msg, &dex_files)) //如果LoadDexFiles上面没有获得dex_files,直接DexFile::Open打开加载原始的dexfile
[C++] 纯文本查看 复制代码std::vector<:unique_ptr dexfile>> OatFileManager::OpenDexFilesFromOat(
const char* dex_location,
jobject class_loader,
jobjectArray dex_elements,
const OatFile** out_oat_file,
std::vector<:string>* error_msgs) {
ScopedTrace trace(__FUNCTION__);
CHECK(dex_location != nullptr);
CHECK(error_msgs != nullptr);
// Verify we aren't holding the mutator lock, which could starve GC if we
// have to generate or relocate an oat file.
Thread* const self = Thread::Current();
Locks::mutator_lock_->AssertNotHeld(self);
Runtime* const runtime = Runtime::Current();
OatFileAssistant oat_file_assistant(dex_location,
kRuntimeISA,
!runtime->IsAotCompiler());
// Lock the target oat location to avoid races generating and loading the
// oat file.
std::string error_msg;
if (!oat_file_assistant.Lock(/*out*/&error_msg)) {
// Don't worry too much if this fails. If it does fail, it's unlikely we
// can generate an oat file anyway.
VLOG(class_linker) << "OatFileAssistant::Lock: " << error_msg;
}
const OatFile* source_oat_file = nullptr;
if (!oat_file_assistant.IsUpToDate()) {
// Update the oat file on disk if we can, based on the --compiler-filter
// option derived from the current runtime options.
// This may fail, but that's okay. Best effort is all that matters here.
switch (oat_file_assistant.MakeUpToDate(/*profile_changed*/false, /*out*/ &error_ms