
Driver em modo kernel do Windows com cliente em modo usuário que expõe leitura/escrita de memória física e virtual baseada em IOCTL, percurso de tabela de páginas, varredura de padrões e emulação de entrada para trapaça em jogos.
██╗ ██╗████████╗██╗ ██╗██╗██╗ ██╗███╗ ███╗
██║ ██║╚══██╔══╝██║ ██║██║██║ ██║████╗ ████║
██║ ██║ ██║ ███████║██║██║ ██║██╔████╔██║
██║ ██║ ██║ ██╔══██║██║██║ ██║██║╚██╔╝██║
███████╗██║ ██║ ██║ ██║██║╚██████╔╝██║ ╚═╝ ██║
╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═╝
Framework de driver em modo kernel do Windows com cliente em modo usuário
[!IMPORTANT]
Obtenha o projeto completo
Os arquivos da solução estão disponíveis através do servidor do Discord.
Interessado em adquirir o código-fonte completo? Entre em contato comigo no Telegram ou no Discord: @tonythimself.
Lithium é um driver em modo kernel do Windows (lithium-kernel) emparelhado com um cliente em modo usuário (lithium-usermode). Ele se comunica através de uma interface IOCTL personalizada e expõe primitivas de manipulação de memória de baixo nível, percurso de tabelas de páginas e controle de dispositivos de entrada.
| Recurso | Descrição |
|---|---|
| Leitura/Escrita de Memória Física | Leitura/escrita direta de endereços físicos via MmCopyMemory |
| Leitura/Escrita de Memória Virtual | Acesso à memória virtual entre processos via MmCopyVirtualMemory |
| Resolução de DTB | Extração da base da tabela de diretórios via enumeração do banco de dados PFN |
| Percurso de Tabela de Páginas | Tradução de endereço linear com cache das camadas PML4/PDPT/PD/PT |
| Varredura de Padrões | Varredura de assinaturas no estilo IDA pela memória do processo |
| Alocação de Memória | ZwAllocateVirtualMemory no contexto do processo alvo |
| Proteção de Memória | ZwProtectVirtualMemory no contexto do processo alvo |
| Emulação de Mouse | Entrada de mouse em nível de kernel via hook do callback de serviço do MouClass |
| Ocultação de Thread | Falsificação de campos do ETHREAD (endereço de início, CID, horário de criação, etc.) |
| Desativação de Callback NMI | Supressão de callback NMI para evasão de depurador |
| Limpeza de Pool | Remoção de entradas da tabela de big pool do rastreador de pool do kernel |
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
A comunicação é estabelecida ao interceptar a rotina de dispatch IOCTL de um driver existente (ProcObsrvesx.sys). No momento do carregamento, o módulo de kernel localiza o driver alvo, procura por seu manipulador de dispatch de IRP e o sobrescreve com um trampolim para o próprio hooked_ioctl do lithium. O cliente em modo usuário abre \\.\ProcObsrvesx e todos os IOCTLs são redirecionados de forma transparente através do hook.
| Código | Estrutura de Entrada | Ação |
|---|---|---|
invoke_base | base_invoke { pid, handle } | Recuperar a base da imagem do processo |
invoke_dtb | dtb_invoke { pid, dtb } | Resolver a base da tabela de diretórios |
invoke_read | read_invoke { pid, directory_table, address, buffer, size } | Ler memória física |
invoke_write | write_invoke { pid, directory_table, address, buffer, size } | Escrever memória física |
invoke_read_virtual | read_virtual_invoke { pid, address, buffer, size } | Ler memória virtual |
invoke_write_virtual | write_virtual_invoke { pid, address, buffer, size } | Escrever memória virtual |
invoke_allocate | allocate_invoke { pid, type, protection, address, size } | Alocar memória virtual |
invoke_protect | protect_invoke { pid, protection, address, size } | Alterar proteção de memória |
invoke_virtual_query | query_virtual_invoke { pid, address, mbi } | Consultar informações de memória virtual |
invoke_pattern_scan | pattern_invoke { pid, signature, address, pattern_address } | Varredura de padrões na memória |
invoke_move_mouse | mouse_invoke { x, y, flags, button_flags } | Emular entrada de mouse |
O driver itera sobre os intervalos de memória física retornados por MmGetPhysicalMemoryRanges, percorre o banco de dados PFN para localizar a entrada PML4 autorreferenciada e valida cada camada da tabela de páginas para confirmar a base correta da tabela de diretórios para um determinado processo.
A tradução de linear para físico percorre a hierarquia de tabela de páginas x64 de quatro níveis (PML4 → PDPT → PD → PT) com cache por nível. O suporte a páginas grandes (2MB / 1GB) está incluído em caráter de melhor esforço.
O driver localiza os objetos de driver MouClass e MouHID, resolve o MouseClassServiceCallback a partir da extensão de dispositivo HID e injeta pacotes MOUSE_INPUT_DATA diretamente na cadeia de callbacks.
Campos-chave do ETHREAD — horário de criação, endereço de início, endereço de início Win32, pilha do kernel, CID e status de saída — são salvos e substituídos por valores benignos ou nulos. Na desmontagem, os valores originais são restaurados antes do término da thread.
lithium.sln no 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);