---
# System prepended metadata

title: LLVM Pass PWN

---

## 概述

现代编译器普遍采用前后端分离的设计，中间表示（Intermediate Representation, IR）与源语言和目标语言无关
![Clang pipeline](https://hackmd.io/_uploads/SyEM5rAi2.png)
![Rustc pipeline](https://blog.rust-lang.org/images/2016-04-MIR/flow.svg)
LLVM IR仅有一种，其三种表示形式：

   * Human-readable IR, LLVM Assembly(\*.ll)
   * On-disk bitcode IR, LLVM Bitcode(\*.bc)
   * In-memory compiler IR

LLVM pass 是 LLVM 中负责对 LLVM IR 进行 transformation 的组件，Pass 就是“遍历一遍IR，同时对它做一些操作”的意思。翻译成中文应该叫“趟”，编译器的转换和优化部分可以视为若干 Pass 的流水线
作为编译器后端， LLVM 允许编译器开发者向 optimizer 中注入或重写 LLVM pass，在实现上，LLVM的核心库中包含若干 Pass 类可供继承
LLVM Pass的用处是插桩，机器无关的代码优化，静态分析，代码混淆等

参见 [LLVM Pass 入门导引][LLVM Pass Tutorial]

### LLVM 工具

   * llvm-as："汇编器" LLVM Assembly -> LLVM Bitcode
   * llvm-dis："反汇编器" LLVM Bitcode -> LLVM Assembly
   * opt：优化器 LLVM IR optimizer 
   * llc："编译器" LLVM IR -> ASM
   * lli："解释器" LLVM IR Interpreter


## LLVM Pass PWN
LLVM Pass PWN 在近年的 CTF 中已经较为常见，其通常提供题目使用的 opt 和存在漏洞的 pass 模块，选手需要编写一段程序, 以 LLVM IR 形式交予加载了该漏洞 pass 编译器编译来获取编译机器上存放的 flag

大多数Pass类题目是这样实现的：重写 runOnFunction，处理 IR 中具有特定名称的函数，这些函数会事先预留一些漏洞，比如后门、任意地址读写、数组越界读写、整数溢出等等。

最常规的模式：任意地址读写 写got表或free_hook
* 红帽杯-2021 simpleVM（任意地址读写读got改free）
* CISCN-2021 staool（堆上脏数据泄露+任意地址执行）
* 强网杯-2022 yakagame（负数索引导致的数组越界写+后门）

栈溢出：
Pass只运行一次，要求利用 leakfree
* CISCN-2022 satool（JIT Spray）


----
[LLVM Pass Tutorial]:https://zhuanlan.zhihu.com/p/122522485
[LLVM Pass PWN]:https://zhuanlan.zhihu.com/p/535985826
