Data Exfiltrator

A New Tactic for Ransomware Adversaries

Visual representation of data exfiltration: A close-up of a glowing Ethernet cable plugged into a network switch, with red binary code (1s and 0s) overlaid on the right side. The word “exfiltrate” appears in white and “data” in bold light blue on the left, emphasizing unauthorized data transfer.

Summary

Over the past year, a major change in tactics employed by ransomware adversaries is to exfiltrate data from the victim's environment. The data then serves as the material for an extortion threat on top of the ransom for encrypted data. This additional tactic became a trend followed by most major ransomware families early last year, 2020 1.To support this tactic, some ransomware operators have added a specific type of malware to perform this exfiltration to their intrusion set 2. The five samples analyzed here perform this type of data exfiltration. They upload a set of files from the victim's computer to command and control servers hosted on IP addresses 51.81.153[.]212, 51.161.82[.]135, and 51.77.110[.]6. All of these IP addresses are owned by OVH SAS, a French hosting company. The malware follows the exfiltration with a single line PowerShell command that stops the malware's running process and then deletes the malware file that was executed. The malware has a type of anti-analysis behavior called "Relocate API Code" according to the Malware Behavior Catalog's 3 categorization 4. The malware reads a copy of system DLLs into memory and resolves imports from there. This causes a problem for debuggers such as x64dbg 5.

Interestingly, these files share code with an earlier malware sample with completely different capabilities. This earlier file has been observed alongside TrickBot, CobaltStrike, and ransomware 6. This earlier malware additionally uses the same anti-analysis technique, but does not exfiltrate data. It has the capability to download a CobaltStrike beacon and execute it 7. In addition to this overlap in code and behavior, the command and control (C2) infrastructure domains are registered via the same registrar. Also, the C2 IP addresses are owned by the same hosting company, OVH.

Anti-analysis Trick

Relocate API Code

The first behavior one observes when running these samples in a sandbox or in a debugger is that at the point where the imports are resolved an exception is raised. Debugging past this point is not possible without circumvention of an anti-analysis trick. This circumvention starts by examining the first encoded string the samples decode. Encoded strings are found in two general forms in these samples. First is with all the rest of the strings in the file in the .data section. Some of these can be seen in Figure 1 with one example highlighted.

Hex view of encoded binary data from the .data section of an executable, with ASCII representation on the right. A red arrow highlights a visible encoded string "vrosfjMquo9|u~..m0rxxxx..." in the ASCII panel.

Figure 1: Encoded Strings

Notice the "mOrxxxx" characters that trail each of the encoded strings. These trailing characters will be examined below.

The other location where encoded strings are found is split up character-by-character as stack strings. Each byte is moved one-by-one to a location on the stack before the decoding operation occurs. The first string of this type is in the function that resolves imports from kernel32.dll. This encoded string is shown in Figure 2.

Disassembled code showing a sequence of mov instructions pushing byte values onto the stack, forming a string. Highlighted function call to decode_string is seen at the end, used to resolve kernel32.dll.

Figure 2: First Encoded String

This first string decodes to "C:\Windows\System32\kernel32.dll". This path is then used to read the DLL from the filesystem into memory. Imports are then resolved against this copy of the DLL rather than the system DLL. The function calls to copy the DLL are shown in Figure 3.

Assembly listing showing API calls to VirtualAllocExNuma, CreateFileW, and ReadFile, used for injecting or reading from C:\Windows\System32\kernel133.dll. Red arrows indicate memory locations for these operations.

Figure 3: Copy DLL Function

In the debugger's environment, this read fails with an exception which then prevents the imports from being properly resolved 8. A detailed explanation of what's happening here can be found on OALabs YouTube channel 9.To circumvent this trick, one can create a copy of the DLLs on the filesystem and change their names along with the decoded path strings. This way the DLLs can be read correctly and the imports properly resolved. This change can be done on the fly in the debugger after the strings are decoded. An example of changing this on the fly using the filename kernel33.dll is shown in Figure 4.

Debugger memory dump highlighting the decoded path C:\Windows\System32\kernel133.dll in ASCII and hex views. Overlay matches the decoded string from a binary's memory segment.

Figure 4: Change DLL Name

Alternatively, the single encoded byte needed for this change can be modified in the sample with a hex editor to make this change permanent. This also makes restarting the analysis in the debugger less annoying. This byte difference is highlighted using HexFiend's 10 comparison function and can be seen in Figure 5.

Binary diff viewer comparing two versions of an executable (934c5.exe and 934c5_patch.exe). A single byte difference at offset 0x25ba is highlighted, showing a change from 4E to 4F.

Figure 5: Original Compared to Patch

After the DLL path has been decoded, the various imports from that DLL are then decoded from similar stack strings. One example with LoadLibraryW is shown in Figure 6. Again, please note the trailing "mOrxxxx" string immediately after the encoded bytes of the "LoadLibraryW" string.

Disassembly view showing a function call to load_sections, followed by multiple mov instructions loading individual characters into memory. On the right, strings like "LoadLibraryW" and "m0Rxxxx" are decoded and annotated with red arrows pointing to ASCII interpretations of hexadecimal values.

Figure 6: Encoded LoadLibraryW with Trailing Additional String

Once the import strings are decoded, a custom implementation of GetProcAddress is used on the copy of kernel32.dll to resolve the imports. The results of this process can be seen in Figure 7.

Decompiled code showing several calls to a decode_string function followed by get_proc_address. The image highlights imported functions like LoadLibraryW, GlobalMemoryStatusEx, GetDiskFreeSpaceExA, GetProductInfo, and GetVersionExA.

Figure 7: After Imports Resolved

Examining the exports for these samples shows a DLL name "Input.exe" as well as one exported function "bsearch". These exports are shown in Figure 8.

A snippet of C-like structure definitions showing a DLL export table. Strings "Input.exe" and "bsearch" are highlighted as values of __pe_Input_export_dll_name and __export_name(bsearch) respectively.

Figure 8: Exports

This bsearch function is a version of the binary search algorithm 11. It appears once in the samples as part of the custom GetProcAddress implementation. This function call is highlighted in Figure 9.

Decompilation of a function named get_proc_address, showing the function calling bsearch at address 1400015dd. The call is highlighted with a red box, indicating dynamic resolution of function addresses.

Figure 9: Function Call to bsearch in Custom GetProcAddress

After the imports from kernel32.dll have been resolved, the next DLL is ntdll.dll. The process shown above is repeated for this DLL. The alternative name used here was npdll.dll. The path after this change is shown in Figure 10.

A hex dump showing the string "C:\Windows\System32\npdll" rendered in ASCII on the right side. The red rectangle highlights the ASCII string embedded in memory at a specified address.

Figure 10: DLL Name Change

Some of the resolved imports give an idea of what's to come and what the capabilities are for these samples. Examples of this are the imports of "HttpAddRequestHeadersW" and "EnumProcesses" as shown in Figures 11 and 12.

Assembly instructions show decoded strings being moved into registers, followed by a function call to HttpAddRequestHeadersW, highlighted with a yellow box and red arrow indicating its invocation.

Figure 11: Import HttpAddRequestHeadersW

Disassembly showing a call to decode_string, followed by another call to the EnumProcesses API. A red arrow points to the resolved function name highlighted in yellow.

Figure 12: Import EnumProcesses

The rest of the DLLs after ntdll.dll that are loaded are not loaded using this same antianalysis trick. These other DLLs are user32.dll, wininet.dll, and psapi.dll. The steps to decode and resolve imports from each DLL are divided into separate functions. Each of these functions is shown in figure 13.

Function labeled resolve_imports with a sequence of call instructions to subroutines like resolve_kernel32, resolve_ntdll, resolve_user32, resolve_wininet, and resolve_psapi, followed by a cleanup and return.

Figure 13: Resolve Import Functions

In the code of these samples, another interesting library function calling pattern is to call NtAllocateVirtualMemory using syscall to allocate memory. This pattern of function call is shown in Figure 14.

Disassembled system call for NtAllocateVirtualMemory using syscall instruction. The instruction and function name are emphasized with red highlighting and a box around the label on the right.

Figure 14: Syscall Used on NtAllocateVirtualMemory


Collect Environment Information

The first set of capabilities in these samples is to collect information about the victim's environment. The first bit of information collected is the name of the computer. The call to GetComputerNameExA is shown in Figure 15.

Decompiled code displaying a function call to GetComputerNameExA, with the resolved function highlighted in yellow and boxed in red. The right panel shows the ASCII output: the system name "DESKTOP-xxxxx" where part is redacted.

Figure 15: Collect Computer Name

The next bit of environmental information collected is the physical and virtual memory status. This is done via a call to GlobalMemoryStatusEx 12 which is shown in Figure 16.

Disassembled code view showing a function call to GlobalMemoryStatusEx, labeled "memory_status", with register and memory operations leading up to the API call.

Figure 16: Measure Physical and Virtual Memory Status

The memory status is not sent back to the command and control (C2) infrastructure. It is probably used in the file processing algorithm because the primary purpose of these samples is to exfiltrate files from the victim's computer. These files must be copied from the filesystem to memory for processing before being sent to the C2.

The next data point collected is the username that ran the malware file. This data point does not appear to be sent back to the C2 according to the fields in the network traffic. The API call to GetUserNameA is shown in Figure 17.

Disassembled code view showing a function call to GetUserNameA, labeled "username", with register manipulation and conditional jumps, displaying partial redacted username strings.

Figure 17: Collect Username

Next the samples check the free disk space via GetDiskFreeSpaceExA as shown in Figure 18.

Disassembled code with a call to GetDiskFreeSpaceExA labeled "disk_space", alongside stack pointer adjustments and register preparation for the API call.

Figure 18: Check Disk Free Space

Next the OS version and product information is collected via calls to GetVersionExA and GetProductInfo. These calls are shown in Figure 19.

Assembly code showing consecutive calls to GetVersionExA and GetProductInfo, with a label "version", highlighting the retrieval of OS version details.

Figure 19: Gather OS Version and Product Information

Malware Configuration

After the environment information has been collected, the malware configuration strings are then decoded. As opposed to the stack strings used in the import resolution process, the configuration strings are normal strings in the .data section as shown above. All of these strings have a trailing "mOrxxxx" string. Interestingly this additional data does not cause problems for the decoding process. The reason for this is the decoding function works on a null terminated string. Examining the encoded strings closely, this null termination can be seen before the additional characters. An example of this null termination in a configuration string is shown in Figure 20.

Debugger snapshot showing a LEA instruction to a memory location holding the string "m0rxxxx", with red annotations pointing to the string and a null byte used for termination.

Figure 20: Null Termination

An example of this null termination in a stack string is shown in Figure 21.

List of assembly instructions loading individual bytes of the string "m0rxxxx" onto the stack, with annotated arrows indicating the null terminator and character sequence.

Figure 21: Null Termination in Stack String

The configuration strings for one particular sample 13 are shown in Figure 22.

Disassembled code showing a sequence of API calls including Sleep, and multiple GET/POST string references, highlighting URLs, User-Agent string, and an IP address.

Figure 22: Decoded Configuration Strings

The second configuration string from the top in Figure 22 above is used in a field called "key" in the C2 traffic along with the exfiltrated data. Each of the samples analyzed here have different key strings. The following table shows each of these strings along with the first five characters of the SHA256 hash of the file the string was collected from.

SHA256 Prefix

Key

dcc4a

46rnyegq235etnerhgf43trrthgbfRYdfnhg

68af2

8953n7b8ewurdfb3njnyuridrwdb

934c5

huve3fn298vmfu293jKVFDSfvjjfe893

a7cf0

huve3fn298vmfu293jKVFDSfvjjfe893

8cfd5

3f9n8uv0n43809vn3d092v09290

Exfiltration

The data exfiltration process starts by enumerating the logical drives that are available on the victim's computer. This is determined using a call to GetLogicalDriveStringsW and is shown in Figure 23.

Assembly call to GetLogicalDriveStringsW with dump view below showing decoded drive letters (C:\ and D:), emphasizing access to system drives.

Figure 23: Determine Available Logical Drives

For each of these logical drives, a function is called that walks the file system searching for targeted files and exfiltrating them. This walk function interestingly is recursive. This recursion is shown in Figure 24.

Code navigation view showing two calls to the "walk_drives" function, with arrows highlighting the recursive call relationship.

Figure 24: Walk Function Recursion

The first steps taken in the walk drives function is to add an asterisk to the path that is the input of the function. This is numbered "1" below. Then memory is allocated twice in a row. This is numbered "2" below. The string with the trailing asterisk is then written to one of the two allocated memory locations. This is numbered "3" below. Finally, this string is used to call "FindFirstFileW" with the second allocated memory location as the output location that receives the structure resulting from the API call. These are all shown in Figure 25.

Disassembled walk_drives function showing a sequence of memory allocation, string copying, and a call to FindFirstFileW, representing a directory traversal algorithm.

Figure 25: Finding Files

As the malware walks the file system, any files that contain one of the following strings in the filename are exfiltrated.

.doc

.xls

.pdf

.docx

.xlsx

 


Interestingly, the algorithm used to find these files is probably not what the adversary expected. Rather than checking for a file extension as a suffix it actually matches any infix of the above strings. Because of this, any file with .xlsx will already match .xls for example. These target file extensions are shown in Figure 26.

Screenshot of a memory dump showing a list of target file extensions encoded in hex, including .doc, .docx, .xls, .xlsx, and .pdf, aligned in memory and highlighted in a red box on the right.

Figure 26: Target File Extensions

Next the file size is determined using a call to GetFileSize. This information is included in the exfiltrated data. The API call is shown in Figure 27.

Disassembly view highlighting a call to the GetFileSize function. Code instructions show stack manipulation and conditional jumps based on file size comparisons.

Figure 27: Determine File Size

As the file system walk proceeds, the path strings are emitted as debug strings via a call to OutputDebugStringW. This is followed immediately by bytes for a Windows carriage return line feed. These two are shown in Figure 28.

Debugger view showing a call to the OutputDebugStringW function. A hex dump below highlights ASCII content containing a PowerShell command. Red annotations connect the memory address to the source code invocation.

Figure 28: Emit Debug Strings

This malware can exfiltrate large files. It does this by dividing the file into chunks according to a hard coded "frame size". This hard coded size is 32535 bytes and is highlighted in Figure 29.

Screenshot of a web debugging proxy showing an HTTP POST request to uploadFile.php. The request body includes parameters such as filename testfile.doc, PC name, and encoded data. A matching inspector panel shows parsed parameter values.

Figure 29: Frame Size

The above also shows all the other fields that are used in the C2 traffic. The frame number starts at "-0" then "1", "2" etc. The "filecrc" field is the cyclic redundancy check (CRC) which is used as a checksum for error detection 14. The last two fields are the filename and the computer name.

Using a constructed test file named "testfile.doc" the TLS encrypted C2 traffic is intercepted and analyzed using Burp 15 and Inetsim 16. The body parameters and the request headers from this test file are shown in Figure 30.

Screenshot of a web debugging proxy showing an HTTP POST request to uploadFile.php. The request body includes parameters such as filename testfile.doc, PC name, and encoded data. A matching inspector panel shows parsed parameter values.

Figure 30: Test Document Shown Being Exfiltrated in C2 Network Traffic

Interestingly, the configuration strings include "GET" in addition to "POST". However, this capability does not appear to be used in these samples. A check is performed which determines which of the two request methods are used. This check is shown at the top of Figure 31. The POST and GET options are shown in the center, and the call to HttpOpenRequestW is shown at the bottom.

Assembly code showing a conditional check for the string POST, followed by a call to HttpOpenRequestW. Arrows highlight branching logic and transitions based on detected HTTP method.

Figure 31: Request Method Options

The algorithm used to determine which files are exfiltrated is flawed in that it will match files that are not Word, Excel, or PDF documents. It will exfiltrate any file that contains the target strings anywhere in the filename. A test of this is shown in Figure 32 which uses a fake file with the extension ".txt" and ".pdf" in the middle of the filename.

Inspector panel showing a filename field with the value this_is_not.pdf-it-is-text.txt, illustrating a deceptive file extension. The highlighted portion emphasizes the embedded .pdf string within a non-PDF file.

Figure 32: Unexpected Exfiltration

After all the filesystem walking has completed, the next function called sends a dummy "end of transmission" file out to the C2. The filename of the file is ".lock" and the content is "locked". This file only exists in memory and network traffic. It is not written to the filesystem. The strings for this dummy file are shown in Figure 33.

Decompiled function with lines of assembly code showing the use of static string references to "locked" and ".lock". These are moved into memory, indicating creation of file indicators or tags.

Figure 33: Dummy File Strings

This dummy file as seen in the network traffic is shown in Figure 34.

HTTP POST request inspector panel showing a data upload labeled locked with a .lock filename. Other parameters include a PC name and file size. This indicates the final stage of data exfiltration or tagging.

Figure 34: End of Transmission Dummy File

After all of the above is finished, the last action taken by the samples is to run a PowerShell command from a string. This command gets the process ID of the parent process of the command itself. It uses that process ID to kill the malware's process. It then deletes the malware file from the filesystem. This is to clean up after the data exfiltration is complete. The command is executed by a call to CreateProcessA as shown in Figure 35.

Disassembly showing execution of a PowerShell command: "powershell.exe -nop -w hidden -C...". The command is stored in memory and passed to a CreateProcessA call, initiating execution of the hidden script.

Figure 35: PowerShell Cleanup Command

The full text of the PowerShell command is shown in Figure 36.

a command determines the parent process of the current PowerShell instance, stops it, overwrites its binary file with a 1MB zero-byte buffer, and then deletes the binary, all while suppressing confirmation prompts and errors. It is typically associated with stealthy post-exploitation or malware cleanup behavior.

Evolving Variants

The earliest observed variant of this malware family was compiled on April 24th, 2021 according to the PE header TimeDateStamp field. It was then first seen in the Titanium Platform on April 25th, 2021. This earliest variant did not include the PowerShell cleanup that was used in the later two variants. The comparison of the older sample 18 and the newer sample 19 analyzed using Relyze 20 is shown in Figure 36.

Pseudocode representation of a function containing a PowerShell command: "powershell.exe -nop -w hidden -C...". The bottom of the screen highlights function differences indicating this code was newly added.

Figure 36: Addition of PowerShell Cleanup Capability

Another difference between this oldest sample and most of the newer ones is the inclusion of a program database (PDB) path. This path is shown in Figure 37.

PDB Path String

Figure 37: PDB Path String

The two newer samples have very few differences. Code-wise, there is one single function that is ~55% different between the two. The rest of the code is identical or nearly identical. This small difference is shown in Figure 38.

Visual diff view comparing two functions with highlighted structural differences in disassembly.

Figure 38: Difference in Newer Samples

Another interesting difference between the two newer samples is that the newest sample does not call back to a hostname for C2 communication. It is configured to call back to the C2 URL on a bare IP address.

Related Malware

One function in particular that is found in each of the three samples analyzed above is the string decoding function. Encoding and decoding functions are a good area of code to examine closely and to hunt for in malware repositories. This type of function can be stable across samples and tends to be reused by an adversary in multiple campaigns even if the capabilities of the malware are radically different. Building a YARA rule based on this function reveals an older malware sample 21 which was blogged about by researchers at Walmart 22. The results of a retrohunt in the Titanium Platform using this YARA rule is shown in Figure 39. The result shown in orange is a false positive. This file is a copy of one of the other actual malware files but appears to have been modified by a researcher.

Dashboard showing detection of malware samples via the "DataExfiltrator_Decoder" YARA rule, including timestamps and threat labels.

Figure 39: Retrohunt Results

This sample is definitely related to the three samples analyzed here. It uses the same anti-analysis trick as well as the same string obfuscation including the "mOrxxxx" trailing characters. Both the standard string form as well as the stack strings are found in this sample. However, this older sample is a CobaltStrike beacon loader rather than a data exfiltrator. The YARA rule for detecting this code overlap is provided at the end of the blog. As opposed to earlier YARA rules that I have written, I read the advice from Marc Ochsenmeier on Twitter about adding comments with the meaning of opcodes in YARA rules meant for sharing 23. This rule and future rules will include the assembly as well as the bytecode strings.

In addition to this older malware sample that is definitely related, a hunt for other malware that contains variations of the string "mOrxxxx" reveals a multitude of potentially related malware samples. These are nearly uniformly detected as malicious. A future blog will address these additional files. The results of a retrohunt for the full string "mOrxxxx" is shown in Figure 40.

Cloud retrohunt UI listing 14 matched samples of "DataExfiltrator_m0Rxxxx", including threat types like Dyreza, Upatre, and CobaltStrike.

Figure 40: Full String mOrxxxx

The results of retrohunts for this string with two Xs and one X are shown in Figure 41 and 42.

Summary heatmap visualization showing 530/530 and 10,000/10,000 samples matched across a large telemetry corpus.

Figure 42: Retrohunt for String with One X

Analysis of the results of these retrohunts will be the topic of a future blog post.

IOCs

Sample 1
File

Filename

Input.exe

Filename

v2c.exe

MD5

1010bec081572dc3bd16e26a1e37d815

SHA1

bfc0219efb60fb270cee0b7b102afc0d4b0a121a

SHA256

dcc4ac1302ac5693875c4a4b193242cbb441b77cd918569c43fe318bcf64fe3d

Import Hash

85ce0801668e488873e72eeb306503da

SSDEEP

768:ycscKP14scGOqEMQcanOPBbEbeFpUGC/YDR5Ws:yV3cGOqEMQcanOJFpUGC/Y9

Timestamp

2021-04-24T17:34:20Z

PDB

E:\work\proj\file_sender\x64\file_sender.pdb

Magic

PE32+ executable (GUI) x86-64, for MS Windows

File Type

Win64 EXE

File Size

35328

First Seen

2021-04-25


User Agent

Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.309 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36


URL

hxxps[://]files[.]pablotech[.]info/uploadFile.php


Hostname

files[.]pablotech[.]info


Domain

Name

Registrar

IANA ID

pablotech[.]info

Hosting Concepts B.V. d/b/a Registrar.eu

1647



Sample 2
File

Filename

Input.exe

Filename

sender.exe

MD5

e3300ec2f31f5730970c5bb066d2f0ed

SHA1

c768882e102a5dd3d1c17d306698c5cfc3d9d8d5

SHA256

68af250429833d0b15d44052637caec2afbe18169fee084ee0ef4330661cce9c

Import Hash

6473877da5764bbd5a9b16892ef13b69

SSDEEP

768:zp2FXczP/cpWyB/3RtUcGOqEMIcqfz/YghUx:zp2FsTcB/UcGOqEMIcqfz/Yg4

Timestamp

2021-04-28T03:00:08Z

Magic

PE32+ executable (GUI) x86-64, for MS Windows

File Type

Win64 EXE

File Size

36352

First Seen

2021-05-03


User Agent

Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) discord/0.0.309 Chrome/83.0.4103.122 Electron/9.3.5 Safari/537.36


URL

hxxps[://]figures[.]pablotech[.]info/uploadFile.php


Hostname

figures[.]pablotech[.]info


Domain

Name

Registrar

IANA ID

pablotech[.]info

Hosting Concepts B.V. d/b/a Registrar.eu

1647

 

Sample 3
File

Filename

Input.exe

Filename

v2c.exe

MD5

4af8b45c9b0f73d47a499d92064b6c2e

SHA1

424f3c281f46e4cf2350c78cfa89a87873e0b994

SHA256

934c557e52bd47fa312ea4098e05781145d0b81c9dc543ef42b266813bdb05d4

Import Hash

6473877da5764bbd5a9b16892ef13b69

SSDEEP

768:9vutX7Qp6CPRp8Yh/ZYWcGOqEMUcgk9/Y7hCeUpU:K7QpJp8YFrcGOqEMUcg0/Y7lk

Timestamp

2021-05-17T20:33:40Z

Magic

PE32+ executable (GUI) x86-64, for MS Windows

File Type

Win64 EXE

File Size

36352

First Seen

2021-05-18


User Agent

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0


URL

hxxps[://]51.161.82[.]135/uploadFile.php


IP Address

IP

Owner

ASN

51.161.82[.]135

OVH SAS

16276

 

Sample 4
File

Filename

Input.exe

Filename

v2.exe

MD5

7c801e3c256d2e9e1f4462fe84e44c68

SHA1

4cd9cecd1d093f290e6f8f0ad6d5e76dbedbf3d9

SHA256

a7cf0f72bb6f1e0a61fbf39e3a3a36db6540250caeef35b47fb51a8959f40984

Import Hash

9f86f12427bca134faaa21bcc0d849d3

SSDEEP

768:vkcGOqEMccVhPO4TrASVqipOHMd6m/YFh50:ccGOqEMccV7rAZipOHA/YFT

Timestamp

2021-05-24T23:06:16Z

PDB

E:\work\proj\file_sender\x64\file_sender.pdb

Magic

PE32+ executable (GUI) x86-64, for MS Windows

File Type

Win64 EXE

File Size

37376

First Seen

2021-06-01


User Agent

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0


URL

hxxps[://]51.161.82[.]135/uploadFile.php


IP Address

IP

Owner

ASN

51.161.82[.]135

OVH SAS

16276

 

Sample 5
File

Filename

file_sender.exe

Filename

sender.exe

MD5

12a7595d94e142847a04f11659ed183d

SHA1

f80a2f102ca0297d053c75e0676049dc87cb3f35

SHA256

8cfd554a936bd156c4ea29dfd54640d8f870b1ae7738c95ee258408eef0ab9e6

Import Hash

9f86f12427bca134faaa21bcc0d849d3

SSDEEP

768:sPcGOqEMccNNPayYDcfHyIY2QUy2h08wx:2cGOqEMccNEDuhY2FS84

Timestamp

2021-06-15T10:57:36Z

PDB

E:\work\proj\file_sender\x64\file_sender.pdb

Magic

PE32+ executable (GUI) x86-64, for MS Windows

File Type

Win64 EXE

File Size

36352

First Seen

2021-06-16


User Agent

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0


URL

hxxp[://]51.77.110[.]6/uploadFile.php


IP Address

IP

Owner

ASN

51.77.110[.]6

OVH SAS

16276

 

YARA Rule

private rule WindowsPE
{
   condition:
      uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550
}

rule DataExfiltrator_Decoder
{
   meta:
      author = "Malware Utkonos"
      date = "2021-05-07"
      description = "String decoding function found in data exfiltration malware."
exemplar = "dcc4ac1302ac5693875c4a4b193242cbb441b77cd918569c43fe318bcf64fe3d"
   strings:
      $a = { 4489442418 // mov dword [rsp+0x18 {arg_18}], r8d
           88542410 // mov byte [rsp+0x10 {arg_10}], dl
           48894c2408 // mov qword [rsp+0x8 {arg_8}], rcx
           4883ec28 // sub rsp, 0x28
           8b442440 // mov eax, dword [rsp+0x40 {arg_18}]
           33d2 // xor edx, edx {0x0}
           b904000000 // mov ecx, 0x4
           48f7f1 // div rcx
           }
   condition:
      WindowsPE and $a
}



References:

1  https://research.checkpoint.com/2020/ransomware-evolved-double-extortion/
2  https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_5ol9xlbbnrdn
3  https://github.com/MBCProject/mbc-markdown/tree/master/yfaq
4  https://github.com/MBCProject/mbc-markdown/blob/master/anti-behavioral-analysis/evade-debugger.md
5  https://x64dbg.com/
6  https://medium.com/walmartglobaltech/trickbot-crews-new-cobaltstrike-loader-32c72b78e81c
7  Ibid.
8 Thanks to Sandor Nemes for assistance in understanding this behavior.
9  https://www.youtube.com/watch?v=242Tn0IL2jE&t=1053s
10 https://hexfiend.com/
11 https://en.cppreference.com/w/c/algorithm/bsearch
12 https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex
13 934c557e52bd47fa312ea4098e05781145d0b81c9dc543ef42b266813bdb05d4
14 https://en.wikipedia.org/wiki/Cyclic_redundancy_check
15 https://portswigger.net/burp
16 https://www.inetsim.org/
17 dcc4ac1302ac5693875c4a4b193242cbb441b77cd918569c43fe318bcf64fe3d
18 Ibid.
19 68af250429833d0b15d44052637caec2afbe18169fee084ee0ef4330661cce9c
20 https://www.relyze.com/
21 0234f80c6fd3768f9619d6fcd50d775ec686719fcc665007bfd1606bbe787744
22 https://medium.com/walmartglobaltech/trickbot-crews-new-cobaltstrike-loader-32c72b78e81c
23 https://twitter.com/ochsenmeier/status/1379546812437118980 

Back to Top