Encontrando funções no Windows com WinDbg — Parte 1
Introdução
Antes de desenvolver qualquer driver ou técnica de hooking, precisamos entender como encontrar e analisar funções do sistema Windows. Neste post, vou compartilhar minha experiência usando o WinDbg para localizar e estudar funções do kernel.
⚠️ Aviso: Este conteúdo é exclusivamente educacional. Use apenas em ambientes controlados (VMs) e para fins de aprendizado.
Primeiro Passo: Entendendo a Função que Vamos Analisar
Antes de desenvolver qualquer driver, precisamos entender algumas coisas sobre as funções que vamos interceptar. Para isso, precisamos ter o WinDbg instalado e configurado para kernel debugging.
Configurando o WinDbg
- Abra o WinDbg
- Vá em File → Kernel Debug
- Configure a conexão (Serial, USB, ou Network)
Encontrando o Processo Explorer
Agora vamos localizar o processo explorer.exe para entender como o sistema funciona:
!process 0 0 explorer.exe

Este comando lista informações sobre o processo explorer.exe. Como você pode ver na imagem acima, ele retorna detalhes importantes como:
- SessionId: ID da sessão
- Cid: Process ID (PID)
- Peb: Endereço do Process Environment Block
- DirBase: Diretório base
- Image: Nome da imagem (explorer.exe)
Recarregando o Módulo dxgkrnl.sys
Agora vamos recarregar o módulo dxgkrnl.sys para garantir que temos os símbolos atualizados:
.reload /f dxgkrnl.sys
Este comando força o reload do driver dxgkrnl.sys (DirectX Graphics Kernel), atualizando os símbolos e endereços na memória.
Abrindo o Disassembler
Agora vem a parte interessante! Vamos abrir o Disassembler no WinDbg:
- Vá em View → Disassembly
- Digite o nome da função:
NtOpenCompositionSurfaceSectionInfo
Aqui começa a brincadeira! Esta é a função que estamos analisando.

Como a Função Está Antes do Hook
Como você pode ver na imagem acima, esta é exatamente como a função NtOpenCompositionSurfaceSectionInfo está antes de aplicarmos qualquer modificação.
Observando o código assembly, vemos que a função original é bem simples:
mov rax, rsp- Move o valor do ponteiro da stack (RSP) para o registrador RAXret- Retorna da função
Importante: Na imagem você pode ver que 48 8b c4 está destacado - esses são 3 bytes do código original. Isso é perfeito para nosso hook, pois precisamos de 12 bytes no total: 2 bytes para o mov rax, 8 bytes para o endereço que vamos hookar, e 2 bytes para voltar. Essa função tem espaço suficiente para nossa técnica funcionar.
Esta é a função “limpa” que vamos analisar. Ná print abaixo, quando aplicarmos modificações, esses primeiros bytes serão substituídos pelo nosso código:

Após Fazer o Hook
Agora que entendemos como a função está antes do hook, vamos ver exatamente o que vamos colocar no lugar dos bytes originais:
48 B8 [endereço de 64 bits] FF E0
│ │ └─────────┬─────────┘ │ │
│ │ │ │ └─> JMP RAX
└─ └─────────────┴─────────────┴───> MOV RAX, <endereço>
Detalhamento:
- 48 B8: Opcode para
MOV RAX, imm64 - [8 bytes]: Endereço da nossa função
- FF E0: Opcode para
JMP RAX
Este shellcode de 12 bytes substituirá os primeiros bytes da função original, fazendo com que qualquer chamada para NtOpenCompositionSurfaceSectionInfo seja redirecionada para nossa função personalizada.
Outras Funções Disponíveis
Podemos procurar mais funções e encontrei esse site excelente: https://j00ru.vexillium.org/syscalls/win32k/64/
Este site contém uma tabela completa de todas as system calls do Windows, incluindo as funções do win32k.sys. A gente só precisa analisar uma função e trocar no driver/usermode.
Algumas anotações pessoais:
- Funções com nome de “composition” nelas são boas para hook
- Funções
NtOpen*geralmente funcionam bem - Evite funções
NtD*(podem não funcionar)
⚠️ Dica importante: Algumas funções têm proteções ou usam secure cookie / regiões críticas. Evite modificar/alterar código em regiões marcadas como críticas até entender o comportamento.
Experiência pessoal: Muitas telas azuis nos meus testes! 😅 Sempre teste em VM com snapshots!
Conceitos Importantes
1. Assembly x64
| Instrução | Opcode | Descrição |
|---|---|---|
MOV RAX, imm64 | 48 B8 | Move valor para RAX |
JMP RAX | FF E0 | Pula para endereço em RAX |
XOR EAX, EAX | 33 C0 | Zera EAX |
RET | C3 | Retorna da função |
Próximos Passos
Agora que sabemos como encontrar e analisar funções, podemos:
- Desenvolver o driver que vai interceptar essas funções
- Implementar o function hook para redirecionar chamadas
- Criar comunicação entre kernel e usermode
- Testar e debugar nossa implementação
Próximo post: Desenvolvendo driver para hooking de funções — Parte 2