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



dimanche 12 mars 2017

Les Hashs composite couple(Module!Function)

I.          Avant-propos


Un développeur qui écrire du code dans un programme normal en C ou C++ via Visual Studio peut utiliser les fonctions de la DLL kernel32.dll avec les Api LoadLibraryA(..) et GetProcAddress(..) pour charger des DLLs arbitraire et récupérer les pointeurs de fonctions exportées de la DLL. 
Les Auteurs de shellcode sont souvent confrontés à des contraintes de taille, donc y compris la chaîne complète de chaque fonction de l'API qu'il souhaite utiliser pourrait être prohibitif. 
Plutôt que d'utiliser la chaîne complète, une méthode efficace pour réduire la taille est de pré-calcul les hashs numériques des noms de fonctions et d'inclure ces valeurs dans le shellcode. 
Cela implique de modifie le processus de résolution d'importation dans le shellcode.
Comme le shellcode ne peuvent plus compter sur GetProcAddress pour récupérer les pointeurs de fonction. Au contraire, il devra analyser les fichiers DLL et le PE en mémoire pour trouver le répertoire d'exportation et de parcourir son éventail table des fonctions exporté. Pour chaque nom de fonction d'exportation, le shellcode calcule le hachage et la compare la valeur intrinsèque dans le shellcode. La fonction API correspondante a été trouvée lorsque les valeurs correspondent.

Cela peut sembler difficile de retrouver qu'elle hash correspond à qu'elle fonction API.Mais heureusement, la plupart des auteurs shellcode réutiliser des algorithmes et des valeurs de hachage connues, ce qui rend l'analyse de l'inverse l'ingénierie beaucoup plus simple. La fonction de hachage la plus commun que nous avons vu dans les échantillons de shellcode récupéré est inclus sur Metasploit est l'algorithme ROR13(Additive+1) ou ROR13(Additive).



Le hachage est en aucune façon une forte de hachage cryptographique, mais il accomplit le but de calculer une valeur entière basée sur une chaîne d'entrée de longueur arbitraire. La seule contrainte réelle sur l'algorithme de hachage est que chaque fonction de l'API que le développeur souhaite utiliser dans une DLL doit avoir une valeur de hachage unique, et ce simple calcul ROR-13 est très efficace. Des hashs insolites que nous avons rencontré sont généralement de légère variante de cette idée: ils peuvent soit tourner d'une valeur différente,ou tournent à gauche plutôt que à droite, ou d'utiliser d'autres opérateurs de mélanger sur les caractères de la chaîne d'entrée pour former un résultat entier.
Maintenant soyons réaliste le Ror13(Additive) ou Ror13(Additive+1) n'est plus celui qui est le plus utiliser dans les malwares depuis bien longtemps ( celle-ci est utiliser surtout pour apprendre et initialisation des jeunes à cette technique).
nous allons voir dans la suite des hashs ayant plus d'intérêt et qui on une plus forte utilisation dans les malwares.
le Hash composite qui sont une évolution naturelle du Hash de fonction vu au dessus.
Le développeur de shellcode à besoin plus souvent d'un couplé ( Module + Function )
de ce principe est née la composition qui est la comme de 2 Hashs celui du module additionner à celui du hash de la fonction  qui sont nommé soit Composite ou Hybride
Hach(Module+ Function) = Hash(Module) by (AlgoHashX) + Hash(Function) by (AlgoHashY)

II.          Introduction

Nous pouvons les caractérisés par la formule suivant:

Hach(Module+ Function) = Hash(Module) by (AlgoHashX) + Hash(Function) by (AlgoHashY)
En générale, il utilise AlgoHashX = AlgoHashY pour des raisons de simplicité du code dans les malwares. mais cela va duré qu'un temps des variants sont déjà visible sur différents sources.

de ce fait vous pouvez vous douté qu'il existe une infinité de variante possible est qui n'est pas simple de déterminer l'algorithme que l'auteur d'un malware a utilisé.

Cela peut sembler difficile, mais heureusement, la plupart des auteurs shellcode réutiliser des algorithmes composite et des valeurs de hachage connues.
Pourquoi, cela s'explique par le fait qu'il utilise souvent des codes qu'ils ont développé et cela dans des Rootkits perso ou même utilise des codes d'autre.

Voici certains hashes largement utilisés qui sont tous de tirer de  l'algorithme Hash Hybride

"Algo Hash Hybride : ( HashRor13Additive+1)Unicode Upper + (HashRor13Additive+1)Ansi"

Nous les avons regroupés par Module pour vous permettre de mieux les retrouvés

0x006B8029
"ws2_32.dll! WSAStartup"
0xE0DF0FEA
"ws2_32.dll! WSASocketA"
0x6737DBC2
"ws2_32.dll! Bind"
0xFF38E9B7
"ws2_32.dll!listen"
0xE13BEC74
"ws2_32.dll!accept"
0x614D6E75
"ws2_32.dll! Closesocket"
0x6174A599
"ws2_32.dll! Connect"
0x5FC8D902
"ws2_32.dll! Recv"
0x5F38EBC2
"Ws2_32.dll! Send"

0x5BAE572D
"kernel32.dll! WriteFile"
0x4FDAF6DA
"kernel32.dll! CreateFileA"
0x13DD2ED7
"kernel32.dll! DeleteFileA"
0xE449F330
"kernel32.dll! GetTempPathA"
0x528796C6
"kernel32.dll! CloseHandle"
0x863FCC79
"kernel32.dll! CreateProcessA"
0xE553A458
"kernel32.dll! VirtualAlloc"
0x300F2F0B
"kernel32.dll! VirtualFree"
0x0726774C
"kernel32.dll! LoadLibraryA"
0x7802F749
"kernel32.dll! GetProcAddress"
0x601D8708
"kernel32.dll! WaitForSingleObject"
0x876F8B31
"kernel32.dll! WinExec"
0x9DBD95A6
"kernel32.dll! GetVersion"
0xEA320EFE
"kernel32.dll! SetUnhandledExceptionFilter"
0x56A2B5F0
"kernel32.dll! ExitProcess"
0x0A2A1DE0
"kernel32.dll! ExitThread"

0x6F721347
"ntdll.dll! RtlExitUserThread"

0x23E38427
"advapi32.dll! RevertToSelf"

Nous avons développer un outil permettant de visualisé l'algorithme utilisé pour les cas cité au dessus :

Pour l'exemple nous allons effectué le calcule du Hash Hybride de "kernel32.dll!GetTempPathA" qui va nous donnée 0xE449F330

I.    Petit POC via un exemple de ShellCode

Nous allons voir un petit shellcode utilisant un hash composite. Ce shellcode ne fera que un simple WinExec("notepad.exe")

Nous avons besoin que le shellcode utilise l'Api "WinExec" contenu dans Kernel32.dll. Nous utiliserons un hash avec l'algorithme présenté au dessus.
 "( HashRor13Additive+1)Unicode Upper + (HashRor13Additive+1)Ansi"

Pour ce faire, nous allons utiliser un petit outil qui calcule est Hash. Cela pour vous permettre de bien comprendre le Hash . Unitairement le hash du module est 0x92AF16DA et comme il est Unicode Upper. Cela signifie que quelque soit l'écriture majuscule ou minuscule de "kernel32.dll". Vous aurez toujours la même valeur. Ce que vous pouvez visualiser sur l'outil

"Kernel32.Dll"        => 0x92AF16DA
"KeRNeL32.DLl"   => 0x92AF16DA

le Hash de "WinExec" en ROR13AdditivePlus1Ansi est 0xF4C07457



de ce fait, il est simple de construire le hash du couple (Kernel32.dll , WinExec )

0x92AF16DA + 0x92AF16DA = 0x876F8B31


Voici notre petit shellcode basique pour monter l'utilisation du Hash Hybride 0x876F8B31

\x55\x8B\xEC\x55\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B
\x52\x30\x8B\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31
\xFF\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2
\xF0\x52\x57\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0
\x74\x4A\x01\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49
\x8B\x34\x8B\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38
\xE0\x75\xF4\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01
\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89
\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12
\xEB\x86\x5D\x68\x01\x00\x00\x00\xE8\x0C\x00\x00\x00\x6E\x6F\x74
\x65\x70\x61\x64\x2E\x65\x78\x65\x00\x68\x31\x8B\x6F\x87\xFF\xD5
\x5D\x8B\xE5\x5D\xC3

Pour ce qui ne sont familiariser avec les Shellcodes ( en OpCode ), nous allons vous le transcrire en code Asm X86 via un outil d'analyse perso qui redonne le code assembleur du shellcode quelconque " EzShellCodeAnalyzerX32.exe" 





Cela donne en code Assembleur X32



 
voici le listing que nous allons étudier dans notre exemple

00000000:   55                         PUSH EBP
00000001:   8B EC                    MOV EBP,ESP
00000003:   55                         PUSH EBP
00000004:   E8 89 00 00 00       CALL 00000089h (+89h ->:00000092)
00000009:   60                         PUSHAD
0000000A:   89 E5                     MOV EBP,ESP
0000000C:   31 D2                    XOR EDX,EDX
0000000E:   64 8B 52 30            MOV EDX,DWORD PTR FS:[EDX+30h]
00000012:   8B 52 0C                MOV EDX,DWORD PTR DS:[EDX+0Ch]
00000015:   8B 52 14                MOV EDX,DWORD PTR DS:[EDX+14h]
00000018:   8B 72 28                MOV ESI,DWORD PTR DS:[EDX+28h]
0000001B:   0F B7 4A 26            MOVZX ECX,WORD PTR [EDX+26h]
0000001F:   31 FF                      XOR EDI,EDI
00000021:   31 C0                    XOR EAX,EAX
00000023:   AC                         LODSB
00000024:   3C 61                    CMP AL,61h
00000026:   7C 02                    JL 02h (rel8)(+02h ->:0000002A)
00000028:   2C 20                    SUB AL,20h
0000002A:   C1 CF 0D               ROR EDI,0Dh (13)
0000002D:   01 C7                    ADD EDI,EAX
0000002F:   E2 F0                     LOOP F0h (-FFFFFFF0h=>:00000021)Dec ECX or CX jmp if !=0
00000031:   52                         PUSH EDX
00000032:   57                         PUSH EDI
00000033:   8B 52 10                MOV EDX,DWORD PTR DS:[EDX+10h]
00000036:   8B 42 3C                MOV EAX,DWORD PTR [EDX+3Ch]
00000039:   01 D0                    ADD EAX,EDX
0000003B:   8B 40 78                MOV EAX,[EAX+78h]
0000003E:   85 C0                    TEST EAX,EAX
00000040:   74 4A                     JZ 4Ah (-FFFFFFB6h ->:0000008C)
00000042:   01 D0                    ADD EAX,EDX
00000044:   50                         PUSH EAX
00000045:   8B 48 18                MOV ECX,DWORD PTR[EAX+18h]
00000048:   8B 58 20                MOV EBX,DWORD PTR DS:[EAX+20h]
0000004B:   01 D3                    ADD EBX,EDX
0000004D:   E3 3C                    JECXZ 3Ch (-FFFFFFC4h ->:0000008B)
0000004F:   49                          DEC ECX
00000050:   8B 34 8B                MOV ESI,[EBX+ECX*4]
00000053:   01 D6                    ADD ESI,EDX
00000055:   31 FF                     XOR EDI,EDI
00000057:   31 C0                    XOR EAX,EAX
00000059:   AC                         LODSB
0000005A:   C1 CF 0D               ROR EDI,0Dh (13)
0000005D:   01 C7                    ADD EDI,EAX
0000005F:   38 E0                     CMP AL,AH
00000061:   75 F4                     JNZ F4h (rel8)(-0Ch ->:00000057)
00000063:   03 7D F8                ADD EDI,DWORD PTR [EBP-08h]
00000066:   3B 7D 24                CMP EDI,DWORD PTR [EBP+24h]
00000069:   75 E2                     JNZ E2h (rel8)(-1Eh ->:0000004D)
0000006B:   58                         POP EAX
0000006C:   8B 58 24                MOV EBX,DWORD PTR DS:[EAX+24h]
0000006F:   01 D3                     ADD EBX,EDX
00000071:   66 8B 0C 4B           MOV CX,WORD PTR DS:[EBX+ECX*2]
00000075:   8B 58 1C                MOV EBX,DWORD PTR DS:[EAX+1Ch]
00000078:   01 D3                    ADD EBX,EDX
0000007A:   8B 04 8B                MOV EAX,[EBX+ECX*4]
0000007D:   01 D0                    ADD EAX,EDX
0000007F:   89 44 24 24            MOV DWORD PTR[ESP+24h],EAX
00000083:   5B                         POP EBX
00000084:   5B                         POP EBX
00000085:   61                         POPAD
00000086:   59                         POP ECX
00000087:   5A                         POP EDX
00000088:   51                         PUSH ECX
00000089:   FF E0                     CALL EAX
0000008B:   58                         POP EAX
0000008C:   5F                         POP EDI
0000008D:   5A                         POP EDX
0000008E:   8B 12                     MOV EDX,DWORD PTR [EDX]
00000090:   EB 86                     JMP 86h (-7Ah ->:00000018)
00000092:   5D                         POP EBP
00000093:   68 01 00 00 00       PUSH 00000001h ""
00000098:   E8 0C 00 00 00       CALL 0000000Ch (+0Ch ->:000000A9)
                                               db "notepad.exe"
0000009D:   6E 6F 74 65 70 61 64 2E 65 78 65 00
000000A9:   68 31 8B 6F 87       PUSH 876F8B31h "1‹o‡"
                                               (876F8B31=Hash[Ror13-Hybrid](Kernel32.dll!WinExec)
000000AE:   FF D5                     CALL EBP
000000B0:   5D                         POP EBP
000000B1:   8B E5                     MOV ESP,EBP
000000B3:   5D                         POP EBP
000000B4:   C3                         RET


Nous allons simplifier la compréhension du shellcode, l'outil dispose de signature de fonction basique présent dans le shellcode. Cela permet de donner une le lecture plus simple et débuter l'analyse de ShellCode sans détaille technique. Cela avez crée pour détecter les souches de code utiliser entre différents shellcode disponible sur le Net.


Les Hashs de Dridex

Les Hash ROL9XOR(Additive+1)

Lors de l'analyse de "Dridex", nous avons pu observer que les Hashs utilisés sont de type ROL9XOR(Additive+1)


I.    Liste de hash de fonction de l'API résolus connue dans Dridex

Hash Value
API Function
0AB48C65
LdrLoadDll
DE604C6A
RtlDosPathNameToNtPathName_U
925F5D71
RtlFreeAnsiString
EFD32EF6
LdrProcessRelocationBlock
B8E06C7D
RtlComputeCrc32
831D0FAA
RtlExitUserThread
A62BF608
NtSetInformationProcess
102DE0D9
NtAllocateVirtualMemory
7CD8E53D
NtFreeVirtualMemory
6815415A
NtOpenFile
E7F9919F
NtQueryDirectoryFile
64C4ACE4
NtClose
028C54D3
memcpy
82D84ED3
memset

II.          Analyse de l'algorithme de Hash

Nous savons que celui-ci est basé sur un ROL 9 vu les différents échantillons
Nous avons pu déterminer cela avec l'outil "Api Hash Predator V1.7"

Prenons l'exemple de l'API "LdrLoadDll" dont la valeur du hash est '0AB48C65'



l'algorithme ROL9 reconstruit à partir de la capture Asm du code nous donne le même résultat que ROLXOR(Additive+1)