一般安卓加载代码都是通过classloader来装取本地代码到内存中去的。
classloader有两种加载方式:
1.通过路径寻找本地代码,然后载入内存:
基本的源码顺序是 BaseDexClassLoader->DexPathList->makeDexElements->loadDexFile->Dexfile.loadDex
最后DexFile中有一个native方法 OpenDexFileNative 对应了 DexFile_openDexFileNative 方法。其中的OpenDexFileFormOat便是最主要的方法了。
当然这里我们就跳过,需要了解classloader的机制可以自行去看xref,因为这里是路径加载的方式,一般加固不会选择这里的方法去加载的。
2.直接映射到内存中去:
在4.x版本的DexFile.java有
native private static int openDexFile(byte[] fileContents);
这个函数在5.x中的java方法已经摒弃,在native层中依旧存在于/art/runtime/dex_file.cc中。
其方法为OpenMemory函数。我们只需要在此从内存中扣出文件就好了。
const DexFile* DexFile::OpenMemory(const byte* base,
size_t size,
const std::string& location,
uint32_t location_checksum,
MemMap* mem_map,
const OatFile* oat_file,
std::string* error_msg) {
CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
std::unique_ptr<DexFile> dex_file(
new DexFile(base, size, location, location_checksum, mem_map, oat_file));
if (!dex_file->Init(error_msg)) {
return nullptr;
} else {
__android_log_print(ANDROID_LOG_DEBUG,"chason 's DexFile::OpenMemory",
"size is:%zu,location is:%s", size, location.c_str());
if (!strcmp(location.c_str(),"/data/data/com.autohome.mycar/.jiagu/classes.dex"))
{
int fd = open("/data/data/com.autohome.mycar/classes.dex",O_CREAT|O_EXCL|O_WRONLY,S_IRWXU);
__android_log_print(ANDROID_LOG_DEBUG,"chason's copy is starting!","hello");
if (fd>0)
write(fd,base,size);
else
__android_log_print(ANDROID_LOG_DEBUG,"chason's copy is failed!","codeis:%d",fd);
close(fd);
}
return dex_file.release();
}
}
最后在路径里找到dex就ok了。。。
PS:先看logcat里的location字符串是啥,然后再去写if判断字符串是否是这个~
分享apk以及脱完的dex。。。希望请大神们指点思路O(∩_∩)O
链接: http://pan.baidu.com/s/1jHPidqm 密码: yznd
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)