Affichage des articles dont le libellé est ollydbg. Afficher tous les articles
Affichage des articles dont le libellé est ollydbg. Afficher tous les articles

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 !

samedi 16 février 2008

samedi 2 février 2008

3v1l 0r n0t ? - Part I.

Bonjour à tous,
Me revoilà avec un petit article, celui-ci traitera de l’analyse d’un malware récent : naked.com.
Cette analyse m’a prit pas mal de temps en effet, j’y est donc consacré deux semaines (ce qui explique l’absence de post la semaine dernière).
Ceci dit, celui-ci sera un peu plus long.

Conseils préliminaires :

-Tous d’abord, si vous comptez lancer le vers, munissez vous d’une machine virtuel (vmware par exemple).
Personnellement j’ai utilisé vmware, avec une machine virtuel où j’y ai installé Windows.

-Ensuite je vous conseil d’utiliser la fonction ’snapshot’ de vmware, celle-ci permet de prendre une image du système tel que, au cas ou vous voudriez revenir avec un système vierge de toute infection, on charge l’image de notre Windows et nous revoilà avec un système vierge.

-De plus, des outils sont nécessaire pour analyser un peu le malware, on ne peut pas se passer de désassembleur et d’un débuggeur bien évidemment.
En ce qui me concerne, j’utiliserais IDA ainsi qu’OllyDbg en tant que débuggeur.
Je voulais aussi ajouter que IDA est vraiment un outil, tout simplement merveilleux. Ce qu’il apporte en plus, c’est tout d’abord la possibilité de renommer les variables, les fonctions et j’en passe.
Le dump devient de plus en plus lisible, car il vous appartient!
Profitez pleinement de ce gros avantage.
Mais on peut citer des outils, comme RegMon , snort, ProcessExplorer, ou encore Wireshark, sans oublier les exécutables natifs comme regedit.
Ceci dis, si vous avez confiance en vous et en votre analyse, le débuggeur et le désassembleur suffira .

-Une dernière petite chose qu’il faut à mon goût penser, c’est que nous partons sur la base que l’exécutable à analyser peut faire n’importe quoi ; c’est pour cela je vous conseil de désactivé l’accès à tous types de réseaux, que ce soit un réseau local ou autres.

Je pense avoir résumé le tout, vous êtes à présent apte à analyser un petit malware.

Je tiens à préciser que je ne fournirais aucun binaire relatif à mon analyse, afin d’éviter toutes détériorations massives par des kiddies ou autres.
Au cours de ce petit post, je vais présenter les actions de notre petit malware.
Si il y a des passages où l’analyse est erroné, n’hésiter pas à prendre contact avec moi, il s’agit de ma première analyse de malware.

Je vous file quelques petits papers qui peuvent être intéressant à lire avant :

-http://www.netix.free.fr/tutos/ida/ida1/ida1.htm -> prise en main d’IDA.
-http://milw0rm.com/papers/133 -> Anatomy of a Malware, ce pdf vous présente une analyse concrète avec dumps.

Après c’est quelques avertissements, nous allons pouvoir attaquer le vif du sujet.

Premier contact avec le loader.

Nous allons tout d’abord vérifier si notre exécutable est protégé contre le reversing.
Il peut être en effet packer, ce qui peut nous gêner au cours de notre analyse.
Je lance un coup de PEID sur l’exécutable.




Je vais donc aller, regarder du côté des sections de l’exécutable et là..



Le nom des sections est UPX0 etc. En tant qu’être normalement constitué, je télécharge le packer UPX, et puis je le test avec sa fonction d’ unpack sur mon exécutable.
Je relance PEID, pour voir si ce n’était pas un vilain trick du codeur.





Le ton est a priori donné, nous allons débuguer/désassembler un code C/C++, une bonne nouvelle me direz vous.

Trip in da binaire

Et nous voilà partis, IDA d’un côté, et Olly de l’autre, nous sentons l’adrénaline qui monte, let's go !!
Dès le début de notre analyse, on remarque des actions plutôt bizarre : on se retrouve avec des appels aux apis GetTickCount et Sleep().
C’est à ce moment là que l’on se demande a quoi il joue : c’est en faite très simple, il s’agit d’un anti-debug (abrégé anti-dbg ).
Si l’exécutable est debuggué il se peut, que vous allez rester du temps sur une instructions, or si le sleep dure plus de temps (millisecondes) que celui demandé, on se retrouvera avec une différence de seconde!
Bon, un petit anti-dbg qui vaut pas grand-chose à mon avis, continuons.
Nous tombons, sur une routine qui va décrypter une chaîne de caractères : c’est enfaîte un xor de la lettre avec le nombre 139.
Un petit code C est fournis en fin d’article pour décoder ce genre de chaîne.
Nous avançons, on manipule des structures du type PROCESS_INFORMATION et STARTUPINFO, on flag les structures de façons a avoir une fenêtre caché, si un éventuel appel à CreateProcess.
On récupère à présent le path sur le dossier temporaire de la bécane, grâce à GetTempPath(), c’est un peu plus loin que l’on va formater une chaîne de caractère du type : DossierTemporaire\services.exe.
On se doute que ce fichier sera, le cœur de notre ver.
Nos petites suppositions était loin d’être fausse, car le loader va créer ce fichier dans le dossier temporaire justement, on y écris le code binaire qui est stocké dans le loader.
On lance alors le processus, services.exe, précédemment créer (d’où le flag des structures etc.).

Nous voilà déjà avec un binaire pas très gentil (supposons) de créer, et de lancer.
Continuons!

Afin de ne pas alerter la victime, le loader va tout d’abord, créer un fichier image.jpg dans le dossier courant, pour après allez l’afficher dans une fenêtre.
Me direz vous, il faut pas être très fin pour ne pas se douter de quelque chose, mais passons.
Voilà, le loader s’arrête ici.
A présent, analysons services.exe.

Services.exe, un parfait cachottier.

De retour, accompagné de nos fidèles instruments.
Petit reflex, vérifié si l’exécutable n’est pas protégé.



Première chose que nous remarquons d’intéressants, c’est bien sure l’appel à deux calls.
On s’engage droit dedans, on trace, on trace, de call en call, les routines s’éclaircissent.
On comprend peu à peu qu’il s’agit enfaîte des routines qui se chargent de décrypter toutes les chaînes dont le programme aura besoin.
Et cela, grâce a un xor de la lettre et du chiffre 7 cette fois-ci.
Le programme fait ensuite appel aux APIs GetProcAddress et GetModuleHandle afin de récupérer l'adresse des API qui lui seront utile par la suite.
Une fois ceci effectué, on constate une injection de code dans l’explorer.exe!
Rien de bien croustillant, juste un control au niveau de la mutes ainsi qu’un WinExec sur le services.exe justement.
On ne se décourage, on continus.
Cette fois-ci nous arrivons sur une récupération de pointeur sur la fonction InternetReadFile exportée par WinInnet.dll, on génère ensuite une chaîne de caractères de 6lettres, et là.. On télécharge un fichier hébergé à l’adresse : http://james.ccpower.ru/dima.exe, le fichier est donc enregistrer sous le nom de la string précédemment généré dans le répertoire courant.
(Par faute de temps je n’ai pas analysé cette exécutable, si une personne l’a déjà fait, qu’il me fasse signe merci.)
Une fois le fichier écrit, on l’exécute bien évidemment.
A présent, on aperçoit plusieurs apis/fonctions permettant de formater des chaînes de caractères.
Tout d’abord, on formate une chaîne du genre : « C:\\services.exe:*:Enabled:Flash Player2 » ..
Mais pourquoi?!
Juste en dessous, on crée une clé dans la base de registre Windows, a cette emplacement : « HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ » sous le nom de FlashPlayer2..le petit vilain : ).



On a bien compris, cette clé va permettre d’assurer l’exécution de l’exécutable lors des redémarrages de l’ordinateur.
Une autre clé de créer, cette fois ci c’est ici : « HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\
Parameters\\FirewallPolicy\\StandardProfile\\AuthorizedApplications\\List\\
» avec pour nom le path vers l’exécutable, et pour valeur le full path concaténé avec « :*:Enabled:Flash Player2 » (d’où notre formatage de chaîne de caractère précédemment).
Cette clé va permettre d’autoriser les connections de services.exe, le firewall Windows ne viendra donc pas afficher de message d‘alerte par exemple.
Mais, une question devrait vous venir à l’esprit : le « :*:Enabled:Flash Player2 », que signifie t-il?
Hum apparemment, c’est histoire de tromper l’utilisateur.
Allez donc voir dans le panneau de configuration, dans les propriétés du firewall de Windows, dans les exceptions.. Que voit-on? Flash Player2 : ).



A présent, la dernier clé ajouté à l’emplacement : « HKEY_CLASSES_ROOT\\.htc ».
On y créer une clé qui se prénomme : Content Type avec la valeur ryan1918.com.
Bon, cette fois ci c’est plutôt explicite, on change le mime type des fichiers .htc.




Nous continuons, jusqu’à tomber sur une routine de décryptage de chaîne de caractères, on y trouve des messages en toutes langues du genre : « c'est pas toi?!! » ou « emoticon with your face ».
Ces messages correspondraient normalement a ceux envoyé par MSN afin d’assurer la propagation du ver.
Nous arrivons à la fin, le plus juteux sûrement, une socket!
En analysant un peu les routines, on constate que c’est enfaite une connection sur un serveur irc (asl.aldanma.net) sur le port tcp 7575.
Cependant, le malware prend le soin de récupérer des informations sur lequel il est lancé, comme la langue utilisé (par le biais de GetLocaleInfo).
Ensuite on formate une chaîne de caractères qui nous servira de pseudo sur le serveur, une chaîne du style : « [FRA-0H-avwooezrf ».
C’est ici que la première partie de cet article s’arrête : ).
J’ai décidé de traiter le dernier call, le plus intéressant et le plus long à analyser, la semaine prochain donc, cela vous laisse le temps de mener votre petit enquête vous aussi.

Mais normalement.. Une question subsiste.
Lors de l’injection de code dans l’explorer au début de notre malware, comment peut-on bien faire pour debugguer la routine lancée par le thread?
Je vais vous filer une petite astuce.

Tout d’abord, créer vous un programme bidon, une messagebox tout simplement.
Nous allons l’ouvrir avec Olly, lancer le prog, et donc ne pas valider la messagebox, de sorte que le processus reste en debug.
Ensuite, nous ouvrons notre malware sous Olly.
Nous arrivons a l’OpenProcess(), nous allons alors modifié le PID du processus sur lequel on va créer le remote thread, de sorte a pouvoir le debugguer.
On modifie donc le registre qui va être pusher pour l’appel a OpenProcess.
Nous allons donc ouvrir notre processus ’bidon’, notre messagebox.
Ensuite au moment du VirtualAllocEx, nous récupérons dans eax l’adresse sur laquelle on a écrit les données.

On retourne du côté de notre messagebox sous Olly, et on s’en va rechercher cette adresse justement.
« No Memory Address », bien évidemment Olly n’est pas au courant que nous avons allouer de la mémoire dans le processus (VirtualAllocExec), on va donc dans view, puis Memory.
Nous recherchons donc notre adresse, et là magique ça fonctionne!
A présent nous posons un break point sur la routine, et nous allons lancer le CreateRemoteThread à partir du Olly qui debug notre malware.
Et BIM ça break!

Voilà une petite astuce permettant de pouvoir tracer une routine créer dans un autre processus.

Ce petit article, est donc terminé, en espérant avoir été clair, et vous avoir apporter quelque chose.
Cette analyse, m'aura beaucoup apporter, que ce soit au niveau de la manipulation d'outil tel que OllyDbg et IDA, mais aussi sur le plan de la compréhension par le biais de dump asm.
N'hésiter donc pas, à analyser un binaire, que ce soit un malware ou pas, on y trouve souvent des petites techniques intéréssantes au niveau coding.

Je vous file un petit code permettant de décrypter des chaînes qui sont xorer avec une certaine clé ainsi qu‘un petit pack contenant les binaires et les .idbs (faites en bonne usage):
-Dexor.c.
-Pack_Analyse_Naked.com.rar.

Cya.

PS : Merci à Baboon!