
Uno strumento di instrumentazione basato su LLVM per il taint tracking universale, l'analisi dei flussi di dati e il tracing.
PolyTracker è uno strumento originariamente creato per l'Automated Lexical Annotation and Navigation of Parsers, un retroacronimo ideato esclusivamente allo scopo di riferirsi ad esso come The ALAN Parsers Project. Tuttavia, si è evoluto in uno strumento di uso generale per eseguire in modo efficiente l'analisi del flusso di dati e del flusso di controllo dei programmi. PolyTracker è un pass LLVM che strumenta i programmi per tracciare quali byte di un file di input vengono elaborati da quali funzioni. Produce un database contenente le informazioni sul flusso di dati, oltre a una traccia di runtime. PolyTracker fornisce anche una libreria Python per interagire con e analizzare il suo output, nonché una REPL Python interattiva.
PolyTracker può essere usato in combinazione con PolyFile per determinare automaticamente lo scopo semantico delle funzioni in un parser. Dispone inoltre di una funzionalità sperimentale in grado di generare una grammatica libera dal contesto che rappresenta il linguaggio accettato da un parser.
A differenza delle alternative di strumentazione dinamica come Taintgrind, PolyTracker impone un overhead prestazionale trascurabile per quasi tutti gli input ed è in grado di tracciare ogni byte di input contemporaneamente. PolyTracker è nato come fork del DataFlowSanitizer di LLVM e trae molta ispirazione dall' Angora Fuzzer. Tuttavia, a differenza del sistema Angora, PolyTracker è in grado di tracciare l'intera provenienza di un taint. Nel febbraio 2021, il DataFlowSanitizer di LLVM ha aggiunto una nuova funzionalità per tracciare la provenienza del taint chiamata origin tracking. Tuttavia, può tracciare al massimo 16 taint contemporaneamente, mentre PolyTracker può tracciarne fino a 231-1.
Questo README funge da guida generale all'uso per installare PolyTracker e compilare/strumentare binari. Per interagire o estendere PolyTracker a livello programmatico tramite la sua API Python, nonché per interagire con le tracce di runtime prodotte dal codice strumentato, consulta la documentazione Python.
PolyTracker è controllato tramite uno script Python chiamato polytracker. Puoi
installarlo eseguendo
pip3 install polytracker
PolyTracker richiede un ambiente di sistema molto particolare per funzionare, quindi quasi tutti
gli utenti probabilmente lo eseguiranno in un ambiente containerizzato. Fortunatamente,
polytracker rende tutto semplice. Tutto ciò che devi fare è avere docker installato,
poi esegui:
polytracker docker pull
e
polytracker docker run
Quest'ultimo comando monterà la directory di lavoro corrente nel container Docker di PolyTracker e ti consentirà di compilare ed eseguire programmi strumentati.
Lo script di controllo polytracker — che puoi eseguire sia dal sistema host
sia dall'interno del container Docker — dispone di una varietà di comandi, sia per
strumentare programmi sia per analizzare gli artefatti risultanti. Ad
esempio, puoi esplorare i flussi di dati nell'esecuzione, ricostruire il
grafo del flusso di controllo del programma strumentato e persino estrarre una grammatica
libera dal contesto che corrisponde agli input accettati dal programma. Puoi esplorare questi
comandi eseguendo
polytracker --help
Lo script polytracker è anche una REPL, se eseguito senza argomenti da riga di comando:
$ polytracker
PolyTracker (4.0.0)
https://github.com/trailofbits/polytracker
Type "help" or "commands"
>>> commands
PolyTracker include anche un comando build. Questo comando consente all'utente di
eseguire qualsiasi comando di build in un ambiente strumentato Blight.
Verrà prodotto un file blight_journal.jsonl che
registra tutti i comandi eseguiti durante la build. Se hai un target C/C++, puoi
strumentarlo invocando polytracker build e passando il tuo comando di build:
polytracker build gcc -g -o my_binary my_source.c
Per strumentare un target di build, usa il comando instrument-targets. Per impostazione predefinita
il comando userà un blight_journal.jsonl nella tua directory di lavoro
corrente per creare una versione strumentata del tuo target di build. Il
target di build strumentato verrà compilato usando gli stessi flag del target di build
originale.
polytracker instrument-targets my_binary
build supporta anche programmi più complessi che usano un sistema di build come
autotiools o CMake:
polytracker build cmake .. -DCMAKE_BUILD_TYPE=Release
polytracker build ninja
# or
polytracker build ./configure
polytracker build make
Quindi esegui instrument-targets su qualsiasi target della build:
polytracker instrument-targets a.bin b.so
Quindi a.instrumented.bin e b.instrumented.so saranno le versioni
strumentate. Consulta i Dockerfile nella directory
examples
per esempi di come strumentare programmi reali.
Il software strumentato scriverà il suo output nel percorso specificato in
POLYDB, o in polytracker.tdag se omesso. Si tratta di un file binario su cui è possibile
operare eseguendo:
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}"
)
Puoi anche eseguire un binario strumentato direttamente dalla 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")
Questo eseguirà automaticamente il binario strumentato in un container Docker, se necessario.
⚠️ Se si esegue PolyTracker in Docker o in una VM: PolyTracker può essere molto lento se eseguito in un ambiente virtualizzato e se il file di input o, soprattutto, il database di output si trovano in una directory mappata o montata dal sistema host. Ciò è particolarmente vero quando si esegue PolyTracker in Docker da un host macOS. La soluzione è scrivere il database in un percorso all'interno del container/VM e poi copiarlo sul sistema host alla fine.
La documentazione dell'API Python è disponibile qui.