dimanche 19 juillet 2009

Demenagement.

Comme le titre du post l'indique, j'ai décidé de quitter blogspot ; en effet j'ai eu de très nombreux problèmes de mise en page lors de la rédaction de mes articles, a tel point que la rédaction devenait insupportable.
Résultat, j'ai fais une demande d'hébergement chez tuxfamily ou j'ai installé un Wordpress.
Au final, le nouveau blog me plait, sobre/sombre/sérieux, je continuerais donc mes publications sur celui-ci :
http://0vercl0k.tuxfamily.org/bl0g/

Mettez à jour vos RSS ;).
A la prochaine o/.

mardi 19 mai 2009

Understand phook's internals.

Je me décide finalement à publier un petit quelque chose, malgré tous le taff que les études peuvent me demander en ce moment :).

Entrons dans le vif du sujet, "phook" est le nom donné à un PoC réalisé par Shearer and Dreg concernant une technique de hook peu commune, je dirais même nouvelle.
Un paper à d'ailleurs été publié dans la dernière issues de phrack (65).
Après sa lecture, la mise en place de la technique reste assez floue, je decide donc de partager mon PoC (même pas complet !) ; celui-ci m'a permis de me rendre compte qu'au final la technique est loin d'être parfaite et imprenable.

Pour situer le sujet, les auteurs nous propose de combiner de "l'iat patching", avec leur nouvel technique donc, pour nous assurer un total contrôle des apis.
La nouveauté dans tout cela, c'est qu'avec une simple modification de la table des importations d'un binaire, nous allons contrôler seulement les appels "statiques", ceux qui ne seront pas résolus dynamiquement.
En effet, si dans le cadre d'un hook d'iat nous retrouvons nos fonctions dynamiquement en utilisant GetModuleHandle et GetProcAddress et bien la technique devient inutile.

Nos deux compères nous proposent alors un périple dans le PEB, pour être plus précis, ils nous proposent de falsifier les champs DllBase, EntryPoint et SizeOfImage des structures LDR_DATA_TABLE_ENTRY pointé par chaque entrée de la liste doublement chainée PEB.Ldr.InLoadOrderModuleList.
Voici sa structure :

lkd> dt nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x008 InMemoryOrderLinks : _LIST_ENTRY
+0x010 InInitializationOrderLinks : _LIST_ENTRY
+0x018 DllBase : Ptr32 Void
+0x01c EntryPoint : Ptr32 Void
+0x020 SizeOfImage : Uint4B
+0x024 FullDllName : _UNICODE_STRING
+0x02c BaseDllName : _UNICODE_STRING
+0x034 Flags : Uint4B
+0x038 LoadCount : Uint2B
+0x03a TlsIndex : Uint2B
+0x03c HashLinks : _LIST_ENTRY
+0x03c SectionPointer : Ptr32 Void
+0x040 CheckSum : Uint4B
+0x044 TimeDateStamp : Uint4B
+0x044 LoadedImports : Ptr32 Void
+0x048 EntryPointActivationContext : Ptr32 Void
+0x04c PatchInformation : Ptr32 Void

Pour rappel, cette liste stocke les modules chargés par un binaire dans l'ordre de chargement en mémoire, on est donc censé trouvé en premier lieu ntdll.dll bien sur suivit de kernel32.dll etc :

kd> !process 0 0 calc.exe
PROCESS 814ad740 SessionId: 0 Cid: 01a4 Peb: 7ffdb000 ParentCid: 05bc
DirBase: 0d88d000 ObjectTable: e15ccbc0 HandleCount: 37.
Image: calc.exe

kd> .process 814ad740
Implicit process is now 814ad740
WARNING: .cache forcedecodeuser is not enabled
kd> !peb
PEB at 7ffdb000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: No
ImageBaseAddress: 01000000
Ldr 001a1e90
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 001a1f28 . 001a2d18
Ldr.InLoadOrderModuleList: 001a1ec0 . 001a2d08
Ldr.InMemoryOrderModuleList: 001a1ec8 . 001a2d10
Base TimeStamp Module
1000000 3b7d8410 Aug 17 22:52:32 2001 C:\WINDOWS\system32\calc.exe
7c910000 4125331a Aug 20 01:09:14 2004 C:\WINDOWS\system32\ntdll.dll
7c800000 4623a01c Apr 16 18:11:08 2007 C:\WINDOWS\system32\kernel32.dll
7c9d0000 4125330f Aug 20 01:09:03 2004 C:\WINDOWS\system32\SHELL32.dll
77be0000 45d97cd4 Feb 19 11:32:52 2007 C:\WINDOWS\system32\msvcrt.dll
77ef0000 45f030c5 Mar 08 16:50:29 2007 C:\WINDOWS\system32\GDI32.dll
7e390000 45f030c6 Mar 08 16:50:30 2007 C:\WINDOWS\system32\USER32.dll
77da0000 412532e8 Aug 20 01:08:24 2004 C:\WINDOWS\system32\ADVAPI32.dll
[...]

Pour comprendre le principe même de la technique, il faut savoir que l'api GetModuleHandle par exemple, va parser cette liste afin de récupérer l'image base d'une dll par exemple.
Imaginer que l'on echange le champs DllBase de la dll kernel32.dll, avec une dll factice ; et bien un GetModuleHandle("kernel32.dll") nous renverrais l'image base de notre dll factice !
C'est en fait le coeur de la technique, car celle-ci nécessite quelques pré-requis pour sa mise en place.

Notre dll devra donc répondre à quelques exigences, en effet elle devra exporter le même nombre de fonctions que la dll original, avec les mêmes noms de fonctions, ainsi que les mêmes ordinaux.
Le premier problème auquel on est confronté, c'est alors de créer une dll qui exporte les mêmes noms de fonctions que kernel32.dll par exemple, en effet si l'on veut créer une exportation pour GetModuleHandle (par exemple), et bien, bien sur le compilateur nous crie dessus étant donné que cette fonction est déjà définie/déclarée dans les headers windows.

Nos amis utilisent alors des fichiers de définitions (.def) à lier au binaire lors de l'édition des liens (avec mingw c'est l'option --def, et avec vc c'est /DEF:).
Par exemple, pour exporter GetModuleHandleA, nous définirons/déclarerons la fonction comme suit :

DLLEXPORT void GetModuleHandleA_()
{
//do the stuff
}


Et notre fichier de définitions sera comme cela :

LIBRARY kernel32
EXPORTS

GetModuleHandleA=GetModuleHandleA_ @ 29


Ou 29 est l'ordinal d'exportation !

Vous devez commencer à comprendre que notre dll, va être ni plus ni moins qu'une espèce de proxy entre le binaire, et la véritable dll ; cependant si l'appel nous intéresse nous le ré-définirons à notre guise, et nous appellerons l'api originel, à la manière d'un hook donc.

Le second problème, est alors de retrouver l'adresse de cette api originel, pour cela nous utiliserons une macro qui grosso-modo réalisera :

GetProcAddress(GetModuleHandleA("kernel32_.dll"), "NotreApi")

Ou kernel32_.dll est le nom de NOTRE dll, car si vous reflechissez 30 secondes, une fois que le PEB hook aura été réalisé, et bien les images bases auront été echangées ; or il nous faut récupérer l'image base de la véritable dll, ce qui sera donc obtenu avec GetModuleHandleA("Kernel32_.dll") .
La macro proposée par les auteurs est la suivante :

unsigned long tmp;

#define JMP( lib, func ) \
__asm \
( "pushad \n" \
" push edx \n" \
" push %1 \n" \
" call eax \n" \
" pop edx \n" \
" push %2 \n" \
" push eax \n" \
" call edx \n" \
" mov %4, eax \n" \
" popad \n" \
\
: : \
"a" (GetModuleHandle) , \
"g" (lib) , \
"g" (func) , \
"d" (GetProcAddress) , \
"g" (tmp) \
); \
asm ( "jmp %0" : : "g" (tmp) );


Je vous l'accorde ça pique les yeux, c'est très moche, mais ça compile avec mingw (avec l'option de compilation -masm=intel) c'est pour cela que je n'ai pas transposé cette macro à coup de _asm compilable seulement avec vcpp.
La macro réalise donc une sauvegarde des registres avec un pushad/popad afin de préserver l'environnement dont nécessite l'api, nous stockons l'adresse de la véritable api dans une variable, et enfin nous sautons sur l'api.

Cette dernière étape soulève un problème un peu plus important, celui-ci se situe au niveau de la pile et donc des arguments.
Il faut être, dans ce code, capable de fournir une pile propre, et utilisable par l'api et cela sans passer par un prototype spécifique ; en effet toutes les fonctions qui nous intéresserons pas, leurs prototypes seront :

void MaFonction_();

En tant normal, une tel fonction n'est pas censé recevoir de paramètre, cependant une option nous permet de réaliser cela, et donc de trouver une solution à notre problème : il faut compiler avec l'option -fomit-frame-pointer.
C'est en fait, le problème le plus délicat à résoudre dans ce projet, je ne sais pas si il est d'ailleurs possible de procéder autrement, j'ai simplement suivie la technique proposé par nos hookeurs de peb.
J'ai d'ailleurs tenté de compiler le code sans spécifiée l'option, et il semblerait que le tout fonctionne toujours..si quelqu'un peut m'éclairer à ce niveau là :].

Bon, une fois réalisé tout cela, nous obtenons un contrôle sur la résolution dynamique des apis ; si nous voulons obtenir un contrôle total, il faut mettre en place une reconstruction de la table d'importation du binaire, afin de faire pointer les importations de kernel32.dll vers NOTRE dll.

Et enfin, il faut aussi reconstruire les tables des importations des autres modules que notre binaire utilisent, à condition que ceux ci importent des fonctions de kernel32.dll ; tous cela dans le but de les rediriger vers NOTRE dll ! Et dans ce cas là, nous avons le contrôle sur tous les appels fait sur les apis de kernel32.dll.

Maintenant, il reste deux/trois détails à résoudre, en effet si l'on veut pouvoir intercepter tous les appels de fonctions en destination de kernel32.dll, nous devons créer le processus dans un état suspendu, à ce moment là on peut enfiler notre casquette "trappeur de PEB" et corrompre les différents champs.
C'est pour moi le point faible de la technique, en effet il faut pouvoir créer le processus pour pouvoir mettre en place correctement l'attaque.

A présent parlons implémentation, dreg & shearer ont choisis d'injecter un code qui va charger la dll (celle qui va mettre en place le peb hook et la reconstructions des imports), leurs code est plutôt original, il injecte en mémoire une structure formé des opcodes nécessaire au chargement de la dll ; les opcodes sont forgés à la volée : funny :)).

Pour ma part, j'ai tout simplement choisis de créer un thread distant sur la fonction LoadLibraryA afin de chargé ma dll.
Celle-ci se chargera de mettre en place le peb hook, et la reconstructions des importations du binaire, par manque d'envie je n'ai pas codé la reconstructions successive des IATs des différents modules chargés par le binaire.

Concernant leurs PoC, après l'avoir testé il semble défectueux chez moi.
En effet, au lieu d'injecter une dll réalisant le peb hook et le patch des imports, ils ont décidés d'interfacer la mise en place de l'attaque par le biais d'une espece de console.
Vous êtes alors contraint de vous connectez à une socket, on vous propose alors un menu (n'utilisez pas putty :p) ..enfin bon je trouve que le poc est entouré de fonction qui n'apporte pas de réel plus value au projet !

Dans la suite d'outil qu'ils nous proposent on trouve, bien sur,un générateur de code, celui-ci est capable de nous générer le code d'une dll avec les mêmes exportations etc ; celui-ci étant codé en C, j'ai décidé de me coder un petit script python (mon premier !:]]) avec le module pefile.
Cela m'a permis d'appréhender python pour finalement lacher le perl !
Je pense en effet qu'il est plus judicieux d'utilisé un language de script pour réaliser une tache de ce genre !

En lançant mon implémentation, si tout ce passe correctement, vous devriez obtenir un dump du genre :

[3876] [ PebPwnDll implémentation par 0vercl0k, idée original de Shearer & Dreg ].
[3876] [DBG] RtlGetCurrentPeb : 0x7c970e89.
[3876] [DBG] PEB en : 0x7ffdf000.
[3876] [DBG] PEB_LDR_DATA en : 0x361e90.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 361ec0.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 361f18.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 361fc0.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 362060.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 362100.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 3622d0.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 362328.
[3876] [DBG] LDR_DATA_TABLE_ENTRY : 3623c8.
[3876]
[3876] [DBG] LDR_DATA_ENTRY_TABLE de la dll hook : 0x3622d0.
[3876] ImageBase : 0x623c0000
[3876] EntryPoint : 0x623c1000
[3876] SizeOfImage : 0x9f000
[3876]
[3876] [DBG] LDR_DATA_ENTRY_TABLE de la dll hooké : 0x361fc0.
[3876] ImageBase : 0x7c800000
[3876] EntryPoint : 0x7c80b5be
[3876] SizeOfImage : 0x105000
[3876]
[3876] [DBG] Kernel32.dll en 0x623c0000.
[3876] [DBG] Eat dumped !
[3876] [DBG] Patch de l'iat du binaire..
[3876] [DBG] Patch de l'iat du binaire, concernant la dll 'kernel32.dll'.
[3876] [DBG] Patch du binaire terminé.
[3876] [DBG] Attaque complète.


Pour tester la mise en place de la technique, j'ai tout simplement rajouter une MessageBox lors d'un appel à l'api Beep().
Si vous voulez tracer le binaire pour constater le fonctionnement, j'ai glissé une int 3, il vous suffit donc de définir OllyDbg comme JIT debugger.


Maintenant, on peut s'interroger si la technique est utilisable dans le cadre d'un malware..j'aurais tendance à dire oui bien sur, seulement un peb hook reste très simple à détecter : il suffit de constater les champs DllBase/EntryPoint/SizeOfImage en mémoire, et ceux du binaire en dur. On se rend vite compte que sa mise en place est aussi contraignante, car beaucoup d'actions sont réalisées, et que plus il y a d'actions à réalisées, plus il y a de chances pour que l'attaque tombe à l'eau (si l'une d'entres elles echoue, c'est la technique entière qui se voit tomber en miettes).

Cependant, une technique de ce type peut-être intéressante pour virtualiser certaines apis (les auteurs en parlent en fin de leur article) ou encore pour réaliser un traceur d'api ; c'est peut-être un peu lourd je vous l'accorde.
Enfin bref, c'est vraiment un article que j'ai A.D.O.R.E, jouer comme cela avec des structures accessible en userland c'est vraiment des techniques que je kiffe :).

Il est temps de lacher les sources, pour cette fois je vous fait une archive contenant source et binaire :

UnderstandPhooksInternals.zip

Sinan voici quelques liens en vrac :
Voilà, j'en ai finis pour aujourd'hui, en espérant que ça vous aura plu ;).


samedi 21 mars 2009

Flirt with the session space.

Je vais aujourd'hui vous parlez d'un espace un peu spécial situé dans le kernel land ; j'ai du mener de longues recherches, des nuits de reverses et j'en passe :).
Tous cela parce qu'il s'agit d'un sujet qui au final reste très très peu documenté, on trouve très peu de précision et lorsque le sujet est abordé dans certains article, les descriptions sont plutôt sommaire.

Le session space, est en fait un espace session (comme son nom l'indique) ; comme vous le savez les OS modernes sont tous capables de gérer les sessions multiples ; et bien windows dédie un espace privé par session !
Une session est en fait un espace privé reservé pour chaque utilisateur par exemple, le fait que plusieurs utilisateurs puissent se connecter en même temps implique alors le cloisonnement de celles-ci !

En fait, tous commence lorsque je me mis à rédiger un Proof of concept concernant la technique de xrayn. Celle-ci permettait de cacher ses hooks dans la SSDT/SSDT Shadow ; 90% environ des anti-rootkits étaient mis à l'echec !
A première vue, le code ne devrait pas trop me poser de problèmes..jusqu'au moment où je dois réaliser une copie de la SSDT Shadow.
En bref la SSDT Shadow est la SSDT pour les threads qui vont gérer une interface graphique ; la SSDT shadow se décompose en deux parties : la première qui est la SSDT que l'on connait bien (dite SSDT system), et la seconde est la SSDT gui.
Un petit dump du kd pour vous montrez ça :

kd> dd nt!KeServiceDescriptorTable l 0x8 80559b80 804e2d20 00000000 0000011c 804d8f48 80559b90 00000000 00000000 00000000 00000000 kd> dd nt!KeServiceDescriptorTableShadow l 0xC 80559b40 804e2d20 00000000 0000011c 804d8f48 80559b50 bf999400 00000000 0000029b bf99a110 80559b60 00000000 00000000 00000000 00000000
Les threads gui peuvent alors gérer les syscalls système, et les syscalls gui sans aller chercher les fonctions dans une autre table.
Sans rentrer dans les détails de la technique (un article sortira bientôt concernant cette technique), lorsque que mon driver tentait d'accéder au tableau de pointeurs sur les fonctions syscalls de win32k et ben BIM BOOOM %*&1 écran bleu !

Je sors alors mon kd :

kd> dd nt!KeServiceDescriptorTableShadow l 0x8
80559b40 804e2d20 00000000 0000011c 804d8f48
80559b50 bf999400 00000000 0000029b bf99a110

kd> dds poi(nt!KeServiceDescriptorTableShadow+0x4*4)
bf999400 ????????
bf999404 ????????
bf999408 ????????
bf99940c ????????
bf999410 ????????
bf999414 ????????
bf999418 ????????
bf99941c ????????
bf999420 ????????
bf999424 ????????

Hmm l'espace mémoire parait comme innexistant, et c'est là que le problème s'esquisse.
Tout ça parait plutôt floue, j'ai donc potasser un peu les Windows internals, c'est donc à ce moment que je découvre le session space !
On peux y lire :

Each session has a session-specific paged pool area used by the kernel-mode portion of the Windows subsystem (Win32k.sys) to allocate session-private GUI data structures.
In addition, each session has its own copy of the Windows subsystem process (Csrss.exe) and logon process (Winlogon.exe).
The session manager process (Smss.exe) is responsible for creating new sessions, which includes loading a session-private copy of Win32k.sys,
creating the session-private object manager namespace, and creating the session-specific instances of the Csrss and Winlogon processes.

When a process is created, this range of addresses is mapped to the pages appropriate to the session that the process belongs to.


Nous voilà avec quelques pistes, on se rend compte alors que la Shadow n'est accessible seulement aux processus qui appartiennent à la dîtes session ; autrement dit tous les threads de ces processus auront accès à cet table.

Cet à ce moment qu'il faut réfléchir un peu si l'on veut dégoter quelques informations intéressante ; on pourrait déjà regarder du coté du gestionnaire de sessions : smss.exe, ensuite du driver win32k.sys ..j'ai donc essayé de les analyser à la recherche d'infos plus ou moins pertinente.
Smss.exe se charge à son initialisation de charger le driver win32k.sys :

Main!smss.exe
-> smss!SmpInit
-> smss!SmpLoadDataFromRegistry
-> smss!SmpLoadSubSystemsForMuSession

.text:485887B2 push offset aSystemrootSyst ; "\\SystemRoot\\System32\\win32k.sys"
.text:485887B7 lea eax, [ebp+DestinationString]
.text:485887BA push eax ; DestinationString
.text:485887BB call ds:__imp__RtlInitUnicodeString@8 ; RtlInitUnicodeString(x,x)
.text:485887C1 push 8
.text:485887C3 lea eax, [ebp+DestinationString]
.text:485887C6 push eax
.text:485887C7 push 26h
.text:485887C9 call edi ; NtSetSystemInformation(x,x,x) ; NtSetSystemInformation(x,x,x)
Smss.exe utilise une technique peu rencontré pour charger le driver, certains parle de "quick an dirty-way" (cf Suberving the windows kernel). Il suffit d'appeler NtSetSystemInformation avec l'argument SystemLoadAndCallImage ainsi que le full path du driver.
On parle de dirty way, tout simplement parce que le driver sera chargé dans une zone mémoire swappable, pour plus d'information chapitre 2 du bouqin :).

Une fois le driver lancé, celui-ci va ajouter la SSDT shadow :

INIT:BF9AFF13 push offset _W32pArgumentTable
INIT:BF9AFF18 push _W32pServiceLimit
INIT:BF9AFF1E mov _countTable, esi
INIT:BF9AFF24 push esi
INIT:BF9AFF25 push offset _W32pServiceTable
INIT:BF9AFF2A call ds:__imp__KeAddSystemServiceTable@20 ; KeAddSystemServiceTable(x,x,x,x,x)

.data:BF999B00 _W32pServiceTable dd offset _NtGdiAbortDoc@4
.data:BF999B04 dd offset _NtGdiAbortPath@4 ; NtGdiAbortPath(x)
.data:BF999B08 dd offset _NtGdiAddFontResourceW@24 ; NtGdiAddFontResourceW(x,x,x,x,x,x)
.data:BF999B0C dd offset _NtGdiAddRemoteFontToDC@16 ; NtGdiAddRemoteFontToDC(x,x,x,x)
.data:BF999B10 dd offset _NtGdiAddFontMemResourceEx@20 ; NtGdiAddFontMemResourceEx(x,x,x,x,x)
.data:BF999B14 dd offset _NtGdiRemoveMergeFont@8 ; NtGdiRemoveMergeFont(x,x)
.data:BF999B18 dd offset _NtGdiAddRemoteMMInstanceToDC@12 ; NtGdiAddRemoteMMInstanceToDC(x,x,x)
.data:BF999B1C dd offset _NtGdiAlphaBlend@48 ; NtGdiAlphaBlend(x,x,x,x,x,x,x,x,x,x,x,x)
[...]

.data:BF99A810 _W32pArgumentTable db 4 ; DATA XREF: DriverEntry(x,x)+E4o
.data:BF99A811 db 4
.data:BF99A812 db 18h
.data:BF99A813 db 10h
.data:BF99A814 db 14h
.data:BF99A815 db 8
.data:BF99A816 db 0Ch
.data:BF99A817 db 30h
[...]
Avec ce session space il y a donc une histoire d'espace qui est accessible/existe, dans certains contexte ; en fait tous les processus d'une session voient cette table, seul system ne peux y accéder ; par analogie c'est comme un processus avec ses dlls, system serait un processus sans la dll Session space (c'est bien sûr une analogie, soyons d'accord :)) .

On peut verifier tout ça avec le kd ; en premier lieu se placer dans le contexte du processus System (le cas de notre driver donc), et ce placer dans le contexte d'un tout autre processus :

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 817cc7c0 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00039000 ObjectTable: e1001cb0 HandleCount: 206.
Image: System
[..]
kd> .process /i 817cc7c0
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
804e3b25 cc int 3
kd> dds poi(nt!KeServiceDescriptorTableShadow+0x4*4)
bf999400 ????????
bf999404 ????????
bf999408 ????????


kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
[..]
PROCESS
81549b28 SessionId: 0 Cid: 05a8 Peb: 7ffdf000 ParentCid: 0588
DirBase: 093c9000 ObjectTable: e1a74620 HandleCount: 346.
Image:
explorer.exe
[..]
kd> .process /i
81549b28
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
804e3b25 cc int 3
kd> dds poi(nt!KeServiceDescriptorTableShadow+0x4*4)
bf999400 bf9357a3 win32k!NtGdiAbortDoc
bf999404 bf947361 win32k!NtGdiAbortPath
bf999408 bf896625 win32k!NtGdiAddFontResourceW
bf99940c bf93ef25 win32k!NtGdiAddRemoteFontToDC
bf999410 bf948978 win32k!NtGdiAddFontMemResourceEx
[..]
J'ai donc réaliser une fonction qui permettait ça copie, celle-ci fonctionne plutôt simplement, je m'attache au processus explorer.exe (Il faut s'attacher à un processus qui sera lancé sur le systeme ; j'ai pris explorer.exe comme j'aurais pu prendre calc.exe!), et réalise la copie normalement (vous verrez alors que mon ancienne technique qui utilisait un apc kernel envoyé sur un thread gui était bien trop compliqué pour pas grand chose :).

Sinon, on pourrait s'occuper de mapper win32k.sys dans l'espace du driver en utilisant son adresse physique avec des apis comme MmMapIoSpace(), il suffirait ensuite de parser le pe du binaire, pour atterrir dans la section .data ; où est stocké la SSDT Shadow.

.data:BF999C00 ; Segment type: Pure data
.data:BF999C00 ; Segment permissions: Read/Write
.data:BF999C00 _data segment para public 'DATA' use32
.data:BF999C00 assume cs:_data
.data:BF999C00 ;org 0BF999C00h
.data:BF999C00 _W32pServiceTable dd offset _NtGdiAbortDoc@4
.data:BF999C00 ; DATA XREF: DriverEntry(x,x)+F6o
.data:BF999C00 ; NtGdiAbortDoc(x)
.data:BF999C04 dd offset _NtGdiAbortPath@4 ; NtGdiAbortPath(x)
.data:BF999C08 dd offset _NtGdiAddFontResourceW@24 ; NtGdiAddFontResourceW(x,x,x,x,x,x)
.data:BF999C0C dd offset _NtGdiAddRemoteFontToDC@16 ; NtGdiAddRemoteFontToDC(x,x,x,x)
.data:BF999C10 dd offset _NtGdiAddFontMemResourceEx@20 ; NtGdiAddFontMemResourceEx(x,x,x,x,x)
.data:BF999C14 dd offset _NtGdiRemoveMergeFont@8 ; NtGdiRemoveMergeFont(x,x)
.data:BF999C18 dd offset _NtGdiAddRemoteMMInstanceToDC@12 ; NtGdiAddRemoteMMInstanceToDC(x,x,x)
.data:BF999C1C dd offset _NtGdiAlphaBlend@48 ; NtGdiAlphaBlend(x,x,x,x,x,x,x,x,x,x,x,x)
.data:BF999C20 dd offset _NtGdiAngleArc@24 ; NtGdiAngleArc(x,x,x,x,x,x)
.data:BF999C24 dd offset _NtGdiAnyLinkedFonts@0 ; NtGdiAnyLinkedFonts()
.data:BF999C28 dd offset _NtGdiFontIsLinked@4 ; NtGdiFontIsLinked(x)
.data:BF999C2C dd offset _NtGdiArcInternal@40 ; NtGdiArcInternal(x,x,x,x,x,x,x,x,x,x)
.data:BF999C30 dd offset _NtGdiBeginPath@4 ; NtGdiBeginPath(x)

Un peu tricky, mais ça se tiens, seul problème c'est la translation de l'adresse Virtuelle à l'adresse Physique, étant donné que le driver ne voit pas l'espace en question, l'adresse physique ne peut être récupérer avec MmGetPhysicalAddress() (l'idéal serait de ne pas s'attacher à un processus).


Bilan de ce post, un peu décevant, mes recherches ont été longues pour au final pas grand chose..m'enfin bon :].
Sinan, je vous recommande le blog de bons amis, Futurezone ; le blog est mis à jour regulierement avec des articles très clean et tout, c'est que du bonheur quoi.


Voilà pour aujourd'hui :
CopySSDTShadow.c

Je compte aussi sortir une version un peu plus propre de HC-L, en effet j'ai décidé d'embarquer le NDK, de séparer les en-têtes de fonctions des définitions, ajouter des fonctions etc..!


mercredi 24 décembre 2008

H-CL vous souhaite un joyeux noël !

Un revenant ? Et oui me revoilà back from h3ll après quelques semaines d'inactivités.
Je vais profiter de ce petit article, pour vous racontez mes péripéties. Mais celles-ci ne se déroulent non pas dans les contrées rocheuses avoisinant mon chère kernel, mais belle et bien In Real Life.

Il y a quelques semaines de cela, mon laptop a subit une terrible perte ; un petit texte pour vous contez ces aventures.
Ma maudite machine plutôt jeune et jusqu'à présent assez performante me laissa tomber : un beau matin en l'allumant, j'entends alors de vieux bips systèmes..après quelques recherches de faite il s'avère que c'est ma motherboard :(.

Me voilà face au gouffre, le ciel prêt à s'écraser sur ma tête : obliger de renvoyer la bestiole au sav.

Jusqu'à présent rien de bien grave..
L'unique problème c'est que bien sur je n'ai aucun backup..AUCUN .
Mes neurones en ébullition se rassemblent dans l'espoir de trouver une solution me permettant de sauvegarder mon disque dur..Mais rien ! Si je tente toutes bidouilles avec le disque dur interne du laptop, la garantie saute.

Après un petit coup de fil avec le réparateur, il me propose de sauvegarder un dossier

"Quel dossier je vous sauvegarde monsieur ?"
"Humm, le dossier C:\kernel s'il vous plait !"
"heu..il n'y a pas de dossier kernel"
"le dossier k3rn3l !"

Encore un technicien ignorant le 1337 sp34k1ng.

Mais aujourd'hui je reviens, avec des (merci hzv <3) laptops tout propre, ready, avec backup :] (merci ivan:p).

C'est donc en ce soir de nowel, que je vous propose le début d'un projet qui me tiens plutôt à cœur car à mon avis plus qu'utile.

L'idée n'a rien de transcendante, c'est en fait une espèce de librairie.
Un header contenant quelques fonctions useful quand on aime bien trifouiller son kernel.

L'originalité du projet, je pense, est le fait que tout est réunis dans UN unique fichier : personnellement je trouve que ça simplifie grandement les choses quant à l'utilisation.

Concernant l'avancement du projet ; c'est encore au stade embryonnaire à peine 5 fonctions pour le moment.

Disons que, ça intéressera surement quelques personnes : d'ailleurs si certains on des reports de bugs, ou autres n'hésitez pas à me laisser un commentaire ; j'aimerais bien faire un truc propre et pourquoi pas utilisé ?
Tant que j'y pense, si vous avez des idées de fonctions à implémenter n'hésitez pas encore une fois à laisser un petit mot ; merci :)).

Je vais donc bien sur continuer à poster régulièrement maintenant que tout est rentré dans l'ordre !
En attendant je vous laisse avec mon .h en espérant que ça servira à quelques mangeur de chips fan de black-métal ; ça serait un bon début :)).

-H-CL.h

En tous cas, joyeux noël à vous, passer de bonnes fêtes :).

dimanche 2 novembre 2008

#hzv 1 released !

#Hzv 1 est enfin out !
Après plusieurs mois d'attente, le voici enfin sortit.
J'y ai publié mon plus gros article concernant l'exploitation des stacks overflows sous windows.
Je reprends un des articles publié sur mon blog, en le peaufinant, en ajoutant des illustrations des jolies phrases :D . De tous cela découle bien sur un contenu bien plus riche.
Un article qui m'a pris énormément de temps à écrire enfin bref j'y ai mis du coeur :)).

Maintenant je vous laisse en compagnie du premier opus : Hzv#1.
Je remercie donc tous le staff pour leur travail (même si dans le sommaire se sont plantés dans mon pseudo :p).
Je posterais un petit feedback des articles une fois que je les aurais lu :).
Bonne soirée à tous !

Après demande de certains, je mets à disposition l'archive de mon paper contenant, les illustrations, et les codes ;).
En espérant qu'ils vous plaisent :
-Stack Overflow.rar

Je vous parlais d'un petit feedback quant aux écrits ; le voici celui-ci à été rédigé conjointement avec sh4ka :
  • 1ère article) Le codage des données par celelibi.
Un article clair, concernant ce qui se cache vraiment derrière toutes nos variables ; car c'est bien jolie de savoir coder en C mais savoir comment est codé notre information peu s'avérer très utile voir fondamentale.
Il explique très bien l'abstraction (par rapport au codage de ces données) que nous fournissent les langages de programmation avec les types de variables par exemple.
Autrement dit qu'un long c'est pareil qu'un int ou qu'un DWORD : c'est 4 octets d'informations !
Je le recommande donc à ceux qui ne s'y sont jamais intéressé.
  • 2ème article) Exploitation avancée de débordement de tampon par camille bertrand.
Cette article plutôt technique va nous parler de débordement de tampon ; mais aussi de shellcodes.
En effet, j'ai l'impression que l'auteur se centre plus sur l'élaboration de shellcode générique / polymorphisme que sur l'exploitation avancée de la faille.
Il nous explique clairement les étapes essentiels à l'élaboration d'un shellcode capable de se débrouiller seul (dit générique) dans un environnement windows.
Les codes sont clair ; très commentés ; bien illustrés..il nous propose même un petit exercice d'application en fin d'article.
Conclusion l'article est très didactique, un bon papier.
  • 3ème article) Redirection de flux en C sous windows par Cocowebman.
Encore un article pour windows (décidément :)), il illustre un type de communication inter processus : les pipes (prononcé à l'anglaise).
Il redirige les sorties standard dans le tuyau dans lequel il va lire par exemple ; très utile dans un bind/reverse shell par exemple.
L'article est encore une fois agréable à lire ; des illustrations ; c'est mimi en tout cas.
  • 4ème article) La toile à nue face au renard par FaSm et SnAkE.

Un article décevant, le contenu est plutôt très classique et donc n'apprenant pas grand chose au lecteur.

  • 5ème article) Nintendo DS Le wifi Ultra Portable par Virtualabs.
Alors cette article c'est vraiment mon coup de cœur ; moi qui attendait une espèce de compte rendu de sa conférence à la nuit du hack ..et bien me voilà gâter.
Une superbe aventure en fait ; il nous explique un peu son cheminement, ces objectifs, ce qu'il a réussit à faire (impressionnant :o) enfin j'en dévoile pas plus lisez le ! merci virtualabs.
  • 6ème article) Attaque d'un serveur, Prise d'empreinte par Floux.

Article de Floux présentant l'étape préliminaire à un audit,et non des moindres, la prise d'empreinte. L'article survole (peut être un peu trop) les principes classique de ce domaine, sans trop entrer dans les détails(Whois,traceroute,dns,transfert de zone,scan de port,..).Un article plus poussé sur le sujet aurait été apprécié.

PS:"La prise d’empreinte (ou pentest pour les intimes ;))"

Prise d'empreinte=Fingerprinting pas pentesting

  • 7ème article) Démystification d'exploits visant des applications web par Apophis.

Derrière ce titre se cache l'explication d'apophis, concernant une vulnérabilité touchant punbb au travers de la récupération du "cookie_seed" ; afin de calculer le mot de passe aléatoire ainsi que le lien d'activation généré par punbb lors de la réinitialisation d'un compte (suite à l'utilisation de l'option "mot de passe oublié").Par l'étude de cette faille et la programmation de l'exploit, l'auteur nous montre les vulnérabilités touchant au web sous une autre forme que les classiques injections sql,xss,include et cie.

  • 8ème article) Les réseaux de robots, action et prevention par Valéry RASPLUS.

Il s'agit d'un article survolant le monde des botnets, expliquant leurs principes, leurs méthodes, leurs buts et proposant aussi des pistes pour s'en protéger. L'auteur sans rentrer dans la partie technique, permet d'expliquer de façon simple et donc de sensibiliser l'utilisateur sur les dangers que peuvent apporter les botnets.

  • 9ème article) La stéganographie de interger binary numbers par Thierry Crettol.

Un article qui je dois dire me laisse perplexe, l'auteur utilise un vocabulaire « spéciale ». Je cite: « les 54 premiers caractères sont réservés pour le cartouche de l'image bmp », ici cartouche signifie header? Ensuite d'après ce que j'ai pu comprendre, il s'agit en fait de steganographie utilisant la technique des LSB dans les images bmp. Malgré que ce sujet soit intéressant, ici le manque de clarté de l'explication et surtout d'exemple par la mise en place du procédé par la programmation, gâche un peu l'article.


Voilà, conclusion le mag reste intéressant malgré 2/3 bémols comme la qualités des images etc.

Bonne lecture, et espérons que ces bémols seront corrigés dans le prochain !

lundi 27 octobre 2008

Feel the power with TDI !

N'avez vous jamais pensé à avoir un support réseau pour votre merveilleux rootkit ?
Avoir la main sur cette bête même à distance ?

Je vais aujourd'hui réaliser votre rêve :)), plus sérieusement ce post traitera de l'une des interfaces proposées par microsoft pour nous permettre de faire du réseau ; et celle-ci porte le doux nom de TDI acronyme de "Transport Driver Interface".
Je cite microsoft techNet :

"The Transport Driver Interface (TDI) is a common interface for drivers (such as the Windows 2000 redirector and server) to use to communicate with the various network transport protocols. This allows services to remain independent of transport protocols."


Il faut déjà savoir qu'il existe plusieurs manières d'accéder aux ressources réseaux du kerneland

; c'est différent moyens sont implémentés ou pas selon la version de windows :

  • Avant les systèmes vista, nous avions à disposition TDI ainsi que NDIS acronyme de Network Driver Interface Specification.
  • Sous vista nous avons à disposition TDI, NDIS et les Kernels Sockets.
  • Et puis il est prévu de troquer TDI contre les Kernels Sockets pour les autres systèmes qui suivront vista ; autrement dit on ferra du reseau avec NDIS ou/et les Kernels Sockets.
J'ai donc choisis l'utilisation de TDI pour tout d'abord avoir une espèce de rétro-compatibilitée avec "l'avant vista" ; de plus l'utilisation de TDI est assez simple car les opérations à réaliser suivent un même schéma que je detaillerais plus bas.
L'utilisation de TDI est d'ailleurs très bien documentée ; non pas par la masse des écrits sur le sujet mais par la qualité des quelques papers trouvés.
Je veux bien sûr faire références à deux écrit :
  • Subverting The Windows Kernel , chapitre "Kernel TCP/IP Support for Your Rootkit Using TDI"
  • Audi-K - Nouvelles aventures en Kernel Land, paper parut dans le zine des blackclowns ; c'est un S.U.P.E.R.B.E article écrit par Tolwin ..pour couronner le tout c'est du français.Cette article est donc juste priceless, merci à lui.
Ces deux écrits permettent largement de se coder un petit Proof Of Concept quant à l'utilisation de TDI.
J'ai donc choisis de mettre en place une connexion à la manière d'un classique Reverse Shell ; autrement dit un serveur hébergé chez le h4ck3rz, le driver s'y connecte et propose des fonctions exécutées chez la victime tout cela sous forme d'un shell avec un jolie prompt toussa :D.
Seulement ce qui m'a intéressé dans ce code c'est l'implémentation de la partie reseau, vous comprendrez donc pourquoi je n'ai codé aucune fonction entrant dans le cadre du reverse shell ..c'est un travail on ne peux plus fastidieux ; de plus ce n'etait pas le but ! Au passage si quelques d'entre vous sortent leurs jolies IDEs avec comme objectif de rendre mon bout de code utilisable..ben qu'ils me previennent :D.


Entrons dans le vif du sujet ; chers passagers je vous prie de bien vouloir boucler vos ceintures, le voyage va bientôt commencer !

Comme je le disais un peu plus haut, TDI s'avère assez simple, peut-être un poil velus au départ mais au fur et à mesure que l'on code on se rend vite compte que les principales opérations sont redondantes.
Il faut aussi savoir que jouer avec TDI, c'est accepter de dealer avec le driver tcpip.sys.
Si on fouille dans les tools signé OSR, on peut tomber sur DeviceTree ; un outil assez pratique pour observer l'organisation des drivers, devices et autres :



Vous vous doutez bien que nous allons nous occuper du driver tcp, seulement lui !
On remarque aussi au passage que le device est en mode IO_DIRECT ; autrement dit le buffer d'entré et de sortie sera le même ; aucun gaspillage quant à la manipulation/recopie de ceux ci etc.
Le code va donc se résoudre à de multiples échanges entres le driver, et le notre par le biais d'IRP.
En effet, notre code se résout à , préparer une requête (l'IRP), l'envoyer au driver, bloquer pendant que le driver traite notre requête, et puis agir en fonction du code de retour.
Tout cela est simplifié mais dans l'idée c'est exactement ce qu'il faut faire ; microsoft nous propose alors un lot de macro tel que :
  • TdiBuildSend
  • TdiBuildReceive
  • TdiBuildConnect
  • TdiBuildInternalDeviceControlIrp
Entrons un peu plus dans les détails maintenant.
Les deux premières étapes consistent en la création de deux objets, un "Connection Object" ainsi qu'un "Transport Object" l'un servant à stocker les informations relatives a l'host et au port (le TransportObject donc) ; et un second objet gérant la connection (le Connection Objet).

Ces objets seront créés grâce à la fonction ZwCreateFile ; pour mener à bien la construction de ces objets ont doit passer des paramètres à la fonction qui va gérer la construction des objets contenu dans le driver bien sur.
Ceux-ci seront passé par encapsulation dans une structure du type FILE_FULL_EA_INFORMATION ; dans l'avant dernier argument de ZwCreateFile "EaBuffer".
Voici la définition de la structure :

typedef struct _FILE_FULL_EA_INFORMATION
{
ULONG NextEntryOffset;
UCHAR Flags;
UCHAR EaNameLength;
USHORT EaValueLength;
CHAR EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;

Je m'explique quant à cette histoire d'encapsulation ; le but est de pouvoir passé plusieurs structures au driver.

1. On alloue la mémoire total, c'est l'addition des tailles des structures à faire passé en argument plus la structure de type FILE_FULL_EA_INFORMATION.
2. On remplis les premiers champs de la structure : NextEntryOffset, Flags etc.
3. On écrit à la suite du dernier champs (EaBuffer) le contenus de nos structures.

Voilà le principe, la structure de type FILE_FULL_EA_INFORMATION englobe les autres, c'est le principe.

Je noterais EA la structure qui sert d'encapsulation.
Pour le Connection Object nous avons le schéma suivant :
  • [EA -> CONNECTION_CONTEXT]
Pour le Transport Object nous avons :
  • [EA -> TA_IP_ADDRESS]
Je ne sais pas si j'ai réussi à comprendre, mais j'ai fais de mon mieux, c'est pas facile :].

Bon voilà c'est beau, c'est magique, de la véritable poudre de perlinpinpin mais notre voyage est loin d'être terminé.

Il faut ensuite associer ces deux handles..à partir de cette étape le chemin restera toujours le même :
  1. Allocation de l'irp, grâce à la macro TdiBuildInternalDeviceControlIrp.
  2. Construction de l'irp par le biais de la macro associée à l'action désirée (TdiBuildSend, TdiBuildReceive, TdiBuildAssociateAddress etc).
  3. On transmet l'irp au driver en utilisant la fonction IoCallDriver.
  4. On bloque tant que le traitement n'est pas terminé avec la fonction KeWaitForSingleObject.
C'est en fait le schéma dont je vous parlais plus haut, c'est celui-ci que vous allez répéter pour chacune de vos actions ; vous comprendrez alors pourquoi je ne détaillerais pas le reste :)).

Concernant mon petit code, il va se connecter sur une ip sur un port donné, il envoit alors un prompt à la manière d'un shell tout simplement.
J'ai d'ailleurs tout mis en place pour faciliter l'implémentation de fonctions ..si il y a des courageux comme je le disais :)).
Un petit screenshot:




Sinan dans le genre priceless, mon s1th vient de nous dégotter un OllyDbg customisé on ne peux plus cool :)).
Il est blindé de scripts/plugins, et possède un gestionnaire de raccourcis pour placer tous ces tools préférés :



On voit aussi qu'il possède une barre de commande immunityDbg like :) ; enfin bon à avoir d'urgence !
Ensuite je voulais vous parlez d'un ami, Squallsurf et son nouveau outil H.a.r.P.E (une espèce de plateforme de manipulation/visualisation du PE ; projet prometteur :)).
N'hésitez donc pas à lui rendre visite, ou encore lui rapporter bugs et/ou amélioration quant à son joujou :).

Les codes de mon Proof Of Concept :
Esrever.c

En espérant avoir intéressé quelques uns :), cya.
PS : petit coucou à securfrog o/ ; merci à baboon !

dimanche 28 septembre 2008

L'union fait la force.

Me revoilà pour un nouveau post, (un peu tardif me direz vous, mais bon pas toujours facile avec les cours) mais cette fois-ci c'est un peu spécial.
En effet, lilxam et moi même vous proposons aujourd'hui une archive liant deux papers écrit en "collaboration".
Un gros travail d'entraide à été mis en place sur cette série de papers, une expérience à renouveler je pense car très efficace.
Tout cela pour dire que l'on sera surement amené à renouvelé ce type d'opération, hein lilxam :)?

Entrons dans le vif du sujet.

L'archive est composé d'un premier paper signé lilxam traitant des débordements de tampons appliqué et exploité sur php 5.x.
L'approche est vraiment intéréssante car mon chère collègue à due mener de nombreuses recherches sur l'organisation, l'appel des fonctions au seins de php.exe.
Une fois cette étape de franchis, il entamme la recherche de fonctions faillibles en codant un fuzzer like maison qui m'a foi à porté ces fruits :).
Non loin d'une dizaine de fonction faillible sur la version 5.2.6, l'exploitation rentre donc maintenant en jeux.
La technique utilisé est une réécriture de SEH (Structured Exception Handling), afin de rediriger le flot d'éxecution de php sur un vilain shellcode :).
Voilà en gros le fil rouge du paper, le tout est bien sûr agrementé de schéma/screenshots/codes et d'explications :).

Avec le second paper on change complétement de sujet ; je présente en premier temps les TLS CallBacks, puis l'HotPatching, et enfin une à deux petites applications liant les deux "outils" vu precedemment.Rien de bien méchant en tout cas, un contenus très soft :).
J'ai mis à disposition dans l'archive l'éboche, la tentative de rédaction d'une classe cpp (et oui, je m'y mets!) permettant l'implémentation d'une tls callback..la classe est vraiment très simple et peu fiable je pense cependant elle m'aura permis d'allonger du code pour me faire la main avec ce language.

Je vous laisse en compagnie de nos écris :
-L'Union Fait la Force.zip.

En espérant que ça plaira bonne après midi :).