Android APK脱壳工具之FDex2

脱壳原理

通过Hook ClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),在将里面的dex写出。

云盘下载提取码: kdst

支持模块

需VirtualXposed或者Xposed才能用,不在叙述怎么安装,具体得自己找资料

VirtualXposed:https://vxposed.com/

Xposed:https://repo.xposed.info/

实践实践

我这里安装得是Android4.4 Xposed

因为VirtualXposed不支持X86,就是不支持模拟器。穷屌丝我没钱

打开Xposed得模块

开启FDex2

打开FDex2要进行脱壳得软件

之后在脱壳软件得data/data/软件目录下把DEX拷贝出来

脱出得DEX效果如下;

 

灰常不错。。。

FDex2核心代码MainHook

  1. package com.ppma.xposed;
  2.  
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.OutputStream;
  7. import java.lang.reflect.Method;
  8.  
  9. import de.robv.android.xposed.IXposedHookLoadPackage;
  10. import de.robv.android.xposed.XC_MethodHook;
  11. import de.robv.android.xposed.XSharedPreferences;
  12. import de.robv.android.xposed.XposedBridge;
  13. import de.robv.android.xposed.XposedHelpers;
  14. import de.robv.android.xposed.callbacks.XC_LoadPackage;
  15.  
  16. public class MainHook implements IXposedHookLoadPackage {
  17.  
  18. XSharedPreferences xsp;
  19. Class Dex;
  20. Method Dex_getBytes;
  21. Method getDex;
  22. String packagename;
  23.  
  24.  
  25. public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
  26. xsp = new XSharedPreferences("com.ppma.appinfo", "User");
  27. xsp.makeWorldReadable();
  28. xsp.reload();
  29. initRefect();
  30. packagename = xsp.getString("packagename", null);
  31. XposedBridge.log("设定包名:"+packagename);
  32. if ((!lpparam.packageName.equals(packagename))||packagename==null) {
  33. XposedBridge.log("当前程序包名与设定不一致或者包名为空");
  34. return;
  35. }
  36. XposedBridge.log("目标包名:"+lpparam.packageName);
  37. String str = "java.lang.ClassLoader";
  38. String str2 = "loadClass";
  39.  
  40. XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() {
  41. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  42. super.afterHookedMethod(param);
  43. Class cls = (Class) param.getResult();
  44. if (cls == null) {
  45. //XposedBridge.log("cls == null");
  46. return;
  47. }
  48. String name = cls.getName();
  49. XposedBridge.log("当前类名:" + name);
  50. byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);
  51. if (bArr == null) {
  52. XposedBridge.log("数据为空:返回");
  53. return;
  54. }
  55. XposedBridge.log("开始写数据");
  56. String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex";
  57. XposedBridge.log(dex_path);
  58. File file = new File(dex_path);
  59. if (file.exists()) return;
  60. writeByte(bArr, file.getAbsolutePath());
  61. }
  62. } );
  63. }
  64.  
  65. public void initRefect() {
  66. try {
  67. Dex = Class.forName("com.android.dex.Dex");
  68. Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]);
  69. getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);
  70. } catch (ClassNotFoundException e) {
  71. e.printStackTrace();
  72. } catch (NoSuchMethodException e) {
  73. e.printStackTrace();
  74. }
  75.  
  76. }
  77.  
  78. public void writeByte(byte[] bArr, String str) {
  79. try {
  80. OutputStream outputStream = new FileOutputStream(str);
  81. outputStream.write(bArr);
  82. outputStream.close();
  83. } catch (IOException e) {
  84. e.printStackTrace();
  85. XposedBridge.log("文件写出失败");
  86. }
  87. }
  88. }

参考链接

Android APK脱壳–腾讯乐固、360加固一键脱壳

【手机端】腾讯乐固,360加固一键脱壳

发表评论

邮箱地址不会被公开。 必填项已用*标注