Detect Hidden Processes – KiWaitListHead

Mon précédent article finissait sur un échec mais grâce à Ivanlef0u je peux continuer :) . Heureusement puisque la première technique que je présentais dans cet article, technique qui m’avais pris plusieurs heures à mettre en place, n’a pas résisté plus de 10 minutes à Overclok :( .
Nous nous étions arrêté à la récupération d’un pointeur sur la table KiWaitListHead après avoir scanné la fonction KeWaitForSingleObject() exportée par ntoskrnl.exe.
Mon problème était de savoir par quelles structures était composée cette table. Je n’est pas la réponse exacte mais j’ai pu recueillir les infos nécessaire ici

On peut imaginer cette structure de cette façon :



offset : x-0×60 PETHREAD Thread

offset : x LIST_ENTRY KiWaitListHead


Pour certaines version de windows autres que XP l’offset de Thread sera x-0×70 d’après le liens ci-dessus.
La table KiWaitListHead est donc une liste double-chainée de structures décrivant les threads et contenant un pointeur vers la structure ETHREAD du thread courant. On va donc pouvoir lister nos threads en parcourant cette table, ce qui confirme ce que je supposais dans mon article précédent :)

Une fois la structure ETHREAD récupérée il nous est facile de remonter au processus par le biais de l’EPROCESS. Voici à quoi ressemble l’ETHREAD :


+0×000 Tcb : _KTHREAD
+0×1c0 CreateTime : _LARGE_INTEGER
+0×1c0 NestedFaultCount : Pos 0, 2 Bits
+0×1c0 ApcNeeded : Pos 2, 1 Bit
+0×1c8 ExitTime : _LARGE_INTEGER
+0×1c8 LpcReplyChain : _LIST_ENTRY
+0×1c8 KeyedWaitChain : _LIST_ENTRY
+0×1d0 ExitStatus : Int4B
+0×1d0 OfsChain : Ptr32 Void
+0×1d4 PostBlockList : _LIST_ENTRY
+0×1dc TerminationPort : Ptr32 _TERMINATION_PORT
+0×1dc ReaperLink : Ptr32 _ETHREAD
+0×1dc KeyedWaitValue : Ptr32 Void
+0×1e0 ActiveTimerListLock : Uint4B
+0×1e4 ActiveTimerListHead : _LIST_ENTRY
+0×1ec Cid : _CLIENT_ID
+0×1f4 LpcReplySemaphore : _KSEMAPHORE
+0×1f4 KeyedWaitSemaphore : _KSEMAPHORE
+0×208 LpcReplyMessage : Ptr32 Void
+0×208 LpcWaitingOnPort : Ptr32 Void
+0×20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION
+0×210 IrpList : _LIST_ENTRY
+0×218 TopLevelIrp : Uint4B
+0×21c DeviceToVerify : Ptr32 _DEVICE_OBJECT
+0×220 ThreadsProcess : Ptr32 _EPROCESS
+0×224 StartAddress : Ptr32 Void
+0×228 Win32StartAddress : Ptr32 Void
+0×228 LpcReceivedMessageId : Uint4B
+0×22c ThreadListEntry : _LIST_ENTRY
+0×234 RundownProtect : _EX_RUNDOWN_REF
+0×238 ThreadLock : _EX_PUSH_LOCK
+0×23c LpcReplyMessageId : Uint4B
+0×240 ReadClusterSize : Uint4B
+0×244 GrantedAccess : Uint4B
+0×248 CrossThreadFlags : Uint4B
+0×248 Terminated : Pos 0, 1 Bit
+0×248 DeadThread : Pos 1, 1 Bit
+0×248 HideFromDebugger : Pos 2, 1 Bit
+0×248 ActiveImpersonationInfo : Pos 3, 1 Bit
+0×248 SystemThread : Pos 4, 1 Bit
+0×248 HardErrorsAreDisabled : Pos 5, 1 Bit
+0×248 BreakOnTermination : Pos 6, 1 Bit
+0×248 SkipCreationMsg : Pos 7, 1 Bit
+0×248 SkipTerminationMsg : Pos 8, 1 Bit
+0×24c SameThreadPassiveFlags : Uint4B
+0×24c ActiveExWorker : Pos 0, 1 Bit
+0×24c ExWorkerCanWaitUser : Pos 1, 1 Bit
+0×24c MemoryMaker : Pos 2, 1 Bit
+0×250 SameThreadApcFlags : Uint4B
+0×250 LpcReceivedMsgIdValid : Pos 0, 1 Bit
+0×250 LpcExitThreadCalled : Pos 1, 1 Bit
+0×250 AddressSpaceOwner : Pos 2, 1 Bit
+0×254 ForwardClusterOnly : UChar
+0×255 DisablePageFaultClustering : UChar

Et le membre qui nous intéresse :
+0×220 ThreadsProcess : Ptr32 _EPROCESS

Maintenant je pense que l’unlink de la table KiWaitListHead est possible, j’attends que Overclok s’en charge.
Cependant le paper sur lequel je me suis appuyé parle d’une autre table, la KiDispatcherReadListHead que je tenterais d’explorer dans un prochain article. Donc je vous laisse sur le mot de la fin :
A suivre…

Le code + binaire ici

Remerciements à Overclok et Ivanlef0u qui nous surveille :)

Lilxam.

Les commentaires sont fermés