foundryzero/llef
GitHub: foundryzero/llef
LLEF 是一个 LLDB 插件,通过 Python API 为逆向工程和漏洞研究提供增强的状态输出、上下文视图和便捷命令,让安全研究人员能够更高效地进行动态分析。
Stars: 483 | Forks: 24
# LLEF
LLEF(发音为 ɬɛf - "hlyeff")是一个 LLDB 插件,旨在使其更适合底层的逆向工程 (RE) 和漏洞研究 (VR)。类似于 [GEF](https://github.com/hugsy/gef),但专为 LLDB 设计。
它使用 LLDB 的 Python API 添加了额外的状态输出和一些新命令,以便安全研究人员可以更轻松地使用 LLDB 来分析正在运行的软件。

## 💻 支持的架构
* x86_64
* arm
* aarch64 / arm64
* i386
* PowerPC
## 📓 系统要求
* LLDB 15+ (https://apt.llvm.org/) _在 macOS 上,此工具已随 Xcode 14.3+ 捆绑安装_
## ⚙ 安装说明
以下说明将安装 LLEF,使其默认被 LLDB 使用。
1. 克隆此代码库。
2. `cd
`
3. 运行 `./install.sh`
4. 选择自动(覆盖 `~/.lldbinit`)或手动安装。
_LLDB 默认对 x86 二进制文件使用 AT&T 反汇编语法。安装程序提供了一个选项来覆盖此设置。_
## ▶ 用法
### 启动 LLDB
```
lldb-15
```
### 使用命令:
#### llefsettings
用于设置、保存、加载和列出 LLEF 特定命令的各种命令:
```
(lldb) llefsettings --help
list list all settings
save Save settings to config file
reload Reload settings from config file (retain session values)
reset Reload settings from config file (purge session values)
set Set LLEF settings
```
设置存储在您主目录下的 `.llef` 文件中,格式如下:
```
[LLEF]
=
```
##### 可用设置
| 设置 | 类型 | 描述 |
| ----------------------- | ------- | -------------------------------------------------- |
| color_output | Boolean | 启用/禁用彩色终端输出 |
| register_coloring | Boolean | 启用/禁用寄存器着色 |
| show_legend | Boolean | 启用/禁用图例输出 |
| show_registers | Boolean | 启用/禁用寄存器输出 |
| show_stack | Boolean | 启用/禁用堆栈输出 |
| show_code | Boolean | 启用/禁用代码输出 |
| show_threads | Boolean | 启用/禁用线程输出 |
| show_trace | Boolean | 启用/禁用跟踪输出 |
| force_arch | String | 强制指定寄存器显示架构(实验性) |
| rebase_addresses | Boolean | 启用/禁用地址重基址输出 |
| rebase_offset | Int | 设置重基址偏移量(默认为 0x100000) |
| show_all_registers | Boolean | 启用/禁用扩展寄存器输出 |
| displayed_registers | List | 以逗号分隔的要显示的寄存器列表。保持原有顺序。使用 `default` 作为内置寄存器的占位符。例如 `llefsettings set displayed_registers default,ymm0,ymm1` |
| enable_darwin_heap_scan | Boolean | 为基于 Darwin 的平台启用/禁用更精确的堆扫描。使用 Darwin malloc 枚举 API,通过 LLDB 的求值引擎在目标应用程序的地址空间中执行代码 |
| max_trace_length | Int | 设置要显示的调用栈回溯的最大长度 |
| stack_view_size | Int | 设置要显示的堆栈读取条目数量 |
| max_disassembly_length | Int | 设置围绕当前 PC 反汇编和显示指令的最大数量 |
| go_support_level | String | 控制 Golang 特定的分析。`disable` / `auto` (默认) / `force`。出于性能原因,Windows 二进制文件中的 Go 支持需要使用 `force`。 |
| go_confidence_threshold | String | 设置要在上下文视图中显示的 Go 对象的置信度阈值 (`low` / `medium` / `high`) |
#### llefcolorsettings
允许设置 LLEF GUI 颜色:
```
(lldb) llefcolorsettings --help
list list all color settings
save Save settings to config file
reload Reload settings from config file (retain session values)
reset Reload settings from config file (purge session values)
set Set LLEF color settings
```
##### 可用的颜色设置
支持的颜色:BLUE, GREEN, YELLOW, RED, PINK, CYAN, GREY
| 颜色 |
| ----------------------------- |
| register_color |
| modified_register_color |
| code_color |
| heap_color |
| stack_color |
| string_color |
| stack_address_color |
| function_name_color |
| instruction_color |
| highlighted_instruction_color |
| line_color |
| rebased_address_color |
| section_header_color |
| highlighted_index_color |
| index_color |
| dereferenced_value_color |
| dereferenced_register_color |
| frame_argument_name_color |
| read_memory_address_color |
| go_type_color |
#### 十六进制转储
使用以下命令查看内存内容:
```
(lldb) hexdump type address [--size SIZE] [--reverse]
```
例如。
```
(lldb) hexdump byte 0x7fffffffecc8 --size 0x38
0x7fffffffecc8 3d 2f 75 73 72 2f 6c 6f 63 61 6c 2f 73 62 69 6e =/usr/local/sbin
0x7fffffffecd8 3a 2f 75 73 72 2f 6c 6f 63 61 6c 2f 62 69 6e 3a :/usr/local/bin:
0x7fffffffece8 2f 75 73 72 2f 73 62 69 6e 3a 2f 75 73 72 2f 62 /usr/sbin:/usr/b
0x7fffffffecf8 69 6e 3a 2f 73 62 69 6e in:/sbin
(lldb) hexdump word 0x7fffffffecc8 --reverse
0x7fffffffece6│+001e: 0x4654
0x7fffffffece4│+001c: 0x4361
0x7fffffffece2│+001a: 0x746f
0x7fffffffece0│+0018: 0x4e23
0x7fffffffecde│+0016: 0x3f73
0x7fffffffecdc│+0014: 0x6968
0x7fffffffecda│+0012: 0x742d
0x7fffffffecd8│+0010: 0x6564
0x7fffffffecd6│+000e: 0x6f63
0x7fffffffecd4│+000c: 0x6564
0x7fffffffecd2│+000a: 0x2d75
0x7fffffffecd0│+0008: 0x6f79
0x7fffffffecce│+0006: 0x2d64
0x7fffffffeccc│+0004: 0x6964
0x7fffffffecca│+0002: 0x2d79
0x7fffffffecc8│+0000: 0x6857
```
#### 上下文
使用以下命令刷新 LLEF GUI:
```
(lldb) context
```
使用以下命令刷新 LLEF GUI 的组件:
```
(lldb) context [{registers,stack,code,threads,trace,all} ...]
```
#### Pattern Create (创建 Pattern)
```
(lldb) pattern create 10
[+] Generating a pattern of 10 bytes (n=4)
aaaabaaaca
[+] Pattern saved in variable: $8
(lldb) pattern create 100 -n 2
[+] Generating a pattern of 100 bytes (n=2)
aabacadaea
[+] Pattern saved in variable: $9
```
#### Pattern Search (搜索 Pattern)
```
(lldb) pattern search $rdx
[+] Found in $10 at index 45 (big endian)
(lldb) pattern search $8
[+] Found in $10 at index 0 (little endian)
(lldb) pattern search aaaabaaac
[+] Found in $8 at index 0 (little endian)
(lldb) pattern search 0x61616161626161616361
[+] Found in $8 at index 0 (little endian)
```
#### (Go) Unpack Type (解包类型)
```
(lldb) go unpack-type 0xc000130000 []main.Country
[{Name:'Japan' Capital:'Tokyo' Continent:'Asia'} {Name:'Germany' Capital:'Berlin' Continent:'Europe'}]
(lldb) go unpack-type 0xc000130000 []main.Country --depth 1
[0xc000142000.. 0xc000142030..]
(lldb) go unpack-type 0xc000142000 main.Country
{Name:'Japan' Capital:'Tokyo' Continent:'Asia'}
(lldb) go unpack-type 0xc000142000 [6]uintptr
[0xc000114140 0x5 0xc000114145 0x5 0xc00011414c 0x4]
```
#### (Go) Find Function (查找函数)
```
(lldb) go find-func main.main
0x55c6894c0280 - main.main (file address = 0x4c0280)
(lldb) go find-func 0x55c689454a3a
0x55c689454a20 - runtime.(*moduledata).textAddr (file address = 0x454a20)
```
#### (Go) Get Type (获取类型)
```
(lldb) go get-type json.mapEncoder --depth 3
json.mapEncoder = struct { elemEnc func(*json.encodeState, struct { typ_ *abi.Type; ptr unsafe.Pointer; flag uintptr }, struct { quoted bool; escapeHTML bool }) }
Size in bytes: 0x8
(lldb) go get-type json.encodeState --depth 1
json.encodeState = struct { Buffer bytes.Buffer; ptrLevel uint; ptrSeen map[interface {}]struct {} }
Size in bytes: 0x38
```
### 断点钩子
这是自动的,会在断点处打印所有当前已实现的信息。
#### 地址重基址
通过 `rebase_addresses` 设置进行配置,地址重基址功能会对输出中呈现的每个代码地址执行查找,以显示关联的二进制文件和相对地址。此相对地址的偏移量由 `rebase_offset` 设置中定义的值决定,该值默认为 Ghidra 的基址 `0x100000`。结果是一个可以轻松复制并粘贴到 IDE 的“转到地址”功能中的地址输出,而无需进行数学运算来从运行时地址进行转换。
重基址后的地址显示在运行时地址后的括号中:

## 👷♂️ LLDB Python 支持故障排除
LLDB 捆绑了运行 LLEF 所需的 python 模块。如果在启动带有 LLEF 的 LLDB 时遇到 `ModuleNotFoundError` 消息,您可能需要手动将 LLDB python 模块添加到您的 python 路径中。
为此,请运行以下命令以确定您的 site-packages 位置:
```
python3 -m site --user-site
```
然后找到 LLDB python 模块的位置。这通常位于 `/usr/lib/llvm-15/lib/python3.10/dist-packages` 这样的位置,但具体取决于您的 python 版本。
最后,修改并执行以下命令,将上述 LLDB 模块路径添加到上面发现的 site-packages 位置的一个新文件 `lldb.pth` 中。
```
echo "/usr/lib/llvm-15/lib/python3.10/dist-packages" > ~/.local/lib/python3.10/site-packages/lldb.pth
```
## 性能优化
在某些平台上,观察到在每个断点处渲染 LLEF 输出的速度很慢。其根本原因已追溯到底层的 `GetMemoryRegions` LLDB API 调用。幸运的是,这仅用于识别寄存器值是指向代码、堆栈还是堆地址。
要禁用寄存器着色并可能显著提高 LLEF 性能,请使用以下 `llefsettings` 命令禁用 `register_coloring` 功能。
```
llefsettings set register_coloring False
```
## 👏 致谢
我们显然是站在了巨人的肩膀上——我们要特别感谢 [hugsy](https://twitter.com/_hugsy_) 的 [GEF](https://github.com/hugsy/gef),这个工具从中获得了*极大的*灵感!请将这种模仿视作赞美 🙂
如果您想了解更多关于 LLEF 的信息,可以访问我们的[首发博客文章](https://foundryzero.co.uk/2023/07/13/llef.html)。标签:GEF替代, LLDB, LLDB插件, PowerPC, Python API, x86_64, 二进制分析, 云安全运维, 云资产清单, 低级分析, 情报收集, 汇编分析, 漏洞研究, 调试器扩展, 逆向工具, 逆向工程