vendredi 7 février 2020

Le ransomware Clop, l'algorithme de Hash



I.    Introduction

Ce nouveau ransomware a été découvert pas Michael Gillespie le 8 février 2019.

L'objectif principal de Clop est de crypter tous les fichiers d'une entreprise et de demander un paiement pour recevoir un décrypteur pour décrypter tous les fichiers concernés.

Pour y parvenir, nous avons référencé quelques nouvelles techniques utilisées par les auteurs de cette famille de malware qui n'etait  ne semble jamais vues auparavant sur ce type programme.

Il est clair qu'au cours des derniers mois, nous avons vu apparaître des techniques plus innovantes dans les ransomwares et qui continue à évoluer.

Dans cette article, nous allons surtout regarder la partie des hashs utilisé. Cela pour effectué des regroupement avec d'autre type de malware.

II.          Référence des hashs


A partir d'information disparate existant sur le web, nous avons regroupé des hachs utilisés par le ransomware.
 
Pour la partie recherche des folders

Hash
String Folder
0xE892B59F
WINDOWS
0x0853E7D4
BOOT
0xBEBA4434
PROGRAM FILES
0x621EC8D1
PROGRAM FILES (X86)
0x1BE85856
ALL USERS
0x0D6CC512
LOCAL SETTINGS
0x971F3464
PROGRAMDATA
0x28B5FD61
TOR BROWSER
0x08916CC4
APPDATA
0x8A53E4D9
CHROME
0x55B2AC88
SYSTEM VOLUME INFORMATION
0x6932F547
PERFLOGS

Pour la partie recherche de processus en cours d'exécution

Hash
String Process
0x9153962A
MSFTESQL.EXE
0x04540E56
SQLAGENT.EXE
0xF767B2C3
SQLBROWSER.EXE
0xF2780D43
SQLWRITE.EXE
0x87526206
ORACLE.EXE
0x0A5622D9
OCSSD.EXE
0x4776560A
DBSNMP.EXE
0x16723C4E
SYNCTIME.EXE
0x0D0A9207
AGENTSVC.EXEISQLPLUSSVC.EXE
0x36DEB6D0
XFSSVCCON.EXE
0x76505296
SQLSERVR.EXE
0x41C3F023
MYDESKTOPSERVICE.EXE
0x06421B08
OCAUTOUPDS.EXE
0xFD2A6DFD
AGENTSVC.EXEAGNTSVC.EXE
0x255A866D
AGENTSVC.EXEENCSVC.EXE
0x96631362
FIREFOXCONFIG.EXE
0xAED6267A
TBIRDCONFIG.EXE
0x5E2AC3B4
MYDESKTOPQOS.EXE
0x9A565229
OCOMM.EXE
0x9C762A07
MYSQLD.EXE
0x8D82EED8
MYSQLD-NT.EXE
0x6C1026A4
MYSQLD-OPT.EXE
0x404C60CF
DBENG50.EXE
0xD3857BB5
SQBCORESERVICE.EXE
0x80606269
EXCEL.EXE
0xCA795942
INFOPATH.EXE
0xF65FCE38
MSACCESS.EXE
0x68762EE9
MSPUB.EXE
0x104C4106
ONENOTE.EXE
0x614841D3
OUTLOOK.EXE
0x807E3DDB
POWERPNT.EXE
0x86787A49
STREAM.EXE
0x0D5A6662
THEBAT.EXE
0x8758AFD4
THEBAT64.EXE
0xD20D9AA1
THUNDERBIRD.EXE
0xA3422209
VISIO.EXE
0x8B7E4735
WINWORD.EXE
0x97583BAE
WORDPAD.EXE

III.     Algorithme de création des hashs


Nous avons vérifier quelques algorithmes connue ou utilisés par d'autre malware pouvez génére ce type de hash à partir de ces listings

En testant différents algorithmes, nous somme arrivé sur un algorithme  ROL7XOR de hash

Nous mettons la capture écran de l'un de nos outils qui a permit d'arriver à cette conclusion

 



















 


Pour vous permettre de plus facilement trouver des relations avec cette algorithme. Il est plus simple de cherche sur le hash 0x1FC0EAEE qui correspond à l'Api "GetProcAddress"
L'intérêt est que vous aurez plus facilement trouver des sources python ou asm.

Dans le cas de recherche cela permet de revenir au quelques Apis utiliser comme référence d'école. Comme pour exemple que nous traitons par la suite, la recherche aurait pu se porter sur le hash 0xABBC680D correspondant à l'api "MessageBox"

Mais en générale, on porte sur des api dit de socle de base comme "LoadLibrayA", "GetProcAddress".. etc.

Nous mettons l'algorithme crée du hash ROL7XOR en C++ en dessous:

// Version traitant une chaîne ansi  par Algo Rol7Xor pour le calcule de Hash
DWORD CalcHashA_ROL7XOR_MalwareRef2_C_V1(char* Str )
{
            if (!Str ) return -1;

            DWORD dwHash = 0;
            char *CopyStr = Str;

            while ( *CopyStr != 0)
            {
                        dwHash = (( dwHash << 7 ) & (DWORD)( -1 ) ) | ( dwHash >> ( 32 - 7 ));
                        dwHash = dwHash ^ ( *CopyStr );
                        CopyStr++;
            }

            return dwHash;
}
  
Nous avons intégré à un testeur dédié au hash du ransomware Clop.



 

Nous pouvons donc fixer, le fait qu'il utilise bien cette algorithme pour les hashs cité

IV.    Allons plus loin dans ses hashs ROL7XOR


Nous avons cherché quelques sites parlant ou référent le hash 0x1FC0EAEE au travers de google.

Nous arrivons sur Hesperbot un trojan bancaire est lui aussi utilise des hashs sur ce même algorithme Rol7Xor

Hash
Api
0x1FC0EAEE
GetProcAddress
0xC8AC8026
LoadLibraryA
0xA9DE6F5A
VirtualProtect
0x697A6AFE
VirtualAlloc
0x3A35705F
VirtualFree

Nous allons maintenant partir sur la création d'un exécutable via nasm qui à pour but d'appeler une MessageBox et utilisant des hash Rol7Xor pour déterminer les adresses des Apis. Cela est un bonne exemple pour manipuler ses hashs

Nous mettons le listing du fichier "CodeAsmRol7XorExB2.asm" en dessous:

[BITS 32]
[SEGMENT .text]
                          GLOBAL __WinMainCRTStartup ;Masm poLink

__WinMainCRTStartup:
;Step(1) : Get Kernel Base(read it from PEB,NT ONLY).
mov eax,[fs:30h]
mov eax,[eax+0Ch]
mov esi,[eax+1Ch]
lodsd
mov ebx,[eax+08h]
;Step(2) : Find 'GetProcAddress' address.
push 0x1FC0EAEE; hashed Rol7Xor 'GetProcAddress'
push ebx ;kernel32 base
call .getproc
mov ecx,eax
;Step(3) : Find 'LoadLibraryA' address.
push 0xC8AC8026 ; hashed Rol7Xor 'LoadLibraryA'
push ebx ;kernel32 base
call .getproc
;Step(4) : Load the 'user32.dll'
push DWORD sUser32
call eax
;Step(5) Find 'MessageBoxA' address.
push 0xABBC680D    ;hashed Rol7Xor 'MessageBoxA'
push eax ;user32 base
call .getproc
;Step(6) Testing,now in eax pointer to 'MessageBoxA' func.
;i dont use here(push 0) if it 4 times pasted = 8 bytes,i use:
;(xor ecx,ecx) and 4 times (push ecx) = 6 bytes
xor ecx,ecx
push 0                                     ; 0x0 <=> MB_OK
push DWORD sMsgText
push DWORD sMgCaption
push 0             ; hWnd =0x0 ( NULL )
call eax
ret

.getproc:
pushad
mov eax,[esp+0x24] ;module handle
mov ebx,eax ;save module handle
add eax,[eax+3Ch];pe header
mov edx,[eax+78h];export table rva
add edx,ebx ;module handle
mov ecx,[edx+0x18];Num of Name Pointers
mov edi,[edx+0x20];Name Pointers RVA
add edi,ebx ;module handle
.getproc_scan:
mov esi,ebx ;module handle
add esi,[edi+(ecx-1)*4] ;poiner to apiname
xor eax,eax
.getproc_hash:
rol eax,7
xor al,[esi]
inc esi
cmp byte[esi],0
jnz .getproc_hash
xor eax,[esp+0x28] ;~cmp ... if eax=[esp+0x28] then eax =0 and jump
jz .getproc_found
loop .getproc_scan
xor eax, eax
jmp .getproc_quit
.getproc_found:
mov eax,[edx+28h+(ecx-1)*4]
add eax,ebx
.getproc_quit:
mov dword[esp+01Ch],eax ; return result on eax
popad
retn 8

[SEGMENT .rdata]
               sUser32        DB "user32",0
                                      sMsgText      DB "ExB (9B113D1A)",0
                                      sMgCaption   DB "Use Hash Rol7Xor",0

Pour compilé le fichier .asm , vous pouvez taper directement la ligne


C:\NASM\nasm.exe -f win32 C:\Asm\ExB\CodeAsmRol7XorExB2.asm -o C:\Asm\ ExB\CodeAsmRol7XorExB2.obj


Pour notre part, nous utilisons un outil maison qui est conçu pour faire cela en mode graphique.

 
Pour le linkage le fichier obj généré, il vous suffit de taper


C:\PellesC\Bin\PoLink.exe /SUBSYSTEM:WINDOWS /LIBPATH:C:\Asm\Library\X32 kernel32.lib user32.lib  C:\Asm\ExB\CodeAsmRol7XorExB2.obj


Notre dans mon cas, nous avons fixer le répertoire ou se trouve les lib

Mais si vous avez fait une installation standard de PoLink, vous avez que à taper


C:\PellesC\Bin\PoLink.exe /SUBSYSTEM:WINDOWS C:\Asm\ExB\CodeAsmRol7XorExB2.obj


nous avons plus qu'a lancer notre exécutable généré



Maintenant, nous allons compilé en mode bin et lire les opcodes généré

vous pouvez effectué cela en tapant la ligne suivant:


C:\NASM\nasm.exe -f bin C:\Asm\ExB\CodeAsmRol7XorExB2..asm -o C:\Asm\ExB\CodeAsmRol7XorExB2.bin


Nous le fessons à partir de notre outil qui permet également l'affichage en mode shellcode le fichier binaire généré.


 


<ATTENTION>

 Ce shellcode contient des références constant, ce qui implique qu'il n'est pas indépendant de la localisation du code. Cela est fonctionnelle pour générer des exécutables. Mais pas pour un shellcode à but relogeable et indépendant de l'emplacement.

Nous avons modifiés les éléments de chaîne avec une référence constante et sauvegarde des registres avec l'ajout d'un prolog & epilog sur le code et ainsi avoir un code relogeable et également permettant effectuer un l'appel en fonction.


Cela donne le fichiers assembleur suivant:

[BITS 32]
[SEGMENT .text]
                                 GLOBAL __WinMainCRTStartup ;Masm poLink

__WinMainCRTStartup:

PUSH EBP
MOV EBP,ESP

pushad

;Step(1) : Get Kernel Base(read it from PEB,NT ONLY).
mov eax,[fs:30h]
mov eax,[eax+0Ch]
mov esi,[eax+1Ch]
lodsd
mov ebx,[eax+08h]
;Step(2) : Find 'GetProcAddress' address.
push 0x1FC0EAEE; hashed Rol7Xor 'GetProcAddress'
push ebx ;kernel32 base
call .getproc

mov ecx,eax
;Step(3) : Find 'LoadLibraryA' address.
push 0xC8AC8026 ; hashed Rol7Xor 'LoadLibraryA'
push ebx ;kernel32 base
call .getproc

;Step(4) : Load the 'user32.dll'
;push DWORD sUser32

jmp .get_user32_Start
.get_user32_return:

call eax

;Step(5) Find 'MessageBoxA' address.
push 0xABBC680D    ;hashed Rol7Xor 'MessageBoxA'
push eax ;user32 base
call .getproc

;Step(6) Testing,now in eax pointer to 'MessageBoxA' func.
;i dont use here(push 0) if it 4 times pasted = 8 bytes,i use:
;(xor ecx,ecx) and 4 times (push ecx) = 6 bytes
xor ecx,ecx
push 0                                   ; 0x0 <=> MB_OK
;push DWORD sMsgText
;push DWORD sMgCaption

jmp  .get_MsgText_Start
.get_MsgText_return:

jmp  .get_MgCaption_Start
.get_MgCaption_return:

push 0             ; hWnd =0x0 ( NULL )
call eax

popad

MOV ESP,EBP
POP EBP
RET

.getproc:
pushad
mov eax,[esp+0x24] ;module handle
mov ebx,eax ;save module handle
add eax,[eax+3Ch];pe header
mov edx,[eax+78h];export table rva
add edx,ebx ;module handle
mov ecx,[edx+0x18];Num of Name Pointers
mov edi,[edx+0x20];Name Pointers RVA
add edi,ebx ;module handle
.getproc_scan:
mov esi,ebx ;module handle
add esi,[edi+(ecx-1)*4] ;poiner to apiname
xor eax,eax
.getproc_hash:
rol eax,7
xor al,[esi]
inc esi
cmp byte[esi],0
jnz .getproc_hash
xor eax,[esp+0x28] ;~cmp ... if eax=[esp+0x28] then eax =0 and jump
jz .getproc_found
loop .getproc_scan
xor eax, eax
jmp .getproc_quit
.getproc_found:
mov eax,[edx+28h+(ecx-1)*4]
add eax,ebx
.getproc_quit:
mov dword[esp+01Ch],eax ; return result on eax
popad
retn 8

.get_user32_Start:
call .get_user32_return
 DB  "user32",0

 .get_MsgText_Start:
call .get_MsgText_return
DB "ExB (9B113D1A)",0

 .get_MgCaption_Start:
call .get_MgCaption_return
DB "Use Hash Rol7Xor",0


Nous avons compilé ce code assembleur avec notre outils comme précedament.


Nous vous mettons en dessous le shellcode généré

\x55\x89\xE5\x60\x64\xA1\x30\x00\x00\x00\x8B\x40\x0C\x8B\x70\x1C
\xAD\x8B\x58\x08\x68\xEE\xEA\xC0\x1F\x53\xE8\x2D\x00\x00\x00\x89
\xC1\x68\x26\x80\xAC\xC8\x53\xE8\x20\x00\x00\x00\xEB\x62\xFF\xD0
\x68\x0D\x68\xBC\xAB\x50\xE8\x11\x00\x00\x00\x31\xC9\x6A\x00\xEB
\x5B\xEB\x6D\x6A\x00\xFF\xD0\x61\x89\xEC\x5D\xC3\x60\x8B\x44\x24
\x24\x89\xC3\x03\x40\x3C\x8B\x50\x78\x01\xDA\x8B\x4A\x18\x8B\x7A
\x20\x01\xDF\x89\xDE\x03\x74\x8F\xFC\x31\xC0\xC1\xC0\x07\x32\x06
\x46\x80\x3E\x00\x75\xF5\x33\x44\x24\x28\x74\x06\xE2\xE5\x31\xC0
\xEB\x06\x8B\x44\x8A\x24\x01\xD8\x89\x44\x24\x1C\x61\xC2\x08\x00
\xE8\x99\xFF\xFF\xFF\x75\x73\x65\x72\x33\x32\x00\xE8\xA0\xFF\xFF
\xFF\x45\x78\x42\x20\x28\x39\x42\x31\x31\x33\x44\x31\x41\x29\x00
\xE8\x8E\xFF\xFF\xFF\x55\x73\x65\x20\x48\x61\x73\x68\x20\x52\x6F
\x6C\x37\x58\x6F\x72\x00

Nous avons passé dans un désassembleur maison, pour voir la traduction des opcodes générés et aussi l'intérêt de l'outil est qui est plus facile pour visualiser les chaînes.


Nous mettons le listing, pour voir la globalité des opcodes en dessous sous forme texte:


00000000:   55                                                      PUSH EBP
00000001:   89 E5                                                 MOV EBP,ESP
00000003:   60                                                      PUSHAD
00000004:   64 A1 30 00 00 00                             MOV EAX,DWORD PTR FS:[00000030]
0000000A:   8B 40 0C                                           MOV EAX,DWORD PTR[EAX+0x0C]
0000000D:   8B 70 1C                                           MOV ESI,DWORD PTR[EAX+1Ch]
00000010:   AD                                                     LODSD (Loads DS:[SI](ESI for LODSD) val into AL,AX,EAX and inc SI)
00000011:   8B 58 08                                            MOV EBX,DWORD PTR [EAX+08h]
00000014:   68 EE EA C0 1F                                 PUSH 1FC0EAEEh
00000019:   53                                                      PUSH EBX
0000001A:   E8 2D 00 00 00                                 CALL 0x0000002D (+2Dh ->:0000004C)
0000001F:   89 C1                                                 MOV ECX,EAX
00000021:   68 26 80 AC C8                                 PUSH C8AC8026h
00000026:   53                                                      PUSH EBX
00000027:   E8 20 00 00 00                                  CALL 0x00000020 (+20h ->:0000004C)
0000002C:   EB 62                                                 JMP 62h +62h ->:00000090)
0000002E:   FF D0                                                 CALL EAX
00000030:   68 0D 68 BC AB                                PUSH ABBC680Dh
00000035:   50                                                      PUSH EAX
00000036:   E8 11 00 00 00                                  CALL 0x00000011 (+11h ->:0000004C)
0000003B:   31 C9                                                 XOR ECX,ECX
0000003D:   6A 00                                                PUSH 00h (0) '
0000003F:   EB 5B                                                 JMP 5Bh +5Bh ->:0000009C)
00000041:   EB 6D                                                 JMP 6Dh +6Dh ->:000000B0)
00000043:   6A 00                                                 PUSH 00h (0) '
00000045:   FF D0                                                 CALL EAX
00000047:   61                                                      POPAD
00000048:   89 EC                                                 MOV ESP,EBP
0000004A:   5D                                                     POP EBP
0000004B:   C3                                                      RET
0000004C:   60                                                      PUSHAD
0000004D:   8B 44 24 24                                       MOV EAX,DWORD PTR[ESP+0x24]
00000051:   89 C3                                                 MOV EBX,EAX
00000053:   03 40 3C                                            ADD EAX,DWORD PTR[EAX+0x3C]
00000056:   8B 50 78                                            MOV EDX,DWORD PTR [EAX+78h]
00000059:   01 DA                                                ADD EDX,EBX
0000005B:   8B 4A 18                                           MOV ECX,[EDX+18h]
0000005E:   8B 7A 20                                           MOV EDI,[EDX+20h]
00000061:   01 DF                                                 ADD EDI,EBX
00000063:   89 DE                                                 MOV ESI,EBX
00000065:   03 74 8F FC                                       ADD ESI,PTR[EDI+ECX*4-0x04]
00000069:   31 C0                                                 XOR EAX,EAX
0000006B:   C1 C0 07                                           ROL EAX,0x07 (7)
0000006E:   32 06                                                 XOR AL,BYTE PTR[ESI]
00000070:   46                                                      INC ESI
00000071:   80 3E 00                                            CMP BYTE PTR [ESI],00h ('
00000074:   75 F5                                                 JNZ F5h (rel8)(-0Bh ->:0000006B)
00000076:   33 44 24 28                                       XOR EAX,DWORD PTR[ESP+0x28]
0000007A:   74 06                                                 JZ 0x06 (+06h ->:00000082)
0000007C:   E2 E5                                                 LOOP E5h (-FFFFFFE5h=>:00000063) Dec ECX or CX jump if !=0
0000007E:   31 C0                                                 XOR EAX,EAX
00000080:   EB 06                                                 JMP 06h +06h ->:00000088)
00000082:   8B 44 8A 24                                      MOV EAX,DWORD PTR [EDX+ECX*4+0x24]
00000086:   01 D8                                                 ADD EAX,EBX
00000088:   89 44 24 1C                                       MOV DWORD PTR[ESP+1Ch],EAX
0000008C:   61                                                      POPAD
0000008D:   C2 08 00                                            RET(imm16) 0008h
00000090:   E8 99 FF FF FF                                  CALL 0xFFFFFF99 (-67h ->:0000002E)
                                                               db "user32"
00000095:  75 73 65 72 33 32
0000009B:   00                                                     
0000009C:   E8 A0 FF FF FF                                 CALL 0xFFFFFFA0 (-60h ->:00000041)
                                                               db "ExB (9B113D1A)"
000000A1:  45 78 42 20 28 39 42 31 31 33 44 31 41 29
000000AF:   00                                                     
000000B0:   E8 8E FF FF FF                                  CALL 0xFFFFFF8E (-72h ->:00000043)
                                                               db "Use Hash Rol7Xor"
000000B5:  55 73 65 20 48 61 73 68 20 52 6F 6C 37 58 6F 72
000000C5:   00                      
                              

Il ne nous reste plus qu'à tester, ce shellcode dans un testeur




V.    Conclusions


L'intérêt si on identifie la méthode de génération des hashs d'api, on peut lister les Apis utiliser par le programme malveillant et aussi faire des rapprochement entre des échantillons
différents. Les auteur de ce programme utilise des sous-routines ou bloc qui on déjà fait leurs preuve dans d'autre projet et testé . Donc si on part du fait, que ses auteurs on utilisé des codes qu'il aurait tiré de leurs expériences. Ils ont soit écrit des shellcodes ou des fichiers asm.
Et s'ils sont partie de compilateur évolué comme Visual Studio, les blocs propres ou métier
ne sont probablement pas récrit totalement.

Il ne faut pas oublier que cela peut prendre du temps de crée ses blocs de code comme tous développeurs. Ils se construisent des tools kits de développement au cours du temps pour capitaliser leurs travaux.
Il ne réécrit pas tous mais assembles des blocs comme des classes métier ou dédié à des opérations précise.

Il est assez, bizarre également que dans ce type de malware soit intégré des restrictions sur des payes à ne pas infecter en contrôlant le "keyboard layout" via l'api GetKeyboardLayout(..). On pourrait poser l'hypothèse que cela est fait pour éviter des hostilité du pays en investissant du temps à la recherche des auteurs ou qu'il peuvent aussi ne pas vouloir infecté leurs zone géographiques proches.  

Nous espérons que ce petit exemple sur le hash Rol7Xor, vous a permis de comprendre le codage en assembleur et la recherche d'algorithme de hash.