[技术]Android APK一键脱壳(腾讯乐固、360加固)

作者: BI1IHA 分类: 技术文章 发布时间: 2019-04-03 14:14

概述

现在使用Proguard进行混淆的代码,也很容易被破解,所以就出现了加固工具,让反编译的难度更大。但是有了加固技术,就会有反加固技术,正所谓道高一尺魔高一丈。

经过加固后的apk,通过dex2jar反编译:

腾讯乐固:

1.png

360加固:

1.png

从上面可以看出,经过加固后的apk,通过常规方法反编译无法获取到源码。

下载工具

脱壳工具FDex2

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

下载地址:

链接:FDex2_1.1.zip

VirtualXposed

链接:VirtualXposed_0.17.2.zip

脱壳

Step1:

VirtualXposedFDex2需要脱壳的应用都安装到手机上。

Step2:

启动VirtualXposed,并在VirtualXposed中安装FDex2:

1.gif

Step3:

VirtualXposed中激活FDex2:

1.gif

Step4:

VirtualXposed中安装要脱壳的应用,方法和Step2一样。

Step5:

启动VirtualXposed中的FDex2,并配置要脱壳的应用。

1.png

Step6:

VirtualXposed中运行要脱壳的应用。

Step7:

脱壳后的dex文件:

导出脱壳的dex文件:

root设备:

adb root
adb pull /data/user/0/iv.va.exposed/virtual/data/user/0/{packageName}   {电脑上的目录}

未root设备:

VirtualXposed中,设置–>高级设置–>文件管理,安装文件管理器,然后通过文件管理器进入到指定的目录,通过分享功能发到电脑上。

Step8:

通过dex2jar对 脱壳的dex进行反编译:

1.png

从上图就可以看到脱壳后的dex文件被成功的反编译。

FDex2核心代码MainHook

package com.ppma.xposed; 
import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.lang.reflect.Method; 
import de.robv.android.xposed.IXposedHookLoadPackage;import de.robv.android.xposed.XC_MethodHook;import de.robv.android.xposed.XSharedPreferences;import de.robv.android.xposed.XposedBridge;import de.robv.android.xposed.XposedHelpers;import de.robv.android.xposed.callbacks.XC_LoadPackage; 
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("文件写出失败");
        }
    }
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

3条评论
  • 褡裢

    2020年9月15日 18:39

    你好 我拖出来的文件夹之比/data/data/pkgName 里面的东西多了三个文件夹:/lib、/.jiagu、 /.oabugaij 没有找到dex文件……请问是哪里出问题了吗?
    adb pull /data/user/0/io.va.exposed/virtual/data/user/0/pkgName

  • 褡裢

    2020年9月15日 18:15

    你好,显示“这台设备不支持本软件” 已root的oppo手机,请问这个软件现在适配哪些手机啊?

  • niu

    2019年11月6日 18:35

    然而未ROOT设备 打不开要脱壳的应用

发表评论

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