ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MASTG 移动应用混淆(Obfuscation)技术全景:从名称混淆到加壳的防护与检测实战指南

MASTG 移动应用混淆(Obfuscation)技术全景:从名称混淆到加壳的防护与检测实战指南 文档教程网络安全【免费下载链接】mastgThe OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.项目地址https://gitcode.com/gh_mirrors/ow/mastg点击查看免费下载混淆Obfuscation是移动应用安全加固方案的核心组成部分其目标是通过转换代码与数据让逆向工程师难以理解有时甚至难以反汇编应用的真实逻辑。本文以 OWASP MASTG 的通用混淆知识页 MASTG-KNOW-0111 为主体结合 Android 与 iOS 平台知识页MASTG-KNOW-0033、MASTG-KNOW-0089及仓库内的测试用例与工具文档系统讲解六类核心混淆技术、各平台落地方式以及如何依据 MASTG 测试用例评估混淆效果。读完本文你将掌握名称混淆、指令替换、控制流平坦化、死代码注入、字符串加密与加壳的原理、配置示例和检测方法并能在实际加固与逆向评估中直接复用。混淆的本质与定位MASTG-KNOW-0111 将混淆定义为把代码和数据变换得更加难以理解有时甚至难以反汇编的过程它通常是软件保护方案中不可分割的一部分。混淆并非一个可以简单打开/关闭的开关——程序可以整体或部分地、以不同程度被变得难以理解。该知识页对应 MASVS-RESILIENCE 类别的加固目标。在 MASTG 体系里混淆与反调试、反篡改、反 Root/越狱检测等共同构成弹性Resilience测试域仓库中的 Android 与 iOS 测试用例如 MASTG-TEST-0051、MASTG-TEST-0093都要求测试者验证核心功能不应轻易被辨识。关于混淆的能力边界原文档给出了一个必须牢记的前提下文介绍的所有技术都无法阻止一个拥有足够时间和预算的人逆向你的应用。然而组合使用这些技术会显著增加逆向工作的难度。其目的因此是劝退逆向工程师、让他们觉得继续分析不值得。换句话说混淆的工程价值在于抬高攻击成本而非实现绝对安全。这一前提决定了后续所有技术取舍多样性、随机性和纵深组合比单一技巧更重要。MASTG 将可用的混淆技术归纳为六类名称混淆Name obfuscation指令替换Instruction substitution控制流平坦化Control flow flattening死代码注入Dead code injection字符串加密String encryption加壳Packing名称混淆抹去语义标识符原理与实战示例标准编译器会基于源码中的类名、函数名生成二进制符号。若不做任何混淆符号名将保持可读攻击者可以轻易从二进制中提取。例如一个检测越狱的函数可以靠搜索jailbreak等关键词直接定位。MASTG-KNOW-0111 以 MASTG-APP-0024DVIA-v2一个包含 15 漏洞的 Swift 越狱脆弱 iOS 应用见 apps/ios/MASTG-APP-0024.md为例子展示了这一对比。混淆前函数JailbreakDetectionViewController.jailbreakTest4Tapped的反汇编符号清晰可读__T07DVIA_v232JailbreakDetectionViewControllerC20jailbreakTest4TappedyypF: stp x22, x21, [sp, #-0x30]! mov rbp, rsp混淆后符号名不再具有任何语义__T07DVIA_v232zNNtWKQptikYUBNBgfFVMjSkvRdhhnbyyFySbyypF: stp x22, x21, [sp, #-0x30]! mov rbp, rsp需要注意的是名称混淆只作用于函数、类与字段的名字实际代码保持不变攻击者仍然可以阅读反汇编后的函数体并推断其用途例如还原某个安全算法的逻辑。平台落地Android 的 R8/ProGuard 与 keep 规则在 Android 上Java/Kotlin 源码被编译为 DEX 字节码逆向时通常先反编译成类 Java 伪代码工具链见 MASTG-TECH-0017。MASTG-KNOW-0033 指出类、方法、字段、包名乃至局部变量都可以被重命名为短小无意义的标识符这是一种不影响程序性能的布局混淆layout obfuscation。R8 与 MASTG-TOOL-0022ProGuard都能在 release 构建中完成标识符重命名行为由构建配置与 keep 规则控制。一个标准的 Gradle 配置如下android { buildTypes { release { // Enables code shrinking, obfuscation, and optimization for only // your projects release build type. minifyEnabled true // Includes the default optimization rules files packaged with // the Android Gradle plugin. To learn more, go to the section about // R8 configuration files. proguardFiles( getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro ) } } }proguard-rules.pro用于定义自定义规则-keep可以保留 R8 可能误删的关键代码避免运行时错误。典型示例-keep class com.example.api.PublicApi { *; } -keepclassmembers class * { android.webkit.JavascriptInterface methods; }此外MASTG-TOOL-0153dProtectProGuard 的混淆增强扩展见 tools/android/MASTG-TOOL-0153.md将混淆从符号层面扩展到代码层面提供算术混淆、常量混淆、字符串加密、控制流混淆等更深的 Java/Kotlin 混淆能力。平台落地iOS 的 Swift 重命名与运行时依赖iOS 应用编译为原生 Mach-O 二进制静态分析面对的是 ARM64 机器码、Objective-C/Swift 运行时元数据与符号。MASTG-KNOW-0089 强调了一个关键约束运行时特性可能依赖稳定的名称——例如NSClassFromString、键值编码KVC、反射、Codable键映射、动态 selector、objc声明、Storyboard 引用与 nib 加载。因此 iOS 混淆工具普遍借助 keep 规则、映射文件或构建期项目分析来保留运行时与资源仍需要的名字。一个典型的源码级 Swift 名称混淆工具是 MASTG-TOOL-0068SwiftShield见 tools/ios/MASTG-TOOL-0068.md它分析 Xcode 工程并在编译前替换选中的 Swift 标识符为对象包括 Pods 与 Storyboards生成不可逆的加密名称。其文档特别警告SwiftShield 会不可逆地覆盖所有源文件因此理想做法是只在 CI 服务器上、仅对 release 构建执行。需要注意区分 Swift/C 的名称修饰name mangling与刻意的混淆修饰把类型与命名空间信息编码进编译器特定的符号格式多数情况下可用去修饰工具还原可读名称相关操作见 MASTG-TECH-0114。指令替换与算术混淆让运算不再直白指令替换Instruction Substitution用更复杂的等价表示替换标准二元运算符。原文档给出的经典例子是加法x a b可以表示为x -(-a) - (-b)。MASTG-KNOW-0111 特别提醒如果始终使用同一种替换表示变换很容易被识破因此建议对同一场景准备多种替换方案并引入随机因子。虽然该技术在反编译阶段可以被逆转但替换的复杂度与深度决定了逆转是否耗时。这一思想在原生代码层面被扩展为算术混淆Arithmetic Obfuscation将简单的算术或位运算改写为更复杂的等价表达式使敏感计算在反汇编中不再贴近源码级操作。O-MVLL基于 LLVM 的开源原生混淆器提供了对应的算术混淆 pass配置示例def obfuscate_arithmetic(self, mod: omvll.Module, func: omvll.Function) - omvll.ArithmeticOpt: if func.name encode: return omvll.ArithmeticOpt(rounds8) return FalseiOS 知识页也给出了同一技术的用法针对compute_token这类敏感函数说明指令替换/算术混淆是跨平台的通用手法只是作用于 LLVM IR 或机器码层面Android NDK 原生层见 MASTG-KNOW-0033。控制流平坦化用状态机打散自然分支控制流平坦化Control Flow Flattening把函数体拆成基本块并将它们全部放入一个由 switch 语句驱动的无限循环中由调度器dispatcher控制程序流向。由于移除了通常让代码易于阅读的自然条件结构程序流会变得极难跟踪。MASTG-KNOW-0111 中的图示直观展示了变换前后代码形态的差异上图即原始出处图片仓库中位于 Document/Images/Chapters/0x06j/control-flow-flattening.png原始代码按顺序的分支结构被重排为通过状态变量驱动的扁平化 switch 分发结构。从逆向视角看控制流平坦化作用于函数控制流图control-flow graph——反编译流程的早期产物。除平坦化外常见的控制流混淆还包括不透明谓词opaque predicates以及对分支指令如GOTO #offset的变换。原生代码层面O-MVLL 提供控制流平坦化 pass示例配置只对指定函数生效def flatten_cfg(self, mod: omvll.Module, func: omvll.Function): if func.name check_password: return True return FalseiOS 上 O-MVLL 还提供控制流破碎control-flow breakingpass其文档记录了该 pass 在 iOS Swift 下的局限应只作用于用户自定义函数见 MASTG-KNOW-0089。Java/Kotlin 层的等价能力由 dProtect 的控制流混淆 pass 提供可通过-obfuscate-control-flow规则按类精确圈定混淆范围-obfuscate-control-flow class com.example.sensitive.** { *; }死代码注入让静态分析输出变噪死代码注入Dead Code Injection向程序中注入不影响原始行为的桩代码stub使控制流更复杂从而抬高逆向工程的开销。原文档的定义强调其不改变程序行为只增加需要人工排查的代码量。在原生层面这一思路被细化为垃圾代码Junk Code增加重复基本块、冗余分支或额外代码路径扩大控制流图的规模与复杂度。O-MVLL 的 Basic Block Duplicate pass 会复制选中的基本块并在运行时插入一个分支在功能等价的多个版本之间随机选择示例配置def basic_block_duplicate(self, mod: omvll.Module, func: omvll.Function): return omvll.BasicBlockDuplicateWithProbability(20)MASTG-KNOW-0033 还澄清了一个容易混淆的边界死代码注入与控制流混淆不同——控制流混淆主要重构真实逻辑而死代码注入是额外添加程序结果并不需要的逻辑。字符串加密把硬编码秘密藏进运行时应用常常携带硬编码的密钥、许可证、令牌与端点 URL默认情况下它们以明文形式存放在二进制数据段中。字符串加密String Encryption会加密这些值并在程序中注入在使用前解密数据的桩代码。应用该技术后原始字符串不再直接出现在反编译代码或提取出的二进制数据里明文只在运行时短暂存在。Android 侧的字符串加密MASTG-KNOW-0033 指出字符串字面量可能泄露端点 URL、文件路径、功能名、API 密钥、Root/越狱路径等检测特征与错误消息——这些都是逆向时的高价值线索。dProtect 扩展了 ProGuard 规则格式来支持字符串混淆示例-obfuscate-strings class com.example.sensitive.ApiClient { private static java.lang.String API_KEY; public java.lang.String buildHeader(); }iOS 侧的字符串加密与例外iOS 知识页补充了一个重要例外部分字符串无法被变换——因为平台框架或应用资源会按名称引用它们例如 Objective-C selector、运行时使用的类名、Storyboard 标识符、本地化键以及外部服务消费的值见 MASTG-KNOW-0089。字符串可能出现在 Mach-O 段如__TEXT.__cstring、Swift 元数据、Objective-C 元数据、资源文件或生成代码中。原生代码的字符串编码由 O-MVLL 提供可对指定字符串字节启用本地编码选项def obfuscate_string(self, _, __, string: bytes): if string bOMVLL: return omvll.StringEncOptLocal() return False资源与资产加密混淆并不限于可执行代码。Android 应用可对assets/、res/raw/中的配置数据、脚本、模型文件或 Web 资产进行编码/加密运行时再用javax.crypto.Cipher解密示例见 MASTG-KNOW-0033val encrypted assets.open(rules.json.enc).readBytes() val cleartext cipher.doFinal(encrypted) val rules JSONObject(cleartext.decodeToString())iOS 同样可对 bundle 中的security-rules.json.enc、model.bin.enc等文件使用 CryptoKit 或 CommonCrypto 解密后再解析示例见 MASTG-KNOW-0089let url Bundle.main.url( forResource: security-rules, withExtension: json.enc )! let encrypted try Data(contentsOf: url) let cleartext try decrypt(encrypted, with: runtimeKey) let rules try JSONDecoder().decode(SecurityRules.self, from: cleartext)需要注意的是资源加密能防止从 APK/IPA 直接提取明文资源但无法阻止运行时分析恢复解密数据或解密材料。加壳Packing压缩加密 动态还原加壳Packing是一种动态重写型混淆技术对应 MITRE ATTCK 技术 T1027.002将原始可执行文件压缩或加密成数据在执行期间动态恢复。加壳还会改变可执行文件的文件签名以规避基于签名的检测。Android动态代码加载Android 应用可以把部分逻辑放在静态 DEX 视图之外运行时再通过DexClassLoader、PathClassLoader或InMemoryDexClassLoader加载附加代码或把代码存为变换后的表示、执行前还原。MASTG-KNOW-0033 给出的示例是应用在assets/中存放payload.dex.enc启动后解密并用InMemoryDexClassLoader加载val encrypted assets.open(payload.dex.enc).readBytes() val dexBuffer ByteBuffer.wrap(decrypt(encrypted, runtimeKey)) val loader InMemoryDexClassLoader(dexBuffer, classLoader) val entry loader.loadClass(com.example.protected.Entry)检测侧可使用 MASTG-TOOL-0009APKiD配合 MASTG-TECH-0165 识别 APK 中已知的编译器、混淆器与加壳器特征但缺少已知签名并不能证明不存在动态加载或自定义加壳。iOS签名约束下的加载器 加密数据模式iOS 的代码签名与平台内存保护限制了任意自修改代码与运行时代码生成因此加壳实践通常不同MASTG-KNOW-0089 指出应用屏蔽产品一般会在签名前完成变换、使用已签名的原生加载器或专注于数据与控制流资产的运行时解码。一个实用模式是随 App bundle 携带已签名的加载器/解释器/状态机与加密数据如policy.vm.enc启动后由加载器解密并解释内存中的字节码。静态提取 IPA 只能看到加密 blob 与加载器而动态分析在解密后仍可能恢复明文表示。反射与间接调用让调用图断边Java 反射允许程序在运行时动态检查类型并调用构造器、方法与字段。MASTG-KNOW-0033 将其单独列为一种间接化手段代码不再直接调用方法而是用Class.forName获取类、用getDeclaredMethod解析方法、再经反射 API 执行从而减少反编译代码中显式调用点的数量。反射与动态代码加载是两回事反射操作的是已存在于应用中的代码只是改变了代码被引用和执行的方式。iOS 原生层对应的是混淆函数调用Obfuscated function calls把直接调用替换为间接或重建的调用使静态分析工具无法直接从反汇编中跟踪所有调用边调用图因此难以恢复。O-MVLL 提供间接调用indirect callpass示例def indirect_call(self, mod: omvll.Module, func: omvll.Function): if func.name check_password: return True return False更多原生层混淆不透明常量、符号剥离与 Objective-C 元数据清理除上述主技术外MASTG 平台知识页还记录了若干补充手段不透明常量Opaque constants把整型常量替换为运行时重建原值的复杂计算让魔法数字与算法特定常量在静态分析中不再显眼。O-MVLL 配置示例class Config(omvll.ObfuscationConfig): def obfuscate_constants(self, mod: omvll.Module, func: omvll.Function): if init_context_all in func.demangled_name: return True return False符号剥离Symbol stripping删除函数名等符号信息是原生代码最基本的混淆形式。但使用基于名称解析的 JNI 时Java_*导出符号即使剥离后仍会暴露通过JNI_OnLoadRegisterNatives动态注册可减少这种暴露见 MASTG-KNOW-0033。Objective-C 元数据清理类名、方法名、selector 与协议信息会泄露大量语义O-MVLL 提供 Objective-C Cleaner pass但其文档标注为进行中work in progress生产工具仍必须保留 Objective-C 运行时与资源所依赖的元数据见 MASTG-KNOW-0089。用 MASTG 测试用例评估混淆效果混淆是否有效最终要落到可验证的评估方法上。MASTG 为此提供了专门的测试用例AndroidMASTG-TEST-0051Testing Obfuscation要求反编译 APK 并审查代码重点确认有意义的标识符类名、方法名、变量名是否已被丢弃字符串资源与二进制内字符串是否已加密受保护功能的代码与数据是否被加密、加壳或隐藏。对原生代码还要检查 libc API 是否被替换为系统调用以及是否应用了 Obfuscator-LLVM 式的控制流平坦化/伪造控制流。iOSMASTG-TEST-0093 要求反汇编 IPA 中的 Mach-O 及 Frameworks 目录下的库文件验证同样的三点标识符已丢弃、字符串已加密、核心功能代码已加密/加壳/隐藏。检测工具方面MASTG-TOOL-0009APKiD可快速识别应用使用的混淆器、加壳器与反调试措施。MASTG-TEST-0051 给出了针对 MASTG-APP-0015 的实测输出示例apkid mastg/Crackmes/Android/Level_04/r2pay-v1.0.apk [] APKiD 2.1.2 :: from RedNaga :: rednaga.io [*] mastg/Crackmes/Android/Level_04/r2pay-v1.0.apk!classes.dex |- anti_vm : Build.TAGS check, possible ro.secure check |- compiler : r8 |- obfuscator : unreadable field names, unreadable method names该输出显示 APKiD 检测到了不可读字段名与方法名等混淆迹象。当面对混淆应用时还常会遇到开发者把关键数据与功能藏进原生库的情况——MASTG-APP-0004UnCrackable Level 2就是一个典型例证其校验逻辑位于native bar(byte[])方法中相关内容可参考 Android 反调试测试用例 MASTG-TEST-0046。小结把六类技术组合成纵深防线回到原文档的六类技术框架可以提炼出 MASTG 的混淆方法论技术核心思想典型工具/配置载体名称混淆抹去标识符语义R8/ProGuardMASTG-TOOL-0022、SwiftShieldMASTG-TOOL-0068指令替换/算术混淆等价复杂化运算O-MVLL Arithmetic、dProtectMASTG-TOOL-0153控制流平坦化调度器驱动的 switch 状态机O-MVLL Flattening、dProtect Control-flow死代码注入注入不影响行为的桩代码O-MVLL Basic Block Duplicate字符串加密运行时才重建明文dProtect Strings、O-MVLL Strings Encoding加壳压缩/加密后动态还原类加载器Android、签名加载器 加密数据iOS每一种技术单独使用都很容易被还原但正如原文档反复强调的组合这些技术并引入随机性才能显著提高逆向成本让攻击者放弃深入分析。在实战中加固方案应同时考虑平台差异Android 的 DEX 层 原生层、iOS 的 Mach-O 与运行时元数据依赖、运行时依赖keep 规则、selector、Storyboard 引用以及检测评估手段APKiD 等工具与 MASTG 测试用例从而构建既有深度又可验证的混淆防线。赞分享文档教程网络安全【免费下载链接】mastgThe OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.项目地址https://gitcode.com/gh_mirrors/ow/mastg点击查看免费下载相关推荐3分钟打造专业音乐播放器foobox-cn美化终极指南3分钟打造专业音乐播放器foobox cn美化终极指南 你是不是厌倦了foobar2000那过于朴素的默认界面想要一个既专业又美观的音乐播放体验今天我要为桌面应用音视频Reactive Data Client与Redux集成如何在现有项目中渐进式采用Reactive Data Client与Redux集成如何在现有项目中渐进式采用 Reactive Data Client是一个强大的异步状态管理库它支持前端终极指南如何通过lowlevelprogramming-university掌握代码混淆与逆向防护技术终极指南如何通过lowlevelprogramming university掌握代码混淆与逆向防护技术 lowlevelprogramming univers教程上一篇OpenArkWindows系统安全分析的终极利器下一篇如何快速下载网页视频VideoDownloadHelper免费插件完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表