
Pilote en mode noyau Windows avec client en mode utilisateur exposant la lecture/écriture de mémoire physique et virtuelle via IOCTL, le parcours de tables de pages, le scan de motifs et l'émulation d'entrées pour la triche aux jeux.
██╗ ██╗████████╗██╗ ██╗██╗██╗ ██╗███╗ ███╗
██║ ██║╚══██╔══╝██║ ██║██║██║ ██║████╗ ████║
██║ ██║ ██║ ███████║██║██║ ██║██╔████╔██║
██║ ██║ ██║ ██╔══██║██║██║ ██║██║╚██╔╝██║
███████╗██║ ██║ ██║ ██║██║╚██████╔╝██║ ╚═╝ ██║
╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═╝
Framework de pilote en mode noyau Windows avec client en mode utilisateur
[!IMPORTANT]
Obtenir le projet complet
Les fichiers de solution sont disponibles via le serveur Discord.
Intéressé par l'achat du code source complet ? Contactez-moi sur Telegram ou Discord : @tonythimself.
Lithium est un pilote en mode noyau Windows (lithium-kernel) associé à un client en mode utilisateur (lithium-usermode). Il communique via une interface IOCTL personnalisée et expose des primitives de manipulation de mémoire de bas niveau, de parcours de tables de pages et de contrôle de périphériques d'entrée.
| Fonctionnalité | Description |
|---|---|
| Lecture/Écriture mémoire physique | Lecture/écriture directe d'adresses physiques via MmCopyMemory |
| Lecture/Écriture mémoire virtuelle | Accès inter-processus à la mémoire virtuelle via MmCopyVirtualMemory |
| Résolution du DTB | Extraction de la base de la table de répertoires via l'énumération de la base de données PFN |
| Parcours de tables de pages | Traduction d'adresses linéaires avec mise en cache des couches PML4/PDPT/PD/PT |
| Analyse de motifs | Analyse de signatures de style IDA dans la mémoire d'un processus |
| Allocation mémoire | ZwAllocateVirtualMemory dans le contexte du processus cible |
| Protection mémoire | ZwProtectVirtualMemory dans le contexte du processus cible |
| Émulation de souris | Entrée souris au niveau noyau via un hook du callback du service MouClass |
| Dissimulation de threads | Falsification des champs ETHREAD (adresse de début, CID, heure de création, etc.) |
| Désactivation du callback NMI | Suppression du callback NMI pour l'évasion de débogueur |
| Nettoyage du pool | Suppression d'entrées de la table big pool du traqueur de pool du noyau |
lithium/
├── lithium-kernel/ # Kernel-mode driver (KMDF)
│ ├── entry.cpp # DriverEntry entry point
│ ├── core/
│ │ ├── dispatch/ # IOCTL dispatch and request routing
│ │ ├── requests/
│ │ │ ├── directory-table-base/ # DTB resolution & page table walk
│ │ │ ├── image-base/ # Process module base retrieval
│ │ │ ├── mouse/ # Mouse input emulation via MouClass
│ │ │ ├── read-write/ # Physical and virtual memory R/W
│ │ │ └── virtual-memory/ # Allocate, protect, query, pattern scan
│ │ └── utilities/
│ │ ├── kernel/ # Module enumeration, NMI, thread ops
│ │ └── ... # Pool cleaner, CRT shim
│ └── dependencies/
│ ├── additional/
│ │ ├── crt/ # Minimal CRT implementation
│ │ ├── security/ # skCrypter string encryption, oxorany
│ │ └── structures/ # Shared invoke data structures
│ └── includes.hpp # Master include header
│
└── lithium-usermode/ # User-mode client
├── entry.cpp # Client entry point
├── core/
│ └── driver/ # IOCTL communication layer
└── dependencies/
├── additional/
│ └── structs.hpp # Page table entry unions & helpers
└── includes.hpp
La communication est établie en hookant la routine de dispatch IOCTL d'un pilote existant (ProcObsrvesx.sys). Au chargement, le module noyau localise le pilote cible, recherche son gestionnaire de dispatch IRP et l'écrase avec un trampoline vers le hooked_ioctl de lithium. Le client en mode utilisateur ouvre \\.\ProcObsrvesx et tous les IOCTL sont redirigés de manière transparente via le hook.
| Code | Structure d'entrée | Action |
|---|---|---|
invoke_base | base_invoke { pid, handle } | Récupérer la base de l'image du processus |
invoke_dtb | dtb_invoke { pid, dtb } | Résoudre la base de la table de répertoires |
invoke_read | read_invoke { pid, directory_table, address, buffer, size } | Lire la mémoire physique |
invoke_write | write_invoke { pid, directory_table, address, buffer, size } | Écrire dans la mémoire physique |
invoke_read_virtual | read_virtual_invoke { pid, address, buffer, size } | Lire la mémoire virtuelle |
invoke_write_virtual | write_virtual_invoke { pid, address, buffer, size } | Écrire dans la mémoire virtuelle |
invoke_allocate | allocate_invoke { pid, type, protection, address, size } | Allouer de la mémoire virtuelle |
invoke_protect | protect_invoke { pid, protection, address, size } | Modifier la protection mémoire |
invoke_virtual_query | query_virtual_invoke { pid, address, mbi } | Interroger les informations de mémoire virtuelle |
invoke_pattern_scan | pattern_invoke { pid, signature, address, pattern_address } | Analyse de motifs en mémoire |
invoke_move_mouse | mouse_invoke { x, y, flags, button_flags } | Émuler une entrée souris |
Le pilote itère sur les plages de mémoire physique retournées par MmGetPhysicalMemoryRanges, parcourt la base de données PFN pour localiser l'entrée PML4 auto-référencée, et valide chaque couche de table de pages pour confirmer la base de la table de répertoires correcte pour un processus donné.
La traduction linéaire-vers-physique traverse la hiérarchie de tables de pages x64 à quatre niveaux (PML4 → PDPT → PD → PT) avec mise en cache par niveau. La prise en charge des grandes pages (2 Mo / 1 Go) est incluse au mieux.
Le pilote localise les objets pilotes MouClass et MouHID, résout le MouseClassServiceCallback depuis l'extension de périphérique HID, et injecte des paquets MOUSE_INPUT_DATA directement dans la chaîne de callbacks.
Les champs clés d'ETHREAD — heure de création, adresse de début, adresse de début Win32, pile noyau, CID et statut de sortie — sont sauvegardés et remplacés par des valeurs bénignes ou nulles. Lors du démontage, les valeurs d'origine sont restaurées avant la terminaison du thread.
lithium.sln dans Visual Studiolithium-kernel → lithium-kernel.syslithium-usermode → lithium-usermode.exeOu via MSBuild :
msbuild lithium.sln /p:Configuration=Release /p:Platform=x64
#include <core/driver/driver.hpp>
g_driver->initialize_handle();
DWORD pid = g_driver->get_process_id(L"target.exe");
g_driver->attach(pid);
g_driver->image_base = g_driver->get_image_base(0);
g_driver->dtb = g_driver->resolve_directory_table_base();
auto value = g_driver->read<uintptr_t>(g_driver->image_base + 0xOFFSET);
g_driver->mouse_event(-10, -10, 0, 0);