ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

apk安全加固、加壳、脱壳技术

2021-06-06 10:30:48  阅读:552  来源: 互联网

标签:dex VirtualXposed 脱壳 log apk XposedBridge 加壳 import


为了增加apk的安全性,防止被反编译破解(例如:常用到的反编译工具jadx-gui)。
apk在开发时,开发者会在工程项目proguard-rules.pro文件内加入google常用的混淆,并用加密秘钥(key alias)加密打包之后,也会用一些第三方加固方式(加固、一定程度的压缩、安全性增强)或者apk加壳技术(文件会压缩、安全性增加、缺点:版本更新后不可用)加固出包。

apk目前 常用的加固方式:
腾讯乐固、360加固和爱加密、或者使用官网网站加固:腾讯加固地址

360加固有个缺点:加固后的apk会自动生成libjiagu.so库 某些机型偶尔报错:(根据同事几年的工作经验提示:其实问题还是在自己代码里)
在这里插入图片描述
虽然加密后,让软件的安全性更高了,但并不是无懈可击,一些反加固技术和脱壳技术应运而生。今天要说的就是腾讯乐固、360加固一键脱壳。

工具
要对Android的apk文件进行脱壳,需要使用的软件有:

FDex2
VirtualXposed
不过,需要说明的是,此技术在Android9.0及以上版本是行不通的,并且VirtualXposed有软件版本限制。
FDex2
下载地址:
链接: https://pan.baidu.com/s/10ZfD2MSfukuLdxvUZIAyjA 提取码: asu1

VirtualXposed
VirtualXposed:无需root手机即可使用Xposed框架
下载链接:
https://vxposed.com/

脱壳
首先,将VirtualXposed、FDex2和需要脱壳的应用都安装到手机上。然后,启动VirtualXposed,并在VirtualXposed中安装FDex2。
在这里插入图片描述
然后,在VirtualXposed中选择模块管理激活FDex2。
在这里插入图片描述
在VirtualXposed中安装要脱壳的应用,具体和上面的步骤一样。然后,启动VirtualXposed中的FDex2,并配置要脱壳的应用。

在这里插入图片描述
在VirtualXposed中运行要脱壳的应用,脱壳后的dex文件如下图:
在这里插入图片描述

然后,使用adb pull命令将脱壳后的dex文件导出到电脑。

adb pull /data/user/0/iv.va.exposed/virtual/data/user/0/{packageName} 

最后,再通过dex2jar对 脱壳的dex进行反编译。

在这里插入图片描述
FDex2核心代码

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("文件写出失败");
        }
    }
}

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

标签:dex,VirtualXposed,脱壳,log,apk,XposedBridge,加壳,import
来源: https://blog.csdn.net/qq_44761063/article/details/117619408

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有