LLVM学习笔记(In Progress)
LLVM学习笔记
什么是LLVM
LLVM 是一个高度模块化、可重用的编译器基础框架。它通过统一的中间表示(IR)连接了编程语言和目标硬件,让创造新语言、支持新硬件变得更简单,同时提供了一流的代码优化能力。LLVM主要聚焦于编译器后端功能,如代码生成、代码优化、代码混淆、JIT等。
LLVM的架构
- LLVM大致架构与传统编译器相同,都由前端、优化器、后端组成。
- 但传统编译器的前端、优化器、后端是高度耦合的,对于不同的编程语言,往往需要不同的前端、优化器、后端来得到特定平台的机器码。
- 举个例子: 如果要支持 M 门语言和 N 个硬件平台,就需要开发近乎 M x N 个不同的编译器或进行大量的重复性适配工作,维护成本和开发难度极高。每新增一个支持,就需要M或N个编译器,或者大量的适配工作。
- 而LLVM则是将不同,因其引入了统一的中间表示,它更加“松散”。
- 同样的例子,LLVM新增支持可能仅需关心一对一,即如何到IR或者IR到新硬件平台的机器码。
- 工作流程表示:
源代码 (C++, Swift, Rust 等)
|
v
[ 前端:Clang / rustc 等 ]
|
v
LLVM 中间表示 (IR)
|
v
[ 优化器:进行各种代码优化 ]
|
v
优化后的 LLVM IR
|
v
[ 后端:针对 x86, ARM 等 ]
|
v
特定平台的机器码
前端 (Frontend)
- 作用:负责将各种不同的高级编程语言源代码,解析并转换为统一的、与语言无关的 LLVM IR。
优化器 (Optimizer)
作用:这是 LLVM 的核心。它接收来自前端生成的 LLVM IR,并对其进行一系列的分析和优化,目的是让代码运行得更快、体积更小,或者进行保护。
特点:过程完全独立于源代码语言和目标硬件的,为通用的优化层。
后端 (Backend)
- 作用:负责将经过优化器处理过的 LLVM IR,转换为特定硬件平台(CPU 架构)的原生机器码。
LLVM 是一个编译器基础设施(平台),而 Clang 是这个平台上最官方、最著名的前端之一。
广义的LLVM是指整个LLVM架构,一般狭义的LLVM指的是LLVM后端(包含代码优化和目标代码生成)。
代码混淆
定义:代码混淆是将计算机程序的代码,转换成一种功能上等价,但是难以阅读和理解的形式的行为。
开发者通常会编写自定义的 LLVM Pass 来实现一种或多种混淆技术。
一个著名且强大的的混淆技术就是控制流平坦化(Control Flow Flattening)
- 原始代码:代码有清晰的 if-else、for、while、switch 结构,其控制流图(CFG)逻辑清晰。
混淆后:
- 将函数内所有的代码块(Basic Blocks)打散,放入一个巨大的 switch 语句中。 - 用一个主分发器(通常是一个 while 循环)来控制程序流程。 - 引入一个“状态变量”,循环的每一步都根据这个状态变量的值,switch 到对应的代码块去执行。 - 每个代码块执行完毕后,会修改这个状态变量,告诉主分发器下一步应该跳到哪里。效果:原始的逻辑结构完全消失了,取而代-之的是一个巨大的、扁平的循环。逆向工程师无法再通过分析控制流图来理解程序逻辑,分析难度呈指数级上升。
学习混淆的意义
对于软件开发者:一定程度上防止代码被逆向破解
对于逆向工程师:帮助我们研究反混淆技术
这就得提到OLLVM了。
什么是OLLVM
OLLVM (Obfuscator-LLVM):基于 LLVM 的代码混淆框架
核心定义与目标
OLLVM (Obfuscator-LLVM) 是一个著名的、基于 LLVM 框架的开源代码混淆项目。它最初由瑞士西北应用科技大学安全实验室于2010年发起,其核心目标是创建一个 LLVM 的特殊分支,通过在编译过程中自动注入代码混淆和防篡改逻辑,极大地提升逆向工程的分析门槛,从而增强软件的最终安全性。
技术实现原理:基于 Pass 的 IR 层混淆
OLLVM 的精髓在于其基于 Pass 的混淆机制。它完美利用了 LLVM 的模块化架构,在编译器的心脏地带——中间表示(IR)层面——进行操作。开发者通过编写一系列自定义的混淆 Pass(例如控制流平坦化、虚假控制流等),将原本结构清晰的 IR 代码变得逻辑复杂、难以理解。
由于后续的后端流程完全基于这份 IR 来生成机器码,因此这份复杂性便被忠实地保留在了最终的可执行文件中。
核心优势:跨语言与跨平台
得益于 LLVM 的解耦设计,OLLVM 的混淆能力是跨语言、跨平台的。原则上,任何能够被编译成 LLVM IR 的语言(如 C, C++, Objective-C 等),都能利用 OLLVM 进行混淆,并最终部署到 LLVM 支持的任意硬件平台(如 x86, ARM 等)上,而无需修改混淆逻辑本身。
项目现状与影响
OLLVM 本身是一个里程碑式的历史性项目,其官方支持的 LLVM 版本较为陈旧,目前已不再积极维护。
尽管如此,它的设计思想和开源实现对后来的代码混淆技术产生了深远的影响,催生了许多功能更强大、支持更新 LLVM 版本的现代化项目(例如 Hikari 等)。因此,OLLVM 至今仍是学习 LLVM Pass 开发和代码混淆技术的重要参考。
