[机翻] [ABD] 04_混淆工具使用指南

04 混淆工具使用指南

https://github.com/malrev/ABD

⚠️ API 版本说明:本文档中的 Miasm API 代码示例已于 2026-07 更新至 Miasm 0.1.5+ 版本。课程原始材料使用的是 0.1.3 版本(2020年),部分 API 已发生 breaking change。更新处以 【更新】 标注,旧版用法以 【旧版 v0.1.3】 标注。

本章介绍商业混淆工具与学术混淆工具,重点讲解 O-LLVM 与 Tigress 的原理、选项与使用方法,并列出课程的测试用 C 源码与 Makefile 构建规则,供 Hands-On 实践参考。


4.1 商业混淆工具

以下是一些常见的商业混淆工具,它们被广泛应用于软件保护(同时也可能被恶意软件滥用):

工具 说明
Themida 由 Oreans Technologies 开发,提供多层保护机制,包括反调试、反内存转储、代码虚拟化与代码变形。是市场上知名的加壳保护工具之一。
Code Virtualizer 同样来自 Oreans,专注于代码虚拟化(Virtualization Obfuscation),将 x86/x64 指令转换为自定义虚拟机字节码。
VMProtect 提供代码虚拟化、加壳与授权管理功能。广泛用于软件保护,也常见于恶意软件样本中。
Enigma Enigma Protector,提供加壳、虚拟化、反调试与授权管理。
Epona 商业软件保护工具,提供代码混淆与反逆向功能。

注意:这些商业工具在恶意软件分析中经常出现——许多恶意软件样本使用这些工具加壳以逃避检测。因此,逆向分析者需要熟悉这些工具的特征与脱壳方法。


4.2 学术混淆工具

学术混淆工具通常开源或可免费获取,便于教学与研究。本课程重点介绍两个工具:O-LLVMTigress


4.2.1 O-LLVM (Obfuscator-LLVM)

【更新】O-LLVM 原始项目已停止维护github.com/obfuscator-llvm/obfuscator 仓库自 2017 年起不再更新,最后支持的 LLVM 版本为 4.0。以下是目前活跃的替代 fork:

这些 fork 支持更新的 LLVM 版本,部分还新增了更多混淆选项。下文 O-LLVM 的选项说明(-sub/-fla/-bcf)对 goron 仍然适用;Hikari 和 Pluto 有额外的混淆选项。

原理

O-LLVM 是基于 LLVM 的开源混淆器。其核心原理是:

  • 将混淆实现为编译器工具链中的一个 optimization pass(优化通道)
  • 混淆作用于 LLVM IR(中间表示) 层面。
  • 由于混淆在 IR 层进行,可以支持 LLVM 支持的所有目标架构。
源代码 (.c) ──► LLVM Frontend (clang) ──► LLVM IR
                                              │
                                              ▼
                                    ┌──────────────────┐
                                    │ Obfuscation Pass │  ← O-LLVM 的混淆在此插入
                                    │  -sub / -fla /   │
                                    │  -bcf            │
                                    └────────┬─────────┘
                                              │
                                              ▼
                                    混淆后的 LLVM IR
                                              │
                                              ▼
                                    LLVM Backend ──► 机器代码

选项

O-LLVM 提供三个混淆选项:

选项 名称 对应技术 说明
-sub Instruction Substitution 指令替换 用等效但复杂的指令序列替换原始指令。
-fla Control Flow Flattening 控制流平坦化 将基本块展平为 switch-case 结构。
-bcf Bogus Control Flow 不透明谓词 插入不透明谓词与虚假控制流。

-bcf 还可配合 -bcf_prob 参数控制插入概率(0-100)。

参考文献

  • Junod et al. Obfuscator-LLVM – Software Protection for the Masses. SPRO'15 (Workshop on Software Protection, 2015).

o-llvm.sh 脚本内容

以下是对单个 C 文件应用三种混淆变换的核心命令:

# 指令替换
${OLLVM} –m32 –mllvm –sub ${FILE} –o "${FILE_NO_EXT##*/}-sub.bin"

# 控制流平坦化
${OLLVM} –m32 –mllvm –fla ${FILE} –o "${FILE_NO_EXT##*/}-fla.bin"

# 虚假控制流(不透明谓词),bcf_prob=100 表示 100% 插入概率
${OLLVM} –m32 –mllvm –bcf –mllvm –bcf_prob=100 ${FILE} –o "${FILE_NO_EXT##*/}-bcf.bin"

参数说明:

  • ${OLLVM}:O-LLVM 的 clang 可执行文件路径。
  • –m32:编译为 32 位。
  • –mllvm –sub / –mllvm –fla / –mllvm –bcf:启用对应的混淆变换。
  • ${FILE}:输入的 C 源文件。
  • ${FILE_NO_EXT##*/}:去除路径与扩展名后的文件名,用于命名输出文件。

完整 o-llvm.sh 脚本逻辑

完整的 o-llvm.sh 脚本逻辑:遍历 src 目录下的所有 .c 文件,对每个文件应用三种混淆变换。

#!/bin/bash
#
# o-llvm.sh - 对 src 目录下所有 .c 文件应用 O-LLVM 三种混淆变换
#

# O-LLVM 的 clang 路径(需根据实际环境配置)
OLLVM=/path/to/ollvm/build/bin/clang

# 源代码目录
SRC_DIR=src

# 输出目录
OUT_DIR=out

# 创建输出目录
mkdir -p ${OUT_DIR}

# 遍历 src 目录下的所有 .c 文件
for FILE in ${SRC_DIR}/*.c; do
    # 提取文件名(不含路径与扩展名)
    FILE_NO_EXT="${FILE%.c}"

    echo "========================================"
    echo "Processing: ${FILE}"
    echo "========================================"

    # 1. 指令替换 (-sub)
    ${OLLVM} –m32 –mllvm –sub ${FILE} –o "${OUT_DIR}/${FILE_NO_EXT##*/}-sub.bin"

    # 2. 控制流平坦化 (-fla)
    ${OLLVM} –m32 –mllvm –fla ${FILE} –o "${OUT_DIR}/${FILE_NO_EXT##*/}-fla.bin"

    # 3. 虚假控制流 / 不透明谓词 (-bcf),插入概率 100%
    ${OLLVM} –m32 –mllvm –bcf –mllvm –bcf_prob=100 ${FILE} –o "${OUT_DIR}/${FILE_NO_EXT##*/}-bcf.bin"

    echo "Done: ${FILE}"
    echo ""
done

echo "All files processed. Output in ${OUT_DIR}/"

4.2.2 Tigress

简介

  • TigressUniversity of Arizona 维护,由 Christian Collberg 领导开发。
  • 与 O-LLVM 不同,Tigress 混淆的是 C 源代码(而非 IR)。
  • Christian Collberg 是软件混淆领域的先驱学者之一,也是混淆分类法的重要贡献者。

选项

Tigress 的主要选项:

选项 说明
Transform 指定要应用的变换名称。
AddOpaqueCount 指定插入的不透明谓词数量。
AddOpaqueKinds 指定不透明谓词的种类。
Functions 指定要混淆的函数(可指定多个)。
Environment 指定运行环境(如操作系统)。
out / o 指定输出文件名。

6 种变换

Tigress 提供 6 种变换:

序号 变换名称 说明
1 EncodeLiterals 编码文字常量(Encode Literals)。
2 EncodeArithmetic 编码算术运算(Encode Arithmetic / MBA)。
3 Flatten 控制流平坦化(Control Flow Flattening)。
4 InitOpaque + AddOpaque 初始化并添加不透明谓词(Opaque Predicate)。
5 InitEntropy + InitOpaque + AddOpaque 复合变换:先初始化熵源,再添加不透明谓词。
6 Virtualize 虚拟化混淆(Virtualization Obfuscation)。

Transform 和 Functions 可堆叠:可以在一条命令中指定多个 Transform,并对多个函数应用变换。Tigress 会按照指定顺序依次应用变换。

运行示例

以下是对每个变换的完整命令行示例。假设源文件为 test-add.c,混淆的函数为 add

# 1. EncodeLiterals - 编码文字常量
tigress \
    --Transform=EncodeLiterals \
    --Functions=add \
    --out=test-add-encode_literals.c \
    test-add.c

# 2. EncodeArithmetic - 编码算术
tigress \
    --Transform=EncodeArithmetic \
    --Functions=add \
    --out=test-add-encode_arithmetic.c \
    test-add.c

# 3. Flatten - 控制流平坦化
tigress \
    --Transform=Flatten \
    --Functions=add \
    --out=test-add-flatten.c \
    test-add.c

# 4. InitOpaque + AddOpaque - 不透明谓词
tigress \
    --Transform=InitOpaque \
    --Functions=add \
    --Transform=AddOpaque \
    --AddOpaqueCount=5 \
    --AddOpaqueKinds=call,bug,true \
    --Functions=add \
    --out=test-add-addopaque.c \
    test-add.c

# 5. InitEntropy + InitOpaque + AddOpaque - 复合变换
tigress \
    --Transform=InitEntropy \
    --Functions=add \
    --Transform=InitOpaque \
    --Functions=add \
    --Transform=AddOpaque \
    --AddOpaqueCount=5 \
    --AddOpaqueKinds=call,bug,true \
    --Functions=add \
    --out=test-add-entropy_opaque.c \
    test-add.c

# 6. Virtualize - 虚拟化混淆
tigress \
    --Transform=Virtualize \
    --Functions=add \
    --out=test-add-virtualize.c \
    test-add.c

tigress.sh 脚本

tigress.sh 脚本通过 Docker 运行 Tigress(因为 Tigress 的本地安装较为复杂)。脚本使用 sed 替换占位符 __TMPDIR__

#!/bin/bash
#
# tigress.sh - 通过 Docker 运行 Tigress 混淆器
#
# 使用 sed 替换模板中的 __TMPDIR__ 占位符为实际临时目录路径
#

# Docker 镜像名
TIGRESS_IMAGE=tigress/tigress:latest

# 临时工作目录
TMPDIR=$(mktemp -d)

# 对模板进行 sed 替换,将 __TMPDIR__ 替换为实际路径
sed "s|__TMPDIR__|${TMPDIR}|g" tigress_template.sh > ${TMPDIR}/tigress_run.sh

# 通过 Docker 运行 Tigress
# 将临时目录挂载到容器中
docker run --rm \
    -v ${TMPDIR}:/work \
    ${TIGRESS_IMAGE} \
    /bin/bash /work/tigress_run.sh

# 清理临时目录
rm -rf ${TMPDIR}

参考链接


4.3 测试用 C 源码

课程提供了 4 个测试用 C 源码文件,用于验证不同混淆技术的效果。

4.3.1 test-add.c

三个常量加法运算,用于测试指令替换、编码算术等。

#include <stdio.h>

int add(int n) {
    return 12 + 56 + 127 + n;
}

int main() {
    int n;
    scanf("%d", &n);
    printf("%d\n", add(n));
    return 0;
}
  • 函数 add 计算 12 + 56 + 127 + n
  • 包含多个常量加法,适合测试 -sub(指令替换)、EncodeArithmetic
  • 常量 12, 56, 127 可被 EncodeLiterals 处理。

4.3.2 test-hello.c

字符串打印,用于测试编码文字(Encode Literals)。

#include <stdio.h>

int main() {
    printf("hello world\n");
    return 0;
}
  • 仅打印字符串 "hello world\n"
  • 适合测试 EncodeLiterals(将字符串逐字符编码)。
  • 无算术运算,因此 -subEncodeArithmetic 不适用(*2)。

4.3.3 test-mod2.c

取模分支,用于测试控制流相关的混淆。

#include <stdio.h>

int mod2(int n) {
    if (n % 2 == 0) {
        return 0;
    } else {
        return 1;
    }
}

int main() {
    int n;
    scanf("%d", &n);
    printf("%d\n", mod2(n));
    return 0;
}
  • 函数 mod2 判断 n 的奇偶性,返回 0(偶数)或 1(奇数)。
  • 包含条件分支,适合测试 -bcf(不透明谓词)、-fla(控制流平坦化)、AddOpaqueVirtualize
  • 基本块数量足够,适用于大多数混淆技术。

4.3.4 test-mod2-add.c

使用魔数(magic numbers)的复合运算,综合测试多种混淆。

#include <stdio.h>

int mod2_add(int n) {
    int magic1 = 0xdeadbeef;
    int magic2 = 0x8badf00d;
    int result = (magic1 ^ magic2) + n;

    if (result % 2 == 0) {
        return 0;
    } else {
        return 1;
    }
}

int main() {
    int n;
    scanf("%d", &n);
    printf("%d\n", mod2_add(n));
    return 0);
}
  • 函数 mod2_add 使用两个魔数 0xdeadbeef0x8badf00d
  • 包含异或运算、加法运算与条件分支。
  • 综合了常量、算术与控制流,适合测试多种混淆技术的叠加效果。

注:0xdeadbeef0x8badf00d 是经典的"调试魔数"(magic debug numbers),在恶意软件分析中也常作为特征值出现。


4.4 Makefile

课程为各 Hands-On 实验提供了 Makefile,用于自动化构建混淆后的二进制文件。

4.4.1 hands-on1/Makefile

Hands-On 1 使用 O-LLVM 进行混淆。Makefile 使用 O-LLVM 的 clang,以 -m32 -O0 编译:

# hands-on1/Makefile
# 使用 O-LLVM 的 clang 进行混淆编译

# O-LLVM 的 clang 路径
CC = /path/to/ollvm/build/bin/clang

# 编译选项:32 位、不优化(-O0 保留混淆效果,防止编译器优化掉混淆代码)
CFLAGS = -m32 -O0

# 源文件
SRCS = $(wildcard src/*.c)

# 目标文件(将 .c 替换为 .bin)
BINS = $(patsubst src/%.c,out/%.bin,$(SRCS))

# 默认目标
all: $(BINS)

# 编译规则
out/%.bin: src/%.c
	@mkdir -p out
	$(CC) $(CFLAGS) $< -o $@

# 清理
clean:
	rm -rf out

.PHONY: all clean

关键点:

  • -m32:编译为 32 位二进制(便于分析)。
  • -O0关闭优化。这是关键——如果开启优化,编译器可能会将混淆插入的"无用代码"优化掉,使混淆失效。因此使用 -O0 保留混淆效果。
  • 每个源文件编译为对应的 .bin 输出。

4.4.2 hands-on2 ~ hands-on6/Makefile

Hands-On 2 到 6 各有不同的实验目标,Makefile 根据实验内容定制构建规则:

# hands-on2/Makefile(示例结构)
# 每个 hands-on 的 Makefile 根据实验内容定制

CC = gcc
CFLAGS = -m32 -O0

# 实验特定的源文件与目标
SRCS = test-add.c test-hello.c test-mod2.c
BINS = $(SRCS:.c=.bin)

all: $(BINS)

%.bin: %.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -f *.bin

.PHONY: all clean

各 Hands-On 实验概览:

Hands-On 实验内容 使用工具
hands-on1 O-LLVM 混淆实验 O-LLVM (-sub, -fla, -bcf)
hands-on2 Tigress 混淆实验 Tigress (6 种变换)
hands-on3 数据流分析反混淆 自定义 Python 脚本
hands-on4 符号执行反混淆 angr / miasm
hands-on5 等价性检查 SMT solver (Z3)
hands-on6 综合 Hands-On 综合

注:以上 Makefile 为教学示例,实际使用时需根据环境调整工具路径与编译选项。


4.5 工具对比总结

O-LLVM vs Tigress

特性 O-LLVM Tigress
混淆层次 LLVM IR(中间表示) C 源代码
维护方 开源社区 University of Arizona (Christian Collberg)
混淆选项 3 种(-sub, -fla, -bcf) 6 种(含复合变换)
虚拟化混淆 不支持 支持(Virtualize)
编码文字 不支持 支持(EncodeLiterals)
MBA 不支持 支持(EncodeArithmetic)
输出 二进制(机器代码) C 源代码(需再编译)
安装难度 需编译 LLVM 提供 Docker 镜像

选择建议

  • 需要 控制流平坦化指令替换:两者皆可,O-LLVM 更简单。
  • 需要 虚拟化混淆:使用 Tigress(Virtualize)。
  • 需要 MBA:使用 Tigress(EncodeArithmetic)。
  • 需要 隐藏字符串:使用 Tigress(EncodeLiterals)。
  • 需要混淆后直接得到二进制:使用 O-LLVM(Tigress 输出 C 源码需二次编译)。

4.6 本章小结

  • 商业混淆工具(Themida、VMProtect 等)提供强大但闭源的保护,也常被恶意软件使用。
  • O-LLVM 是基于 LLVM IR 的开源混淆器,提供 -sub-fla-bcf 三种变换,通过 o-llvm.sh 脚本批量处理。
  • Tigress 是基于 C 源代码的混淆器,提供 6 种变换,通过 Docker 运行,支持变换堆叠。
  • 课程提供了 4 个测试用 C 源码,覆盖常量加法、字符串打印、取模分支与魔数复合运算等场景。
  • Makefile 使用 -O0 编译以保留混淆效果,避免编译器优化消除混淆代码。
  • 至此,课程的混淆技术部分讲解完毕,后续将进入反混淆技术(Dataflow Analysis、Symbolic Execution、Equivalence Checking)部分。
posted @ 2026-08-05 15:55  DirWangK  阅读(18)  评论(0)    收藏  举报