从源码视角解析Arkari间接跳转混淆
字数 2018 2025-08-29 08:29:58

Arkari间接跳转混淆技术深度解析

一、Arkari概述

Arkari是一个基于LLVM 19.x的代码混淆框架,支持多种混淆技术,主要针对ARM64架构。其支持的混淆特性包括:

  1. 过程间相关混淆:

    • 间接跳转并加密跳转目标 (-mllvm -irobf-indbr)
    • 间接函数调用并加密目标函数地址 (-mllvm -irobf-icall)
    • 间接全局变量引用并加密变量地址 (-mllvm -irobf-indgv)
    • 字符串加密 (-mllvm -irobf-cse)
  2. 过程内相关混淆:

    • 控制流平坦化 (-mllvm -irobf-cff)
    • 整数常量加密 (-mllvm -irobf-cie)
    • 浮点常量加密 (-mllvm -irobf-cfe)

二、间接跳转混淆原理

基本概念

在ARM64架构中,间接跳转混淆通过将程序中的直接跳转指令(如B/BL)替换为通过通用寄存器(如X17)的间接跳转(如BR X8),破坏静态控制流的可读性。由于静态分析工具无法确定寄存器中的值,导致程序原始控制流在静态分析下被截断。

混淆流程

混淆过程主要在IndirectBranch.cpp文件的runOnFunction函数中实现,这是pass执行的入口点。主要分为四个步骤:

  1. 随机打乱基本块
  2. 初始化加密密钥
  3. 根据opt选择混淆强度
  4. 解密真实块地址并插入间接跳转指令

三、详细实现分析

Step 1: 随机打乱基本块

  1. 初始化数据结构

    • BBNumbering:存储基本块到随机化编号的映射
    • BBTargets:临时存储所有唯一条件分支目标块
  2. 关键边分割

    • 调用SplitAllCriticalEdges函数,在有多个前驱和后继的边之间插入新基本块
  3. 基本块随机化

    • 调用NumberBasicBlock函数
    • 寻找条件跳转的后继基本块
    • 使用随机数打乱基本块顺序
    • 对基本块进行重新编号

Step 2: 初始化加密密钥

声明三个关键全局变量:

  1. GXorKey (GlobalVariable*):存储全局异或密钥(用于Level 1或2混淆)
  2. DestBBs (GlobalVariable*):存储加密后的跳转地址数组(核心跳转表)
  3. XorKeys (GlobalVariable*):存储动态生成的异或密钥数组(用于Level 3混淆)

Step 3: 混淆强度选择

Arkari支持通过两种方式控制混淆强度:

  1. 通过annotate对特定函数指定混淆强度

    • 例如^flag=1表示当前函数设置某功能强度等级为1
  2. 通过命令行参数指定

    • 例如:-mllvm -irobf-icall -mllvm -level-icall=3

混淆强度分为四个级别:

Level 0

  • 生成加密地址的全局变量数组(GV)
  • 加密公式:加密地址 = 原始地址 + EncKey
    • 注意:EncKey是负数,代码表现为加密地址 = 原始地址 - EncKey

Level 1

  • 修改点:ConstantExpr::getXor(AddKey, XorKey)
  • 加密公式:加密地址 = 原始地址 + (AddKey ^ XorKey)

Level 2

  • 修改点与Level 1类似
  • 加密公式:加密地址 = 原始地址 + [AddKey ^ (XorKey * Idx)]
    • 特点:密钥与基本块编号挂钩,每个基本块对应不同的解密key

Level 3

  • 加密公式:加密地址 = 原始地址 + [EncKey1 ^ ( (XorKeys[Idx] ^ EncKey1) * Idx )]
  • 特点:
    • 在Level 2基础上增加对密钥的混淆
    • 使用完全随机化的动态密钥
    • 采用双数组隔离+混淆设计
    • 使硬编码的密钥更加安全
    • 解密时再对混淆的密钥进行还原

Step 4: 解密真实块地址并插入间接跳转指令

基本流程:

  1. 获取加密的跳转地址
  2. 根据混淆级别选择相应的解密算法
  3. 解密得到真实的基本块地址
  4. 插入间接跳转指令(如BR X8

四、技术特点与创新

  1. 多级别混淆:提供0-3四个级别的混淆强度选择
  2. 动态密钥:Level 3引入完全随机化的动态密钥
  3. 密钥混淆:对密钥本身进行混淆处理
  4. 双数组隔离:增加安全性
  5. 基本块关联:密钥与基本块编号关联,增加破解难度

五、对抗思路

  1. 静态分析:由于密钥混淆和动态计算,静态分析难以恢复原始控制流
  2. 动态分析:可能需要使用类似Angr的工具强制程序走不同分支
  3. 符号执行:可能有效但计算成本较高
  4. 模式识别:识别密钥生成和使用的固定模式

六、总结

Arkari的间接跳转混淆技术,特别是Level 3的实现,通过动态密钥生成、密钥混淆和双数组隔离等创新设计,显著提高了逆向工程的难度。其多级别混淆策略为开发者提供了灵活的安全选择,同时也为安全研究人员提出了新的挑战。

Arkari间接跳转混淆技术深度解析 一、Arkari概述 Arkari是一个基于LLVM 19.x的代码混淆框架,支持多种混淆技术,主要针对ARM64架构。其支持的混淆特性包括: 过程间相关混淆: 间接跳转并加密跳转目标 ( -mllvm -irobf-indbr ) 间接函数调用并加密目标函数地址 ( -mllvm -irobf-icall ) 间接全局变量引用并加密变量地址 ( -mllvm -irobf-indgv ) 字符串加密 ( -mllvm -irobf-cse ) 过程内相关混淆: 控制流平坦化 ( -mllvm -irobf-cff ) 整数常量加密 ( -mllvm -irobf-cie ) 浮点常量加密 ( -mllvm -irobf-cfe ) 二、间接跳转混淆原理 基本概念 在ARM64架构中,间接跳转混淆通过将程序中的直接跳转指令(如B/BL)替换为通过通用寄存器(如X17)的间接跳转(如BR X8),破坏静态控制流的可读性。由于静态分析工具无法确定寄存器中的值,导致程序原始控制流在静态分析下被截断。 混淆流程 混淆过程主要在 IndirectBranch.cpp 文件的 runOnFunction 函数中实现,这是pass执行的入口点。主要分为四个步骤: 随机打乱基本块 初始化加密密钥 根据opt选择混淆强度 解密真实块地址并插入间接跳转指令 三、详细实现分析 Step 1: 随机打乱基本块 初始化数据结构 : BBNumbering :存储基本块到随机化编号的映射 BBTargets :临时存储所有唯一条件分支目标块 关键边分割 : 调用 SplitAllCriticalEdges 函数,在有多个前驱和后继的边之间插入新基本块 基本块随机化 : 调用 NumberBasicBlock 函数 寻找条件跳转的后继基本块 使用随机数打乱基本块顺序 对基本块进行重新编号 Step 2: 初始化加密密钥 声明三个关键全局变量: GXorKey ( GlobalVariable* ):存储全局异或密钥(用于Level 1或2混淆) DestBBs ( GlobalVariable* ):存储加密后的跳转地址数组(核心跳转表) XorKeys ( GlobalVariable* ):存储动态生成的异或密钥数组(用于Level 3混淆) Step 3: 混淆强度选择 Arkari支持通过两种方式控制混淆强度: 通过annotate对特定函数指定混淆强度 : 例如 ^flag=1 表示当前函数设置某功能强度等级为1 通过命令行参数指定 : 例如: -mllvm -irobf-icall -mllvm -level-icall=3 混淆强度分为四个级别: Level 0 生成加密地址的全局变量数组(GV) 加密公式: 加密地址 = 原始地址 + EncKey 注意:EncKey是负数,代码表现为 加密地址 = 原始地址 - EncKey Level 1 修改点: ConstantExpr::getXor(AddKey, XorKey) 加密公式: 加密地址 = 原始地址 + (AddKey ^ XorKey) Level 2 修改点与Level 1类似 加密公式: 加密地址 = 原始地址 + [AddKey ^ (XorKey * Idx)] 特点:密钥与基本块编号挂钩,每个基本块对应不同的解密key Level 3 加密公式: 加密地址 = 原始地址 + [EncKey1 ^ ( (XorKeys[Idx] ^ EncKey1) * Idx )] 特点: 在Level 2基础上增加对密钥的混淆 使用完全随机化的动态密钥 采用双数组隔离+混淆设计 使硬编码的密钥更加安全 解密时再对混淆的密钥进行还原 Step 4: 解密真实块地址并插入间接跳转指令 基本流程: 获取加密的跳转地址 根据混淆级别选择相应的解密算法 解密得到真实的基本块地址 插入间接跳转指令(如 BR X8 ) 四、技术特点与创新 多级别混淆 :提供0-3四个级别的混淆强度选择 动态密钥 :Level 3引入完全随机化的动态密钥 密钥混淆 :对密钥本身进行混淆处理 双数组隔离 :增加安全性 基本块关联 :密钥与基本块编号关联,增加破解难度 五、对抗思路 静态分析 :由于密钥混淆和动态计算,静态分析难以恢复原始控制流 动态分析 :可能需要使用类似Angr的工具强制程序走不同分支 符号执行 :可能有效但计算成本较高 模式识别 :识别密钥生成和使用的固定模式 六、总结 Arkari的间接跳转混淆技术,特别是Level 3的实现,通过动态密钥生成、密钥混淆和双数组隔离等创新设计,显著提高了逆向工程的难度。其多级别混淆策略为开发者提供了灵活的安全选择,同时也为安全研究人员提出了新的挑战。