简书 android 加固,Android apk加固(加壳)整理

article/2025/10/6 14:38:50

一、Dex加壳由来

最近在学习apk加密,在网上看了一篇《Android中的Apk的加固(加壳)原理解析和实现》,我发现原文把整个apk都写入到dex文件中,如果apk小还好,当原APK大于200M,客户端解壳很费劲,打开后应用就卡住了,如果只是把原apk的dex加壳不就很容易解开了嘛。我不是原创,只是按照我自己的思路将大神的加固稍作调整,并且将整个项目整理如下。

二、Dex结构

8a6fa811c2b1

dex_structure.png

如图所示,新的dex由解壳dex、dex集合、dex集合描述和描述长度组成

三、核心代码

加壳

/**

* 给apk加壳

* @param primaryApkPath 原apk

* @param unShellApkPath 解壳apk

* @param outApkPath 加壳后新APK

* @throws Exception

*/

public static void apkShell(String primaryApkPath,String unShellApkPath,String outApkPath) throws Exception{

if(!FileUtils.isExit(primaryApkPath, unShellApkPath)){

throw new RuntimeException("check params");

}

//解压原apk

String unPrimaryApkDstPath = primaryApkPath.replace(".apk", "");

ApkToolUtils.decompile(primaryApkPath, unPrimaryApkDstPath);

String primaryManifestPath = unPrimaryApkDstPath + File.separator + "AndroidManifest.xml";

//解压解壳apk

String unShellApkDstPath = unShellApkPath.replace(".apk", "");

ApkToolUtils.decompile(unShellApkPath, unShellApkDstPath);

String unShellManifestPath = unShellApkDstPath + File.separator + "AndroidManifest.xml";

String unShellDexPath = unShellApkDstPath + File.separator + "classes.dex";

File unShellFile = new File(unShellDexPath);

File unApkDir = new File(unPrimaryApkDstPath);

ArrayList dexArray = new ArrayList();

for(File file : unApkDir.listFiles()){//读取解壳后的dex

if(file.getName().endsWith(".dex")){

dexArray.add(file);

}

}

String shellDexPath = unPrimaryApkDstPath + File.separator + "classes.dex";

shellDex(dexArray, unShellFile, shellDexPath);//生产新的dex(加壳)

String mateInfPath = unPrimaryApkDstPath + File.separator +"META-INF";//删除meta-inf,重新签名后会生成

FileUtils.delete(mateInfPath);

for(File file : dexArray){//清理多余dex文件

if(file.getName().equals("classes.dex")){

continue;

}

FileUtils.delete(file.getAbsolutePath());

}

String unShellApplicationName = AndroidXmlUtils.readApplicationName(unShellManifestPath);//解壳ApplicationName

String primaryApplicationName = AndroidXmlUtils.readApplicationName(primaryManifestPath);//原applicationName

AndroidXmlUtils.changeApplicationName(primaryManifestPath, unShellApplicationName);//改变原Applicationname为解壳ApplicationName

if(primaryApplicationName != null){//将原ApplicationName写入mateData中,解壳application中会读取并替换应用Application

AndroidXmlUtils.addMateData(primaryManifestPath, "APPLICATION_CLASS_NAME", primaryApplicationName);

}

//回编,回编系统最好是linux

ApkToolUtils.compile(unPrimaryApkDstPath,outApkPath);

//v1签名

SignUtils.V1(outApkPath, SignUtils.getDefaultKeystore());

//清理目录

FileUtils.delete(unPrimaryApkDstPath);

FileUtils.delete(unShellApkDstPath);

}

加壳工程是一个java工程,解压apk使用了apktool,apktool这个工具最好是在linux下使用,xml操作使用了W3C java自带的,不咋个好用,为了项目简单没用其他的jar包。加壳项目中对byte数组的加密使用了aes,也可以用其他方法去实现。

解壳

/**

* 从壳的dex文件中分离出原来的dex文件

* @param data

* @param primaryDexDir

* @throws IOException

*/

public void splitPrimaryDexFromShellDex(byte[] data, String primaryDexDir) throws IOException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchPaddingException {

int shellDexLen = data.length;

byte[] dexFileCommentLenByte = new byte[4];//dex信息长度

System.arraycopy(data, shellDexLen-4, dexFileCommentLenByte, 0, 4);

ByteArrayInputStream bais = new ByteArrayInputStream(dexFileCommentLenByte);

DataInputStream in = new DataInputStream(bais);

int dexFileCommentLen = in.readInt();

byte[] dexFileCommentByte = new byte[dexFileCommentLen];//dex信息正文

System.arraycopy(data,shellDexLen-4-dexFileCommentLen,dexFileCommentByte,0,dexFileCommentLen);

String dexFileComment = new String(dexFileCommentByte);

LogUtils.d("dex comment:"+dexFileComment);

ArrayList<DexFile&gt dexFileArrayList = (ArrayList<DexFile&gt) JSON.parseArray(dexFileComment,DexFile.class);

int currentReadEndIndex = shellDexLen - 4 - dexFileCommentLen;//当前已经读取到的内容的下标

for(int i = dexFileArrayList.size()-1; i&gt=0; i--){//取出所有的dex,并写入到payload_dex目录下

DexFile dexFile = dexFileArrayList.get(i);

byte[] primaryDexData = new byte[dexFile.getDexLength()];

System.arraycopy(data,currentReadEndIndex-dexFile.getDexLength(),primaryDexData,0,dexFile.getDexLength());

primaryDexData = decryAES(primaryDexData);//界面

File primaryDexFile = new File(primaryDexDir,dexFile.getDexName());

if(!primaryDexFile.exists()) primaryDexFile.createNewFile();

FileOutputStream localFileOutputStream = new FileOutputStream(primaryDexFile);

localFileOutputStream.write(primaryDexData);

localFileOutputStream.close();

currentReadEndIndex -= dexFile.getDexLength();

}

}

//代码片段,DexClassLoder加载多个dex

//找到dex并通过DexClassLoader去加载

StringBuffer dexPaths = new StringBuffer();

for(File file:dex.listFiles()){

dexPaths.append(file.getAbsolutePath());

dexPaths.append(File.pathSeparator);

}

dexPaths.delete(dexPaths.length()-1,dexPaths.length());

LogUtils.d(dexPaths.toString());

DexClassLoader classLoader = new DexClassLoader(dexPaths.toString(), odex.getAbsolutePath(),getApplicationInfo().nativeLibraryDir,(ClassLoader) RefInvoke.getFieldOjbect(

"android.app.LoadedApk", wr.get(), "mClassLoader"));//android4.4后ART会对dex做优化,第一次加载时间较长,后面就很快了

将原项目dex从壳dex中获取出来,然后在onCreate中将dex拼接后使用DexClassLoder加载,nativeLibrary咋们只对dex做了加壳所以可以直接使用Application的nativeLibraryDir。

其它核心代码,application替换这类的,可以在原文中查看。

四、效果

8a6fa811c2b1

effect.jpg

从左往右分别为原demo工程的apk,为了实现多dex加了很多费代码,加壳后的apk,解壳apk。可以看出加壳后项目demo工程的dex被隐藏,显示的是解壳工程的代码

五、待优化

将客户端的解密放入native层;

将解密后的dex文件隐藏;

解密后的文件依旧存于应用的私有存储空间中,ROOT了的手机和模拟器很容易就可以拿到解密后的dex,所以这种加壳方法只是将代码从apk中隐藏。

如果有好的解决方法,或者好的加壳方法望告知!

附送整个项目代码代码传送门


http://chatgpt.dhexx.cn/article/Vk8ryZNJ.shtml

相关文章

019 Android加固之APK加固的原理和实现

文章目录 前言加载Activity遇到的问题APK的启动过程替换ClassLoader流程获取ActivityThread类对象获取AppBindData类对象mBoundApplication获取LoadedApk类对象info获取info对象中的ClassLoader 设计傀儡dex文件手工加固APK代码实现APK加固实现步骤 总结 前言 动态加载dex之后…

【Android 安全】Android 应用 APK 加固总结 ( 加固原理 | 应用加固完整的实现方案 | 源码资源 )

文章目录 一、 APK 加固原理1、 Android 应用反编译2、 ProGuard 混淆3、 多 dex 加载原理4、 代理 Application 开发5、Java 工具开发6、Application 替换 二、 应用加固完整的实现方案1、 代理 Application( 1 ) ProxyApplication( 2 ) OpenSSL 解码 Kotlin 类( 3 ) 反射工具…

android资源加固,Android apk加固实现原理

apk加固是每一个app发布之前必须要做的事情;如果一个apk没有加固那么别人就很容易被别人反编译&#xff0c;看到这其中的原码&#xff0c;虽然现在有代码混淆、把业务写到native层&#xff0c;但是这都是治标不治本。反编译的技术在更新&#xff0c;那么保护Apk的技术就不能停止…

Android中Apk加固代码实现

前言&#xff1a;上一篇博客已经把Apk加固的思路详细的介绍过了&#xff0c;也开始创建了一个空的demo进行&#xff0c;然后在项目中添加一个代理module&#xff08;解密&#xff0c;和系统源码交互功能&#xff09;和tools工具加密Java library 的module &#xff0c;这里开始…

Android APK加固原理

一、前言 Android作为开源框架&#xff0c;开放之余&#xff0c;所要面临的就是安全问题&#xff0c;世间之事&#xff0c;有正就有邪&#xff0c;有攻就有守&#xff0c;作为开发者虽然不需要进入专业安全领域&#xff0c;但还是需要掌握基本的安全常识和原理。 二、加壳 加…

APK加固原理详解

一、前言 之前使用的360加固&#xff0c;挺好用的&#xff0c;从2021年底的时候限制每天每个账号仅上传2次apk&#xff08;免费的&#xff0c;不知道VIP的是不是这样&#xff09;。通过这个事情&#xff0c;感觉技术还是掌握在自己手里稳妥点&#xff0c;不用受制于人&#xf…

Android中的Apk的加固(加壳)原理解析和实现

本文转载自&#xff1a;Android中的Apk的加固(加壳)原理解析和实现 - roccheung - 博客园 一、前言 今天又到周末了&#xff0c;憋了好久又要出博客了&#xff0c;今天来介绍一下Android中的如何对Apk进行加固的原理。现阶段。我们知道Android中的反编译工作越来越让人操作熟…

浅谈安卓apk加固原理和实现

转载本文需注明出处&#xff1a;微信公众号EAWorld&#xff0c;违者必究。 引言&#xff1a; 在安卓开发中&#xff0c;打包发布是开发的最后一个环节&#xff0c;apk是整个项目的源码和资源的结合体&#xff1b;对于懂点反编译原理的人可以轻松编译出apk的源码资源&#xff0c…

安卓逆向笔记--apk加固

安卓逆向笔记–apk加固 资料来源: 浅谈安卓apk加固原理和实现 Android中的Apk的加固(加壳)原理解析和实现 前两个太老了所以具体代码借鉴下面的 Android Apk加壳技术实战详解 一、apk常见加固方法 (1)代码层级加密–代码混淆 代码混淆是一种常见的加密方式。本质是把工程中原…

imx6ull uboot移植

以下内容来自&#xff1a;正点原子Linux驱动文档 一、简介 uboot移植主要是根据原厂的uboot移植&#xff1a;芯片厂商通常会做一块自己的评估板并发布BSP&#xff0c;当我们需要定制自己的开发板时可以根据自己的需求&#xff08;硬件上的不同&#xff09;&#xff0c;对原厂…

全志V3S嵌入式驱动开发(uboot移植)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 安装了ubuntu操作系统,有了开发板,下面就可以进行我们的开发工作了。第一步,我们要面临的问题就是uboot移植。一般来说,嵌入式的基础环境就是uboot、linux和rootfs。uboot完成一…

2021-09-14 uboot移植开发

引言&#xff1a;最近要改动uboot&#xff0c;实现像微软PC上&#xff0c;u盘一键刷机或手机上安全模式下刷机的操作 专门去好好研究了点uboot的启动过程&#xff1b;以下为总结&#xff1a; 嵌入式系统 微软-PC ——…

iTOP4412 uboot移植教程

好多刚开始学习uboot移植的同学总是觉得uboot好难&#xff0c;但是再难的问题如果把它一步步拆开&#xff0c;一个个解决&#xff0c;问题也就将迎刃而解。做uboot移植&#xff0c;我们首先就得了解uboot的编译流程&#xff0c;这里以在iTOP4412精英版2G内存的板子上移植u-boot…

<Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分)

&#xff1c;Linux开发&#xff1e; -之-系统移植 uboot移植过程详细记录&#xff08;第二部分&#xff09; 第一部分链接&#xff1a;系统移植-之-uboot移植第一部分 第一部分主要讲解了&#xff0c;uboot移植过程中使用的一些工具的安装&#xff0c;以及测试nxp远程uboot&a…

X210开发板(S5PV210芯片)uboot移植DM9000驱动移植

前言 本文是介绍在uboot中如何移植DM9000的驱动&#xff0c;并不深入去讲解DM9000芯片的操作时序和内部寄存器&#xff0c;想要读懂驱动代码要仔细阅读DM9000芯片的数据手册。移植的基础是手里有DM9000芯片可以用的驱动代码&#xff0c;只需要根据开发板中DM9000芯片的接线方式…

嵌入式linux UBoot移植篇

如何在U-boot添加自己的linux板卡并启动呢&#xff1f; uboot 的移植并不是说我们完完全全的从零开始将 uboot 移植到我们现在所使用的开发板或者开发平台上。这个对于我们来说基本是不可能的&#xff0c;这个工作一般是半导体厂商做的&#xff0c; 半导体厂商负责将 uboot 移…

Uboot移植流程

linux-Bootloader&#xff08;Uboot&#xff09;移植流程 前言 最近在做ZigBee的温室大棚项目&#xff0c;将自己学习的过程和经验分享给大家。本文基于linux3.4.39内核版本&#xff0c;s5p6818开发板实现。 1、uboot启动简介 uboot启动的过程比较复杂&#xff0c;这里就只…

IMX6ULL Uboot 移植

使用的开发板&#xff1a;正点原子ALPHA V2.2 Uboot简介 在学习STM32的过程中使用过IAP在线升级就会知道&#xff0c;有引导程序APP程序&#xff0c;即bootloader程序APP。在学习嵌入式Linux的时候也一样&#xff0c;这个引导程序就是Uboot. uboot移植主要是根据原厂的uboot移…

二、uboot移植

二、uboot移植 版本作者时间备注V 1.0bug设计工程师2021/11/10创建文件软件网盘链接0交叉编译工具链接:https://pan.baidu.com/s/1yFO2NDMet9_b1E1q1rMwEA提取码:42kluboot源码同上linux源码同上文件系统工具同上tftp工具同上2.1 简单说明 uboot制作结束会生成 u-boot-etc44…

linux-uboot 移植四 uboot的移植

概述 前边的章节中介绍到如果要移植uboot的话&#xff0c;最好的参考就是由官方提供的demo。 1、移植 1.1 添加board对应的板级文件夹 uboot 中每个板子都有一个对应的文件夹来存放板级文件&#xff0c;比如开发板上外设驱动文件等等。 NXP 的 I.MX 系列芯片的所有板级文件…