# A Deep Dive into The Grief Ransomware’s Capabilities ### Prepared by: LIFARS, LLC Date: 12/30/2021 #### 1 ----- ## EXECUTIVE SUMMARY Grief ransomware is the successor of the DoppelPaymer ransomware, which emerged from the BitPaymer ransomware. Grief is deployed in an environment already compromised by Dridex and where the threat actor performed post-exploitation activities using Cobalt Strike. The ransomware is obfuscated and employs anti-analysis techniques that include API hashing, Vectored Exception Handling (VEH) manipulation, the Heaven’s Gate technique, encrypt relevant data using RC4. Grief runs with specific parameters computed based on the victim's environment and crashes if no/incorrect parameters are provided (if you have been a victim of Grief ransomware, please [contact us). The malware deletes all Volume Shadow Copies using vssadmin and Diskshadow and](https://lifars.com/contact-us/) disables Microsoft Defender Antivirus. The encrypted files have the “.pay0rgrief” extension, and the malware imports an RSA public key that will be used to encrypt the generated AES file encryption keys. ----- ## ANALYSIS AND FINDINGS SHA256: 2d1d08fce7156053c017825b722968b3117c9230412f4e7da5f89699ec9913cd The DLL file is one of the most challenging malware samples we’ve even analyzed because of the multiple layers of obfuscation, API hashing, Vectored Exception Handling, and relevant strings decrypted at runtime using RC4. We will sequentially explain how we’ve overcome every obstacle and what challenges remain. The binary has only one export function called “RoonlpvfdRoomvlof”: Figure 1 The malware retrieves the path of the executable file of the current process (which in our case is rundll32.exe) using the GetModuleFileNameW API: Figure 2 The process gets a module handle for a module called “self.exe”: Figure 3 ----- VirtualAlloc is utilized to allocate memory in the address space of the current process (0x1000 = **MEM_COMMIT, 0x4 = PAGE_READWRITE):** Figure 4 The binary writes a new executable to the newly created memory area and transfers the execution flow to a function inside it. The LoadLibraryA routine is used to load multiple DLLs into the address space of the process: Figure 5 The GetProcAddress API is utilized to retrieve the address of export functions from multiple DLLs: Figure 6 The process changes the protection of the memory area where the malicious DLL resides by calling the VirtualProtect routine (0x4 = PAGE_READWRITE): Figure 7 ----- The original DLL’s code is modified, and a different DLL file appears in place of it. After the modifications are done, the memory protection is changed again (0x2 = PAGE_READONLY): Figure 8 The binary disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the newly created DLL: Figure 9 The final DLL represents the last stage of Grief ransomware. It has 5 export functions, however, only one is relevant in our analysis: DllRegisterServer. The other 4 exports jump in the middle of other functions, and we believe the threat actor didn’t intend to use any of them: Figure 10 ----- An important hint which suggests that the file is encrypted/obfuscated is the lack of imports: GetCommandLineW, lstrcpyW, CommandLineToArgvW, and RtlComputeCrc32. Grief, like its predecessor DoppelPaymer [1], is designed to run only with specific argument(s), otherwise it will crash. The ransomware extracts the arguments using the GetCommandLineW and CommandLineToArgvW APIs. The malware computes the CRC32 checksum of the last argument, adds 0x1EC6086B to the result, and finally adds the instruction pointer address to this final value (figure 11 is almost identical to the figure presented at [1] regarding the DoppelPaymer Control Flow Obfuscation). If no arguments/incorrect arguments are provided, the ransomware crashes. This action represents an anti-sandbox technique and a drawback for malware analysis (if you’re not the victim, of course): Figure 11 ----- We were able to find good insights even without the required arguments, based on the analysis of the most complex functions. The first anti-analysis technique we present consists of inserting lots of “int 3” (0xCC) instructions in the code. This technique is like the one employed by Dridex and explained at [2]. An example of such instructions is shown in figure 12: Figure 12 Grief registers a new customized Exception Handler by calling the RtlAddVectoredExceptionHandler API: Figure 13 The exception handler displayed in figure 14 expects an exception code as an argument. Whether the exception code is 0xC0000005 (ACCESS_VIOLATION), 0xC00000FD (STATUS_STACK_OVERFLOW), and 0xC0000374 (Heap Corruption), the malware kills itself by calling the NtTerminateProcess API. If the exception code is 0x80000003 (EXCEPTION_BREAKPOINT), the function mimics the “call eax” instruction, which means that two “int 3” instructions can be interpreted as a “call eax” instruction. We’ve patched the binary by replacing the “0xCCCC” bytes with “0xFFD0”. ----- Figure 14 Grief implements API hashing in multiple functions. The first argument is the hashed DLL name, and the 2nd argument is the hashed API name: Figure 15 Figure 16 ----- A snippet of one of the functions that parse the PEB (Process Environment Block) structure, performs XOR operations, and determines which APIs should be used, is shown below: Figure 17 The result of the above operations, which is the address of an API, is stored in the EAX register. For example, figure 18 reveals an API that is used to kill the current process: Figure 18 Capa [3] has been used to detect any encryption algorithms in our malicious DLL. It has identified the RC4 algorithm in sub_6A996248 based on the structure of the operations: ----- Figure 19 Figure 20 The CryptAcquireContextW routine is utilized to acquire a handle to a key container within a CSP (cryptographic service provider). The arguments are szProvider = "Microsoft Enhanced RSA and AES Cryptographic Provider", 0x18 = **PROV_RSA_AES,** and 0xF0000000 = **CRYPT_VERIFYCONTEXT:** ----- Figure 21 The function identified above is utilized to decrypt relevant strings using the RC4 algorithm. The RC4 key is changing frequently and has 48 bytes. We enumerate a list of decrypted strings and their explanations according to our analysis and the OSINT. Grief doesn’t encrypt the files which contain the following strings in their name and also the files that have the following extensions: Figure 22 The ransomware doesn’t encrypt the files that are located in the following directories: Figure 23 The malware also decrypts a list of environment-variable strings, which will be used as arguments for the ExpandEnvironmentStringsA function: ----- Figure 24 A list of services to be stopped is also decrypted using RC4 (see figure 25). These services might lock important files such as databases, and the ransomware wouldn’t be able to encrypt them. Figure 25 The binary also decrypts a list of Sophos services that will be stopped: ----- Figure 26 Grief appends the following extension to the file name of the encrypted files: Figure 27 The ransom note file name is also decrypted using RC4: Figure 28 An RSA public key that is Base64-encoded is decrypted by the process: ----- Figure 29 The content of the ransom note is also revealed: Figure 30 The LegalNoticeCaption and LegalNoticeText registry values will be modified to contain the client’s name, a password, and the Dark web link that needs to be accessed in order to communicate with the threat actor. We’ve redacted the company name, however, we’ve confirmed that it was listed on the Grief’s page: Figure 31 ----- Figure 32 The process also decrypts the Windows Defender Registry Key and the DisableAntiSpyware registry key, which will be utilized to turn off Microsoft Defender Antivirus: Figure 33 Figure 34 A list of commands that will be used to delete the Volume Shadow Copies is decrypted by the ransomware: Figure 35 Figure 36 Grief decrypts even more data using RC4, however, we’ve included the other less relevant strings in the appendix for completeness. The ransom note called “.iwant2survive.html” is displayed in figure 37: ----- Figure 37 ExpandEnvironmentStringsA is utilized to expand an environment-variable string and replace it with the value defined for the current user: Figure 38 The malicious process extracts the NetBIOS name of the local computer via a function call to GetComputerNameW: Figure 39 The binary acquires a handle to a key container within a CSP (cryptographic service provider) using the CryptAcquireContextW API (0x18 = **PROV_RSA_AES,** 0xF0000000 = **CRYPT_VERIFYCONTEXT):** ----- Figure 40 The CryptCreateHash function is used to create a handle to a CSP hash object (0x8003 = **CALG_MD5):** Figure 41 The binary computes the MD5 hash of the computer name by calling the CryptHashData routine: Figure 42 The hash size (16 bytes) is extracted by calling the CryptGetHashParam API (0x4 = **HP_HASHSIZE):** Figure 43 The hash value is retrieved using the same API (0x2 = HP_HASHVAL): ----- Figure 44 From our analysis and the OSINT, one of the parameters that Grief is supposed to run with is “”. Based on this observation, the parameter changes from one host to another. The binary retrieves the command line string for the current process: Figure 45 CommandLineToArgvW is utilized to parse the command line string and return an array of pointers to the cmd line arguments: Figure 46 The malicious process retrieves the path of the executable of the current process via a function call to GetModuleFileNameW: Figure 47 The ransomware also computes the MD5 hash of the string “1”: ----- Figure 48 The file creates an event object using the NtCreateEvent routine (0x1F0003 = **EVENT_ALL_ACCESS):** Figure 49 The process creates a mutant object by calling the NtCreateMutant function (0x1F0001 = **MUTEX_ALL_ACCESS):** Figure 50 The malware decodes the Base64-encoded RSA public key using the CryptStringToBinaryA function (0x1 = CRYPT_STRING_BASE64): Figure 51 ----- Figure 52 Grief decodes a structure of the **X509_PUBLIC_KEY_INFO type by calling the** CryptDecodeObject API (0x10001 = **PKCS_7_ASN_ENCODING |** **X509_ASN_ENCODING,** 0x8 = X509_PUBLIC_KEY_INFO): Figure 53 Figure 54 ----- CryptImportPublicKeyInfo is utilized to convert and import the RSA public key information into the provider (0x10001 = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING): Figure 55 The RSA public key is in the ASN.1 format, and a great explanation of this format is presented at [4]. The public key is used to encrypt the generated AES file encryption keys. We were not able to reach the point where the malware encrypts the files due to the lack of the initial parameters. Grief also implements the Heaven’s Gate technique, which is fully described at [5]. Shortly, the process running as a 32-bit binary switches to the 64-bit environment and executes some instructions there. As we can see in figure 56, the binary pushes 0x33 (the segment selector) on the stack and calls the next line. The retf instruction is a “far return” and specifies the address where the execution returns and the segment. The code that starts after the retf instruction should be interpreted as 64-bit and debugged accordingly (for example, using WinDbg because x64dbg or the IDA Pro debugger can’t be used to perform the switch). Figure 56 ----- **Deletion of Volume Shadow Copies using vssadmin and Diskshadow. Disable** **Microsoft Defender Antivirus** The ransomware initializes the COM library for use by the calling thread using the CoInitializeEx API (0x2 = COINIT_APARTMENTTHREADED): Figure 57 The binary calls the CoCreateInstance function in order to create a Group Policy Object with the CLSID {EA502722-A23D-11D1-A7D3-0000F87571E3} (0x1 = CLSCTX_INPROC_SERVER): Figure 58 The OpenLocalMachineGPO method is used to open the default GPO for the computer and load the registry information (0x1 = GPO_OPEN_LOAD_REGISTRY): Figure 59 GetRegistryKey is utilized to retrieve a handle to the root of the registry key for the computer section (0x2 = GPO_SECTION_MACHINE): ----- Figure 60 The malicious binary opens the "SOFTWARE\Policies\Microsoft\Windows Defender" registry key (0x3 = KEY_QUERY_VALUE | KEY_SET_VALUE): Figure 61 The process turns off Microsoft Defender, as well as 3rd-party antivirus software and apps by setting the “DisableAntiSpyware” registry value to 1: Figure 62 Figure 63 The Save method is used to save the specified registry policy settings to disk and update the revision number. The parameter called pGuidExtension is set to the GUID {35378eac-683f-11d2a89a-00c04fbbcfa2} and pGuid is set to {3D271CFC-2BC6-4AC2-B633-3BDFF5BDAB2A}: ----- Figure 64 The GPO object created earlier is deleted using the Delete method: Figure 65 Grief enumerates the executable files located in the System32 directory using the FindFirstFileExW routine (0x1 = FindExInfoBasic, 0x2 = FIND_FIRST_EX_LARGE_FETCH): Figure 66 The process computes a “hash” (4-byte value) of each executable name using a custom function: ----- Figure 67 The hash value is XOR-ed with 0x84794EF2, and then compared with 0x668B9032 (hard-coded value). Whether the two values aren’t equal, the malware continues the enumeration by calling the FindNextFileW API: Figure 68 The binary is looking for vssadmin.exe. It disables file system redirection for the current thread using Wow64DisableWow64FsRedirection: Figure 69 The ransomware deletes all Volume Shadow Copies using vssadmin (0x08000000 = **CREATE_NO_WINDOW):** ----- Figure 70 The process restores file system redirection for the current thread via a function call to Wow64RevertWow64FsRedirection: Figure 71 The process of enumerating the executable files from the System32 folder is repeated one more time, and the XOR-ed result is compared with 0x96164682 (hard-coded value). Based on our analysis, the targeted file is Diskshadow.exe. CryptGenRandom is utilized to generate 4 random bytes 3 times: Figure 72 The binary creates an empty temporary file with a prefix string generated based on the random bytes: Figure 73 ----- The malware retrieves the short path form of the specified path by calling the GetShortPathNameW routine: Figure 74 Grief ransomware opens the newly created file using CreateFileW (0xC0000000 = **GENERIC_READ** | **GENERIC_WRITE,** 0x5 = **TRUNCATE_EXISTING,** 0x80 = **FILE_ATTRIBUTE_NORMAL):** Figure 75 The malware calls the SetFileTime function in order to prevent file operations using the file handle from modifying the last access time and the last write time (dwLowDateTime and dwHighDateTime are set to 0xFFFFFFFF): Figure 76 The file is populated with the following content: ----- Figure 77 The ransomware deletes all Volume Shadow Copies by creating a Diskshadow process and then running the “delete shadows all” command: Figure 78 The malicious file retrieves the share names available on the local computer using the NetShareEnum API: Figure 79 ----- ## REFERENCES 1. [https://www.crowdstrike.com/blog/doppelpaymer-ransomware-and-dridex-2/](https://www.crowdstrike.com/blog/doppelpaymer-ransomware-and-dridex-2/) 2. [https://cyber-anubis.github.io/malware%20analysis/dridex/](https://cyber-anubis.github.io/malware%20analysis/dridex/) 3. [https://github.com/mandiant/capa](https://github.com/mandiant/capa) 4. [https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-](https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa) [styles-of-public-key-format-one-begin-rsa](https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa) 5. [https://blog.malwarebytes.com/threat-analysis/2018/01/a-coin-miner-with-a-heavens-](https://blog.malwarebytes.com/threat-analysis/2018/01/a-coin-miner-with-a-heavens-gate/) gate/ ----- ## APPENDIX The other strings decrypted using the RC4 algorithm are shown in the following pictures: Figure 80 Figure 81 Figure 82 ----- Figure 83 Figure 84 Figure 85 Figure 86 Figure 87 Figure 88 Figure 89 List of files and file’s extensions to be skipped: - svsho*.exe;schre*.bat;V01.lo*;V01.ch*;V01res*.jrs;RacWmi*.sdf;Web*V01.dat;default.r dp;NTUSER.DA*;*.lnk;*.ico;*.ini;*.msi;*.chm;*.sys;*.hlf;*.lng;*.inf;*.ttf;*.cmd;*.LNK;* .ICO;*.INI;*.MSI;*.CHM;*.SYS;*.HLF;*.LNG;*.INF;*.TTF;*.CMD List of directories to be skipped: - System Volume Information;$RECYCLE.BIN;$Recycle.Bin;WebCache;Caches;VirtualStore ----- List of environment-variable strings: - %ProgramData%\\Microsoft\\Windows\\WER\\ReportQueue\\;%windir%;%temp%;%A PPDATA%\\Local\\VirtualStore\\;%HOMEDRIVE%\\Documents and Settings\\All Users\\Application Data\\Application Data\\;%HOMEDRIVE%\\Users\\All Users\\Application Data\\Application Data\\;%SystemDrive%\\Documents and Settings\\All Users\\Application Data\\Application Data\\;%SystemDrive%\\Users\\All Users\\Application Data\\Application Data\\ List of services to be stopped: - msolap$*;mssql$*;sqlagent$*;reportserver$* - sophos client firewall*;sophos mcs*;sophos web intelligence*;sophospatch* Extension of encrypted files: - .pay0rgrief Grief’s Dark web site and the impacted client: - "CROMOLOGY SERVICES ... ZOLPAN, you are fu**ed." (Redacted) - "DO NOT TOUCH ANYTHING!\r\n\r\nWhat to do ( password: oN********* ):\r\nhttp[:]//payorgz3j6hs2gj66nk6omfw65atgmqwzxqbbxnqi3bv2mlwgcirunad[.]onion/ demand/da597c8432bc4458b9475627fd55eded\r\n\r\nUSE TOR.\r\n\r\nP0G_\r\n\r\n" (Redacted) ----- #### API hashing table |A169D93E B7303F40 F1E04D0E 14134842 D8FC22B5 C4B669CF 1D4786C2 2CE276DD BD63F85D 589C7CD4 2596A7DB D7509C5D 8EB1B560 22C3F66E 78120C03 ECED49A4 BC8CDE49 A88A7EA6 F5656839 86089CF3 D9DE4146 E66CC345 65C66CA1 AE320B72 F68850CB 1EF9AB7B AF2A8DE9 F246E304 BA71B979 AA297AF9 C0ED06A6 F61D52F9 459F8107 9224D8AB 8F5E891D CA2E3F55 5DCB4A66 D5D107B9 5321A741 1F442F52 99CD5D11 72A2E993 4FCE620F 84A5D7E5 569C7845 A5F904F1 6BBEA486 23820F97 8D254D22 489018E0 7E44617A A160FFA8 BBD6B3B8 2236F20A 4348FE4D E1369068 3E4FB2EF 784487EE 7D5DB015 98B31D0F 9F5CDB 565B4A16 5C52B868 7380D608 58AD2EB 5982AEC6 BBB8F37F 5E116D7D 4D05510D|ExitProcess GetCurrentDirectoryW CreateDirectoryW CreateThread CreateProcessW CreateFileMappingW QueryDosDeviceW MapViewOfFile UnmapViewOfFile GetFileType CreateFileW GetVolumeNameForVolumeMountPointW DeviceIoControl ExpandEnvironmentStringsA GetModuleFileNameW FileTimeToSystemTime SystemTimeToFileTime GetShortPathNameW GetLogicalDrives GetDriveTypeW SetThreadPriority GetDiskFreeSpaceExW SetFileAttributesW MoveFileW MultiByteToWideChar WideCharToMultiByte GetVersionExW GetSystemInfo LocalFree IsWow64Process GetSystemWow64DirectoryW GetSystemDirectoryW GetEnvironmentStringsW GetTempFileNameW GetWindowsDirectoryW GetComputerNameW GetCommandLineW IsBadReadPtr GetThreadId GetProcessId GetCurrentProcessId SearchPathW Wow64DisableWow64FsRedirection Wow64RevertWow64FsRedirection GetLastError SetFileTime SetFilePointer GetFileSize ReadFile WriteFile FlushFileBuffers SetEndOfFile GetFileTime GetFileAttributesExW RemoveDirectoryW DeleteFileW GetHandleInformation QueryFullProcessImageNameW GetProcessTimes GetExitCodeProcess LocalSize GetSystemTime FindClose FindFirstFileExW FindNextFileW SetLastError LoadLibraryA FreeLibrary GetProcAddress|7408F6CF CB74E56B 3440E30C 3FA0503A C094565D 8D388F19 2D504FC7 B1978170 49A2BC02 2478983B 2C39743C 826FDC1D 429ACFE2 5B40E61E D8EFD506 8E1D8F12 53F5694D D4E43A30 DE78F152 6F75B3F1 69836B71 8A2AACA0 7EBEE13C 7F0B03AE 8B6FA607 3373DF6A 2EE029FE F40C812D F66A15F1 9675A67D 5CDDF47 3F1483A7 42132256 26652D0D E8C5D221 518E8878 29DBE130 787BAFBC F2EC9F3E 922CE64F 7DBF48E7 B514674F 9C01B84F D46EE9FF 434A3624 967918CF 62DE91AE 65E4543B 0BCF31C0 53FF883 4266BEEF F5EE9951 A633633A C380FA58 2F9F0714 DD2C7E1F 7809AAC1 71A22286 0B910B2 4D62C13 8631D459|RegDeleteValueA RegSetValueExA RegQueryValueExA RegSetValueExW RegQueryValueExW RegEnumValueA RegCloseKey RegOpenKeyExW RegEnumKeyW RegCreateKeyExW CryptReleaseContext CryptGetHashParam CryptHashData CryptCreateHash CryptAcquireContextW CryptDestroyHash CryptGenRandom CryptEncrypt CryptExportKey CryptGenKey CryptDestroyKey SetSecurityInfo GetSecurityDescriptorSacl ConvertStringSecurityDescriptorToSecurityDescriptorW ControlService OpenServiceW StartServiceCtrlDispatcherW CloseServiceHandle OpenSCManagerW ChangeServiceConfigW StartServiceW QueryServiceConfigW QueryServiceStatus EnumServicesStatusExW SetServiceStatus RegisterServiceCtrlHandlerW GetUserNameW GetSidSubAuthority GetSidSubAuthorityCount GetTokenInformation OpenProcessToken FreeSid ConvertSidToStringSidA EqualSid AllocateAndInitializeSid RegSetKeyValueW CreateProcessAsUserW NetUserEnum NetUserSetInfo NetShareEnum NetApiBufferFree NetShareDel CryptStringToBinaryA CryptDecodeObject CryptImportPublicKeyInfo WTSEnumerateSessionsW WTSQueryUserToken WTSFreeMemory ZwClose RtlExitUserThread GetClassNameW| |---|---|---|---| -----