Android应用加固技术详解

更新:11-14 名人轶事 我要投稿 纠错 投诉

最近在学习apk加密,在网上看到一篇文章《Android中的Apk的加固(加壳)原理解析和实现》。我发现原来的文章将整个apk写入dex文件中。如果apk很小的话也没关系。当原APK大于200M时,客户端解压会非常困难。打开它然后应用程序卡住了。如果你只打包原apk的dex,那么解压起来还是很容易的。我不是原创,只是根据自己的想法稍微调整了master的强化,将整个项目组织如下。

二、Dex结构dex_结构.png

如图所示,新的dex由解压后的dex、dex set、dex set描述和描述长度组成

三、核心代码包装/**

* 打包apk

* @param PrimaryApkPath 原始apk

* @param unShellApkPath 解压apk

* @param outApkPath 打包后的新APK

* @抛出异常

*/

公共静态无效apkShell(字符串primaryApkPath,字符串unShellApkPath,字符串outApkPath)抛出异常{

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

抛出新的RuntimeException("检查参数");

}

//解压原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";

文件unShellFile=新文件(unShellDexPath);

文件unApkDir=新文件(unPrimaryApkDstPath);

ArrayListdexArray=new ArrayList();

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

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

dexArray.add(文件);

}

}

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")){

继续;

}

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

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。包。打包项目中字节数组的加密使用的是aes,也可以使用其他方法来实现。

拆包/**

* 将原始dex文件与shell的dex文件分离

* @参数数据

* @参数primaryDexDir

* @抛出IOException

*/

公共无效splitPrimaryDexFromShellDex(字节[]数据,字符串primaryDexDir)抛出IOException,InvalidKeyException,BadPaddingException,NoSuchAlgorithmException,IllegalBlockSizeException,NoSuchPaddingException {

int shellDexLen=data.length;

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

System.arraycopy(数据, 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(数据,shellDexLen-4-dexFileCommentLen,dexFileCommentByte,0,dexFileCommentLen);

字符串dexFileComment=new String(dexFileCommentByte);

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

ArrayListDexFilegt dexFileArrayList=(ArrayListDexFilegt) JSON.parseArray(dexFileComment,DexFile.class);

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

for(int i=dexFileArrayList.size()-1; igt=0; i--){//获取所有dex并写入payload_dex目录

DexFile dexFile=dexFileArrayList.get(i);

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

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

PrimaryDexData=decryAES(primaryDexData);//接口

文件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: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进行优化。第一次加载时间较长,之后原项目dexed很快。从shell dex中获取,然后在onCreate中拼接dex并使用DexClassLoder加载。 NativeLibrary只打包了dex,因此可以直接使用Application的nativeLibraryDir。

其他核心代码、应用替换等可查看原文。

四、效果效果.jpg

从左到右分别是原始demo工程的apk、为了实现multi-dex而添加的大量昂贵代码、加壳的apk、解压后的apk。可以看到,打包后,项目demo项目的dex被隐藏,而显示了解包项目的代码,五、待优化

用户评论

单身i

哎,我最近项目用到apk加固技术,准备好好研究一下这篇文章

    有7位网友表示赞同!

小清晰的声音

感觉这篇文章应该能解决很多关于android apk加固的问题,挺实用的

    有12位网友表示赞同!

如梦初醒

做移动开发的都知道要加固apk,这样安全性就更高了

    有6位网友表示赞同!

。婞褔vīp

加壳技术太复杂了吧?希望能在这篇文章里找到一些入门级信息

    有10位网友表示赞同!

安之若素

以前没明白apk加固的原理,现在想好好学习一下,看看这篇文章能不能给我解答。

    有11位网友表示赞同!

青楼买醉

安卓app越来越重要,保护用户数据更关键了,加固apk是必不可少的

    有11位网友表示赞同!

(り。薆情海

最近学到了些Java相关知识,感觉可以尝试自己学习一下apk加固的操作了

    有20位网友表示赞同!

淡抹丶悲伤

希望这篇文章能够详细介绍不同的加固 Techniques,以及它们的优缺点比较。

    有17位网友表示赞同!

站上冰箱当高冷

我的app一直都有被反编译的风险,看了文章应该能提升安全性吧! अच्छी статья!

    有12位网友表示赞同!

呆萌

学习加固技能总是没完没了,看来这篇文章能给我带来不少新的发现

    有5位网友表示赞同!

拥抱

做开发的小伙伴们一定要关注apk加固,保障app安全性和用户隐私!

    有9位网友表示赞同!

孤败

安卓apk加固确实是一个热门话题,想了解更多知识,看看这篇文章能提供多少干货

    有12位网友表示赞同!

闲肆

希望文章里能够给出一些实用的工具和资源,方便我们学习和实践加固技术

    有6位网友表示赞同!

你tm的滚

加壳技术对我的理解还是比较浅的,这篇文章应该能帮我更深入地了解它

    有11位网友表示赞同!

厌归人

apk加固不仅仅是技术,还跟用户隐私保护、合规性有关

    有8位网友表示赞同!

心亡则人忘

看了文章总结之后,就能更好地判断使用哪种加固方式最合适了吧!

    有18位网友表示赞同!

请在乎我1秒

学习新技能总是很有挑战,但我相信加固技术也能让我在开发领域更上一层楼

    有7位网友表示赞同!

将妓就计

安卓apk加固越来越常见了,这篇文章应该能帮助到许多开发者们!

    有20位网友表示赞同!

忘故

希望这篇文章能够深入浅出地讲解加固技术,方便小白理解

    有11位网友表示赞同!

执念,爱

学习起来吧!加固apk可以让我们在开发过程中更加安全可靠

    有12位网友表示赞同!

【Android应用加固技术详解】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活

上一篇:穿越奇幻之旅:探秘奈何桥与孟婆汤的神秘传说 下一篇:网络强势语言传播中模因理论的应用与影响