From 677b16e09cf4d4dc68acc414b916405b81ff9475 Mon Sep 17 00:00:00 2001 From: kalidor Date: Fri, 20 May 2022 22:13:17 +0200 Subject: [PATCH 1/4] Fix error when service is already running --- lib/msf/core/post/windows/services.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/msf/core/post/windows/services.rb b/lib/msf/core/post/windows/services.rb index 2c91db43bba8..c7729727059e 100644 --- a/lib/msf/core/post/windows/services.rb +++ b/lib/msf/core/post/windows/services.rb @@ -424,6 +424,9 @@ def service_start(name, server=nil) open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager| open_service_handle(manager, name, "SERVICE_START") do |service_handle| retval = advapi32.StartServiceA(service_handle,0,nil) + if retval["GetLastError"] == Error::SERVICE_ALREADY_RUNNING + return Error::SERVICE_ALREADY_RUNNING.to_s + end return retval["GetLastError"] end From e09169b281b2bc32a392cddfb05cef8d577e8fd2 Mon Sep 17 00:00:00 2001 From: kalidor Date: Fri, 20 May 2022 22:41:27 +0200 Subject: [PATCH 2/4] Raise Error::SERVICE_ALREADY_RUNNING --- lib/msf/core/post/windows/services.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/post/windows/services.rb b/lib/msf/core/post/windows/services.rb index c7729727059e..43bc3b5359eb 100644 --- a/lib/msf/core/post/windows/services.rb +++ b/lib/msf/core/post/windows/services.rb @@ -425,7 +425,7 @@ def service_start(name, server=nil) open_service_handle(manager, name, "SERVICE_START") do |service_handle| retval = advapi32.StartServiceA(service_handle,0,nil) if retval["GetLastError"] == Error::SERVICE_ALREADY_RUNNING - return Error::SERVICE_ALREADY_RUNNING.to_s + raise Error::SERVICE_ALREADY_RUNNING.to_s end return retval["GetLastError"] From b292586fb3d6e7a10c003099fd0ae6764dbff5ce Mon Sep 17 00:00:00 2001 From: kalidor Date: Thu, 9 Jun 2022 11:58:01 +0200 Subject: [PATCH 3/4] Avoid exception 'TypeError exception class/object expected' --- lib/msf/core/post/windows/services.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/msf/core/post/windows/services.rb b/lib/msf/core/post/windows/services.rb index 43bc3b5359eb..5e919bc40d3d 100644 --- a/lib/msf/core/post/windows/services.rb +++ b/lib/msf/core/post/windows/services.rb @@ -424,9 +424,6 @@ def service_start(name, server=nil) open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager| open_service_handle(manager, name, "SERVICE_START") do |service_handle| retval = advapi32.StartServiceA(service_handle,0,nil) - if retval["GetLastError"] == Error::SERVICE_ALREADY_RUNNING - raise Error::SERVICE_ALREADY_RUNNING.to_s - end return retval["GetLastError"] end @@ -527,7 +524,7 @@ def service_restart(name, start_type=START_TYPE_AUTO, server=nil) vprint_good("[#{name}] Service started") return true else - raise status + raise status.to_s end rescue RuntimeError => s if tried From c94f22cebe99619380f9794a58d8a6341f2fbeab Mon Sep 17 00:00:00 2001 From: Grant Willcox Date: Wed, 15 Jun 2022 19:28:31 -0500 Subject: [PATCH 4/4] Add in fixes from discussion and also update documentation to correctly note what functions can raise --- lib/msf/core/post/windows/services.rb | 78 +++++++++++++-------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/lib/msf/core/post/windows/services.rb b/lib/msf/core/post/windows/services.rb index 5e919bc40d3d..3e280152df1a 100644 --- a/lib/msf/core/post/windows/services.rb +++ b/lib/msf/core/post/windows/services.rb @@ -294,6 +294,7 @@ def service_exists?(service) # Mode is a string with either auto, manual or disable for the # corresponding setting. The name of the service is case sensitive. # + # @raise [RuntimeError] if an invalid startup mode is provided in the mode parameter # def service_change_startup(name, mode, server=nil) if mode.is_a? Integer @@ -338,6 +339,8 @@ def service_change_startup(name, mode, server=nil) # # @return [GetLastError] 0 if the function succeeds # + # @raise [RuntimeError] if OpenSCManagerA failed + # def service_change_config(name, opts, server=nil) open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager| open_service_handle(manager, name, "SERVICE_CHANGE_CONFIG") do |service_handle| @@ -369,6 +372,8 @@ def service_change_config(name, opts, server=nil) # # @return [GetLastError] 0 if the function succeeds # + # @raise [RuntimeError] if OpenSCManagerA failed + # def service_create(name, opts, server=nil) access = "SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS" open_sc_manager(:host=>server, :access=>access) do |manager| @@ -465,6 +470,8 @@ def service_stop(name, server=nil) # # @param (see #service_start) # + # @raise [RuntimeError] if OpenServiceA failed + # def service_delete(name, server=nil) open_sc_manager(:host=>server) do |manager| open_service_handle(manager, name, "DELETE") do |service_handle| @@ -483,7 +490,6 @@ def service_delete(name, server=nil) # # @raise (see #service_start) # - # def service_status(name, server=nil) ret = nil @@ -513,53 +519,41 @@ def service_status(name, server=nil) # # @return [Boolean] indicating success # - # - def service_restart(name, start_type=START_TYPE_AUTO, server=nil) - tried = false + def service_restart(name, start_type=START_TYPE_AUTO, server=nil, should_retry=true) + status = service_start(name, server) - begin - status = service_start(name, server) + if status == Error::SUCCESS + vprint_good("[#{name}] Service started") + return true + end - if status == Error::SUCCESS - vprint_good("[#{name}] Service started") - return true - else - raise status.to_s - end - rescue RuntimeError => s - if tried - vprint_error("[#{name}] Unhandled error: #{s}") - return false + + case status + when Error::ACCESS_DENIED + vprint_error("[#{name}] Access denied") + when Error::INVALID_HANDLE + vprint_error("[#{name}] Invalid handle") + when Error::PATH_NOT_FOUND + vprint_error("[#{name}] Service binary could not be found") + when Error::SERVICE_ALREADY_RUNNING + vprint_status("[#{name}] Service already running attempting to stop and restart") + stopped = service_stop(name, server) + if ((stopped == Error::SUCCESS) || (stopped == Error::SERVICE_NOT_ACTIVE)) + service_restart(name, start_type, server, false) if should_retry else - tried = true + vprint_error("[#{name}] Service disabled, unable to change start type Error: #{stopped}") end - - case s.message.to_i - when Error::ACCESS_DENIED - vprint_error("[#{name}] Access denied") - when Error::INVALID_HANDLE - vprint_error("[#{name}] Invalid handle") - when Error::PATH_NOT_FOUND - vprint_error("[#{name}] Service binary could not be found") - when Error::SERVICE_ALREADY_RUNNING - vprint_status("[#{name}] Service already running attempting to stop and restart") - stopped = service_stop(name, server) - if ((stopped == Error::SUCCESS) || (stopped == Error::SERVICE_NOT_ACTIVE)) - retry - else - vprint_error("[#{name}] Service disabled, unable to change start type Error: #{stopped}") - end - when Error::SERVICE_DISABLED - vprint_status("[#{name}] Service disabled attempting to set to manual") - if (service_change_config(name, {:starttype => start_type}, server) == Error::SUCCESS) - retry - else - vprint_error("[#{name}] Service disabled, unable to change start type") - end + when Error::SERVICE_DISABLED + vprint_status("[#{name}] Service disabled attempting to set to manual") + if (service_change_config(name, {:starttype => start_type}, server) == Error::SUCCESS) + service_restart(name, start_type, server, false) if should_retry else - vprint_error("[#{name}] Unhandled error: #{s}") - return false + vprint_error("[#{name}] Service disabled, unable to change start type") end + else + status = WindowsError::Win32.find_by_retval(s).first + vprint_error("[#{name}] Unhandled error: #{status.name}: #{status.description}") + return false end end