• [免费专栏] Android安全之检测APK中调试代码是否暴露敏感信息



    也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大

    少走了弯路,也就错过了风景,无论如何,感谢经历


    转移发布平台通知:将不再在CSDN博客发布新文章,敬请移步知识星球

    感谢大家一直以来对我CSDN博客的关注和支持,但是我决定不再在这里发布新文章了。为了给大家提供更好的服务和更深入的交流,我开设了一个知识星球,内部将会提供更深入、更实用的技术文章,这些文章将更有价值,并且能够帮助你更好地解决实际问题。期待你加入我的知识星球,让我们一起成长和进步


    Android安全付费专栏长期更新,本篇最新内容请前往:

    0x01 前言

    1.1StrictMode

    StrictMode是Android开发过程中一个必不可缺的性能检测工具,它能帮助开发者检测出APK中一些不合理的代码块

    Android 2.3提供一个称为严苛模式(StrictMode)的调试特性,Google称该特性已经使数百个Android上的Google应用程序受益

    • StrictMode是什么?
      • StrictMode意思为严格模式,是用来检测程序中违例情况的开发者工具
      • 最常用的场景就是检测主线程中本地磁盘和网络读写等耗时的操作
      • StrictMode最常用来捕捉应用程序的主线程,它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policy violation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。我们可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的应用继续执行
      • 严格模式会将应用的违例细节暴露给开发者方便优化与改善

    StrictMode 检查策略的函数:

    • 线程策略(TreadPolicy)
      • 自定义的耗时调用:使用detectCustomSlowCalls()开启
      • 磁盘读取操作:使用detectDiskReads()开启
      • 磁盘写入操作:使用detectDiskWrites()开启
      • 网络操作:使用detectNetwork()开启
    • VM策略(VmPolicy)
      • Activity泄露:使用detectActivityLeaks()开启
      • 未关闭的Closable对象泄露:使用detectLeakedClosableObjects()开启
      • 泄露的Sqlite对象:使用detectLeakedSqlLiteObjects()开启
      • 检测实例数量:使用setClassInstanceLimit()开启

    严格模式需要在debug模式开启,不要在release版本中启用。需要注意严格模式的开启一般情况下会放在Application或者Activity以及其他组件的onCreate方法,那么我们就可以首先去寻找这些关键的地方,优先我们可以去Application的onCreate方法中寻找,因为开发人员为了更好地分析应用中的问题,通常会放在Application的onCreate方法中

    1.1.1 第一种实现方式

    • 开启与否只在这里设置true或者false就可以了
    public final class BuildConfig {
      public static final boolean DEBUG = Boolean.parseBoolean("true");
    }
    
    • 1
    • 2
    • 3
    • 下面的代码放在Application的onCreate方法中,一般放在最开始的地方

    :一般建议在 if 语句中插入带有 DEVELOPER_MODE条件的策略,以及要禁用 StrictMode,且必须禁用发布版构建的 DEVELOPER_MODE

    if (BuildConfig.DEBUG) {
                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                        .detectAll()
                        .penaltyLog()
                        .build());
                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                        .detectAll()
                        .penaltyLog()
                        .build());
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    上面说的StrictMode.setThreadPolicyStrictMode.setVmPolicy,解释如下:

    private void enabledStrictMode() {
            // 开启Thread策略模式
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() // 构造StrictMode
                    .detectNetwork() // 访问网络时输出,这里可以替换为detectAll() 就包括了磁盘读写和网络I/O  
                    .detectCustomSlowCalls()// 监测自定义运行缓慢函数
                   .detectDiskReads() // 当发生磁盘读操作时输出  
                   .detectDiskWrites() // 当发生磁盘写操作时输出  
                    .penaltyLog() // 以日志的方式输出
                    .penaltyDialog() // 监测到上述状况时弹出对话框
                    .build());
            // 开启VM策略模式
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() // 构造StrictMode
                    .detectLeakedSqlLiteObjects() // 探测SQLite数据库操作  
                    .detectLeakedClosableObjects() // 监测没有关闭IO对象
                    .setClassInstanceLimit(MainActivity.class, 1) // 设置某个类的同时处于内存中的实例上限,可以协助检查内存泄露
                    .detectActivityLeaks()
                    .penaltyLog() // 以日志的方式输出
                    .penaltyDeath() // 出现上述情况异常终止
                    .build());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    1.1.2 第二种实现方式

    • 开启与否:使用AndroidMainifest文件中的debuggable属性来实现
    android:debuggable="true"
    
    • 1
    • 下面的代码放在Application的onCreate方法中,一般放在最开始的地方
         // Return if this application is not in debug mode 
         ApplicationInfo appInfo = context.getApplicationInfo(); 
         int appFlags = appInfo.flags; 
         if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { 
           
              StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                        .detectAll()
                        .penaltyLog()
                        .build());
              StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                        .detectAll()
                        .penaltyLog()
                        .build());
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    0x02 检测APK中调试代码是否暴露敏感信息

    APK Demo:https://github.com/wongkyunban/TimeConsumingViolation

    嫌编译麻烦,可用博主同学已编译好的APK:https://download.csdn.net/download/Ananas_Orangey/86505852

    • 使用dex2jar反编译java源码

    将StrictMode-debug.apk直接修改后缀,改为StrictMode-debug.zip,并解压解压后的文件夹中,classes.dex 就是java源码打包后的文件

    在这里插入图片描述

    将命令行定位到dex2jar.bat所在目录
    使用命令行:

    d2j-dex2jar classes.dex
    
    • 1

    会生成classes-dex2jar文件,该文件就是反编译后的java源码文件

    • 使用jadx查看反编译后的java源码,为了确定APK是否使用StrictMode,我们接着全局搜索StrictMode.setThreadPolicyStrictMode.setVmPolicy来确认是否有开启Thread策略模式或开启开启VM策略模式

    在这里插入图片描述

    • 线程策略的检测方法如下(当然也可以尝试搜索这些关键字):
    // 开启Thread策略模式的线程策略
    detectNetwork()
    detectDiskWrites()
    detectDiskReads()
    detectCustomSlowCalls()
    detectAll()  // 通用Thread策略模式和VM策略模式
    
    // 开启VM策略模式的线程策略
    detectActivityLeaks()
    detectLeakedClosableObjects()
    detectLeakedSqlLiteObjects()
    setClassInstanceLimit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    StrictMode VM策略可以监控以下问题:

    • 泄露的 Activity 对象
    • 泄露的 SQLite 对象
    • 泄漏的可关闭对象

    泄露的 Activity 对象和泄露的 SQLite 对象就是字面意思,没啥好解释的,泄漏的可关闭对象可以理解为是检查器通过调用 close()或类似方法在最终确定之前监视应该关闭的对象

    上面说的三种策略,也有多种不同的方式让我们知道APK何时违反了规则。一旦发现违规可以写入 Logcat 日志存储在 DropBox (android.os.DropBox) 服务或ANR日志中。此外,线程策略违规可能会闪烁屏幕背景或显示对话框(当然此处也可以手动检测就是自行开启Android 设备中的监控下的严格模式)

    除了通过日志查看之外,我们也可以在手机的开发者选项中开启严格模式,开启之后,如果主线程中有执行时间长的操作,屏幕则会闪烁,这是一个更加直接的方法

    在这里插入图片描述

    • 下面这些是StrictMode违反线程策略的关键字,尤其是以日志的方式输出
    penaltyLog() // 以日志的方式输出
    penaltyDeath() // 出现上述情况异常终止
    penaltyDialog() // 监测到上述状况时弹出对话框
    
    • 1
    • 2
    • 3
    • 通过日志查看并过滤StrictMode就能得到违例的具体stacktrace信息:
    adb logcat | grep StrictMode
    
    • 1

    在这里插入图片描述

    • 我们应该跟进 StrictMode 生成的大多数警告,但并不是所有该APK产生的StrictMode 警告来判断是否存在敏感信息泄露、能否造成APK应用程序被Doss等漏洞。举个例子,比如在很多情况下,APK在主线程上从磁盘快速读取不会明显阻碍APK应用程序运行或可能开发人员还有其它一些在发布生产版本的APK中存在违规的调试代码

    • 动态分析隐藏APK调试符号方法,比如StrictMode,有如下三种方式(之前我们也涉及的讲过这些内容)

      • Logcat 日志观察StrictMode 关键字
      • 观察应用程序的警告提示弹框,因为违规时可能会弹框提示
      • 应用程序的ANR 崩溃日志信息

    配合之前的文章食用更佳:

    参考链接

    https://www.cnblogs.com/daemon369/p/3227309.html

    https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05i-Testing-Code-Quality-and-Build-Settings.md

    https://support.google.com/googleplay/android-developer/answer/9848633?hl=zh-Hans

    https://blog.csdn.net/beyond702/article/details/56281068

    https://www.jianshu.com/p/271474cd1d91

    https://bbs.huaweicloud.com/blogs/307087

    https://blog.csdn.net/u011033906/article/details/89926229

    https://www.programminghunter.com/article/5661141738/

    https://blog.csdn.net/jovifan/article/details/11782019


    你以为你有很多路可以选择,其实你只有一条路可以走


  • 相关阅读:
    AI智剪:批量剪辑实战,技巧与实例
    ODrive移植keil(四)—— PWM触发ADC采样
    WebLogic:如何实现应用的优雅停止?
    activiti开源工作流集成示例
    MyBatis核心配置文件解析: 一步步深入理解mybatis-config.xml
    Java AOP Framework概述
    《Linux从练气到飞升》No.31 多线程编程实践与线程安全技术
    0基础24岁女硕士生,想转行做月薪30k的测试开发,需要从什么开始学习?
    二叉树【Java】
    手机端 Android WebView 获取 blob 链接文件名并下载网页动态生成的 pdf 文件且调用外部程序打开
  • 原文地址:https://blog.csdn.net/Ananas_Orangey/article/details/126641107