后期-安全相关

apk构建过程

apk构建过程

安全相关

  • 免混淆规则是全局生效(但推荐在各模块自己配置免混淆规则,这样移除该模块的时候会直接把该模块的免混淆规则一起移除)
  • 混淆开关是模块内生效

反编译

反编译需要用到的工具

apktool:资源文件获取,可以提取出图片文件和布局文件进行使用查看

dex2jar:将apk反编译成java源码(classes.dex转化成jar文件)

jd-gui:查看apk中classes.dex转化出额jar,即源码文件

单dex的反编译步骤

  1. classes.dex转成jar

    1
    dex2jar.bat classes.dex
  2. 通过jd-gui查看 jar 内容

    classes-dex2jar.jar 拖到 jd-gui 界面即可查看

多dex的反编译步骤

一个个反编译dex2jar很麻烦,直接反编译全部apk

1
d2j-dex2jar.bat xxx.apk

dex2jar在2.0版本是不支持multidex的。

新版本dex-tools-2.1-SNAPSHOT是支持multidex的。

问题:出现错误Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

解决:d2j_invoke.bat内更改jvm大小为2048 java -Xms512m -Xmx2048m -cp "%CP%" %*

加固了就安全了?几个措施让你的 Android 应用更安全

学习加密,防止核心代码泄露

  • 反编译出来的目录MATE-INF 是放签名文件的。如果dex等代码有变动那么需要重新签名
  • .apk文件生成过程:
    image-20210218113223120
    image-20210218113341085

问题:

  1. 如何达到加密效果?

  2. 为什么是两个系列的dex?

    用后台代码运行。壳dex存放加解密的细节。核心代码在另一个dex中,对这个dex进行加密,这样classLoader就无法识别这个dex。这样反编译就打不开这个dex,达到保护核心代码的目的。

  3. 壳dex怎么来的?

  4. 壳dex如何保护源dex?

  5. 如何签名?

  6. 如何运行新dex(如何脱壳)?

后台代码:
加密流程:对apk进行unzip,遍历dex,对dex进行AES加密,用流写回文件
获取壳dex(这是个library工程中的aar得到的)流程:对apk进行unzip,遍历获取classes.jar,调用命令行dx.bat获取壳dex
解密流程:(安装apk过程中只做校验签名)解密发生在运行时,一边运行一边解密。

思路来源于tinker热修复(github上可以找到源码)(热修复:对Framework层的hook技术)
dex加载顺序(有个数组dexpath[]保存dex,通过dexpath[]的脚标来顺序加载。我们热修复就是新建一个数组,把修复过bug的dex放到数组的最前面)

ClassLoader
双亲委托机制(谁先加载就用谁作为执行的class)–》热修复原理

Application最早执行的方法是attachBaseContext

image-20210218114921013

完成apk加固,需要具备的知识体系有哪些?

知识点 面试体系
熟练掌握Java IO相关代码 Java语言进阶RadomAccessFile
深入研究Android apk的启动流程 精通Android FrameWork层
精通Multidex文件加载机制,精通类加载机制 精通Android FrameWork层 JVM,DVM ClassLoader
明确dex文件的基本构造,了解dex文件相关源码 精通Android FrameWork层 dex
APK打包的基本流程需要理解 Gradle工具数量
掌握C/C++语言及NDK开发 精通C/C++及NDK开发
掌握Java反射和动态代理 Java语言进阶基础

扩展:

微信中加密后的有些类部分可见有些类都不可见:实现是针对某些核心代码进行做标记,针对有标记的部分(都是二进制数据)进行加密,就可以部分不可见。

安全相关问题

H5文件加固检测

应用内若存在明文存储的H5资源文件,则会泄露页面基本布局和一些重要的信息,如登录界面、支付界面等。攻击者可篡改H5资源文件,可能植入钓鱼页面或者恶意代码,导致用户账号、密码、支付密码等敏感信息泄露。更有甚者,通过H5代码暴露相关活动的业务逻辑,可能被黑产团队用来刷红包、薅羊毛等,造成经济损失。

解决方案

可以使用第三方的专业安全加固方案,对应用中的H5文件进行加固保护。

RSA加密算法不安全使用带来的安全风险

RSA加密算法是一种非对称加密算法。当其密钥长度过短,通常认为长度小于512位时,就会存在较高的被破解风险;没有使用正确的工作模式和填充方式,将会存在重放攻击的风险。因RSA加密算法不安全使用造成的加密方法失效,可能造成客户端隐私数据泄露、加密文件破解、传输数据被获取、中间人攻击等后果,导致用户敏感信息被窃取。

解决方案

  1. 使用RSA算法进行数字签名时,建议密钥长不要低于512位,推荐1024位
  2. 使用RSA加密时,如果设置工作模式为ECB,建议填充方式为OAEPWithSHA256AndMGF1Padding

截屏攻击风险

截屏攻击是指在APP运行过程中,界面被监控并且截屏或者录屏。截屏攻击主要发生在APP登录、身份认证、资金操作等界面。Android5.0中增加了一个MediaProjection接口,它提供截屏或者录屏的服务,准许APP拥有截取屏幕或者记录系统音频的能力。同时系统允许其他消息窗口覆盖在系统的录制提示上,从而在用户无感知的情况下启动录屏或者截屏工具。通过此方式,攻击者可以获取APP关键界面的截图或者录像,从而获取用户的敏感信息。

解决方案

在Activity的oncreate()方法中调用:getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);或者getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);来达到防止截屏攻击的目的。

ZipperDown漏洞

如果大量应用会读取zip压缩包进行相关逻辑业务,常见的场景就是从服务器下载压缩包,进行资源、代码热更新。在解压zip包时,如果对文件名没有进行限制,通过在文件名加上 ../../ 前缀的方式,可以将文件解压到任意路径。如果攻击者用远程劫持或者本地替换等方式将APP将要加载的正常zip包替换为带有路径前缀的恶意zip包,而APP又未对解压文件的文件名称进行处理,则可能会出现攻击者可以对应用资源、代码进行任意篡改、替换,从而实现远程代码劫持等安全问题。

解决方案

1. 对zip包进行解压操作时,在获取文件名后,添加过滤代码对文件名中可能包含的 ../ 进行过滤判断。

2. 使用通信协议加密技术,对通信过程中的数据进行加密保护,保证数据不被篡改。

3. 建议客户端与服务端使用加密通道进行数据交互,并对传输数据进行完整性校验,防止zip包被拦截替换。

用户敏感信息明文传输

用户在登录过程中,与服务器端交互时明文传输用户名、密码或者验证码等,可能会导致用户敏感信息暴露。

解决方案

应用与服务器交互过程中,应该对用户名、密码、手机号和验证码等敏感信息进行加密传输。

Java层代码动态调试风险问题

应用级配置文件build.gradlel中的调试标记默认是开启,即可以被Java调试工具如JDB进行调试,但是这样可能会出现被获取和篡改用户敏感信息,甚至可以分析并且修改代码实现的业务逻辑,例如窃取用户密码、绕过验证码防护等。

解决方案

在应用正式发布前,显示设置android:debuggable属性为false,关闭Java动态调试功能、不允许被调试。

数据越权备份风险

Android 2.1以上的系统可以为APP提供应用程序数据的备份和恢复功能,该功能由AndroidMainfest.xml文件中的allowBackup 属性值控制,其默认值为true。当该属性没有显式设置为false时,攻击者可通过adb backup和adb restore对APP的应用数据进行备份和恢复,从而可能获取明文存储的用户敏感信息,如用户的密码、证件号、手机号、交易密码、身份令牌、服务器通信记录等。利用此类信息攻击者可伪造用户身份,盗取用户账户资产,或者直接对服务器发起攻击。

解决方案

将AndroidMainfest.xml文件中的allowBackup属性值设置为false来关闭应用程序的备份和恢复功能;也可以使用专业安全加固方案的本地数据保护功能,避免本地数据泄露。

日志数据泄露风险

调试信息函数可能输出重要的调试信息,常见的就是Log日志类其中包含的信息可能会导致用户信息泄露,泄露核心代码逻辑等,为发起攻击提供便利,例如:Activity的组件名;通信交互的日志;跟踪的变量值等。

解决方案

应用内使用统一的Log控制基类,可以灵活的控制Log的输出打印。(测试环境允许打印日志、正式环境不打印);或者使用第三方的日志框架。

代码混淆相关问题

at com.netease.nis.sdkwrapper.Utils.rL(Native method)

安卓/代码混淆问题1

原因:少添加了对oaidoaid_sdk_1.0.25.aar)的免混淆。

注意:此处com.netease.跟云信的类库名称neteaseim很像很容易搞混

解决:

添加混淆的方式有两种:

  1. 一种是在主module的proguard-rules.pro中统一添加。
  2. 一种是在各自library的proguard-rules.pro中添加。这种方式更灵活些,可以被多个主module使用

此处的是aar,没有自己的proguard-rules.pro,所以添加到主module中

安卓/代码混淆问题2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#OAID
-keep class XI.CA.XI.**{*;}
-keep class XI.K0.XI.**{*;}
-keep class XI.XI.K0.**{*;}
-keep class XI.vs.K0.**{*;}
-keep class XI.xo.XI.XI.**{*;}
-keep class com.asus.msa.SupplementaryDID.**{*;}
-keep class com.asus.msa.sdid.**{*;}
-keep class com.bun.lib.**{*;}
-keep class com.bun.miitmdid.**{*;}
-keep class com.huawei.hms.ads.identifier.**{*;}
-keep class com.samsung.android.deviceidservice.**{*;}
-keep class org.json.**{*;}
-keep public class com.netease.nis.sdkwrapper.Utils {public <methods>;}