** BROUILLON **
Les hooks SSDT en mode noyau n’ont plus le vent en poupe, merci PatchGard :)
Nos éditeurs antivirus et HIPS n’ont plus vraiment le choix (du moins en x64), ils doivent passer par les notifications kernel offertes par Microsoft.
(en revanche rien n’empêche d’implémenter en sus des hooks userland)
- Processus
- Threads
- Images
- Registre
- Fichiers (via minifiltres !
Processus
La mise en place de ces notifications se fait via les méthodes suivantes :
PsSetCreateProcessNotifyRoutine
PsSetCreateProcessNotifyRoutineEx
- Cette routine, seulement disponible en NT6, est plus souple et offre un contrôle avant lancement du processus :
For a new process, the CreateProcessNotifyEx routine is called after the initial thread is created, but before the thread begins running. The driver can cause the process-creation operation to fail by changing the CreateInfo->CreationStatus member to an NTSTATUS error code.
- Cette routine, seulement disponible en NT6, est plus souple et offre un contrôle avant lancement du processus :
Le détachement de la routine de notification se fait par la même méthode que l’attachement : PsSetCreateProcessNotifyRoutine[ex]
, l’on spécifie seulement Remove = TRUE pour le deuxième argument.
Limitation étrange
- NT5 : au maximum 8 callbacks, sous peine de se voir retourner
STATUS_PROCEDURE_NOT_FOUND ; 0xC000007A
PAGE:00597BFE cmp ebx, 8 PAGE:00597C01 jb short loc_597BCF PAGE:00597C03 mov eax, 0C000007Ah
- NT6 : au maximum 64 callbacks, sous peine de se voir retourner
STATUS_PROCEDURE_NOT_FOUND ; 0xC000007A
Cette augmentation est la bienvenue puisque Windows lui même en utilise 6 par défaut, 7 avec MSE…
Retrouvons nos routines dans notre débogueur préféré
Légende :
PspCreateProcessNotifyRoutineCount
; nombre de callbacks créés parPsSetCreateProcessNotifyRoutine
PspCreateProcessNotifyRoutineExCount
; nombre de callbacks créés parPsSetCreateProcessNotifyRoutineEx
PspCreateProcessNotifyRoutine
; tableau de pointeurs des callbacks (avec 3 bits de contrôle), décalé de 4 octets en 32 bits
lkd> dd nt!PspCreateProcessNotifyRoutineCount l1 fffff800`01678184 00000005 lkd> dd nt!PspCreateProcessNotifyRoutineExCount l1 fffff800`01678180 00000001 lkd> dp nt!PspCreateProcessNotifyRoutine l6 fffff800`01677f80 fffff8a0`00004c0f fffff8a0`0024c15f fffff800`01677f90 fffff8a0`0015cbef fffff8a0`000797ff fffff800`01677fa0 fffff8a0`00381c4f fffff8a0`06e0e3df
Regardons de plus près ces callbacks (sortie épurée pour faciliter la compréhension) :
lkd> ln poi(@@(0xfffff8a000004c0f & ~7)) nt!ViCreateProcessCallback = <no type information> lkd> ln poi(@@(0xfffff8a00024c15f & ~7)) ksecdd!KsecCreateProcessNotifyRoutine = <no type information> lkd> ln poi(@@(0xfffff8a00015cbef & ~7)) cng!CngCreateProcessNotifyRoutine = <no type information> lkd> ln poi(@@(0xfffff8a0000797ff & ~7)) tcpip!CreateProcessNotifyRoutineEx = <no type information> lkd> ln poi(@@(0xfffff8a000381c4f & ~7)) CI!I_PEProcessNotify = <no type information> lkd> ln poi(@@(0xfffff8a006e0e3df & ~7)) lkd> lm f a (poi(@@(0xfffff8a006e0e3df & ~7))) start end module name fffff880`034f8000 fffff880`0359e000 peauth \SystemRoot\system32\drivers\peauth.sys
Un petit exemple en 32 bits pour faire apparaitre le décalage de 4 octets du pointeur, et le pilote de MSE / FEP :
lkd> dp nt!PspCreateProcessNotifyRoutine l9 829799a0 87c08ec7 87c5ee5f 87c4db57 88c897c7 829799b0 87db97ef 88c69117 87d13e27 93f4e867 829799c0 97497857 lkd> ln poi(@@(0x87c08ec7 & ~7) + 4) nt!ViCreateProcessCallback = <no type information> lkd> ln poi(@@(0x97497857 & ~7) + 4) lkd> lm f a (poi(@@(0x97497857 & ~7) + 4)) start end module name 947b1000 947d7800 MpFilter \SystemRoot\system32\DRIVERS\MpFilter.sys
Threads
Limitation étrange
Encore une fois…
- NT5 : au maximum 8 callbacks, sous peine de se voir retourner
STATUS_INSUFFICIENT_RESOURCES ; 0xC000009A
- NT6 : au maximum 64 callbacks, sous peine de se voir retourner
STATUS_INSUFFICIENT_RESOURCES ; 0xC000009A
Retrouvons nos routines dans notre débogueur préféré
Légende :
PspCreateThreadNotifyRoutineCount
; nombre de callbacks créés parPsSetCreateThreadNotifyRoutine
PspCreateThreadNotifyRoutine
; tableau de pointeurs des callbacks (avec 3 bits de contrôle), décalé de 4 octets en 32 bits
lkd> dd nt!PspCreateThreadNotifyRoutineCount l1 82979980 00000002 lkd> dp nt!PspCreateThreadNotifyRoutine l2 82979880 87ce05ef 98861407 lkd> ln poi(@@(0x98861407 & ~7) + 4) lkd> lm f a (poi(@@(0x98861407 & ~7) + 4)) start end module name 947b1000 947d7800 MpFilter \SystemRoot\system32\DRIVERS\MpFilter.sys
Images
Limitation étrange
Ils devaient manquer de mémoire chez Microsoft ;)
- NT5 : au maximum 8 callbacks, sous peine de se voir retourner
STATUS_INSUFFICIENT_RESOURCES ; 0xC000009A
- NT6 : au maximum 8 (?) callbacks, sous peine de se voir retourner
STATUS_INSUFFICIENT_RESOURCES ; 0xC000009A
Retrouvons nos routines dans notre débogueur préféré
Légende :
PspLoadImageNotifyRoutineCount
; nombre de callbacks créés parPsSetLoadImageNotifyRoutine
PspLoadImageNotifyRoutine
; tableau de pointeurs des callbacks (avec 3 bits de contrôle), décalé de 4 octets en 32 bits
lkd> dd nt!PspLoadImageNotifyRoutineCount l1 fffff800`01677d40 00000001 lkd> dp nt!PspLoadImageNotifyRoutine l1 fffff800`01677d00 fffff8a0`0006af0f lkd> ln poi(@@(0xfffff8a00006af0f & ~7)) nt!EtwpTraceLoadImage = <no type information>
Registre
Limitation étrange
Microsoft s’est montré un peu plus généreux cette fois ci…
- NT5 : au maximum 100 callbacks, sous peine de se voir retourner
STATUS_INSUFFICIENT_RESOURCES ; 0xC000009A
- NT6 : a priori pas de limitations (?), les callbacks ne sont plus ici stockés dans un tableau statique, mais dans une liste liée dynamique
Retrouvons nos routines dans notre débogueur préféré
Légende :
CmpCallBackCount
; nombre de callbacks créés parCmRegisterCallback(Ex)
, inutile en NT6 ou la liste liée suffit à parcourir les callbacksCmpCallBackVector
; NT5 ; tableau de pointeurs des callbacks (avec 3 bits de contrôle), décalé de 4 octets en 32 bitsCallbackListHead
; NT6 ; liste liée de structure des callbacks
Les callbacks créés sont identifiés par un cookie, et pour NT6 disposent d’une altitude.
NT5
lkd> dd nt!CmpCallBackCount l1 809d8000 00000001 lkd> dp nt!CmpCallBackVector l1 809d8008 e2317b9f lkd> lm f a (poi(@@(0xe2317b9f& ~7) + 4)) start end module name f5b04000 f5b0fc00 PROCMON20 \??\C:\WINDOWS\system32\Drivers\PROCMON20.SYS lkd> dq (poi(@@(0xe2317b9f& ~7) + 8)) l1 e2dc0930 01ccc33c`b6b63089
NT6
lkd> dd nt!CmpCallBackCount l1 fffff800`02e57ae4 00000002 lkd> x nt!CallbackListHead fffff800`02ecc910 nt!CallbackListHead = <no type information> lkd> dt nt!_LIST_ENTRY 0xfffff800`02ecc910 [ 0xfffff8a0`02808080 - 0xfffff8a0`05d750d0 ] +0x000 Flink : 0xfffff8a0`02808080 _LIST_ENTRY [ 0xfffff8a0`05d750d0 - 0xfffff800`02ecc910 ] +0x008 Blink : 0xfffff8a0`05d750d0 _LIST_ENTRY [ 0xfffff800`02ecc910 - 0xfffff8a0`02808080 ] lkd> dq 0xfffff8a0`02808080 l8 fffff8a0`02808080 fffff8a0`05d750d0 fffff800`02ecc910 fffff8a0`02808090 10000000`00000000 01ccc334`922c6342 fffff8a0`028080a0 00000000`00000000 fffff880`0450e9b8 fffff8a0`028080b0 fffff8a0`000c000c fffff8a0`01a3d220 lkd> lm f a (poi(0xfffff8a0`02808080+0x28)) start end module name fffff880`044f3000 fffff880`04524000 MpFilter \SystemRoot\system32\DRIVERS\MpFilter.sys lkd> !ustr 0xfffff8a0`02808080+0x30 String(12,12) at fffff8a0028080b0: 425000 lkd> dq 0xfffff8a0`02808080+0x18 l1 fffff8a0`02808098 01ccc334`922c6342 lkd> dq 0xfffff8a0`05d750d0 l8 fffff8a0`05d750d0 fffff800`02ecc910 fffff8a0`02808080 fffff8a0`05d750e0 42424242`00000000 01ccc334`922c6343 fffff8a0`05d750f0 00000000`00000000 fffff880`071d69d0 fffff8a0`05d75100 42424242`000c000c fffff8a0`056a5cf0 lkd> lm f a (poi(0xfffff8a0`05d750d0+0x28)) start end module name fffff880`071d0000 fffff880`071e4000 PROCMON20 \??\C:\Windows\system32\Drivers\PROCMON20.SYS lkd> !ustr 0xfffff8a0`05d750d0+0x30 String(12,12) at fffff8a005d75100: 425000 lkd> dq 0xfffff8a0`05d750d0+0x18 l1 fffff8a0`05d750e8 01ccc334`922c6343
** BROUILLON **
Fichier
(vous pourrez par ailleurs trouver sur le site WHDC de Microsoft les altitudes alloués par Microsoft à différents produits…)