首页
社区
课程
招聘
[原创]关于安卓APP加固基础的总结
发表于: 2020-3-22 17:05 12772

[原创]关于安卓APP加固基础的总结

2020-3-22 17:05
12772

本文最初发表在CSDN上:
https://blog.csdn.net/weixin_43632667/article/details/105008506
https://blog.csdn.net/weixin_43632667/article/details/104394222

Android应用当中,很多隐私信息都是以字符串的形式存在的。这些隐私信息是明文,对于软件来说是想当不安全的,如果我们能在打包时对Dex中的字符串加密替换,并在运行时调用解密,这样就能够避免字符串明文存在于Dex中。虽然,无法完全避免被破解,但是加大了逆向提取信息的难度,安全性无疑提高了很多。

目前市面上主要存在两种字符串加密方式:
(1)在开发阶段开发者使用加密后的字符串然后手动调用解密,这种方法工程量太大了,缺点很明显。
(2)编译后修改字节码,然后再动态植入加密后的字符串,最后让其自动调用进行解密,这里重点分析的是第二种

工具:

代码(MainActivity.java):

jeb3反编译的效果(MainActivity.java):

首先看加密的方法:StringFog采用的是base64+xor(异或)算法

按照安卓程序加密的字符串测试:

输出结果为:
在这里插入图片描述
显然跟jeb3里面看到的一样。

ps:Base64 packge 下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi 下载后导入commons-codec-1.14.jar

那么我们可以借助asm库拦截方法中的每条LDC指令,然后插入该指令即可

总结:字符串加密方法能够较为有效的阻止他人通过字符串搜素定位代码,但是不能防止Hook,总而言之,这只是一个比较普通的混淆方法

java代码将png图片加密:

在这里插入图片描述

使用winhex查看发现:

在这里插入图片描述变成了:
在这里插入图片描述

然后我们只需要在AS中将编写解密代码即可:

下面是一个简单的测试demo:

测试结果:
在这里插入图片描述

此时,我们打开apk查看assert文件时依然无法看到有用的文件
在这里插入图片描述

ps:同时我们还可以进行资源路径混淆,详情见:https://github.com/shwenzhang/AndResGuard/blob/master/README.zh-cn.md

现在的反编译工具都太先进了,很多纯粹的对抗反编译技术都不在适应了,基本上,我们都可以通过jeb这个强大的反编译工具查看到
但是我们可以将类名进行混淆:

gradle版本在3.4以下时我们使用proguard-rules.pro进行混淆,达到3.4以上时我们使用R8穿插一些proguard规则进行混淆
下面重点研究的是3.4以上版本的情况:

官方文档:https://developer.android.com/studio/build/shrink-code?hl=zh-cn

通用教程:https://www.jianshu.com/p/65027e18c2fe

混淆规则(如下):

这个之前已经写过了:
文档:函数混淆(JNI_Onload).note
链接:http://note.youdao.com/noteshare?id=f6add1ff6a6c4b78aac4a9e27fe390ed&sub=04FF4E2B1F504587A06C69F39C4DF22C

完成程序后,使用AndroidKiller进行修改时,将"我是正版"字符串修改成"我是盗版",在运行程序时,程序会直接闪退
在这里插入图片描述

MainActivity:

native-lib.cpp:

activity_main.xml:

在处于调试状态时,Linux会向/proc/pid/status写入一些进程状态信息,比如TracerPid字段会写入调试进程的pid,因此我们可以自己ptrace自己,然后让android_server不能调试
代码如下:

一旦开始调试,就会出现
在这里插入图片描述

反反调试思路:nop掉anti_debug01()函数调用

根据第一种分析得出Tracepid的值只要不为0 就能说明进程正在被调试,因此我们只需要检测Tracepid的值是不是0,如果不为0,直接退出就行了

在这里插入图片描述

反反调试思路:使用IDA动态调试在函数调用前下断,对比当前TracerPid为4591,将TracerPid对应的寄存器修改为0,达到“0==0”的效果,绕开反调试。

在这里插入图片描述

1.需要加密的APK(源APK)

2.壳程序APK

3.加密工具(负责将源APK进行加密和壳DEX合并成新的DEX)

在这里插入图片描述


这里面需要注意的字段:

1.checksum文件校验码,使alder32算法校验文件除去magic,checksum外余下的所有文件区域,用于检查文件错误。
2.signature使用SHA-1算法hash除去magic,checksum和signature外余下的所有文件区域,用于唯一识别本文件。
3.file_Size Dex文件的大小。
4.在文件的最后,我们需要标注被加密的apk大小,因此需要增加4个字节。
关注的原因如下:

因为我们需要将一个文件(加密之后的源Apk)写入到Dex中,那么我们肯定需要修改文件校验码(checksum).因为他是检查文件是否有错误。那么signature也是一样,也是唯一识别文件的算法。还有就是需要修改dex文件的大小。
不过这里还需要一个操作,就是标注一下我们加密的Apk的大小,因为我们在脱壳的时候,需要知道Apk的大小,才能正确的得到Apk。那么这个值放到哪呢?这个值直接放到文件的末尾就可以了。
总的来说:我们需要做:修改Dex的三个文件头,将源Apk的大小追加到壳dex的末尾就可以了

根据上述修改后的dex文件样式如下

在这里插入图片描述
由原理可知这里需要进行三个步骤了:
1、自己编写一个源程序项目(需要加密的APK)
2、脱壳项目(解密源APK和加载APK)
3、对源APK进行加密和脱壳项目的DEX合并

命名为:SourceApk

MyApplication:

ps:MyApplication的作用:MyApplication类继承Application,查看源码我们知道,Application中有一个attachBaseContext方法,它在Application的onCreate方法执行前就会执行了,这个关键点为后面的加密程序做铺垫。

MainActivity:

就是源程序的一个主要类

SubActivity:

同MainActivity

AndroidManifest.xml

注意一定要加上android:name="com.example.sourceapk.MyApplication"

ProxyActivity:
```
package com.example.packapk;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.Log;
import dalvik.system.DexClassLoader;

public class ProxyApplication extends Application{
private static final String appkey = "APPLICATION_CLASS_NAME";
private String apkFileName;
private String odexPath;
private String libPath;

}

RelInvoke(反射工具类):

分析:
1.首先通过java的反射,置换掉android.app.ActivityTread中的mClassLoader,作为加载解密出的APK的DexClassLoader,,该DexClassloader既加载了源程序,还以mClassLoader作为其父类,使得资源文件和系统代码能正确的被加载

代码解析:

加密程序的AndroidManifest文件也一定要添加上:

且其他的activity必须和源程序保持一致性

例如:源程序为:

那么加密程序必须和其一模一样

需要源程序apk和加密程序apk的dex文件

完成所有的操作后还需要把新的apk进行签名操作,否则会导致错误发生

本项目的地址
github地址:https://github.com/lzh18972615051/AndroidShellCode

 
 
 
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 8
支持
分享
最新回复 (19)
雪    币: 2914
活跃值: (4946)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
能问一下楼主最后那个dex加固android studio版本是多少吗?我自己写的运行到反射调用makeApplication方法直接返回nu然后就闪退了,楼主遇到过这个问题吗?
2020-3-22 20:59
0
雪    币: 3372
活跃值: (762)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
额,没有遇到过,我的as版本是3.5
2020-3-22 21:48
0
雪    币: 2914
活跃值: (4946)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
cnzzh 额,没有遇到过,我的as版本是3.5
同样是as3.5,看来得卸载重装了
2020-3-22 22:21
0
雪    币: 83
活跃值: (1087)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
mark
2020-3-23 08:01
0
雪    币: 14865
活跃值: (6088)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
字符串混淆不要搞那么复杂,没考虑运行效率问题?只要不是明码,简单处理一下就可以了,效果是一样的。
2020-3-23 10:13
0
雪    币: 3372
活跃值: (762)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
tDasm 字符串混淆不要搞那么复杂,没考虑运行效率问题?只要不是明码,简单处理一下就可以了,效果是一样的。
那请问一下用什么处理方式会更好呢
2020-3-23 12:00
0
雪    币: 14865
活跃值: (6088)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
把base64加密去掉即可。
2020-3-23 13:26
0
雪    币: 3372
活跃值: (762)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
tDasm 把base64加密去掉即可。
好的了解了,谢谢大佬指点
2020-3-23 21:59
0
雪    币: 1636
活跃值: (653)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
谢谢,大佬的总结分享。
2020-3-24 15:51
0
雪    币: 688
活跃值: (3630)
能力值: (RANK:15 )
在线值:
发帖
回帖
粉丝
11
谢谢,大佬的总结分享。
最后于 2020-3-24 16:04 被黑的默编辑 ,原因:
2020-3-24 16:03
0
雪    币: 2914
活跃值: (4946)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
12

楼主,关于最后一个dex整体加固,完全复制楼主代码后跑起来直接闪退(部分包名修改了),楼主在测试的时候遇见过这种情况吗?测试机用的是nexus吗?
日志截图:

2020-3-24 16:51
0
雪    币: 3372
活跃值: (762)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
windy_ll 楼主,关于最后一个dex整体加固,完全复制楼主代码后跑起来直接闪退(部分包名修改了),楼主在测试的时候遇见过这种情况吗?测试机用的是nexus吗? 日志截图: ![](upload/attach ...
是不是没修改全面,我没有遇到过这个问题,我用的不是谷歌系的手机
2020-3-25 09:48
0
雪    币: 2914
活跃值: (4946)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
14
cnzzh 是不是没修改全面,我没有遇到过这个问题,我用的不是谷歌系的手机
。。。。。那就不知道是咋回事了,修改应该没问题的,看来这玩意就是玄学
2020-3-25 11:13
0
雪    币: 4883
活跃值: (18890)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
15
感谢分享
2020-4-4 20:56
0
雪    币: 298
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
学习了,多谢。
2020-5-1 12:33
0
雪    币: 23
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
学习了 感谢分享
2020-5-6 06:14
0
雪    币: 156
活跃值: (3806)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
18
感谢
2020-5-19 11:57
0
雪    币: 19950
活跃值: (4942)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
感谢楼主分享
2020-8-2 06:41
0
雪    币: 1195
活跃值: (1125)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
感谢楼主分享
2020-8-2 10:10
0
游客
登录 | 注册 方可回帖
返回
//