Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
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.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
UnhookMe — Dynamischer Windows-API-Resolver und Unhooker, der gehackte Funktionen (IAT, EAT, Inline-Patches) erkennt und wiederherstellt, um unbeobachtete Systemaufrufe aus Red-Team-Malware aufzurufen. | Kitploit
Tools/GitHubGitHub/mgeeky/unhookme
DefensivwerkzeugeRed TeamingPayload-Entwicklung
GitHubmgeeky/unhookme

UnhookMe

Dynamischer Windows-API-Resolver und Unhooker, der gehackte Funktionen (IAT, EAT, Inline-Patches) erkennt und wiederherstellt, um unbeobachtete Systemaufrufe aus Red-Team-Malware aufzurufen.

Repository anzeigen
348488vor 4 JahrenVon 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

UnhookMe - Dynamischer Unhooking-Import-Resolver

In der Ära aufdringlicher AVs und EDRs, die Hot-Patches in laufende Prozesse einbringen, um ihre erweiterten Sichtbarkeitsanforderungen zu erfüllen, benötigen moderne Angreifer ein robustes Werkzeug, um diese Wächter zu umgehen. Die vorgeschlagene Implementierung eines dynamischen Import-Resolvers, der in der Lage ist, verwendete Funktionen im laufenden Betrieb zu enthaken (unhooking), ist ein weiterer Schritt zur Stärkung der Widerstandsfähigkeit von Angreifern.

Die Lösung, die ich hier vorschlage, besteht darin, von der Verwendung linkeraufgelöster WinAPI-Imports, die in den PE-Headern der kompilierten Executables sichtbar bleiben (insbesondere in der Import Address Table), auf einen vollständig dynamischen Ansatz umzusteigen, der darauf beharrt, Imports nur dynamisch aufzulösen. Ein solcher dynamischer Resolver kann mit einer Unhooking-Logik ausgestattet werden, die im Hintergrund abläuft, ohne jegliche Anleitung von Seiten des Bedieners.


Einfachstes Anwendungsbeispiel

So können Sie sicherstellen, dass MessageBoxW ungehakt und unüberwacht aufgerufen wird:

    RESOLVE(user32, MessageBoxW);
    _MessageBoxW(0, L"Look Ma! I'm unhooked!", L"Third - Unhooked", 0);

Die ganze Magie geschieht innerhalb der Makrodefinition RESOLVE, die ein ImportResolver<T>-Objekt namens _MessageBoxW erstellt.


Vorführung

Unhookme Vorführungsanimation

So funktioniert das UnhookMe-Beispiel:

  1. Es präsentiert uns die erste MessageBoxW, die nicht Gegenstand von Hooking ist.
  2. Dann hooken wir selbst den Prolog von MessageBoxW, um sie immer 0 zurückgeben zu lassen, ohne ihre Nachricht anzuzeigen.
  3. Schließlich lösen wir MessageBoxW dynamisch mit dem UnhookingImportResolver-Resolver auf, der angewandte Prolog-Patches erkennt und die ursprünglichen Bytes wiederherstellt, wodurch die Funktionalität von MessageBoxW effektiv enthakt wird.

Während des Erscheinens von MessageBoxen werden diese Logzeilen auf der Konsole ausgegeben:

[~] Resolved symbol kernel32.dll!CreateFileA
[~] Resolved symbol kernel32.dll!ReadProcessMemory
[~] Resolved symbol kernel32.dll!MapViewOfFile
[~] Resolved symbol kernel32.dll!VirtualProtectEx
[#] Found trampoline hook in symbol: MessageBoxW . Restored original bytes from file.
[~] Resolved symbol user32.dll!MessageBoxW

Wie verwendet man es?

Insgesamt gibt es 5 C++-Quellcode-/Header-Dateien, die Ihre Lösung einbinden muss. Ihre Hauptprogrammdatei muss jedoch nur zwei erforderliche Header einbinden, wie unten beschrieben.

  • resolver.h - Header, der den Großteil der UnhookingImportResolver-Implementierung und praktische Makrodefinitionen enthält
  • resolver.cpp - Quellcode mit definierten globalen Optionen
  • usings.h - eine große und umfangreiche Header-Datei mit Dutzenden von using-Typdefinitionen für häufig verwendete WinAPIs
  • PE.cpp - benutzerdefinierte PE-Parser-Quellcode-Datei
  • PE.h - benutzerdefinierte PE-Parser-Header-Datei

Erforderliche Header

Ihr Programm benötigt nur zwei einzubindende Header:

#include "usings.h"
#include "resolver.h"

Globale Optionen

Es gibt einige globale Optionen, die geändert werden können und die Art und Weise beeinflussen, wie der Resolver arbeitet oder seine Aktivität meldet. Diese sind ganz am Anfang der Datei resolver.cpp definiert:

Resolver globale Optionen:

  • globalQuietOption - auf true setzen, wenn Sie keine Ausgabe wünschen
  • globalVerboseOption - auf true setzen, wenn Sie eine detaillierte ausführliche Ausgabe wünschen
  • globalAntiSplicingOption - aufgelöste Funktionen enthaken, wenn sie gehakt sind.
  • globalLogFilePath - wohin die Ausgabe-Logzeilen umgeleitet werden sollen. Bei Leerzeichen wird stdout verwendet.
bool globalQuietOption = false;
bool globalVerboseOption = true;
bool globalAntiSplicingOption = true;

wchar_t globalLogFilePath[MAX_PATH] = L"";

Spezifikation benutzerdefinierter API-Typen

Um den Resolver zu verwenden, muss zunächst ein Funktionszeigertyp mit einer using-Anweisung in strenger Form deklariert werden:

    using fn_FunctionName = ReturnType WINAPI (
        ParamType1 paramName1,
        ...,
        ParamTypeN paramNameN,
    );

Dieses Repository enthält die Headerdatei usings.h mit vordefinierten Using-Typen für Dutzende beliebter Windows-APIs.

Der FunctionName entspricht der WinAPI, die der ImportResolver auflösen soll, und dieser Funktionszeiger muss als mit der WINAPI-Aufrufkonvention ( __stdcall auf x86 und __fastcall auf x64) markiert sein. Der ReturnType muss dem Typmodifizierer WINAPI vorausgehen.

Funktionsauflösung und -verwendung

Nachdem der Funktionszeigertyp wie oben angegeben definiert wurde, können wir ihn wie folgt verwenden:

    RESOLVE(libraryName, FunctionName);
    ReturnType output = _FunctionName(param1, ..., paramN);

Das Makro RESOLVE kümmert sich um die Instanziierung des templatisierten ImportResolver-Objekts und passt den Namen der angegebenen Bibliothek an.

Der Resolver führt mehrere weitere Makrodefinitionen ein, die eine benutzerfreundliche Konstruktoraufruf in verschiedenen Situationen bieten:

#define RESOLVE(mod, func)                    RESOLVE_PARAMETERIZED(mod, func, ::globalVerboseOption, ::globalAntiSplicingOption)
#define RESOLVE_NO_UNHOOK(mod, func)          RESOLVE_PARAMETERIZED(mod, func, ::globalVerboseOption, false)

#define RESOLVE_VERBOSE_UNHOOK(mod, func)     RESOLVE_PARAMETERIZED(mod, func, true, true)
#define RESOLVE_VERBOSE_NOUNHOOK(mod, func)   RESOLVE_PARAMETERIZED(mod, func, true, false)
#define RESOLVE_NOVERBOSE_UNHOOK(mod, func)   RESOLVE_PARAMETERIZED(mod, func, false, true)
#define RESOLVE_NOVERBOSE_NOUNHOOK(mod, func) RESOLVE_PARAMETERIZED(mod, func, false, false)

Resolver-Konstruktor:

    template<typename Ret, typename ...Args>
    ImportResolver<Ret WINAPI(Args...)>(
            std::string dllName,
            std::string funcName,
            bool _verbose = false,
            bool _unhook = false,
            bool *_wasItHooked = nullptr
        )

Wie funktioniert es?

Der zugrunde liegende Resolver nutzt einen benutzerdefinierten PE-Header-Parser, der jedes referenzierte DLL-Modul verarbeitet, um deren Exporte zu kartieren und die Integrität der PE-Header des Moduls sowie die Integrität der Stub-Bytes der referenzierten Funktion zu überprüfen.

Die Idee ist folgende:

Tool herunterladen