跳转到主要内容

基于LLVM的通用污点跟踪、数据流分析和跟踪的仪器工具。

项目描述

PolyTracker


PyPI version Tests Slack Status

PolyTracker是一个最初为《自动词汇注释和导航解析器》(Automated Lexical Annotation and Navigation of Parsers)项目创建的工具,该项目的缩写仅为指代它为《ALAN解析器项目》(The ALAN Parsers Project)。然而,它已发展成为一个通用的工具,用于高效地进行程序的数据流和控制流分析。PolyTracker是一个LLVM传递,它对程序进行仪器化以跟踪哪些函数操作了输入文件中的哪些字节。它输出包含数据流信息以及运行时跟踪的数据库。PolyTracker还提供了一个Python库,用于与其输出进行交互和分析,以及一个交互式Python REPL。

PolyTracker可以与PolyFile结合使用,以自动确定解析器中函数的语义目的。它还具有一个实验性功能,能够生成表示解析器接受的语言的无上下文文法。

与Taintgrind等动态插装替代方案不同,PolyTracker对几乎所有输入都几乎没有性能开销,并且能够同时跟踪输入的每一字节。PolyTracker最初是LLVM DataFlowSanitizer的分支,并从Angora Fuzzer中汲取了许多灵感。然而,与Angora系统不同,PolyTracker能够跟踪taint的整个来源。2021年2月,LLVM DataFlowSanitizer添加了一个名为来源跟踪的新功能,用于跟踪taint来源。然而,它一次只能跟踪最多16个taint,而PolyTracker可以跟踪多达231-1。

本README文件是安装PolyTracker和编译/插装二进制文件的通用使用指南。有关通过Python API与PolyTracker交互或扩展PolyTracker,以及与插装代码生成的运行时跟踪交互的说明,请参阅Python文档

快速入门

PolyTracker通过名为polytracker的Python脚本进行控制。您可以通过运行以下命令进行安装:

pip3 install polytracker

PolyTracker需要特定的系统环境来运行,因此几乎所有用户都可能在一个容器化环境中运行它。幸运的是,polytracker使这变得简单。您只需安装docker,然后运行

polytracker docker pull

polytracker docker run

后一个命令会将当前工作目录挂载到PolyTracker Docker容器中,并允许您构建和运行插装程序。

polytracker控制脚本——您可以从宿主系统或Docker容器内部运行它——具有各种命令,用于插装程序以及分析生成的工件。例如,您可以探索执行中的数据流,重建插装程序的控制流图,甚至提取匹配程序接受的输入的上下文无关文法。您可以通过运行以下命令来探索这些命令:

polytracker --help

如果以不带命令行参数的方式运行,polytracker脚本也是一个REPL。

$ polytracker
PolyTracker (4.0.0)
https://github.com/trailofbits/polytracker
Type "help" or "commands"
>>> commands

插装简单的C/C++程序

PolyTracker还附带了一个build命令。此命令允许用户在Blight插装环境中运行任何构建命令。这将生成一个blight_journal.jsonl文件,记录构建过程中运行的所有命令。如果您有一个C/C++目标,可以通过调用polytracker build并传递您的构建命令来对其进行插装。

polytracker build gcc -g -o my_binary my_source.c

要插装构建目标,请使用instrument-targets命令。默认情况下,该命令将使用您当前工作目录中的blight_journal.jsonl构建构建目标的插装版本。插装后的构建目标将使用与原始构建目标相同的标志进行构建。

polytracker instrument-targets my_binary

build还支持使用构建系统(如autotools或CMake)的复杂程序

polytracker build cmake .. -DCMAKE_BUILD_TYPE=Release
polytracker build ninja
# or
polytracker build ./configure
polytracker build make

然后对构建的任何目标运行instrument-targets

$ polytracker instrument-targets a.bin b.so

然后,a.instrumented.binb.instrumented.so将是插装版本。有关如何插装现实世界程序的示例,请参阅示例目录中的Dockerfile。

运行和分析插装程序

插装软件将输出写入POLYDB指定的路径,如果没有指定则为polytracker.tdag。这是一个二进制文件,可以通过运行以下命令进行操作:

from polytracker import PolyTrackerTrace, taint_dag

trace = PolyTrackerTrace.load("polytracker.tdag")
tdfile = trace.tdfile

first_node = list(tdfile.nodes)[0]
print(f"First node affects control flow: {first_node.affects_control_flow}")

# Operate on all Range nodes
for index, node in enumerate(tdfile.nodes):
  if isinstance(node, taint_dag.TDRangeNode):
    print(f"Node {index}: first {node.first}, last {node.last}")

# Access taint forest
tdforest = trace.taint_forest
n1 = tdforest.get_node(1)
print(
  f"Forest node {n1.label}. Parent labels: {n1.parent_labels}, "
  f"source: {n1.source.path if n1.source is not None else None}, "
  f"affects control flow: {n1.affected_control_flow}"
)

您还可以直接从REPL运行插装二进制文件

$ polytracker
PolyTracker (4.0.0)
https://github.com/trailofbits/polytracker
Type "help" or "commands"
>>> trace = run_trace("path_to_binary", "path_to_input_file")

如果需要,这将自动在Docker容器中运行插装二进制文件。

:警告: 如果在使用 Docker 或虚拟机运行 PolyTracker:PolyTracker 在虚拟化环境中运行可能会非常慢,特别是当输入文件或输出数据库位于从宿主操作系统映射或挂载的目录中时。当在 macOS 宿主机上从 Docker 运行 PolyTracker 时,这一点尤其正确。解决方案是将数据库写入容器/虚拟机内的路径,然后在最后将其复制到宿主机系统。

Python API 文档可在此处查看 here

运行时参数和仪器调整

在运行时,PolyTracker 仪器会查找通过环境变量指定的多个配置参数。这允许用户在不重新编译二进制文件的情况下修改仪器参数。

环境变量

PolyTracker 接受以环境变量形式提供的配置参数,以避免重新编译目标程序。PolyTracker 当前支持的环境变量包括

POLYDB: A path to which to save the output database (default is polytracker.tdag)

WLLVM_ARTIFACT_STORE: Provides a path to an existing directory to store artifact/manifest for all build targets

POLYTRACKER_TAINT_ARGV: Set to '1' to use argv as a taint source.

Polytracker 将按照以下顺序设置其配置参数

  1. 如果通过环境变量指定了参数,则使用该值
  2. 如果没有指定该参数的默认值,则使用默认值
  3. 否则抛出错误

ABI 列表

DFSan 使用 ABI 列表来确定它应该自动仪器化哪些函数,忽略哪些函数,以及存在哪些自定义函数包装器。有关更多信息,请参阅 dfsan 文档

从预构建库创建自定义忽略列表

尝试构建大型软件项目可能很耗时,尤其是旧版/不受支持的版本。尝试修改构建系统以支持更改,如 dfsan 的/我们的仪器化,更是耗时。

polytracker/scripts 目录中有一个脚本,可以在任何 ELF 库上运行,并将输出要忽略的函数列表。当不想跟踪通过特定库(如 libpng)或程序的其他子组件传递的信息时,我们会使用此功能。存在 Dockerfile-listgen.demo 以构建常见的开源库,以便我们可以创建这些列表。

此脚本是对 DataFlowSanitizer 中的脚本的略微修改版本,它专注于忽略系统库。原始脚本可在 dfsan_rt 中找到。

构建示例

检出此 Git 仓库。从根目录开始,要么构建基本的 PolyTracker Docker 映像

pip3 install -e ".[dev]" && polytracker docker rebuild

或者从 DockerHub 拉取最新预构建版本

docker pull trailofbits/polytracker:latest

要演示 PolyTracker 在 MuPDF 解析器上的运行,请运行以下命令

docker build -t trailofbits/polytracker-demo-mupdf -f examples/pdf/Dockerfile-mupdf.demo .

mutool_track 将在 /polytracker/the_klondike/mupdf/build/debug 中构建。运行 mutool_track 将输出 polytracker.tdag,其中包含 taint 分析提供的信息。

要演示 PolyTracker 在 Poppler 工具版本 0.84.0 上的运行,请运行以下命令

docker build -t trailofbits/polytracker-demo-poppler -f examples/pdf/Dockerfile-poppler.demo .

所有 Poppler 工具都将位于 /polytracker/the_klondike/poppler-0.84.0/build/utils

$ cd /polytracker/the_klondike/poppler-0.84.0/build/utils
$ ./pdfinfo_track some_pdf.pdf

从源代码构建 PolyTracker

由于涉及标准库位码的仪器化和非仪器化版本,PolyTracker LLVM 和 PolyTracker 的编译过程相当复杂。我们强烈建议尽可能使用我们预先构建和测试的 Docker 容器。在宿主机系统上安装 PolyTracker Python 包将允许您无缝地与预构建 Docker 容器交互。否则,要本地安装 PolyTracker,我们建议首先从 polytracker-llvm Dockerfile 复制安装过程,然后从 PolyTracker Dockerfile 复制安装过程。

构建依赖项

  • PolyTracker LLVM. PolyTracker 是基于其自己的 LLVM 分支构建的,该分支为 polytracker-llvm。此分支修改了 数据流安全分析器,以使用更大的标签大小(以便跟踪数量级更多的污点),以及存储它们的其他数据结构。我们已经调查了将我们的更改上推到 LLVM 的可能性,但兴趣不大。
  • CMake
  • Ninja (在 Ubuntu 上为 ninja-build

运行时依赖项

以下工具是测试和运行 PolyTracker 所必需的

  • Python 3.7+ 和 pipapt-get -y install python3.7 python3-pip)。这些用于无缝地与 Docker 容器(如果需要)交互,以及后处理和分析运行时跟踪产生的工件。
  • gllvmgo get github.com/SRI-CSL/gllvm/cmd/...)用于创建整个程序的位代码归档,并从目标中提取位代码。

在 Apple 芯片上构建

polytracker-llvm 预构建的 Docker 镜像仅适用于 amd64。使用 arm64 系统的用户将必须本地构建镜像,然后将 polytracker 的 Dockerfile 更改为指向它。

$ mkdir repos && cd repos
$ git clone https://github.com/trailofbits/polytracker
$ git clone https://github.com/trailofbits/polytracker-llvm
$ cd polytracker-llvm
$ DOCKER_BUILDKIT=1 docker build -t trailofbits/polytracker-llvm .
$ cd ../polytracker
$ ## Replace the first line of the Dockerfile with "FROM trailofbits/polytracker-llvm:latest" (no quotes)
$ docker build -t trailofbits/polytracker .

当前状态和已知问题

PolyTracker 目前仅在 Linux 上运行,因为这是唯一支持数据流安全分析器的系统。这种限制仅仅是因为缺乏对其他操作系统系统调用的语义支持,这可能在将来得到解决。然而,这意味着在非 Linux 系统上运行 PolyTracker 将需要安装 Docker。

除非这些库是用 PolyTracker 从源代码编译的,或者 PolyTracker 中实现了对库调用的特定支持,否则污点不会通过动态加载的库传播。目前支持通过大多数未进行插桩的 C 标准库调用传播污点。明确来说,使用未插桩函数的程序仍然可以正常运行,但是,由不受支持的库调用执行的操作不会传播污点。我们目前正在努力添加对 C++ 程序的强大支持,但目前的最佳结果将来自 C 程序。

如果 Docker 出现问题,请尝试执行系统修剪,并为 PolyTracker 和您尝试运行的任何演示使用 --no-cache 构建。

PolyTracker 的最坏情况性能发生在内存中的单个字节同时被来自源文件的大量输入字节污染的情况下。这通常发生在对具有大块大小的压缩和加密算法进行插桩时。目前正在进行研究和开发许多缓解措施。

许可证和致谢

此研究由 Trail of Bits 开发,由国防高级研究计划局(DARPA)在 SafeDocs 计划下作为 Galois 的分包商获得资助。它采用 Apache 2.0 许可证。© 2019,Trail of Bits。

维护者

Evan Sultanik
Henrik Brodin
Marek Surovič
Facundo Tuesca

firstname.lastname@trailofbits.com

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关 安装包 的更多信息。

源代码分发

polytracker-4.0.0.tar.gz (94.8 kB 查看哈希值)

上传时间

构建版本

polytracker-4.0.0-py3-none-any.whl (99.9 kB 查看哈希值)

上传时间 Python 3

支持