Subscribe To Our Daily Enewsletter:

New Malicious Payloads Discovered in WAV Files

BlackBerry Cylance Threat Researchers recently discovered obfuscated malicious code embedded within WAV audio files. Each WAV file was coupled with a loader component for decoding and executing malicious content secretly woven throughout the file’s audio data. When played, some of the WAV files produced music that had no discernible quality issues or glitches. Others simply generated static (white noise).

Author: Anuj Soni of BlackBerry Cylance

Our analysis reveals some of the WAV files contain code associated with the XMRig Monero CPU miner. Others included Metasploit code used to establish a reverse shell. Both payloads were discovered in the same environment, suggesting a two-pronged campaign to deploy malware for financial gain and establish remote access within the victim network.

The WAV file loaders can be grouped into the following three categories, which we will discuss in detail:

  1. Loaders that employ Least Significant Bit (LSB) steganography to decode and execute a PE file.
  2. Loaders that employ a rand()-based decoding algorithm to decode and execute a PE file.
  3. Loaders that employ rand()-based decoding algorithm to decode and execute shellcode.

Each approach allows the attacker to execute code from an otherwise benign file format. These techniques demonstrate that executable content could theoretically be hidden within any file type, provided the attacker does not corrupt the structure and processing of the container format. Adopting this strategy introduces an additional layer of obfuscation because the underlying code is only revealed in memory, making detection more challenging.

It is worth noting that the steganography loader we discovered is also identified in Symantec’s June 2019 analysis[1] of Waterbug/Turla threat actor activity. In addition, Symantec identified WAV files containing encoded Metasploit code. These similarities may point to a relationship between the attacks, though definitive attribution is challenging because different threat actors may use similar tools. Also, our analysis focuses primarily on loaders, which are an initial stage of execution used to launch additional code. Different threat actors may use the same publicly available loader to execute unrelated second-stage malware.

Loaders

Steganography PE Loader

Overview

The first category of loaders employs steganography to extract executable content from a WAV file. Steganography is the practice of concealing a file or message within another file, ideally without raising suspicion about the target file. Attackers have used steganography techniques to hide data in the past; in fact, BlackBerry Cylance Threat Research published a report[2] in April that describes how the OceanLotus Threat Group leveraged steganography to conceal malicious backdoor payloads within image files. In this instance, code is hidden within the audio file using the Least Significant Bit (LSB) technique, where the right-most bit of an individual byte contains the data of interest. One publicly available[3]  WAV file loader we discovered has the following characteristics:

SHA-256 595A54F0BBF297041CE259461AE8A12F37FB29E5180705EAFB3668B4A491CECC
File Type PE32+ executable (GUI) x86-64, for MS Windows
Size 107,008 bytes
Compile Timestamp Tuesday, May 29, 2018 13:07:05 UTC
PDB Path f:\w\xmrig\iskander\x64\release\iskander.pdb
Version Information Language: U.S. English
Company Name: Microsoft Corporation
File Description: Microsoft MediaPlayer
File Version: 12.6.7600.16385
Legal Copyright: Microsoft Corporation. All rights reserved.
Original Filename: MSTCSS.EXE
Product Name: Microsoft Windows Operating System
Product Version: 15.3.7600.16385

Note that the 32-bit version of this loader is also publicly available[4], though it will not be discussed in detail here.

Unlike other loaders mentioned in this article, this loader contains hardcoded strings that specify the filename to load (“Song.wav”) and, once decoded, the exported function to execute (“Start”). The Song.wav file is publicly available[5] within a zip file:

SHA-256 DB043392816146BBE6E9F3FE669459FEA52A82A77A033C86FD5BC2F4569839C9
Filename Song.wav
File Type RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
Size 15,179,596

Upon execution, the loader will read Song.wav (assuming it is in the same directory), extract a DLL in memory, and execute the “Start” export. The extracted file is associated with the XMRig Monero CPU miner:

SHA-256 A2923D838F2D301A7C4B46AC598A3F9C08358B763B1973B4B4C9A7C6ED8B6395
File Type PE32+ executable (DLL) (console) x86-64, for MS Windows
Size 733,696 bytes
Compile Timestamp Monday, May 28 2018 19:45:53 GMT
PDB Path n/a
Exports Start
Version Information Language: Neutral
Company Name: www[.]xmrig[.]com
File Description: XMRig CPU miner
File Version: 2.6.2
Legal Copyright: Copyright (C) 2016-2018 xmrig[.]com
Original Filename: xmrig.exe
Product Name: XMRig
Product Version: 2.6.2

Attackers deploy CPU miners to steal processing resources and generate revenue from mining cryptocurrency. Cryptocurrency miners are a popular malware payload since they provide financial benefit and aim to operate in the background without the user’s knowledge. An effective cryptocurrency botnet can yield thousands of dollars per month for an attacker.

Technical Details

The header of a WAV (RIFF) file is 44 bytes long, and the last four bytes indicate the size of the data section. In Song.wav, the data size is 0xE79F20 (little endian) or 15,179,552 bytes:

Figure 1: WAV file header – data size

In the code snippet below, the loader reads in these four bytes and uses the value to allocate space in memory. Then, it reads the data and closes the WAV file. Finally, the do-while loop iterates over every other byte within the first 64 bytes (i.e., it skips one byte) and extracts LSBs to determine the size of the decoded data:

Figure 2: Decode file size

To better understand the code above, recognize that the loop executes while counter < 32 and counter increments by one with each iteration. Also, data_offset represents the offset within the encoded data, and its value increments by two with each iteration, beginning with zero. In total, this loop will cover the first 64 bytes of data (32 * 2):

Figure 3: WAV file data – 64 bytes

For each byte processed, the loader will extract the LSB and assign it to appropriate bit position in decoded_size, beginning with 31(i.e., the left-most bit) and decrementing by 1 with each iteration. Applying this algorithm to the first 64 bytes of data gives us the following (skipped bytes not included):

Hex Binary (LSB underlined) Bit Position LSB assigned to bit position
FC 11111100 31 00000000 00000000 00000000 00000000
E6 11100110 30 00000000 00000000 00000000 00000000
06 00000110 29 00000000 00000000 00000000 00000000
06 00000110 28 00000000 00000000 00000000 00000000
00 00000000 27 00000000 00000000 00000000 00000000
00 00000000 26 00000000 00000000 00000000 00000000
00 00000000 25 00000000 00000000 00000000 00000000
00 00000000 24 00000000 00000000 00000000 00000000
02 00000010 23 00000000 00000000 00000000 00000000
02 00000010 22 00000000 00000000 00000000 00000000
00 00000000 21 00000000 00000000 00000000 00000000
00 00000000 20 00000000 00000000 00000000 00000000
FF 11111111 19 00000000 00001000 00000000 00000000
FE 11111110 18 00000000 00001000 00000000 00000000
FF 11111111 17 00000000 00001010 00000000 00000000
FF 11111111 16 00000000 00001011 00000000 00000000
FE 11111110 15 00000000 00001011 00000000 00000000
FE 11111110 14 00000000 00001011 00000000 00000000
FF 11111111 13 00000000 00001011 00100000 00000000
FF 11111111 12 00000000 00001011 00110000 00000000
FE 11111110 11 00000000 00001011 00110000 00000000
FE 11111110 10 00000000 00001011 00110000 00000000
FF 11111111 9 00000000 00001011 00110010 00000000
FE 11111110 8 00000000 00001011 00110010 00000000
FC 11111100 7 00000000 00001011 00110010 00000000
FC 11111100 6 00000000 00001011 00110010 00000000
FC 11111100 5 00000000 00001011 00110010 00000000
FC 11111100 4 00000000 00001011 00110010 00000000
FE 11111110 3 00000000 00001011 00110010 00000000
FE 11111110 2 00000000 00001011 00110010 00000000
00 00000000 1 00000000 00001011 00110010 00000000
00 00000000 0 00000000 00001011 00110010 00000000

The final 32-bit binary value 00000000 00001011 00110010 00000000 has a hex representation of 0xB3200 or decimal value of 733,696. This value is placed into decoded_size.

Next, memory of size decoded_size is allocated and various calculations are performed. Default label names were modified to indicate the results of all calculations. These numbers will be used as offsets into the encoded data in the upcoming decoding loop:

Figure 4: Allocate memory and calculate offsets

Following the above code, a do-while loop begins to decode the remainder of the encoded data:

Figure 5: Decode file contents

Similar to the previous decoding loop, this one extracts the LSB of every other byte. One difference, however, is that it begins assigning bits at the lowest (right-most) bit position. Each iteration extracts the LSB from 8 bytes to form 8 bits (1 byte) of decoded data. Let’s apply this algorithm to generate two bytes of decoded data. Since 8 bits comprise a single decoded byte, and one LSB is extracted from every two encoded bytes, generating two decoded bytes requires 32 encoded bytes (2 decoded bytes * 8 LSBs per decoded byte * 2 = 32):

Figure 6: 32 bytes of encoded data

The first byte of decoded data will be produced as follows (skipped encoded bytes not included):

Hex Binary (LSB underlined) Bit Position LSB assigned to bit position
01 00000001 0 00000001
00 00000000 1 00000001
FF 11111111 2 00000101
FF 11111111 3 00001101
FC 11111100 4 00001101
FC 11111100 5 00001101
FD 11111101 6 01001101
FC 11111100 7 01001101

The second byte of decoded data is produced as follows (again, skipped encoded bytes not included):

Hex Binary (LSB underlined) Bit Position LSB assigned to bit position
FE 11111110 0 00000000
FF 11111111 1 00000010
00 00000000 2 00000010
01 00000001 3 00001010
FF 11111111 4 00011010
FE 11111110 5 00011010
FB 11111011 6 01011010
FA 11111010 7 01011010

As a result, the first two bytes have binary values of 01001101 and 01011010, respectively. Hex representations for both bytes are 0x4D5A, referring to the well-known “MZ” bytes typically found at the beginning of a Windows Portable Executable (PE) file.

The do-while loop will continue iterating until the XMRig DLL is produced in memory. Finally, the decoded DLL is mapped into memory and the “Start” export is executed to launch cryptomining activity.

Rand()-based PE Loader

Overview

The second category of loader uses a rand()-based decoding algorithm to hide shellcode. One example of this loader is publicly available[6] and has the following characteristics:

SHA-256 843CD23B0D32CB3A36B545B07787AC9DA516D20DB6504F9CDFFA806D725D57F0
File Type PE32+ executable (GUI) x86-64, for MS Windows
Size 156,672 bytes
Compile Timestamp Tuesday, June 06 2018 11:09:52 UTC
PDB Path d:\source\mining\wavdllplayer\x64\release\wavdllplayer.pdb
Version Information Language: U.S. English
Company Name: Microsoft Corporation
File Description: Host Process for Windows Tasks
File Version: 10.0.16299.15
Legal Copyright: Microsoft Corporation. All rights reserved.
Original Filename: taskhostw.exe
Product Name: Microsoft® Windows® Operating System
Product Version: 10.0.16299.15

To load a WAV file with this loader the following command line must be used:

<Loader EXE> <WAV File> <Decoded PE File Entry Point>

An example of a compatible (and publicly available[7]) WAV file has the following characteristics:

SHA-256 7DC620E734465E2F5AAF49B5760DF634F8EC8EEAB29B5154CC6AF2FC2C4E1F7C
Filename click.wav
File Type RIFF (little-endian) data, WAV audio, Microsoft PCM, 8 bit, mono 44100 Hz
Size 733,740 bytes

Unlike the first WAV file discussed, this audio file has legitimate headers but no music when played – the audio sounds like white noise.

When executing the loader with the above WAV file, the loader will read the file, extract a DLL in memory, and attempt to execute the specified entry point. Similar to the first scenario, the extracted file is associated with the XMRig Monero CPU miner:

SHA-256 ED58FDB450D463B0FE3BBC6B9591203F6D51BF7A8DC00F9A03978CECD57822E1
File Type PE32+ executable (DLL) (console) x86-64, for MS Windows
Size 733,696 bytes
Compile Timestamp Monday, May 28 2018 19:45:53 GMT
PDB Path n/a
Exports Start
Version Information Language: Neutral
Company Name: www[.]xmrig[.]com
File Description: XMRig CPU miner
File Version: 2.6.2
Legal Copyright: Copyright (C) 2016-2018 xmrig[.]com
Original Filename: xmrig.exe
Product Name: XMRig
Product Version: 2.6.2

In fact, this file is almost identical to the DLL decoded from Song.wav, with the exception of four bytes at the end of the file (additional details are in the next section).

Technical Details

Upon execution, this loader will read the WAV header, extract the data size, allocate memory accordingly, and store the WAV data in the newly allocated memory. Next, the loader approaches the code responsible for decoding the WAV file’s data content:

Figure 7: Rand()-based PE loader decoding loop

Note that size_of_data represents the data size extracted from the WAV header and wave_data contains the address of the encoded WAV data.  The loader uses an initial call to srand() and repeated calls to rand() to extract a PE file from the WAV data. As described on Microsoft’s website[8], the srand() API “sets the starting point for generating a series of pseudorandom integers in the current thread”, and the rand API “retrieves the pseudorandom numbers that are generated”. Given a seed supplied to srand(), calls to rand() will return the same pseudorandom numbers each time it is called.

The do-while loop traverses each byte of the encoded data, replacing the byte with the result of subtracting rand() output from the encoded byte. For example, let’s decode the first two bytes of data shown here:

Using the loader and WAV file specified earlier in this section, the chart below shows values for the first two iterations with a srand() seed value of 0x309:

Loop Run WAV Data (Byte) rand() Output      (lower byte) Difference
1 0x5C 0x0F 0x5C – 0x0F = 0x4D
2 0x99 0x3F 0x99 – 0x3F = 0x5A

These first two bytes represent the “MZ” characters typically present at the beginning of a Windows executable. Once the loop runs over all data bytes, the result is a 64-bit DLL associated with the XMRig Monero CPU miner. The resulting DLL differs by only four bytes from the DLL decoded from Song.wav:


Figure 8: Decoded click.wav vs. Song.wav

While it is unclear why these bytes differ, they do not contribute to the functionality of the DLL, so the XMRig DLL files are virtually the same.

Next, the loader acquires the address of the export specified in the command line. If it exists, the loader will launch a thread to execute it:

Figure 9: Identify address of export and launch thread to execute it

Rand()-based Shellcode Loader

Overview

The third category of loader uses a rand()-based decoding algorithm to hide PE files. One example of this loader is publicly available[9] and has the following characteristics:

SHA-256 DA581A5507923F5B990FE5935A00931D8CD80215BF588ABEC425114025377BB1
File Type PE32+ executable (GUI) x86-64, for MS Windows
Size 90,112 bytes
Compile Timestamp Monday, June 18, 2018 18:54:48 UTC
PDB Path D:\source\mining\wavPayloadPlayer\x64\Release\wavPayloadPlayer.pdb
Version Information Language: U.S. English
Company Name: Microsoft Corporation
File Description: Host Process for Windows Tasks
File Version: 10.0.16299.15 (WinBuild.160101.0800)
Legal Copyright: Microsoft Corporation. All rights reserved.
Original Filename: taskhostw.exe
Product Name: Microsoft Windows Operating System
Product Version: 10.0.16299.15

To load a WAV file with this loader, the following command line must be used (no entry point necessary):

<Loader EXE> <WAV File>

Similar to the previous loader, any audio files paired with this loader only contained white noise with no musical content. Upon execution, this loader opens a compatible WAV file, reads its data, decodes its contents, and attempts to execute the shellcode.

While no public samples of compatible WAV files are available, both files discovered contained Metasploit code that launches a reverse shell to a specified IP address.

Technical Details

Similar to the previous loader, this one will read the WAV header, determine the data size, allocate memory, and read the data. The decoding code is virtually identical, including the use of the same srand() seed:

Figure 10: Rand()-based shellcode loader decoding loop

The only notable difference is the immediate call to CreateThread after the decoding loop completes. No supporting code is necessary to parse the file structure since this loader only handles shellcode.

An analysis of the decoded shellcode from two WAV files revealed code strikingly similar to the Metasploit reverse TCP[10] and reverse HTTPS[11] code. In both cases, the shellcode attempts a connection to the IP address 94.249.192.103. The reverse TCP connection occurs over port 3527 while the reverse HTTPS connection occurs over port 443.

Conclusion

Attackers are creative in their approach to executing code, including the use of multiple files of different file formats. We discovered several loaders in the wild that extract and execute malicious code from WAV audio files. Analysis revealed that the malware authors used a combination of steganography and other encoding techniques to deobfuscate and execute code. These strategies allowed attackers to conceal their executable content, making detection a challenging task. In this case, attackers employed obfuscation to both perform cryptomining activities and establish a reverse connection for command and control. The similarities between these methods and known threat actor TTPs may indicate an association or willingness to emulate adversary activity, perhaps to avoid direct attribution.

Appendix

Indicators of Compromise (IOCs):

Indicator Type Description
595A54F0BBF297041CE259461AE8A12F37FB29E5180705EAFB3668B4A491CECC SHA-256 Steg Loader
843CD23B0D32CB3A36B545B07787AC9DA516D20DB6504F9CDFFA806D725D57F0 SHA-256 PE Loader
DA581A5507923F5B990FE5935A00931D8CD80215BF588ABEC425114025377BB1 SHA-256 Shellcode Loader
DB043392816146BBE6E9F3FE669459FEA52A82A77A033C86FD5BC2F4569839C9 SHA-256 WAV  File
7DC620E734465E2F5AAF49B5760DF634F8EC8EEAB29B5154CC6AF2FC2C4E1F7C SHA-256 WAV File
94.249.192.103 IP address Shellcode IP


YARA Rule for Rand() Encoded WAV Files:

rule rand_encoded_wav
{
strings:
$RIFF = “RIFF”
$WAVE = “WAVE”$SHELLCODE = {0B 87 06 53 DF 3A}
$MZ = {5C 99 13 6F F2 52}condition:
$RIFF at 0 and $WAVE at 8 and ($MZ at 44 or $SHELLCODE at 44)
}


MITRE AT&CK Techniques:

Tactic ID Name Description
Defense Evasion T1027 Obfuscated Files or Information Steganography is used to hide a PE file within a WAV audio file.
Execution T1059 Command-Line Interface Encoded shellcode executes Metasploit code to initiate a reverse shell.
Command and Control T1043 Commonly Used Port The reverse HTTPS connection occurs over port 443.
Command and Control T1065 Uncommonly Used Port The reverse TCP connection occurs over po 527.

Citations

[1] https://www.symantec.com/blogs/threat-intelligence/waterbug-espionage-governments

[2] https://threatvector.cylance.com/en_us/home/report-oceanlotus-apt-group-leveraging-steganography.html

[3] https://www.virustotal.com/gui/file
/595a54f0bbf297041ce259461ae8a12f37fb29e5180705eafb3668b4a491cecc/detection

[4] https://www.virustotal.com/gui/file
/d0b99353cb6500bb18f6e83fe9eed9ce16e5a8d5b940181e5eafd8d82f328a59/detection

[5] https://www.virustotal.com/gui/file
/4fd1d0671395b1b0815b0704d31af816779a6a0a516ea6f82a9196f18bf513cc/detection

[6] https://www.virustotal.com/gui/file
/843cd23b0d32cb3a36b545b07787ac9da516d20db6504f9cdffa806d725d57f0/detection

[7] https://www.virustotal.com/gui/file
/7dc620e734465e2f5aaf49b5760df634f8ec8eeab29b5154cc6af2fc2c4e1f7c/detection

[8] https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/srand?view=vs-2019

[9] https://www.virustotal.com/gui/file
/da581a5507923f5b990fe5935a00931d8cd80215bf588abec425114025377bb1/detection

[10] https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x64/src/block/block_reverse_tcp.asm

[11] https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x64/src/block/block_reverse


Author Anuj Soni is a Senior Threat Researcher on the Threat Intelligence team at BlackBerry Cylance. Read more BlackBerry Cylance blogs here.

Return Home

No Comments

Leave a Reply

Your email address will not be published. Required fields are marked *