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.


Aucun commentaire:

Enregistrer un commentaire