
Drltrace ist ein Bibliotheksaufruf-Tracer für Windows- und Linux-Anwendungen.
Windows-Testbuild
Drltrace ist ein dynamischer API-Aufruf-Tracer für Windows- und Linux-Anwendungen. Drltrace basiert auf dem dynamischen Binary-Instrumentierungs-Framework DynamoRIO. Drltrace wurde ursprünglich von Derek Bruening implementiert und mit den Frameworks DynamoRIO und DrMemory verteilt. Dieses Repository enthält eine eigenständige Version von drltrace mit zusätzlichen Skripten und Materialien zur Verwendung bei der Analyse von Malware. Die Release-Version kann hier heruntergeladen werden.
Die Verwendung von drltrace ist sehr einfach. Ein Benutzer muss ein Log-Verzeichnis und den Namen eines Zielprozesses wie folgt angeben:
drltrace -logdir . -- calc.exe
Das war's, das Tool injiziert die erforderlichen DLLs in den Zielprozess, startet die Instrumentierung und protokolliert parallel Informationen über alle Bibliotheksaufrufe, die im Zielprozess ausgeführt werden:
~~43600~~ msvcrt.dll!__wgetmainargs
arg 0: 0x010d2364
arg 1: 0x010d2368
and return to module id:0, offset:0x193a
~~43600~~ ntdll.dll!EtwEventRegister
arg 0: 0x002ff994
arg 1: 0x010d1490
and return to module id:0, offset:0x157e
~~43600~~ ntdll.dll!EtwEventSetInformation
arg 0: 0x007b4b40
arg 1: 0x00000033
and return to module id:0, offset:0x15a1
~~43600~~ SHELL32.dll!ShellExecuteW
arg 0: <null> (type=<unknown>, size=0x0)
arg 1: <null> (type=wchar_t*, size=0x0)
arg 2: calculator:// (type=wchar_t*, size=0x0)
arg 3: <null> (type=wchar_t*, size=0x0)
arg 4: <null> (type=wchar_t*, size=0x0)
arg 5: 0x1 (type=int, size=0x4)
and return to module id:0, offset:0x167d
Das Format der Ausgabe ist einfach und kann leicht von einem externen Skript geparst werden:
~~[thread id]~~ [dll name]![api call name]
arg [arg #]: [value] (type=[Windows type name], size=[size of arg])
and return to module id:[module unique id], offset:[offset in memory]
Das Parsen mit grep ist möglich, wenn das Argument -grepable verwendet wird; dies gibt die Funktionsnamen und Argumente alle in einer Zeile aus:
~~4824~~ KERNELBASE.dll!CreateFileW {0: C:\Windows\Fonts\staticcache.dat (type=wchar_t*, size=0x0)} {1: 0x80000000 (type=DWORD, size=0x4)} {2: 0x3 (type=DWORD, size=0x4)} {3: 0x005cde8c (type=<unknown>*, size=0x0)} {4: 0x3 (type=DWORD, size=0x4)} {5: 0x80 (type=DWORD, size=0x4)}
Die Tabelle der eindeutigen Modulkennungen wird am Ende der Logdatei ausgegeben:
Module Table: version 3, count 70
Columns: id, containing_id, start, end, entry, checksum, timestamp, path
0, 0, 0x010d0000, 0x010da000, 0x010d1b80, 0x0000f752, 0xb5fe3575, C:\Windows\SysWOW64\calc.exe
1, 1, 0x6d4c0000, 0x6d621000, 0x6d563940, 0x00136d65, 0x59ce1b0b, C:\Users\Max\Downloads\drltrace\drltrace\dynamorio\lib32\release\dynamorio.dll
2, 2, 0x73800000, 0x73975000, 0x7380dbf7, 0x00000000, 0x59ce1b0f, C:\Users\Max\Downloads\drltrace\drltrace\bin\release/drltracelib.dll
3, 3, 0x742f0000, 0x742fa000, 0x742f2a00, 0x0000c877, 0x0adc52c1, C:\Windows\System32\CRYPTBASE.dll
4, 4, 0x74300000, 0x74320000, 0x7430c9b0, 0x0002c617, 0x245970b4, C:\Windows\System32\SspiCli.dll
5, 5, 0x74410000, 0x74431000, 0x74416900, 0x0002a940, 0x88a53c1d, C:\Windows\System32\GDI32.dll
6, 6, 0x74440000, 0x74500000, 0x7446fb20, 0x000cc410, 0xd343d532, C:\Windows\System32\RPCRT4.dll
7, 7, 0x74500000, 0x74525000, 0x745047d0, 0x00026737, 0xa39c8991, C:\Windows\System32\IMM32.DLL
8, 8, 0x74550000, 0x745c7000, 0x7456e8a0, 0x00081857, 0x73b971e1, C:\Windows\System32\advapi32.dll
9, 9, 0x748f0000, 0x74929000, 0x748febd0, 0x00045303, 0xa58be652, C:\Windows\System32\cfgmgr32.dll
10, 10, 0x74930000, 0x75c78000, 0x74aa09d0, 0x01377aa6, 0x4b39926b, C:\Windows\System32\SHELL32.dll
Drltrace kann problemlos Zwischenbibliotheksaufrufe herausfiltern und nur API-Aufrufe aus dem Hauptmodul (oder aus dem Heap) einer Zielanwendung ausgeben, indem die Option -only_from_app angegeben wird, was bei Anwendungen, die enorme Logs erzeugen, sehr nützlich ist. Für eine feinere Kontrolle ermöglicht die Option -filter dem Benutzer, eine Filterkonfigurationsdatei anzugeben, um bestimmte Whitelist-Funktionen zu filtern oder Blacklist-Funktionen zu ignorieren (siehe die Datei filter.config für Beispiele). Drltrace verfügt außerdem über mehrere nützliche externe Skripte, um API-Aufrufe für eine bestimmte Bibliothek zu filtern, nur potenziell interessante API-Aufrufe und Zeichenfolgen auszugeben.
Die Hauptmodule von Drltrace werden unter BSD vertrieben.
Einige für drltrace erforderliche Dateien werden unter LGPL vertrieben. Siehe Quelldateien für weitere Details.
Malware-Analyse ist keine einfache Aufgabe. Sophisticierte Software-Packer wie Themida und Armadillo und natürlich Dutzende unbenannter Packer, die von Malware-Autoren geschrieben wurden, sowie Code- und Datenverschlüsselung erleichtern (in einigen Fällen machen sie es völlig unmöglich) das statische Reverse Engineering solcher Proben erheblich, was das Leben von Malware-Analysten erschwert. In solchen Fällen kann die Verfolgung von API-Aufrufen die Zeit, die zum Verständnis der tatsächlichen bösartigen Absicht erforderlich ist, erheblich reduzieren und viele technische Details über den geschützten bösartigen Code offenlegen.
Während die traditionelle Technik des API-Hookings in mehreren Lösungen erfolgreich implementiert wurde, ist der Ansatz von Malware-Autoren gut untersucht und kann leicht erkannt und/oder umgangen werden. Darüber hinaus werden diese Tools als eigenständige, schwergewichtige GUI-Anwendungen (als proprietäre Produkte) vertrieben, die oft nicht einfach in bestehende Malware-Analyse-Workflows integriert werden können.
Wenn wir uns die Linux-Welt ansehen, gibt es ein wunderbares Tool namens ltrace. Mit einem einzigen Befehl in der Bash können wir die vollständige Ablaufverfolgung der API-Aufrufe eines bestimmten ausführbaren Programms erhalten.
Warum haben wir kein solches Tool (wie ltrace unter Linux) für Windows, das auch transparent gegenüber Anti-Research-Tricks moderner Malware ist?
Es stellt sich heraus, dass es eine Technik gibt, die uns helfen kann, ein solches Tool für Windows zu haben und API-Aufrufe transparent gegenüber dem ausgeführten Programm zu verfolgen. Diese Technik wird dynamische Binary-Instrumentierung, kurz DBI, genannt. DBI ist eine Technik zur Analyse des Verhaltens einer binären Anwendung zur Laufzeit durch die Injektion von Instrumentierungscode.
Allerdings ist die Anwendung von DBI für die Malware-Analyse ungerechtfertigt eingeschränkt durch die Automatisierung des Entpackens und verschiedene Proof-of-Concepts für die Ablaufverfolgung von Anweisungen, Basisblöcken und Funktionsaufrufen. Unseres Wissens nach ist drltrace das erste Tool zur API-Aufrufverfolgung auf Basis von DBI, das in der Praxis für die Malware-Analyse eingesetzt werden kann. Wir haben mehrere Beispiele für die Malware-Analyse in unserem Wiki bereitgestellt, in denen wir beschrieben haben, wie drltrace es ermöglichte, in wenigen Minuten viele interne technische Details über anspruchsvolle bösartige Proben zu enthüllen, ohne IDA oder einen Debugger zu starten.
-logdir [ .] Log directory to print library call data
-only_from_app [ false] Reports only library calls from the app
-follow_children [ true] Trace child processes
-print_ret_addr [ false] Print library call's return address
-num_unknown_args [ 2] Number of unknown libcall args to print
-num_max_args [ 6] Maximum number of arguments to print
-default_config [ true] Use default config file.
-config [ ""] The path to custom config file.
-filter [filter.config] The path of the whitelist/blacklist file.
-ignore_underscore [ false] Ignores library routine names starting with "_".
-help [ false] Print this message.
-version [ false] Print version number.
-verbose [ 1] Change verbosity.
-use_config [ true] Use config file
-grepable [ false] Grepable output
Drltrace unterstützt externe Konfigurationsdateien, in denen ein Benutzer beschreiben kann, wie drltrace Argumente für bestimmte API-Aufrufe ausgeben soll.
HANDLE|CreateRemoteThread|HANDLE|SECURITY_ATTRIBUTES*|size_t|THREAD_START_ROUTINE*|VOID*|DWORD|__out DWORD*
Jedes Funktionsargument sollte durch | getrennt werden. Das erste Argument ist der Rückgabetyp, das zweite Argument ist der Funktionsname selbst und der Rest sind die Funktionsargumente. Ein Token __out wird verwendet, um Ausgabeargumente zu kennzeichnen, und ___inout wird verwendet, um Eingabe+Ausgabeargumente zu kennzeichnen.
Beispiele zur Verwendung von drltrace für die Analyse komplexer Malware finden Sie auf unserer Wiki-Seite.
Um die Arbeit mit Logdateien zu erleichtern, haben wir ein Skript namens api_calls_viz.py implementiert, das zur Erzeugung von RGB-Bildern verwendet werden kann, bei denen jede Pixelfarbe einen eindeutigen API-Aufruf darstellt. Das folgende Bild zeigt beispielsweise die Logdatei der WannaCry-Malware.

Die großen grünen Bereiche im Bild repräsentieren API-Aufrufe (wcscmp/wcsicmp), die zur Auswahl von Dateien mit interessanten Erweiterungen (z.B. docx, xls, py) zur Verschlüsselung verwendet werden. Die violetten Bereiche repräsentieren API-Aufrufe (FindFirstFile/FindNextFile/CryptEncrypt), die zum Aufzählen und Verschlüsseln von Dateien und Ordnern auf der Festplatte verwendet werden.
Das Skript kann auch eine HTML-Darstellung des erzeugten RGB-Bildes generieren, bei der jedes Element ausgewählt werden kann, um den Namen eines API-Aufrufs anzuzeigen.

Siehe das api_calls_viz Verzeichnis für weitere Details.
Eine detaillierte Anleitung finden Sie auf dieser Wiki-Seite.
Windows, Linux (macOS in Zukunft).
x86, x64 (ARM auf der Liste).
C- und C++-Standardbibliothek (und Logverarbeitungsskripte, die in Python geschrieben sind).
Wir haben uns entschieden, unseren API-Aufruf-Tracer auf Basis des dynamischen Binary-Instrumentierungs-Frameworks DynamoRIO zu implementieren. Drltrace bittet DynamoRIO, die Instrumentierung des LoadLibrary-Aufrufs durchzuführen, um neue Bibliotheken verarbeiten zu können, die vom Zielprozess geladen werden. Wenn der Prozess versucht, eine neue Bibliothek zu laden, leitet DynamoRIO den Kontrollfluss an drltracelib.dll um. Drltrace wiederum zählt die exportierten Funktionen in der neu geladenen DLL auf und registriert für jede einen speziellen Callback. Wenn also eine exportierte Funktion von Malware aufgerufen würde, wird drltraces Callback vor dieser Funktion ausgeführt, und das Tool kann alle erforderlichen Informationen wie Funktionsname und Argumente protokollieren. Ein weiterer Callback kann nach der Funktion registriert werden, um die Ausführungsergebnisse zu speichern.
Warum nicht Intel Pin? Wir haben uns aus folgenden Gründen für DynamoRIO entschieden:
-syswide_on von drrun.exe). In Zukunft ist es jedoch notwendig, eine spezielle Unterstützung in drltrace für solche Situationen zu implementieren.Unser Issue-Tracker enthält weitere Details zur Zukunft von drltrace.
Maksim Shudrak https://github.com/mxmssh
Derek Bruening https://github.com/derekbruening
Joe Testa https://github.com/jtesta