Colins Security Blog

11 object(s)

New JavaScript Malware - Fake DocuSign Invoices

Decoding a New JavaScript Malware Campaign

Recently researchers from HuntressLabs shared data about a case where a fake DocuSign document resulted in a network compromise involving AvosLocker & data collection with RClone. HuntressLabs identified the inital infection vector as a file with the following name:


Part 1: Gathering Samples on VirusTotal

Leveraging VirusTotal Intelligence I was able to identify ~70 recent samples with the same file naming schema.

IOC Preview

I’ve uploaded the IOCs for these files to github. While reviewing over these results I noticed that there were a lot of .html files. I found one example where the html file was delivered as a email attachement.

Email with a .html attachment

Out of all the possible related samples I decided to further review the file Invoice-DocuSign-Mar03-2023.js

Part 2: Decoding the Malware

This javascript malware has painfully annoying obfuscation so lets use dynamic analysis to speed things up! When you run this malware the first thing you see is a message about file corruption. You might think the malware author made a typo however this popup is actually just to deceive users and security analyst.

After reviewing the javascript malware source code I identified two functions that returned data. One of the functions executed String.fromCharCode to decode data before returning the variable. To capture this output I added a WScript.Echo statement to the malware:

To effectively utilize this decoding trick with javascript malware it’s better to run the malware with cscript instead of wscript and pipe the output to another file like such:

cscript sample.js > data.txt 

Next I used CyberChef to help investigated this partially decoded data. The recipe I used was:

Find_/_Replace({'option':'Simple string','string':';'},';\\n',true,false,true,false)

Although this data now has some functional code such as the popup mentioned earlier there are still multiple variables with encoded data and more analysis needed.

After assembling the multiple base64 encoded varables and throwing it into CyberChef we get this ugly bit of powershell code that uses io.compression to deflate base64 encoded data.

Encoded Powershell

Using CyberChef again I decoded the inner layer to find more encoded powershell!

Encoded Powershell

Finally to investigate this last bit of obfuscation lets open the code in the built-in PowerShell editor. I used the Write-Output function to add output logging for different varables before running the malicious powershell. This revealed the encoded C2 value ( and also showed that a scheduled task was created!

Decoded Powershell

Further investigating Windows Scheduled Tasks confirmed this finding.

Scheduled Task

Part 3: Network Traffic Analysis

While performing dynamic analysis earlier I captured network traffic using MITMProxy.

This malware performs two types of HTTP requests:

  • GET requests to C2 urls that start with /r/
    • This will returned powershell to execute
  • POST requests to c2 urls that start with /c/
    • This contains gathered victim information

Here’s what the C2 response provided to execute:

powershell server response

This powershell contains the logic for automated reconnaissance as well as data encoding using a randomly generated XOR key. Taking a look the POST data request that followed we can confirmed that there is encoded data:

Fortunately the randomly generated XOR key is included in the post request in the variable magic.

Using python3 (and a little bit of help from ChatGPT) I wrote a small program that decodes this data:

import sys

def decode(encoded_str, xor_key):
    decoded_str = ""
    key_len = len(xor_key)
    for i in range(0, len(encoded_str), 2):
        encoded_byte = int(encoded_str[i:i+2], 16) # Convert the hexadecimal byte to an integer
        xor_key_byte = ord(xor_key[i//2 % key_len]) # Get the corresponding byte from the XOR key
        decoded_byte = encoded_byte ^ xor_key_byte # Perform the XOR operation
        decoded_str += chr(decoded_byte) # Convert the result back to a character and append to the decoded string
    return decoded_str

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python <encoded_str> <xor_key>")
        encoded_str = sys.argv[1]
        xor_key = sys.argv[2]
        decoded_str = decode(encoded_str, xor_key)

This code has been uploaded to a Github gist.

Using the data captured I confirmed the decoding works!


Based on what was shared publicly by HuntressLabs and what was found on VirusTotal we can summarize this threat campaign as:

Email Attachment -> JavaScript Malware -> Scheduled Task & C2 Communication > Domain Recon > Ransomware