Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
BYOVD-DriverKiller — Treiber-Reverse & Exploitation | Kitploit
Tools/GitHubGitHub/alex3o/byovd-driverkiller
ExploitationReverse EngineeringPost-ExploitationBinäranalyseLernen & BildungRed Teaming
GitHubalex3o/byovd-driverkiller

BYOVD-DriverKiller

Treiber-Reverse & Exploitation

Repository anzeigen
831411vor 1 JahrVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

BYOVD-DriverKiller

⚠️ Warnung: Dieses Projekt ist streng bildungspädagogisch und demonstrativ. Es ist nicht dafür gedacht, in einem böswilligen Kontext verwendet zu werden. Ziel ist es, die Methodik des Reverse Engineering und die Schritte zur Ausnutzung eines Windows-Treibers zu erlernen.


Hier erkläre ich das Vorgehen, das ich zur Lösung der von d1rk(SaadAhla) https://github.com/SaadAhla vorgeschlagenen Übung gewählt habe. Dabei geht es darum, Reverse Engineering und Exploitation an einem legitimen, signierten Treiber durchzuführen, der nicht in den Blocklisten (HVCI, LOLBIN...) enthalten ist. Ein C-Programm, mit dem sich über diesen Kernel-Mode-Treiber jeder aktive Prozess auf dem System beenden lässt, ist verfügbar; ich erläutere seine Funktionsweise weiter unten.

POC-BYOD

📃 Verwendung: DriverKiller.exe <nom_processus.exe> [-d]

Option -d: Ermöglicht das Entfernen des Dienstes und des Treibers vom System nach der Exploitation. Der Testsigning-Modus muss auf dem Zielcomputer aktiviert sein, da das Zertifikat des Treibers abgelaufen ist.


Teil 1 - Reverse Engineering:

Die Übung stellt eine .sys-Datei bereit, die nach ihrem SHA-256-Hash benannt ist. Der erste Schritt besteht darin, diese Datei mit IDA zu öffnen.
IDA ist kostenlos verfügbar. Es genügt, die Website von Hex-Rays zu besuchen, um eine Lizenz zu generieren und die Software herunterzuladen.

Wir beginnen damit, die IAT (Import Address Table) des Treibers aufzulisten und den Aufruf der relevanten API zu suchen: ZwTerminateProcess.

screen1-git

Durch einen Doppelklick auf ZwTerminateProcess leitet IDA uns zum kompilierten Code dieser Funktion weiter. Wenn man den Eintrag auswählt und dann die Cross-References anzeigt, erhält man die Liste der Treiberfunktionen, die ihn aufrufen.

screen2-git

Man sieht, dass es die Funktion sub_12EF4 bei Offset 1CE ist, die ZwTerminateProcess verwendet. Nach einem Doppelklick zeigt IDA ihren kompilierten Code an.

screen11-git

Der dekompilierte Code zeigt die Aufrufe von ZwOpenProcess (das einen Handle zum Zielprozess öffnet) und ZwTerminateProcess (das den Prozess über diesen Handle beendet).

Wenn man die Dokumentation von ZwOpenProcess (https://learn.microsoft.com/fr-fr/windows-hardware/drivers/ddi/ntddk/nf-ntddk-zwopenprocess) konsultiert, stellt man fest, dass der Parameter ClientID einem Zeiger entspricht, der die PID des Zielprozesses angibt.

In der Zeile darüber wird ClientId.UniqueProcess mit der Variablen v22 initialisiert. Diese wird direkt darüber definiert:

v22 = (void )((_QWORD *)i + 10);

Um diese Zuweisung zu verstehen, muss man die Variable i und das Feld +10 identifizieren.

screen3-git

Weiter oben in dieser Funktion sieht man einen Aufruf von ZwQuerySystemInformation mit dem Parameter SYSTEM_PROCESS_INFORMATION. Man versteht auch, dass i zusammen mit der Variablen v6 der Iterator über die Einträge dieser Struktur ist.

Laut der Dokumentation von ZwQuerySystemInformation: (https://learn.microsoft.com/en-us/windows/win32/sysinfo/zwquerysysteminformation) gibt diese Funktion ein Array zurück, das einen Eintrag pro aktivem Prozess auf dem System enthält.

Die Struktur SYSTEM_PROCESS_INFORMATION wird hier beschrieben: https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntquerysysteminformation

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    BYTE Reserved1[48];
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    PVOID Reserved2;
    ULONG HandleCount;
    ULONG SessionId;
    PVOID Reserved3;
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;
    ULONG Reserved4;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    PVOID Reserved5;
    SIZE_T QuotaPagedPoolUsage;
    PVOID Reserved6;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
    SIZE_T PrivatePageCount;
    LARGE_INTEGER Reserved7[6];
} SYSTEM_PROCESS_INFORMATION;

Zur Erinnerung: Größen einiger Typen unter Windows x64

  • ULONG = 4 Bytes
  • USHORT = 2 Bytes
  • HANDLE = 8 Bytes
  • PWSTR = 8 Bytes
  • KPRIORITY (typedef eines LONG) = 4 Bytes
  • UNICODE_STRING = 16 Bytes, denn hier ist seine Struktur:
  typedef struct _UNICODE_STRING {
    USHORT Length;        -> 2      
    USHORT MaximumLength; -> + 2 = 4
    PWSTR  Buffer;        -> + 8 = 12 (12 ist kein Vielfaches von 8, daher wird 4 Bytes Padding vor dem Buffer hinzugefügt) = 16
} UNICODE_STRING;

Berechnung des Offsets von UniqueProcessId:

    ULONG NextEntryOffset;        -> 4
    ULONG NumberOfThreads;        -> + 4 = 8
    BYTE Reserved1[48];           -> + 48 = 56
    UNICODE_STRING ImageName;     -> + 16 = 72
    KPRIORITY BasePriority;       -> + 4 = 76 (76 ist kein Vielfaches von 8, daher werden 4 Bytes Padding hinzugefügt) = 80
    HANDLE UniqueProcessId;       -> + 8 = 88

Das Element UniqueProcessId befindet sich also bei Offset 0x50 (80 dezimal).

Wenn wir uns die Zuweisung unserer Variablen v22 ansehen, stellen wir fest, dass i in einen QWORD-Zeiger (8 Bytes) gecastet wird

v22 = (void )((_QWORD *)i + 10);
v22 entspricht also der Adresse von i + 10 * 8 = 80 Bytes. Diese Variable enthält also die aus der Struktur SYSTEM_PROCESS_INFORMATION abgerufene PID.

Um herauszufinden, welche PID an ZwTerminateProcess übergeben wird, muss die Bedingung analysiert werden, die diese Zuweisung umgibt.

screen4-git

Man sieht, dass zunächst der Name des Prozessimages abgerufen wird:

v9 = (wchar_t )((_QWORD *)i + 8);
Denn v9 = Adresse von i + 8 × 8 = 64 Bytes. Das entspricht dem Buffer des Elements ImageName, da sich dieses Element bei Offset 56 + 2 (USHORT) + 2 (USHORT) + 4 (Padding) = 64 befindet.

Angesichts der Manipulationen und Schleifen unten kann man die Hypothese aufstellen, dass ein Vergleich zwischen dem als Argument übergebenen Prozessnamen (a2) und den aktiven Prozessen auf dem System v9/String durchgeführt wird.

sub_1C078(String, v9, (int)v13);
v17 = strupr(a2);
v18 = strupr(String);

Es ist also der Parameter a2, der den Namen des über ZwTerminateProcess zu beendenden Prozesses enthalten soll. Man beachte, dass a2 ein Parameter der Funktion sub_12EF4 ist. Um weiterzugehen, müssen die Referenzen dieser Funktion untersucht werden (ich habe sie zur besseren Lesbarkeit in ZwTerminateProcessCaller umbenannt).

Tool herunterladen