第十二章 软件壳(二)(软件壳的特征与侦察)

文章目录

  • 软件壳的特征与侦察
    • 编译器指纹
    • 软件壳的特征
      • DEX 混淆
      • DEX 加密与 Application 替换
      • so 加密
    • 查壳工具

软件壳的特征与侦察

  • 软件壳的特征侦察技术
    • APK 中 DEX 和 so 动态库使用的编译器识别规则
    • 软件壳处理目标 APK 后留下的特征信息

编译器指纹

  • APK 的可执行代码

    • DEX
      • 属于 Java 部分
      • 可用 dx 或 smali 的 dexlib2 库生成
    • so 动态库
      • 属于 Native 部分
      • 可用 gcc 或 Clang 编译器生成
  • 用 dexlib2 生成的 DEX 的特点

    • DexMapList 结构体第八个字段的值固定为 TYPE_STRING_DATA_ITEM
  • 用 yara 编写识别规则

  • Ubuntu 快速安装 yara:sudo apt install yara

  • yara 规则库:git clone https://github.com/Yara-Rules/rules

  • yara 文档

  • 上述规则:

    private rule dexlib2_map_type_order
    {
        condition:
            dex.map_list.map_items[7].type == 0x2002    // TYPE_STRING_DATA_ITEM
    }
    

  • AS 早期版本中,为将用 Java 8 编写的代码编译成 DEX,引入 Jack 编译器

  • 用该编译器生成的 DEX,会向 DEX 字符串表添加 Jack 编译器的版本信息

  • 识别它的方法是在 DEX 中搜索版本信息字符串,用 yara 编写识别规则:

    rule jack_4_12 : compiler
    {
        meta:
            description = "Jack 4.12"
     
        strings:
            // emitter: jack-4.12
            $jack_emitter = {00 12 65 6D 69 74 74 65 72 3A 20 6A 61 63 6B 2D 34 2E 31 32 00}
     
        condition:
            $jack_emitter
    }
    

  • 若用 Clang 编译 so 动态库或 ELF 原生程序,编译器在生成目标文件时会向其中添加编译器版本信息

  • hello.c 为例,生成的 hello.s 汇编文件中 .ident 表示编译器的版本号信息

    image-20200428135925158

    第十二章 软件壳(二)(软件壳的特征与侦察)_第1张图片

    第十二章 软件壳(二)(软件壳的特征与侦察)_第2张图片

  • 编译生成 so 动态库或 ELF 原生程序后,这些信息被存储在 .comment 节区

    第十二章 软件壳(二)(软件壳的特征与侦察)_第3张图片

  • 识别它的方法是在 so 动态库或 ELF 原生程序中搜索该字符串,用 yara 编写识别规则:

    rule clang_8_0 : compiler
    {
        meta:
            description = "clang 8.0"
        strings:
            $clang_comment = {41 6E 64 72 6F 69 64 20 28 35 32 32 30 30 34 32 20 62 61 73 65
            64 20 6F 6E 20 72 33 34 36 33 38 39 63 29 20 63 6C 61 6E 67 20 76 65 72 73 69 6F
            6E 20 38 2E 30 2E 37}   // Android (5220042 based on r346389c) clang version 8.0.7
        condition:
            $clang_comment
    }
    

软件壳的特征

  • 用软件壳为目标程序加壳后,会根据加密强度不同分别使用 DEX 混淆、DEX 加密与 Application 替换、so 加密等

DEX 混淆

  • 常见于 DEX 混淆器,如 DexGuard、DexProtect
  • 识别此类加壳程序:对比和分析它们所生成的 DEX 和常规 DEX
  • 为达到字符串加密和方法流程混淆的效果,混淆器通常会用 Java 的反射机制实现加密,并向代码中插入 getClass().getDeclaredMethod().invoke() 之类的方法调用。配合它们独有的 DEX 字节码特征,很容易识别

DEX 加密与 Application 替换

  • 软件壳处理 APK 时,通常会用 StubApplication 类替换程序的 Application 类,达到接管 APK 启动控制权的目的

  • 不同厂商的加壳程序的 StubApplication 类名称和包名有所不同 —— 识别各厂商软件壳最简单有效的方法

  • 以爱加密的软件壳为例(爱加密官网可免费加壳)

  • 可看出,目前这款软件壳通过一个 N 类加载 Native 动态库 libexec.so

    第十二章 软件壳(二)(软件壳的特征与侦察)_第4张图片

  • 用 010 Editor 打开 libexec.so,可在字符串表中找到 ijiami 字符串

    第十二章 软件壳(二)(软件壳的特征与侦察)_第5张图片


so 加密

  • 分析软件壳特征时,满足的规则越多,准确率越高

  • 再找找上述软件壳更多特征:

    • 特征文件名。其对 APK 处理后,会在 assets 目录添加 ijm_lib 目录和 ijiami.ajm 文件,从名字即可判断

    • 此软件壳的 so 动态库在发布时用了修改版的 UPX 壳进行压缩和加密,可通过分析 libexec.so 是否使用了 UPX 加密进一步判断

    • 若使用 UPX 加密,在 ARM 原生程序与 so 动态库中会出现一段 Stub 代码,内容固定为字符串序列 1E 20 A0 E3 14 10 8F E2 02 00 A0 E3 04 70 A0 E3 00 00 00 EF 7F 00 A0 E3 01 70 A0 E3 00 00 00 EF,在 libexec.so 搜索该字符串序列,会发现的确用了 UPX 加密

      第十二章 软件壳(二)(软件壳的特征与侦察)_第6张图片


查壳工具

  • 本书介绍的是 APKID,但未能识别上述软件壳,此处使用 ApkScan-PKID(下载地址,提取码:5hxy)

  • 下载完成后,打开此工具(java -jar ApkScan-PKID.jar 或右键->”打开方式“->”Java™ Platform SE binary“)

  • 将加壳后的 APK 拖入,即可检测

    第十二章 软件壳(二)(软件壳的特征与侦察)_第7张图片

你可能感兴趣的:(《Android,软件安全权威指南》学习笔记)