dimanche 28 septembre 2008

L'Union Fait la Force.

Voici une archive contenant deux articles qui sont le résultats d'un travail en commun avec Overclok, le fruit d'une entraide conséquente à renouveler puisque plutôt efficace :). En effet depuis quelques temps nous travaillons sur deux sujets : les buffer overflows sous php et les TLS Callbacks.
0vercl0k nous a mijoté une jolie classe toute propre pour gérer l'implémentation de TLS Callbacks le tout en expliquant le fonctionnement de ceux-ci.
Il met en pratique le tout en montrant comment détecter un debugger avant même que celui-ci n'est eu le temps de breaker l'entry point.
Il continue avec un exemple d'HotPatching reprennant le principe de l'inline hooking. Encore un sujet que mon camarade mène avec brio en montrant comment rendre très discret un anti-debugger qui ne l'est pas.
Tout ceci étant bien évidemment accompagné de codes, screenshots, schémas, dumps et explications.
Je ne vous en dis pas plus, à vous de découvrir la suite :).
Pour ma part j'aborde les buffers overflows sous php. Je débute en créant un fuzzer me permettant de trouver des fonctions faillibles. Au total 8 sont détectées. J'entame alors une analyse de PHP.exe pour essayer de localise les failles ainsi que de comprendre pourquoi celles-ci ont lieu d'être. L'exploitation est basée sur la réécriture de SEH et aboutie à deux exploits, l'un pour PHP 5.x et l'autre pour Apache 2.x.

Je vous souhaite donc une bonne lecture.
A bientôt.

L'archive est disponible ici.

Les codes/exploits/binaires de mon paper sont également dispo ici.

Un petit coucou à Freespirit qui revient parmi nous :).

samedi 6 septembre 2008

List Hidden Pocesses suite... (KiWaitListHead method)

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-0x60 PETHREAD Thread
...
offset : x LIST_ENTRY KiWaitListHead
...

Pour certaines version de windows autres que XP l'offset de Thread sera x-0x70 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 :


+0x000 Tcb : _KTHREAD
+0x1c0 CreateTime : _LARGE_INTEGER
+0x1c0 NestedFaultCount : Pos 0, 2 Bits
+0x1c0 ApcNeeded : Pos 2, 1 Bit
+0x1c8 ExitTime : _LARGE_INTEGER
+0x1c8 LpcReplyChain : _LIST_ENTRY
+0x1c8 KeyedWaitChain : _LIST_ENTRY
+0x1d0 ExitStatus : Int4B
+0x1d0 OfsChain : Ptr32 Void
+0x1d4 PostBlockList : _LIST_ENTRY
+0x1dc TerminationPort : Ptr32 _TERMINATION_PORT
+0x1dc ReaperLink : Ptr32 _ETHREAD
+0x1dc KeyedWaitValue : Ptr32 Void
+0x1e0 ActiveTimerListLock : Uint4B
+0x1e4 ActiveTimerListHead : _LIST_ENTRY
+0x1ec Cid : _CLIENT_ID
+0x1f4 LpcReplySemaphore : _KSEMAPHORE
+0x1f4 KeyedWaitSemaphore : _KSEMAPHORE
+0x208 LpcReplyMessage : Ptr32 Void
+0x208 LpcWaitingOnPort : Ptr32 Void
+0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION
+0x210 IrpList : _LIST_ENTRY
+0x218 TopLevelIrp : Uint4B
+0x21c DeviceToVerify : Ptr32 _DEVICE_OBJECT
+0x220 ThreadsProcess : Ptr32 _EPROCESS
+0x224 StartAddress : Ptr32 Void
+0x228 Win32StartAddress : Ptr32 Void
+0x228 LpcReceivedMessageId : Uint4B
+0x22c ThreadListEntry : _LIST_ENTRY
+0x234 RundownProtect : _EX_RUNDOWN_REF
+0x238 ThreadLock : _EX_PUSH_LOCK
+0x23c LpcReplyMessageId : Uint4B
+0x240 ReadClusterSize : Uint4B
+0x244 GrantedAccess : Uint4B
+0x248 CrossThreadFlags : Uint4B
+0x248 Terminated : Pos 0, 1 Bit
+0x248 DeadThread : Pos 1, 1 Bit
+0x248 HideFromDebugger : Pos 2, 1 Bit
+0x248 ActiveImpersonationInfo : Pos 3, 1 Bit
+0x248 SystemThread : Pos 4, 1 Bit
+0x248 HardErrorsAreDisabled : Pos 5, 1 Bit
+0x248 BreakOnTermination : Pos 6, 1 Bit
+0x248 SkipCreationMsg : Pos 7, 1 Bit
+0x248 SkipTerminationMsg : Pos 8, 1 Bit
+0x24c SameThreadPassiveFlags : Uint4B
+0x24c ActiveExWorker : Pos 0, 1 Bit
+0x24c ExWorkerCanWaitUser : Pos 1, 1 Bit
+0x24c MemoryMaker : Pos 2, 1 Bit
+0x250 SameThreadApcFlags : Uint4B
+0x250 LpcReceivedMsgIdValid : Pos 0, 1 Bit
+0x250 LpcExitThreadCalled : Pos 1, 1 Bit
+0x250 AddressSpaceOwner : Pos 2, 1 Bit
+0x254 ForwardClusterOnly : UChar
+0x255 DisablePageFaultClustering : UChar



Et le membre qui nous intéresse :
+0x220 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.

Overclok owned :p - List Hidden Processes

Bonjour/Bonsoir,
nouvelle couleur (oui je sais j'ai un peu fais n'importe quoi, je m'amuse ^^), nouveau départ. En effet voilà bien longtemps que je n'avais pas posté ici, et je me vois obligé de laisser un petit post en réponse à celui d'Overclok, je cite : "How to pwn lilxam's toolz :)". Ce post faisant lui-même référence à mon article " Listing all processes". Bref revoyons un peu tout ça :
-Ivanlef0u puis Overclok s'amuse à cacher des processus à "unlinkant" les structure EPROCESS de ces processus de la table PsActiveProcessList.
-Me viens alors l'idée de trouver un moyen de retrouver ces processus cachés, je met alors en place un Brute Force sur les ID des processus en testant leur existence via OpenProcess(). Rien de bien élégant mais ceci à le mérite de fonctionner.
-Overclok viens alors à présenter 2 autres techniques pour cacher des processus. La première étant l'unlink de la PspCidTable, technique qui met en échec mon précédent tool puisque la fonction OpenProcess() se sert de la table PspCidTable. La seconde est l'unlink d'une structure dans csrss.exe. Ce processus étant un sorte de "sous-système", il a un handle ouvert sur tous les processus. On aurait donc pu lister les processus en récupérant tous les handles ouvert par csrss.exe.

Mon problème alors est d'arriver à lister tous les processus mêmes cachés avec les trois techniques précédentes.

The HandleTableList



Au cours de ma recherche je me suis beaucoup penché sur les handles et l'Object Manager jusqu'à apprendre l'existence d'une table appelé ObjectTable contenue dans chaque processus contenant les handles ouverts par celui-ci. Ces tables sont de type HANDLE_TABLE :


kd> dt nt!_HANDLE_TABLE
+0x000 TableCode : Uint4B
+0x004 QuotaProcess : Ptr32 _EPROCESS
+0x008 UniqueProcessId : Ptr32 Void
+0x00c HandleTableLock : [4] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : Ptr32 _HANDLE_TRACE_DEBUG_INFO
+0x02c ExtraInfoPages : Int4B
+0x030 FirstFree : Uint4B
+0x034 LastFree : Uint4B
+0x038 NextHandleNeedingPool : Uint4B
+0x03c HandleCount : Int4B
+0x040 Flags : Uint4B
+0x040 StrictFIFO : Pos 0, 1 Bit



A noter le pointeur sur la structure EPROCESS en +0x04 et le pointeur sur l'ID du processus en +0x08. Mieux encore, les HANDLE_TABLE des processus forment une liste double-chainée. On note en effet le membre de la structure HandleTableList qui est de type LIST_ENTRY :

kd> dt nt!_LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY


On peut accéder à l'ObjectTable d'un processus par le biais de la structure EPROCESS :

kd> dt nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER
+0x078 ExitTime : _LARGE_INTEGER
+0x080 RundownProtect : _EX_RUNDOWN_REF
+0x084 UniqueProcessId : Ptr32 Void
+0x088 ActiveProcessLinks : _LIST_ENTRY
+0x090 QuotaUsage : [3] Uint4B
+0x09c QuotaPeak : [3] Uint4B
+0x0a8 CommitCharge : Uint4B
+0x0ac PeakVirtualSize : Uint4B
+0x0b0 VirtualSize : Uint4B
+0x0b4 SessionProcessLinks : _LIST_ENTRY
+0x0bc DebugPort : Ptr32 Void
+0x0c0 ExceptionPort : Ptr32 Void
+0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE
...


En +0x0C4 se trouve un pointeur sur notre ObjectTable.
Voici alors les étapes qu'il nous faudrait suivre :
1. Récupérer l'EPROCESS courante ou d'un processus connu.
2. Récupérer un pointeur sur l'ObjectTable.
3. Parcourir la liste chainée des ObjectTable de chaque processus.
4. A chaque ObjectTable récupérer l'ID du processus ainsi qu'un pointeur sur l'EPROCESS.
5. Récupérer le nom du processus grâce à cette dernière (+0x174 ImageFileName : [16] UChar).

Cependant j'ai pensé affirmer un peu vite que les ObjectTable forment une liste chainée. J'ai alors voulu vérifier ceci avant de me mettre à coder ce driver (/me redoute encore le r0), c'est possible avec windbg :

Etape 1 :

kd> !process csrss.exe
PROCESS 80558e80 SessionId: none Cid: 0000 Peb: 00000000 ParentCid: 0000
DirBase: 00039000 ObjectTable: e1001cd8 HandleCount: 173.
Image: Idle
VadRoot 00000000 Vads 0 Clone 0 Private 0. Modified 0. Locked 0.
...


Avec cette commande on peut obtenir un pointeur sur l'EPROCESS à l'adresse 0x80558e80 (et même sur l'ObjectTable mais on va faire comme ci on avait pas vu, pour suivre nos étapes).

Voyons ensuite à quoi ressemble l'EPROCESS de csrss.exe :

kd> dt nt!_EPROCESS 80558e80
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER 0x0
+0x078 ExitTime : _LARGE_INTEGER 0x0
+0x080 RundownProtect : _EX_RUNDOWN_REF
+0x084 UniqueProcessId : (null)
+0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x090 QuotaUsage : [3] 0
+0x09c QuotaPeak : [3] 0
+0x0a8 CommitCharge : 0
+0x0ac PeakVirtualSize : 0
+0x0b0 VirtualSize : 0
+0x0b4 SessionProcessLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x0bc DebugPort : (null)
+0x0c0 ExceptionPort : (null)
+0x0c4 ObjectTable : 0xe1001cd8 _HANDLE_TABLE
...


Etape 2:
On peut alors récupérer un pointeur sur l'objectTable comme prévu à l'adesse 0xe1001cd8.

Voyons à quoi celli-ci ressemble :

kd> dt nt!_HANDLE_TABLE e1001cd8
+0x000 TableCode : 0xe1002000
+0x004 QuotaProcess : (null)
+0x008 UniqueProcessId : 0x00000004
+0x00c HandleTableLock : [4] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY [ 0xe10065d4 - 0x805617c8 ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : (null)
+0x02c ExtraInfoPages : 0
+0x030 FirstFree : 0x520
+0x034 LastFree : 0
+0x038 NextHandleNeedingPool : 0x800
+0x03c HandleCount : 173
+0x040 Flags : 0
+0x040 StrictFIFO : 0y0


Etape 3 :
On se penche ensuite sur l'HanldeTableList :


kd> dt nt!_LIST_ENTRY e1001cd8+0x01c
[ 0xe10065d4 - 0x805617c8 ]
+0x000 Flink : 0xe10065d4 _LIST_ENTRY [ 0xe13d66fc - 0xe1001cf4 ]
+0x004 Blink : 0x805617c8 _LIST_ENTRY [ 0xe1001cf4 - 0xe1661d9c ]


On a en théorie un pointeur sur l'HandleTableList précédente et suivante.
Récupérons la suivante :

kd> dt nt!_LIST_ENTRY 0xe10065d4
[ 0xe13d66fc - 0xe1001cf4 ]
+0x000 Flink : 0xe13d66fc _LIST_ENTRY [ 0xe13c7fd4 - 0xe10065d4 ]
+0x004 Blink : 0xe1001cf4 _LIST_ENTRY [ 0xe10065d4 - 0x805617c8 ]


Etape 4:
Tout semble correct pour l'instant, tentons alors de récupérer l'ObjectTable :

kd> dt nt!_HANDLE_TABLE e10065d4-0x01c
+0x000 TableCode : 0xe128e000
+0x004 QuotaProcess : 0x8163d1a0 _EPROCESS
+0x008 UniqueProcessId : 0x000001ac
+0x00c HandleTableLock : [4] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY [ 0xe13d66fc - 0xe1001cf4 ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : (null)
+0x02c ExtraInfoPages : 0
+0x030 FirstFree : 0x54
+0x034 LastFree : 0
+0x038 NextHandleNeedingPool : 0x800
+0x03c HandleCount : 19
+0x040 Flags : 0
+0x040 StrictFIFO : 0y0


Tout à l'air bon, le PID de ce processus est 0x1ac.

Etape 5 :

Voyons à qui il appartient :

kd> dt nt!_EPROCESS 0x8163d1a0
...
+0x084 UniqueProcessId : 0x000001ac
...
+0x174 ImageFileName : [16] "smss.exe"


Oh mais que voyons ? Il s'agit bien d'un processus :))). Notre hypothèse était donc bonne :).
Et bien voilà pour cette technique, pour le code je vous envoi à la fin de l'article.
Voici un petit exemple de ce que ça donne, ayant caché au préalable calc.exe avec le driver d'Overclok :


Lilxam driver OK

Process : System

Process : smss.exe

Object Table : 0xe145e178

--- PID : 0x370

--- PPEPROCESS : 0xe145e17c

--- PEPROCESS : 0x86071980

--- Name : csrss.exe

Object Table : 0xe1014bb0

--- PID : 0x33c

--- PPEPROCESS : 0xe1014bb4

--- PEPROCESS : 0x860754b8

--- Name : smss.exe

Object Table : 0xe1003ec8

--- PID : 0x4

--- PPEPROCESS : 0xe1003ecc

--- PEPROCESS : 0x0

Object Table : 0x80564b8c

--- PID : 0x0

--- PPEPROCESS : 0x80564b90

--- PEPROCESS : 0x0

Object Table : 0xe134ed10 <---- :))))

--- PID : 0x260

--- PPEPROCESS : 0xe134ed14

--- PEPROCESS : 0x85706a78

--- Name : calc.exe

...

End



Malheureusement cette technique est facilement bypassable et Overclok me l'a déjà prouvé :(. En revanche rkUnhooker arrive encore à trouver le processus d'Overclok...
J'ai alors encore un petite hypothèse que je n'est pas réussi à mettre en place.


Getting list of threads ???




Dans son article, Overclok se pose plusieurs question après avec tenté l'unlink de la structure ETHREAD, je cite :

"
- Comment RkUnhooker remet la main sur mon processus ?
- Quel(s) technique(s) utilise t-il pour cela ?
- Existe t-il un autre endroit où une liste des processus lancées sur le système est disponible ?
"

Mes recherches et mes tentatives mon alors amené sur une table, appelé KiWaitListHead sous XP qui, à ce qui ce dirait, permettrait d'obtenir une liste des threads.
Alors voyons comment trouver cette liste. Après quelques recherches j'apprends que cette table est utilisée par la fonction KeWaitForSingleObject. Un petit disass avec IDA, j'ai préféré l'utilisé à windbg pour pouvoir voir tous les jumps facilement car celui-ci m'a trompé pendant un moment, et on trouve :

loc_40DE4F:
mov ecx, ds:dword_48226C
lea eax, [esi+60h]
mov dword ptr [eax], offset _KiWaitListHead
mov [eax+4], ecx
mov [ecx], eax
mov ds:dword_48226C, eax
jmp loc_40513E


+0x8CB8 mov dword ptr [eax], offset _KiWaitListHead



On va donc scanner cette fonction et on pourra récupérer un pointeur sur la table :).
Mais voilà, une fois la table récupérée je ne sais plus quoi en faire, je n'arrive pas à reconstituer les structures :(.
Donc voilà j'en appelle à vous, peut-être avez-vous une idée ?
A suivre...

Je vous propose donc seulement le code pour récupérer un pointeur sur KiWaitListHead.

Les codes sont dispo ici


Merci à Overclok pour cette petite aventure bien sympatique, peut-être n'est-elle pas finie ;).

Lilxam.