trailofbits/mquire

GitHub: trailofbits/mquire

零依赖的 Linux 内存取证工具,利用内核内嵌的 BTF 和 kallsyms 实现无需外部调试符号的类型感知内存分析。

Stars: 46 | Forks: 2

# mquire mquire 取自 `memory`(内存)与 `inquire`(查询)的组合,是一款受 [osquery](https://github.com/osquery/osquery) 启发的内存查询工具。 ## 核心优势:无需外部调试符号 **mquire 可以在不需要外部调试符号的情况下分析 Linux 内核内存快照。** 分析所需的一切信息都已嵌入在内存转储本身之中。这意味着你可以分析: - 从未见过的未知或自定义内核 - 任何 Linux 发行版,无需事先准备 - 外部调试符号不可用或丢失的内存快照 ### 系统要求 **内核版本要求:** - **BTF 支持**:4.18 或更新版本的内核,且启用了 BTF(大多数现代发行版默认启用) - **Kallsyms 支持**:6.4 或更新版本的内核(由于 `scripts/kallsyms.c` 格式的变更) ## 工作原理 mquire 通过读取嵌入在现代 Linux 内核中的两类信息来分析内核内存: 1. **来自 BTF 的类型信息**([BPF Type Format](https://www.kernel.org/doc/html/next/bpf/btf.html))——描述内核数据类型的结构和布局。BTF 数据使用 [btfparse crate](https://crates.io/crates/btfparse) 进行解析。 2. **来自 Kallsyms 的符号信息**——提供内核符号的内存位置(与 `/proc/kallsyms` 使用的数据相同) 通过结合类型信息和符号位置,mquire 可以查找并读取复杂的内核数据结构,例如: - 进程内存映射(使用 maple tree 结构) - 缓存的文件数据(使用 XArray 结构) - 内核日志消息 这使得可以直接从内核的文件缓存中提取文件成为可能,即使它们已从磁盘上删除。 ### 兼容性说明 Kallsyms 扫描器依赖于内核源码中 `scripts/kallsyms.c` 的数据格式。如果未来的内核版本更改了此格式,扫描器的启发式规则可能需要更新。 ## 功能特性 ### 表 mquire 提供 SQL 表来查询系统的不同方面或工具本身的状态: #### 系统信息 - **os_version** - 内核版本和架构 - **system_info** - 主机名和域名 - **boot_time** - 系统启动时间 - **kallsyms** - 内核符号地址(数据同 `/proc/kallsyms`) - **dmesg** - 内核环形缓冲区消息(数据同 `dmesg` 命令) #### 进程信息 - **tasks** - 正在运行的进程及其命令行和二进制路径 - **task_open_files** - 每个进程打开的文件(需要 `task` 约束 - 参见下方示例) - **memory_mappings** - 每个进程映射的内存区域(需要 `task` 约束) #### 内核模块 - **kernel_modules** - 已加载的内核模块及其元数据(名称、状态、版本、参数、污染标志) #### 网络信息 - **network_connections** - 活动的网络连接(TCP sockets) - **network_interfaces** - 网络接口及其 IP 地址和 MAC 地址 #### 文件系统 - **syslog_file** - 从内核文件缓存中读取的系统日志(即使日志文件被删除或不可用,只要它们被缓存在内存中即可工作) #### 调试 - **log_messages** - 内部 mquire 日志,显示分析进度、警告和错误 ## 命令 mquire 提供三个主要命令: - **`mquire shell`** - 启动交互式 SQL shell 以查询内存快照 - **`mquire query`** - 执行单个 SQL 查询并输出结果(支持 JSON 或表格格式) - **`mquire command`** - 对内存快照执行自定义命令(例如 `.task_tree`、`.system_version`、`.dump`) ## 点命令 mquire 提供以点(`.`)为前缀的特殊命令,以便与 SQL 查询区分开。 ### 内置命令 这些命令可在交互式 shell 和 `mquire query` 中使用: - **`.tables`** - 列出所有可用的表 - **`.schema`** - 显示所有表的结构 - **`.schema `** - 显示特定表的结构 - **`.commands`** - 列出所有可用的自定义命令 - **`.exit`** - 退出交互式 shell(仅限 shell) ### 自定义命令 这些命令可在交互式 shell 和 `mquire command` 中使用: 使用 `--help` 查看任何命令的可用选项和用法信息。例如:`.task_tree --help` #### `.system_version` 显示操作系统版本信息。 这是一个便捷命令,等同于 `SELECT * FROM os_version`,但具有格式化的输出。 #### `.task_tree` 显示正在运行的进程和线程的层级树,类似于 Linux 上的 `pstree` 命令。 **选项:** - `--show-threads` - 除进程外还包括线程。启用时,为每个条目显示 TGID 和 TID。 - `--use-real-parent` - 使用 `real_parent` 字段而不是 `parent` 来构建树结构。`real_parent` 字段显示重定父级之前的原始父进程(有助于跟踪进程创建链,即使在父进程退出后)。 **注意:** - 显示线程时格式为 `[TGID TID]`,隐藏线程时为 `[TGID]`。TGID(Thread Group ID)即通常所说的 PID。对于主线程(TGID == TID),这两个值将相同。 #### `.carve` 将一块虚拟内存区域提取到磁盘。此命令使用给定的页表从特定的虚拟地址范围提取原始内存内容,适用于提取进程内存、堆内容或其他内存区域。 **参数:** - `ROOT_PAGE_TABLE` - 根页表的物理地址(可选 0x 前缀的十六进制字符串)。这决定了用于转换的地址空间。 - `VIRTUAL_ADDRESS` - 开始提取的虚拟地址(可选 0x 前缀的十六进制字符串)。 - `SIZE` - 要提取的字节数。 - `DESTINATION_PATH` - 写入提取内存的输出文件路径。 **注意:** - 命令在写入前会显示已映射与未映射区域的摘要。 - 未映射区域在输出文件中填充为零。 #### `.dump` 从内核文件缓存中提取文件,直接从内存中恢复文件。此命令遍历所有任务及其打开的文件描述符,从页缓存中提取文件内容。 **参数:** - `OUTPUT` - 提取文件的输出目录。文件按 TGID 组织(例如 `tgid_1234/path/to/file`)。 **注意:** - 目前适用于通过文件描述符打开的文件(来自进程文件描述符表)。 - 尚不支持从内存映射文件中提取数据。 - 空文件(页缓存中无数据)会被跳过。 - 读取错误的区域在输出中填充为零。 ## 使用场景 mquire 专为以下场景设计: - **取证分析** - 分析来自受损系统的内存快照,以了解正在运行的程序和访问的文件 - **应急响应** - 快速查询内存转储以查找恶意活动的证据 - **安全研究** - 从内存快照研究内核内部结构和进程行为 - **恶意软件分析** - 检查正在运行的进程及其文件操作而不被发现 - **自定义工具** - 使用 **mquire** 库 crate 构建你自己的分析工具,该库为内核内存分析提供了可复用的 API ## 构建与安装 ### CI 预构建包 预构建包可作为 CI 运行的产物下载。你可以从 [Actions tab](https://github.com/trailofbits/mquire/actions) 选择一个成功的工作流运行并下载产物来获取它们。提供以下包格式: - **linux-deb-package** - Debian/Ubuntu `.deb` 包 - **linux-rpm-package** - Fedora/RHEL/CentOS `.rpm` 包 - **linux-tgz-package** - 通用 Linux `.tar.gz` 归档 ### 从源码构建 mquire 使用 Rust 编写。构建方法: ``` # Clone 仓库 git clone https://github.com/trailofbits/mquire cd mquire # Build 项目 cargo build --release # Binary 将位于 target/release/ # - mquire: 具有 shell、query 和 command 模式的统一工具 ``` ## 获取内存快照 1. 编译 [LiME](https://github.com/504ensicsLabs/LiME) 项目 2. 通过加载构建的内核模块获取原始内存快照:`insmod ./lime-x.x.x-xx-generic.ko 'path=/path/to/memory/dump.bin format=padded'` ## 快速入门 一旦你有了内存快照,就可以使用 SQL 查询和自定义命令与之交互。mquire 提供了三种与快照交互的方式: ### 交互式 shell 启动交互式 SQL shell: ``` mquire shell /path/to/memory.raw ``` 这将打开一个提示符,你可以在其中交互式地运行 SQL 查询和命令: ``` mquire> .tables # List all available tables mquire> .schema tasks # Show schema for a specific table mquire> SELECT * FROM tasks; # Run SQL queries mquire> .task_tree --show-threads # Run custom commands mquire> .exit # Exit the shell ``` ### 一次性 SQL 查询 从命令行执行单个 SQL 查询或内置命令: ``` # 输出为 JSON 格式 (默认) mquire query /path/to/memory.raw "SELECT * FROM os_version" # 输出为 table 格式 mquire query /path/to/memory.raw "SELECT * FROM tasks" --format table # Built-in 命令也可用 mquire query /path/to/memory.raw ".tables" mquire query /path/to/memory.raw ".schema tasks" ``` ### 执行自定义命令 运行自定义命令进行专门分析: ``` # 列出所有可用命令 (默认行为) mquire command /path/to/memory.raw # 显示 system version mquire command /path/to/memory.raw ".system_version" # 显示 process 树 mquire command /path/to/memory.raw ".task_tree" # 显示带 threads 的 process 树 mquire command /path/to/memory.raw ".task_tree --show-threads" # 获取命令帮助 mquire command /path/to/memory.raw ".task_tree --help" ``` ## 自动启动 SQL 文件 mquire 在启动 shell 或执行查询时,会自动从 `~/.config/trailofbits/mquire/autostart/` 加载并执行 SQL 文件。这对于以下情况很有用: - 创建可复用的 SQL 视图 - 设置自定义表 - 定义常用查询 **特性:** - SQL 文件按字母顺序执行 - 文件必须具有 `.sql` 扩展名 - 错误会显示但不会阻止执行 - 同时适用于 `mquire shell` 和 `mquire query` 命令 ### 创建用于进程网络连接的可复用视图 创建文件 `~/.config/trailofbits/mquire/autostart/001_process_network_connections.sql`: ``` CREATE VIEW IF NOT EXISTS process_network_connections AS WITH network_connections_mat AS MATERIALIZED ( SELECT * FROM network_connections ), task_open_files_mat AS MATERIALIZED ( SELECT * FROM task_open_files ), -- Deduplicate tasks by virtual_address since the default query returns -- results from multiple enumeration sources tasks_mat AS MATERIALIZED ( SELECT DISTINCT virtual_address, pid, tgid, comm, binary_path FROM tasks WHERE type = 'thread_group_leader' ) SELECT t.pid, t.comm, t.binary_path, nc.protocol, nc.local_address, nc.local_port, nc.remote_address, nc.remote_port, nc.state, nc.type as ip_type, nc.inode FROM network_connections_mat nc JOIN task_open_files_mat tof ON nc.inode = tof.inode JOIN tasks_mat t ON tof.task = t.virtual_address ORDER BY t.pid, nc.local_port; ``` 然后查询该视图: ``` SELECT * FROM process_network_connections WHERE comm = 'sshd'; ``` ### 比较 task 枚举方法以进行 Rootkit 检测 Rootkit 通常通过将进程从内核的任务列表中取消链接来隐藏进程,同时保持它们运行。mquire 支持多种任务枚举策略,可以进行比较以检测此类隐藏进程。 创建文件 `~/.config/trailofbits/mquire/autostart/002_hidden_process_detection.sql`: ``` CREATE VIEW IF NOT EXISTS hidden_processes AS WITH tasks_from_task_list AS MATERIALIZED ( SELECT virtual_address, pid, comm FROM tasks WHERE source = 'task_list' ), tasks_from_pid_ns AS MATERIALIZED ( SELECT virtual_address, pid, comm FROM tasks WHERE source = 'pid_ns' ) SELECT COALESCE(tl.pid, pn.pid) AS pid, COALESCE(tl.comm, pn.comm) AS comm, COALESCE(tl.virtual_address, pn.virtual_address) AS virtual_address, CASE WHEN tl.virtual_address IS NULL THEN 'hidden_from_task_list' WHEN pn.virtual_address IS NULL THEN 'hidden_from_pid_ns' ELSE 'visible' END AS visibility FROM tasks_from_task_list tl FULL OUTER JOIN tasks_from_pid_ns pn ON tl.virtual_address = pn.virtual_address WHERE tl.virtual_address IS NULL OR pn.virtual_address IS NULL; ``` 然后查询可能隐藏的进程: ``` SELECT * FROM hidden_processes; ``` ## 查询优化 **mquire 查询需要利用嵌入的类型信息和调试符号,通过解引用指针从虚拟内存重建内核数据结构。这种处理可能开销很大,因此请使用查询优化技术来显著提高性能。** ### 使用 `AS MATERIALIZED` 进行物化 当表在 JOIN 中使用或被多次访问时,使用 `AS MATERIALIZED` 提示来缓存表结果。 **何时物化:** - 生成成本高昂的表(例如,`tasks` 需要遍历进程结构的链表,每个进程解引用多个指针) - 在 JOIN 中使用的表(在查询执行期间被多次访问) - 在同一查询中被多次引用的表 **示例:** ``` -- Find network connections for a specific process using materialization WITH target_tasks AS MATERIALIZED ( SELECT * FROM tasks WHERE comm = 'sshd' AND type = 'thread_group_leader' ), network_connections_mat AS MATERIALIZED ( SELECT * FROM network_connections ) SELECT t.tgid, t.comm, nc.local_address, nc.local_port, nc.remote_address, nc.remote_port, nc.state, nc.protocol FROM target_tasks t JOIN task_open_files tof ON tof.task = t.virtual_address JOIN network_connections_mat nc ON nc.inode = tof.inode; ``` **注意:** `task_open_files` 和 `memory_mappings` 表使用 `task` 列作为生成器输入。当与 `tasks` 表连接时,SQLite 会通过嵌套循环连接自动传递约束,这使得直接 JOIN 非常高效。 **性能影响:** 物化可以显著加快包含 JOIN 的查询(通常快 2-5 倍) **示例基准测试结果:** *测试在 Ubuntu 24.04 快照(内核 6.8.0-63)上进行,351 个进程,50 个连接,2142 个打开的文件。性能会因快照大小、内核版本和硬件而异。* | Method | Real Time | User Time | Speedup | |--------|-----------|-----------|---------| | WITHOUT materialization | 12.067s | 16.373s | baseline | | WITH materialization | 3.171s | 8.786s | **3.8x faster** | ### JOIN 顺序优化 **从最小的表开始并向较大的表进行 JOIN**,以尽量减少查询管道早期处理的行数。 **典型表大小:** - `network_connections`:最小 - 仅包含有网络活动的进程 - `tasks`:中等 - 所有进程 - `task_open_files`:最大 - 所有打开的文件描述符 **最佳顺序:** 从过滤后的 tasks 表开始并向较大的表连接: ``` FROM target_tasks t -- filtered tasks JOIN task_open_files tof ON tof.task = t.virtual_address -- open files JOIN network_connections_mat nc ON nc.inode = tof.inode -- matching connections ``` ### 了解查询执行 使用 `EXPLAIN QUERY PLAN` 查看 SQLite 如何执行你的查询: ``` EXPLAIN QUERY PLAN SELECT ... FROM target_tasks t JOIN task_open_files tof ON tof.task = t.virtual_address JOIN network_connections_mat nc ON nc.inode = tof.inode; ``` 关注: - **BLOOM FILTER**:SQLite 针对大型 JOIN 的优化 - **AUTOMATIC COVERING INDEX**:为查找创建的临时索引 - **SCAN**:全表扫描(对于驱动表来说是预期的) - **SEARCH**:基于索引的查找(高效) ### 最佳实践 1. **始终物化在 JOIN 中使用的昂贵表** 2. **从最小的表开始作为驱动表** 3. **在脚本中使用多行 SQL** 以提高可读性 4. **使用 `EXPLAIN QUERY PLAN` 检查复杂查询的查询计划** 5. **在生产环境中避免 `SELECT *`** - 仅指定所需的列 ### 文件提取 将文件从内存提取到磁盘: ``` mquire command /path/to/memory.raw ".dump /output/directory" ``` ### 示例查询 所有查询均使用标准 SQL 语法。 #### 系统版本 ``` $ mquire shell ubuntu2404_6.14.0-37-generic.lime mquire> SELECT * FROM os_version; arch:"x86_64" kernel_version:"6.14.0-37-generic" system_version:"#37~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 10:25:38 UTC 2" ``` #### 系统信息 ``` $ mquire shell ubuntu2404_6.14.0-37-generic.lime mquire> SELECT * FROM system_info; domain:"(none)" hostname:"ubuntu2404" ``` #### 内核模块 ``` $ mquire shell ubuntu2404_6.14.0-37-generic.lime mquire> SELECT name, state, src_version, parameters FROM kernel_modules LIMIT 5; name:"snd_seq_dummy" state:"live" src_version:"7A40E0FD47A0746D1C9CD85" parameters:"ump (perm: 0o444), duplex (perm: 0o444), ports (perm: 0o444)" name:"snd_hrtimer" state:"live" src_version:"81EE6D58896E2C2E63E252D" parameters:"" name:"qrtr" state:"live" src_version:"473C5AB47E04ECEA0106681" parameters:"" name:"virtio_rng" state:"live" src_version:"0852940240D554836D22CB2" parameters:"" name:"intel_rapl_msr" state:"live" src_version:"34853C4F5EB8FCAD28ACFB3" parameters:"" ``` #### 运行中的任务 ``` $ mquire shell ubuntu2404_6.14.0-37-generic.lime mquire> SELECT comm, binary_path, command_line FROM tasks WHERE command_line NOT NULL AND comm LIKE "%systemd%"; comm:"systemd" binary_path:"/usr/lib/systemd/systemd" command_line:"/sbin/init splash" comm:"systemd-oomd" binary_path:"/usr/lib/systemd/systemd-oomd" command_line:"/usr/lib/systemd/systemd-oomd" comm:"systemd-resolve" binary_path:"/usr/lib/systemd/systemd-resolved" command_line:"/usr/lib/systemd/systemd-resolved" comm:"systemd-udevd" binary_path:"/usr/bin/udevadm" command_line:"/usr/lib/systemd/systemd-udevd" comm:"systemd" binary_path:"/usr/lib/systemd/systemd" command_line:"/usr/lib/systemd/systemd --user" comm:"systemd-logind" binary_path:"/usr/lib/systemd/systemd-logind" command_line:"/usr/lib/systemd/systemd-logind" comm:"systemd-journal" binary_path:"/usr/lib/systemd/systemd-journald" command_line:"/usr/lib/systemd/systemd-journald" comm:"systemd-timesyn" binary_path:"/usr/lib/systemd/systemd-timesyncd" command_line:"/usr/lib/systemd/systemd-timesyncd" ``` #### 连 通过连接 tasks、task_open_files 和 network_connections 查找特定进程的网络连接。 ``` $ mquire shell ubuntu2404_6.14.0-37-generic.lime mquire> SELECT t.tgid, t.comm, nc.protocol, nc.local_address, nc.local_port, nc.remote_address, nc.remote_port, nc.state FROM tasks t JOIN task_open_files tof ON tof.task = t.virtual_address JOIN network_connections nc ON nc.inode = tof.inode WHERE t.comm = 'sshd'; tgid:"1134" comm:"sshd" protocol:"tcp" local_address:"0.0.0.0" local_port:"22" remote_address:"" remote_port:"" state:"listen" tgid:"1134" comm:"sshd" protocol:"tcp" local_address:"::" local_port:"22" remote_address:"" remote_port:"" state:"listen" ``` #### 任务打开的文件 通过将 `tasks` 与 `task_open_files` 连接,列出特定进程打开的文件: ``` $ mquire shell ubuntu2404_6.14.0-37-generic.lime mquire> SELECT t.comm, tof.path FROM tasks t JOIN task_open_files tof ON tof.task = t.virtual_address WHERE t.comm LIKE '%systemd%' LIMIT 10; comm:"systemd" path:"/null" comm:"systemd" path:"/null" comm:"systemd" path:"/null" comm:"systemd" path:"/kmsg" comm:"systemd" path:"[eventpoll]" comm:"systemd" path:"[signalfd]" comm:"systemd" path:"inotify" comm:"systemd" path:"/" comm:"systemd" path:"[timerfd]" comm:"systemd" path:"/usr/lib/systemd/systemd-executor" ``` #### 命令行查询示例 ##### JSON 输出(默认) ``` $ mquire query --format=json ubuntu2404_6.14.0-37-generic.lime "SELECT * FROM os_version" [ { "arch": "x86_64", "kernel_version": "6.14.0-37-generic", "system_version": "#37~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 10:25:38 UTC 2" } ] ``` ##### 表格输出 ``` $ mquire query --format=table ubuntu2404_6.14.0-37-generic.lime "SELECT * FROM os_version" arch:"x86_64" kernel_version:"6.14.0-37-generic" system_version:"#37~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 10:25:38 UTC 2" ``` #### 自定义命令示例 ##### 列出可用命令 ``` $ mquire command ubuntu2404_6.14.0-37-generic.lime Available commands: .carve Carve a region of virtual memory to disk .dump Dump all open files from tasks to disk .system_version Display the operating system version .task_tree Display a hierarchical task tree ``` ##### 显示系统版本 ``` $ mquire command ubuntu2404_6.14.0-37-generic.lime ".system_version" System Version: #37~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 10:25:38 UTC 2 Kernel Version: 6.14.0-37-generic Architecture: x86_64 ``` ##### 显示进程树 ``` $ mquire command ubuntu2404_6.8.0-63-generic.lime .task_tree | head -n 10 Parent: task_struct::parent Threads: Disabled Page Table: PhysicalAddress(0x0000000001A60000) └─ [0] (ffffffff90c0fcc0) swapper/0 ╎ ↳ [0] (ffff982a00e33518) \xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd,)\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\x0e ├─ [1] (ffff982a0084a8c0) systemd │ ├─ [430] (ffff982a0d27a8c0) systemd-journal │ ├─ [495] (ffff982a08a88000) systemd-udevd │ ├─ [786] (ffff982a07a60000) systemd-oomd ``` **注意:** 当存在多个具有相同 TID(线程 ID,可能由于内存损坏或快照时机导致)的 `task_struct` 条目时,重复条目会以缩进在主条目下的延续符号 `╎ ↳` 显示。隐藏线程时格式为 `[TGID] (virtual_address) name`,显示线程时为 `[TGID TID]`(其中 TGID 是 Thread Group ID,即通常所说的 PID)。 #### 从内存提取文件 ``` $ mquire command ubuntu2404_6.14.0-37-generic.lime ".dump ./extracted_files" Legend: SK = skipped, OK = all good, ER = errored Summary: Total files processed: 1234 Successfully dumped: 1156 Skipped: 45 Errors: 33 File Status: OK /usr/lib/systemd/systemd (TGID 1) OK /etc/passwd (TGID 1) SK /dev/null (TGID 1) ... ``` ## 开发 本项目使用 [just](https://github.com/casey/just) 作为命令运行器。运行 `just` 查看可用命令: | Command | Description | |---------|-------------| | `just check` | 运行所有检查 (cargo check, cargo clippy, cargo fmt, ruff, mypy) | | `just test` | 运行单元测试 | | `just fmt` | 格式化代码 (cargo fmt, ruff) | | `just integration-test` | 运行 SQL 查询集成测试 | | `just integration-update` | 更新预期测试输出 | | `just package` | 构建发布包 | ### SQL 查询集成测试 这些测试验证 mquire 对内存快照查询产生的输出是否正确。 - **`just integration-test`** - 运行测试并将输出与预期的 JSON 文件进行比较 - **`just integration-update`** - 用实际输出更新预期的 JSON 文件(在更改表结构时使用) 运行 `integration-update` 后,请查看 git diff 以确保更改符合你的预期,然后再提交。 **添加新测试:** 在相应的快照目录中创建一个 `.sql` 文件和匹配的 `.json` 文件,然后运行 `just integration-update` 以填充预期输出。 ## 贡献 欢迎贡献!在贡献时,请遵循以下准则: 1. **测试你的更改** - 在提交之前确保你的更改工作正常 2. **保持依赖最小化** - 仅在绝对必要时添加新依赖 3. **避免缓存易变数据** - 不要缓存可能在内核对象内移动或更改的值。仅缓存稳定的引用,如: - Kallsyms 位置 - `init_task` 虚拟地址 - BTF 数据 ## 许可证 本项目采用 Apache License 2.0 许可。有关详细信息,请参阅 [LICENSE](LICENSE) 文件。
标签:BTF, HTTP请求, Kallsyms, Linux取证, MAPLE TREE, OSQuery, Rust, SecList, Volatility替代, Windows 调试器, XARRAY, 内存取证, 内存快照分析, 内核分析, 内核调试, 可视化界面, 库, 应急响应, 数字取证, 数据结构解析, 文件缓存提取, 无符号表分析, 网络流量审计, 自动化脚本, 通知系统, 通知系统, 通知系统, 零依赖