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 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.
Aucun commentaire:
Enregistrer un commentaire