Skip to content

ELF 混淆器 (obfuscators) ​

obfuscatorELF46 条

elf/obfuscators.yara 检测原生层(.so)代码混淆工具。重头戏是 OLLVM 全版本指纹——从 3.4 到 9.x,覆盖字符串加密(strenc)、控制流平坦化(CFF)、虚假控制流(BCF),以及 Hikari、Armariris、TLL、LSPosed 等衍生分支。注意 epona 虽在此文件中,但它的 tag 是 protector。

🎯 原生混淆的手段 ​

  • 字符串加密:OLLVM 的 .datadiv_decodeXXXX 函数运行时 XOR 解密字符串。
  • 控制流平坦化(CFF):把线性流程拆成 switch 分发,靠状态变量跳转。
  • 虚假控制流(BCF):插入永真/永假的不透明谓词,分支到死代码。
  • 指令替换:用等价但复杂的指令序列。
  • Prolog breakage:Arxan/DexGuard 打断函数序言,靠 BR X8 间接跳转。

📋 规则清单 ​

OLLVM 版本指纹系列 ​

规则tag说明
ollvm_v3_4obfuscatorObfuscator-LLVM 3.4
ollvm_v3_5obfuscatorObfuscator-LLVM 3.5
ollvm_v3_6_1obfuscatorObfuscator-LLVM 3.6.1
ollvm_v4_0obfuscatorObfuscator-LLVM 4.0
ollvm_v5_0_strencobfuscatorOLLVM 5.0(字符串加密)
ollvm_v6_0obfuscatorOLLVM 6.0
ollvm_v6_0_strencobfuscatorOLLVM 6.0(字符串加密)
ollvm_v8obfuscatorOLLVM 8.x
ollvm_v8_strencobfuscatorOLLVM 8.x(字符串加密)
ollvm_v9obfuscatorOLLVM 9.x
ollvm_v9_aobfuscatorOLLVM 9.x(o2e 分支)
ollvm_v9_strencobfuscatorOLLVM 9.x(字符串加密)

OLLVM 衍生分支与通用规则 ​

规则tag说明
ollvm_tllobfuscatorOLLVM TLL(字符串加密,yazhiwang/ollvm-tll)
ollvm_tll_aobfuscatorOLLVM TLL(变体,git URL 指纹)
ollvm_armaririsobfuscatorArmariris OLLVM(字符串加密,GoSSIP-SJTU)
ollvm_strencobfuscatorOLLVM 未知版本(字符串加密兜底)
ollvm_v_regexobfuscatorOLLVM(clang 版本串正则)
ollvmobfuscatorOLLVM 未知版本(兜底,Obfuscator-LLVM /Obfuscator-clang )
ollvm_lsposedobfuscatorLSPosed OLLVM(decrypt.XXXXXXXX 导出 ≥5)

OLLVM 代码级指纹(不依赖 .comment 字符串) ​

规则tag说明
ollvm_cff_arm32obfuscatorOLLVM 控制流平坦化(ARM32,CMP+BEQ 分发链)
ollvm_cff_arm64obfuscatorOLLVM 控制流平坦化(ARM64)
ollvm_bcf_arm64obfuscatorOLLVM 虚假控制流(ARM64,CBNZ/CMP 不透明谓词)
ollvm_string_encryption_arm64obfuscatorOLLVM 字符串加密(ARM64,datadiv_decode/XOR 解密模式)
hikari2_dexprotectorobfuscatorHikari 2.0(DexProtector 变体,decrypt. + LLVM 15)

其它混淆器 ​

规则tag说明
alipayobfuscatorAlipay 混淆器(Alipay clang version/Alipay.Obfuscator.)
byteguard_0_9_3obfuscatorByteGuard 0.9.3
byteguard_0_9_2obfuscatorByteGuard 0.9.2
byteguard_unknownobfuscatorByteGuard 未知版本
firehashobfuscatorFirehash(.firehash 节区 + ARM opcode)
advobfuscatorobfuscatorADVobfuscator(ObfuscatedAddress/MetaString C++ 符号)
arxan_arm32obfuscatorArxan(ARM32,Prolog breakage ≥5)
arxan_arm64obfuscatorArxan(ARM64,BR X8 间接跳转 ≥3)
dexguard_nativeobfuscatorDexGuard(HookDetector JNI 符号)
dexguard_native_aobfuscatorDexGuard 9.x(libdgrt.so + Java_o_)
dexguard_native_arm64obfuscatorDexGuard 9.x(ARM64,Frida 检测 + Prolog breakage + SVC ≥6)
snapprotectobfuscatorSnapProtect(snap.protect version clang 串)
safeengineobfuscatorSafeengine LLVM(Safengine clang version)
dexprotectorobfuscatorDexProtector(ELF 头 DPLF 魔数)
dexprotector_aobfuscatorDexProtector(DPLF 段头)
dexprotector_aliceobfuscatorDexProtector Alice(alice-core/*.cpp 路径)
androidrepublicobfuscatorAndroidRepublic(libemtrepublicv3.so + 标语)
androidrepublic_vipobfuscatorAndroidRepublic VIP(libandroidrepublic.so)
ayobfuscatorAY(adamyaxley/Obfuscate,ay::obfuscated_data::decrypt)
octopus_codevoobfuscatorOctopus SDK Codevo(octopus_obf::obfuscated_data)
eponaprotectorQuarks AppShield Epona(白盒密码学 LDRB 模式)

epona 的 tag 是 protector

epona 虽然物理上位于 obfuscators.yara 文件中,但它的 YARA 声明是 rule epona : protector,所以输出 category: "protector" 而非 obfuscator。它检测的是 Quarks AppShield 的白盒密码学实现,属保护而非混淆。

🔍 检测原理要点 ​

clang 版本串指纹(OLLVM 主线) ​

OLLVM 在编译时把 Obfuscator-LLVM clang version X.Y.Z (based on Obfuscator-LLVM X.Y.Z) 写进 .comment 节区。规则靠精确字符串或正则匹配版本:

yara
rule ollvm_v3_4 : obfuscator {
  strings:
    $clang_version = "Obfuscator-clang version 3.4 "
    $based_on      = "(based on LLVM 3.4"
  condition:
    is_elf and all of them
}

.datadiv_decode 字符串加密指纹 ​

OLLVM 字符串加密会生成 .datadiv_decodeXXXXXXXXXXXXXXXXXX 函数(18~20 位数字),运行时 XOR 解密字符串。_strenc 后缀规则靠匹配这个符号识别字符串加密变体,并排除已知版本:

yara
rule ollvm_v6_0_strenc : obfuscator {
  strings:
    $clang_version = "Obfuscator-LLVM clang version 6.0."
    $based_on      = "(based on Obfuscator-LLVM 6.0."
  condition:
    is_elf and all of them and
    for any i in (0..elf.symtab_entries): (
      elf.symtab[i].name matches /\.datadiv_decode[\d]{18,20}/
    )
}

代码级 CFF/BCF 指纹(.comment 被剥离时) ​

现代 OLLVM 分支常剥离 .comment 节区,版本串失效。APKiD 加了 _cff_/_bcf_/_string_encryption_arm64 规则,直接在 .text 里匹配指令模式:

  • CFF:MOV state → CMP → B.EQ/B.NE 分发链,要求 >3 次重复。
  • BCF:CBZ/CBNZ + 短分支到死代码 + B back,要求 >8 次重复。
  • 这些规则都带一长串 not ollvm_v3_4 and not ... 排除已知版本,避免重复报告。

Prolog breakage(Arxan/DexGuard) ​

Arxan 和 DexGuard 9.x 打断函数序言,用 BR X8 间接跳转到加密的基本块。规则靠 opcode 序列 + 计数阈值识别(如 arxan_arm64 要求 #a > 3 or #b > 3)。

自定义魔数(DexProtector) ​

dexprotector 靠 ELF 头偏移处的 DPLF(DexProtector Linkable Format)魔数识别,dexprotector_a 靠 PT_LOAD 段头的 DPLF 识别。

📊 finding 示例 ​

json
{
  "tag": "obfuscator::ollvm_v9_strenc",
  "category": "obfuscator",
  "source": "app.apk!lib/arm64-v8a/libfoo.so",
  "identifier": "ollvm_v9_strenc",
  "confidence": "medium"
}

OLLVM 规则的版本提取(如 ollvm_v9 → version: "9")由 _extract_version() 处理。

📍 相关 ​

基于 GPL & Commercial 双重许可发布