Contribuez à SecuObs en envoyant des bitcoins ou des dogecoins.
Nouveaux articles (fr): 1pwnthhW21zdnQ5WucjmnF3pk9puT5fDF
Amélioration du site: 1hckU85orcGCm8A9hk67391LCy4ECGJca

Contribute to SecuObs by sending bitcoins or dogecoins.



[WiShMaster - partie 6] Principe et fonctionnement - RConnect/WiShMaster Vs firewalls personnels (3)

Par Benjamin Caillat, Mastère Spécialisé Sécurité ESIEA
Le 16/09/2006


Résumé : Les limites des protections. Analyse des hookings user-land.par patch du header et kernel land par patch de la SDDT. Analyse de l'installation des fonctions callback. Surveillance de la création de processus.



Les limites de ces protections


Analyse du hooking user-land par patch du header

Cette technique de protection est de manière intrinsèque relativement limitée car elle prend place dans le même espace mémoire et possède, du point de vue du système, les mêmes droits que le code à analyser. Reprenons l’exemple de Kerio pour illustrer quelques techniques de contournement.

Le hooking est effectué au niveau de l’API Win32 et n’interceptera donc pas les appels directs à l’API native. Le code de NtCreateThread n’a en effet pas été modifié.

Placer le hooking au niveau l’API native n’apporterait pas une meilleure sécurité puisque le processus a toujours la possibilité d’effectuer lui-même le passage en mode noyau, sans s’appuyer sur les fonctions de ntdll.dll.

A noter que dans ce cas, la portabilité de la backdoor risque de diminuer considérablement car les numéros des services varient d’une version de Windows à une autre. L’API native n’étant pas documentée,

cette méthode peut s’avérer de plus relativement complexe à mettre en œuvre. Une autre solution peut être de repatcher directement le jump du début de la fonction pour éviter l’exécution du code procédant à l’appel du noyau, principe illustré sur la figure suivante :






D’autres firewalls personnels utilisent cette technique de hooking en user-land et peuvent être contournés par des méthodes similaires.

Etant, entre autres, destiné à produire du code injecté dans des processus, WiShMaster intègre un mécanisme appelé « FireBreaker » permettant d’ajouter du code à la fin de la fonction BuildReferences pour détecter et enlever ces éventuelles protections user-land.

FireBreaker analyse l’entête de toutes les fonctions importées afin de détecter un schéma de protection connu, puis, le cas échéant, repatche ces entêtes pour le contourner. La technique utilisée est bien sûr très dépendante de la structure de la protection ; le contournement de chaque firewall demande donc un développement spécifique.

Pour l’instant FireBreaker supporte uniquement le contournement de Kerio et de Tiny Firewall 2005. Cependant, peu de firewalls intègrent ce type de protection et l’ajout du traitement d’un nouveau firewall est relativement rapide. A titre d’exemple, il m’a fallu environ deux heures pour étudier, écrire et tester rapidement le code de contournement pour Tiny Firewall 2005.

L’ajout du code de FireBreaker augmente bien sûr la taille du shellcode produit et n’est pas forcément indispensable. Cette fonctionnalité est donc activable dans les options du projet.


Analyse du hooking kernel-land par patch de la SDDT

Contrairement au hooking user-land, le hooking kernel-land se positionne dans la partie « de confiance » du système et ne pourra donc être altéré par un code malicieux s’exécutant dans une session utilisateur restreint.

Il est important de noter que pour contrer un code malicieux s’exécutant en administrateur, le logiciel de protection devra intégrer une analyse beaucoup plus complète du système (chargement de driver, gestion des services, …), que beaucoup de produit actuels n’implémentent pas. D’où l’importance d’être loggé en utilisateur restreint.

Si cette technique est robuste en théorie, elle reste relativement délicate à mettre en œuvre et les failles vont plutôt apparaître au niveau de l’implémentation. Reprenons l’exemple de Kerio qui utilise le hooking en kernel-land en plus de celui en user-land. Le tableau suivant présente la liste des services hookés :


Service - Numéro du service - Adresse avant hook => après hook

NtClose - 019 - 80566b49 => f82f1110
NtCreateFile - 025 - 80570d48 => f82f0920
NtCreateKey - 029 - 8056e761 => f82ecee0
NtCreateProcess - 02f - 805ad314 => f82eff20
NtCreateProcessEx - 030 - 8058041a => f82efd90
NtCreateThread - 035 - 8057b1c5 => f82f0480
NtDeleteFile - 03e - 805d3c07 => f82f1190
NtDeleteKey - 03f - 80590f78 => f82ed320
NtDeleteValueKey - 041 - 8058e9fa => f82ed3c0
NtLoadDriver - 061 - 805a08ec => f81469a0
NtMapViewOfSection - 06c - 805732fc => f8146b30
NtOpenFile - 074 - 80570ce3 => f82f0bf0
NtOpenKey - 077 - 80567afb => f82ed140
NtResumeThread - 0ce -8057b838 => f82f0510
NtSetInformationFile - 0e0 - 80577e2c => f82f0f00
NtSetValueKey - 0f7 - 80574c1d => f82ed4d0
NtWriteFile - 112 - 805780d5 => f82f0e50



La fonction NtCreateThread, appelée en interne par CreateRemoteThread est hookée. Cependant le code d’analyse ne semble pour l’instant n’effectuer aucune véritable vérification : si IRQL == 0, le service est appelé directement. Cette partie est peut-être en cours de développement.

Analysons maintenant les hooks positionnés par Tiny Firewall 2005 :


Service - Numéro du service - Adresse avant hook => après hook

NtCreateKey - 029 - 8056e761 => f801ffa0
NtCreateSection - 032 - 8056441b => f83a1000
NtOpenKey - 077 - 80567afb => f801ff50
NtSetInformationProcess - 0e4 - 8056bd05 => f83a0070


Nous constatons que plusieurs fonctions critiques ne sont pas surveillées. L’appel de CreateRemoteThread est surveillé par un hook user-land, mais une fois cette protection retirée par FireBreaker, plus rien n’empêche l’injection de thread.

Regardons maintenant le firewall personnel inclu dans la solution de Kaspersky


Service - Numéro du service - Adresse avant hook => après hook

NtClose - 019 - 80566b49 => f81625b0
NtCreateKey - 029 - 8056e761 => f8157280
NtCreateProcess - 02f - 805ad314 => f81622c0
NtCreateProcessEx - 030 - 8058041a => f8162440
NtCreateSection - 032 - 8056441b => f8162ee0
NtCreateSymbolicLinkObject - 034 - 8059d4db => f8162b2e
NtCreateThread - 035 - 8057b1c5 => f8163830
NtDeleteKey - 03f - 80590f78 => f8157340
NtDeleteValueKey - 041 - 8058e9fa => f81573c0
NtDuplicateObject - 044 - 80573ab6 => f8162710
NtEnumerateKey - 047 - 8056ee68 => f8157450
NtEnumerateValueKey - 049 - 8057eb28 => f8157500
NtFlushKey - 04f - 805da2d0 => f81575b0
NtInitializeRegistry - 05c - 8059f813 => f8157630
NtLoadKey - 062 - 805aacf0 => f8157e00
NtLoadKey2 - 063 - 805aab3e => f8157650
NtNotifyChangeKey - 06f - 8058c141 => f81576f0
NtOpenFile - 074 - 80570ce3 => f9e6c028
NtOpenKey - 077 - 80567afb => f81577d0
NtOpenProcess - 07a - 80573c96 => f8162050
NtOpenSection - 07d - 8057769b => f8162d2e
NtQueryKey - 0a0 - 8056eb71 => f8157870
NtQueryMultipleValueKey - 0a1 - 8064c8f8 => f8157920
NtQuerySystemInformation - 0ad - 8057c4aa => f81634c6
NtQueryValueKey - 0b1 - 8056b0bb => f81579d0
NtReplaceKey - 0c1 - 8064d232 => f8157a80
NtRestoreKey - 0cc - 8064bd56 => f8157b10
NtResumeThread - 0ce - 8057b838 => f81637a0
NtSaveKey - 0cf - 8064bdfd => f8157ba0
NtSetContextThread - 0d5 - 8062c143 => f8163b80
NtSetInformationFile - 0e0 - 80577e2c => f8164270
NtSetInformationKey - 0e2 - 8064c45b => f8157c30
NtSetInformationProcess - 0e4 - 8056bd05 => f8166cd0
NtSetValueKey - 0f7 - 80574c1d => f8157cd0
NtSuspendThread - 0fe - 805df81e => f8163750
NtTerminateProcess - 101 - 80582c2b => f8163300
NtUnloadKey - 107 - 8064c02b => f8157dc0
NtWriteVirtualMemory - 115 - 8057e5e0 => f81625d0



La liste des fonctions hookées est beaucoup plus conséquente. Ce firewall ajoute même 13 nouveaux services. La fonction NtCreateThread est cette fois sujette à une véritable analyse. L’implémentation d’une injection de thread en appelant CreateRemoteThread provoquera l’affichage d’une popup de confirmation à l’utilisateur.

Mais même dans le cas d’une implémentation relativement exhaustive comme ici, il peut exister des méthodes de contournement. Reprenons le principe de l’injection de thread : la backdoor lance une instance cachée et suspendue du navigateur par défaut via un appel à CreateProcess.

Elle récupère alors un handle ayant tous les droits sur le processus via la structure PROCESS_INFORMATION, qu’elle utilise pour allouer une portion de mémoire et la remplir avec le shellcode.

A ce moment, au lieu d’appeler CreateRemoteThread, elle peut patcher le point d’entrée avec un jump vers le shellcode, puis résumer l’exécution du processus. Aucun appel à CreateRemoteThread n’a alors été fait et l’injection ne sera pas détectée par Kaspersky. En revanche le lancement du processus « cmd.exe » avec les entrées/sorties standards redirigées sera intercepté.

Le hooking en kernel-land reste, à mon sens, la véritable solution. La difficulté provient du fait que le firewall doit à la fois surveiller un grand nombre de fonctions afin de couvrir toutes les techniques d’évasion, et dans le même temps éviter de remonter sans cesse des alertes à l’utilisateur, qui risque sinon de vite prendre le reflexe de cliquer sur « Accepter ».


Analyse de l’installation de fonctions callback

Ce type de technique est limité aux possibilités offertes par Windows. Certains évènements critiques ne pourront ainsi pas être surveillés. Pour être efficace, elle doit donc être couplée avec un hooking kernel-land, sinon, comme présenté dans le paragraphe suivant, le contournement devient possible.


Surveillance de la création de processus

Plusieurs firewalls exercent un contrôle sur la création de nouveau processus, soit en utilisant un hooking kernel-land, soit en positionnant une fonction callback au niveau Windows. La problématique est de savoir quand afficher une popup de confirmation.

Lorsque cette surveillance est activée, Kerio affiche une popup à chaque fois qu’un nouveau processus est créé. Cette implémentation génère un nombre considérable de messages, notamment lors des installations qui lancent des exécutables en cascade.

L’utilisateur risque alors de rapidement prendre l’habitude d’accepter systématiquement le lancement ou même de désactiver cette fonctionnalité. D’autres firewalls personnels, comme Look’n’Stop ont choisi de n’afficher une popup que si le programme lancé est autorisé à accéder au réseau. Cette solution permet de générer un nombre beaucoup plus faible de popups.

Cependant, si l’injection de thread est possible, cette technique peut être assez facilement contournée. Pour cela, nous allons simplement modifier la partie « Déchiffrement injecter » pour qu’elle recherche le processus « explorer.exe » et lui injecte le shellcode « injecter+RConnect ».

L’instance cachée du navigateur par défaut sera alors lancée par « explorer.exe », opération qui sera autorisée par le firewall personnel puisqu’elle est similaire à un lancement classique.

Le processus navigateur caché va alors lancer le processus « cmd.exe ». Comme celui-ci n’est reconnu comme un programme ayant droit d’accéder au réseau, le firewall n’affichera ici non plus aucune popup.

Le schéma suivant résume ce principe :






Autres ressources dans ce même dossier :

[WiShMaster - Partie 1] Introduction à l'ecriture de shellcodes en C - lien

[WiShMaster - Partie 2] Principe de shellcodisation avec WiShMaster (1) - lien

[WiShMaster - Partie 3] Principe de shellcodisation avec WiShMaster (2) - lien

[WiShMaster - Partie 4] Principe et Fonctionnement - RConnect/WiShMaster Vs firewalls personnels (1) - lien

[WiShMaster - Partie 5] Principe et Fontionnement - RConnect/WiShMaster Vs firewalls personnels (2) - lien

[WiShMaster - Partie 7] Résultat de RConnect avec des firewalls personnels et conclusion - lien