道高一尺魔高一丈嘛,有加固平台,也有脱壳工具,常见的脱壳工具有FDex2,dumpdex,drizzleDumper等。这里我们使用FDex2来实现脱壳。
FDex2通过Hook ClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),在将里面的dex写出。
下载地址:
链接:https://pan.baidu.com/s/1smxtinr 密码:dk4v
我们看下主要的源码:
public class MainHook implements IXposedHookLoadPackage {
Class Dex;
Method Dex_getBytes;
Method getDex = (Method)null;
XSharedPreferences shared;
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam paramLoadPackageParam) {
this.shared = new XSharedPreferences("formatfa.xposed.Fdex2", "package");
this.shared.reload();
initRefect();
String str = this.shared.getString("packagename", (String)null);
if (str == null) {
return;
}
if (!paramLoadPackageParam.packageName.equals(str))
return;
XposedBridge.log(str + " has hook");
ClassLoader classLoader = paramLoadPackageParam.classLoader;
try {
Class clazz = Class.forName("java.lang.String");
XposedHelpers.findAndHookMethod("java.lang.ClassLoader", classLoader, "loadClass", new Object[] { clazz, boolean.class, new XC_MethodHook(this, str, paramLoadPackageParam) {
private final MainHook this$0;
private final String val$aim;
private final XC_LoadPackage.LoadPackageParam val$p1;
@Override
protected void afterHookedMethod(MethodHookParam param1MethodHookParam) {
XposedBridge.log(" after hook : ");
boolean bool = true;
clazz = (Class)param1MethodHookParam.getResult();
if (clazz == null)
return;
try {
str = clazz.getName();
try {
Class clazz1;
(clazz1 = Class.forName("formatfa.xposed.Fdex2.MainHook")).forName(str, false, clazz1.getClassLoader().getSystemClassLoader());
} catch (ClassNotFoundException str) {
throw new NoClassDefFoundError(str.getMessage());
}
} catch (ClassNotFoundException classNotFoundException) {
bool = false;
}
if (bool)
return;
try {
Object object = this.this$0.getDex.invoke(clazz, new Object[0]);
byte[] arrayOfByte = (byte[])this.this$0.Dex_getBytes.invoke(object, new Object[0]);
if (arrayOfByte != null) {
"/data/data/" + this.val$aim + "/" + this.val$aim + arrayOfByte.length + ".dex";
File file = new File(this.this$0.shared.getString("dir", "/sdcard"), this.val$p1.packageName + arrayOfByte.length + ".dex");
if (!file.exists())
FIO.writeByte(arrayOfByte, file.getAbsolutePath());
}
return;
} catch (Exception clazz) {
XposedBridge.log(clazz.toString());
return;
}
}
@Override
protected void beforeHookedMethod(MethodHookParam param1MethodHookParam) {}
} });
return;
} catch (ClassNotFoundException paramLoadPackageParam) {
throw new NoClassDefFoundError(paramLoadPackageParam.getMessage());
}
}
public void initRefect() {
try {
this.Dex = Class.forName("com.android.dex.Dex");
this.Dex_getBytes = this.Dex.getDeclaredMethod("getBytes", new Class[0]);
if (!MainActivity.h.endsWith("0"))
return;
int i = MainActivity.s.length();
if (i != 91)
return;
try {
Class clazz = Class.forName("java.lang.Class");
this.getDex = clazz.getDeclaredMethod("getDex", new Class[0]);
} catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
} catch (Exception exception) {
XposedBridge.log(exception.toString());
}
}
void writeDex(String paramString, Object paramObject) {
try {
paramObject = this.getDex.invoke(paramObject.getClass(), new Object[0]);
byte[] arrayOfByte = (byte[])this.Dex_getBytes.invoke(paramObject, new Object[0]);
if (arrayOfByte != null) {
File file = new File(this.shared.getString("dir", "/sdcard"), paramString + arrayOfByte.length + ".dex");
if (!file.exists())
FIO.writeByte(arrayOfByte, file.getAbsolutePath());
}
return;
} catch (InvocationTargetException paramString) {
return;
} catch (IllegalAccessException paramString) {
return;
} catch (IllegalArgumentException paramString) {
return;
}
}
}
他会根据选中的package,然后运行目标apk的时候把dex文件缓存到/data/data/package下。然后我们可以拿到这些dex文件,通过dex2jar工具转换为jar包,然后再通过jd_gui来查看源码。
关于xposed的hook功能,之后一篇文章会介绍如何使用。
现在的手机很多都是没有root权限的,若是测试机倒没事,要是是自己在用的手机root了权限显得没那么安全。这里我们可以使用VirtualXposed(下载点击这里),即使不root掉权限,我们也可以拿到我们需要的dex文件.
现在我们应该准备好了VirtualXposed、FDex2和需要脱壳的应用ShellApk,可以开始脱壳了。
将准备好的上述应用都安装到手机上
安装完后如下所示:
启动VirtualXposed中的FDex2,选择要hook的目标,也就是ShellApk
启动需要脱壳的应用ShellApk,我们所需要的dex就已经缓存好了
在VirtualXposed中,“设置–>高级设置–>文件管理”,安装文件管理器.Amaze文件管理器,如果没法安装可以手动安装,当然也可以安装Total Commander自定义标签为"/data/data/io.va.exposed"。
在virtual/data/user/0/com.jared.shellapk目录下选中dex文件,然后通过分享传输到电脑上
注:这里要是不能传输的话,可以试试安装qq,可以通过qq传输到电脑上。
拿到了dex文件,我们就可以通过dex2jar来生成jar文件,然后通过jd-gui来查看具体的代码了(怎么从dex到jar并查看源码,这里就不分析了,可以参考这篇文章,《逆向分析反编译》)
和ApkTest的源码比较,基本上一致,这里有两个方法gotoSecondActivity和showStr,下一篇文章基于此做一个hook插件。