原理
安卓7.1(含,及以下)
Class类对象种含有Dex结构体,利用这个可以脱壳
高版本
inline hook libart.so 中 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)
问题
dlopen failed: couldn't map "/data/local/tmp/libnativeDump.so" segment 1: Permission denied
方法
1 放到相关应用私有目录
System.load(“私有目录”)
2 放到 /system/lib 目录下,注意64为lib64
System.loadLibrary(“nativeDump”);
步骤
Xposed hook ClassLoader.loadClass 方法即可得到Class对象
在应用attcah Context时后hook,此时壳还未加载代码,具体可查看参考Android App的启动流程
public static void hook(final LoadPackageParam lp) throws Throwable {
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass", String.class, boolean.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Class result = (Class) param.getResult();
if (result != null) {
String name = result.getName();
if(name.startsWith("android") || name.startsWith("org") || name.startsWith("java")){
return;
}
dumpdexImp(result);
}
}
});
}
});
}
dump
private static void dumpdexImp(Class<?> aClass) {
Object dexCache = XposedHelpers.getObjectField(aClass, "dexCache");
Object o = XposedHelpers.callMethod(dexCache, "getDex");
byte[] dexBytes = (byte[]) XposedHelpers.callMethod(o, "getBytes");
//Environment.getExternalStorageDirectory().getPath()
String sd_dex_path = "/sdcard/Pictures/dex_"+ dexBytes.length +".dex";
File dexFile = new File(sd_dex_path);
if (dexFile.exists()) {
return;
}
write(dexFile, dexBytes); //伪代码
}