FDex2报错: 这台设备不支持此软件
2019-03-13 本文已影响0人
ukyoo
FDex2大多配合VirtualXposed一起使用,大概的原理:
- 通过反射调用
Dex.java
的getBytes()
方法
- 然后通过io把bytes写出到目录下
FDex2源码
public class MainHook implements IXposedHookLoadPackage {
XSharedPreferences xsp;
Class Dex;
Method Dex_getBytes;
Method getDex;
String packagename;
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
xsp = new XSharedPreferences("com.ppma.appinfo", "User");
xsp.makeWorldReadable();
xsp.reload();
initRefect();
packagename = xsp.getString("packagename", null);
XposedBridge.log("设定包名:"+packagename);
if ((!lpparam.packageName.equals(packagename))||packagename==null) {
XposedBridge.log("当前程序包名与设定不一致或者包名为空");
return;
}
XposedBridge.log("目标包名:"+lpparam.packageName);
String str = "java.lang.ClassLoader";
String str2 = "loadClass";
XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class cls = (Class) param.getResult();
if (cls == null) {
//XposedBridge.log("cls == null");
return;
}
String name = cls.getName();
XposedBridge.log("当前类名:" + name);
byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);
if (bArr == null) {
XposedBridge.log("数据为空:返回");
return;
}
XposedBridge.log("开始写数据");
String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex";
XposedBridge.log(dex_path);
File file = new File(dex_path);
if (file.exists()) return;
writeByte(bArr, file.getAbsolutePath());
}
} );
}
public void initRefect() {
try {
Dex = Class.forName("com.android.dex.Dex");
Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]);
getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void writeByte(byte[] bArr, String str) {
try {
OutputStream outputStream = new FileOutputStream(str);
outputStream.write(bArr);
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
XposedBridge.log("文件写出失败");
}
}
}
但是在8.0的真机上会出现这台设备不支持此软件,反编译Fdex源码,发现在反射调用
Class.forName("com.android.dex.Dex")
的时候抛出了该异常.但是在7.0及以下的真机上都没有问题
private void checkSupport() {
Object obj = 1;
try {
Class cls = Class.forName("com.android.dex.Dex");
} catch (ClassNotFoundException e) {
ClassNotFoundException classNotFoundException = e;
obj = null;
}
AlertDialog show = builder.setMessage("这台设备不支持本软件").setPositiveButton("退出", anonymousClass100000000).show();
}
}
猜测是目录的问题,使用 androidxref查看下不同版本的源码
Android O
Android OAndroid N
Android N可以看到, Dex.class
文件在Android O以上就被迁移到了dalivk目录下,我们反射的时候只能调用libcore内的代码