From 84448a334529dbba110c214e8659f5a89439b72f Mon Sep 17 00:00:00 2001 From: ghost-ng Date: Sat, 13 Jan 2024 15:02:22 -0500 Subject: [PATCH] added a method to disable a service, fixed what happens when the remote reg is disabled --- TODO..md | 4 +- src/slingerpkg/__init__.py | 2 +- src/slingerpkg/lib/dcetransport.py | 97 +++++++++++++++++++++++++++--- src/slingerpkg/lib/scm.py | 92 +++++++++++++++++++++++++++- src/slingerpkg/lib/winreg.py | 10 ++- src/slingerpkg/utils/cli.py | 14 +++++ 6 files changed, 206 insertions(+), 13 deletions(-) diff --git a/TODO..md b/TODO..md index c5c5f7d..777c021 100755 --- a/TODO..md +++ b/TODO..md @@ -13,4 +13,6 @@ - sc modify ### Test -- test on a domain \ No newline at end of file +- test on a domain + +### General diff --git a/src/slingerpkg/__init__.py b/src/slingerpkg/__init__.py index d76a09f..91f77e0 100755 --- a/src/slingerpkg/__init__.py +++ b/src/slingerpkg/__init__.py @@ -1,2 +1,2 @@ -__version__ = '0.5.1' +__version__ = '0.6.0' __package__ = 'slinger' \ No newline at end of file diff --git a/src/slingerpkg/lib/dcetransport.py b/src/slingerpkg/lib/dcetransport.py index c5bfbd0..eaf8fc4 100755 --- a/src/slingerpkg/lib/dcetransport.py +++ b/src/slingerpkg/lib/dcetransport.py @@ -112,10 +112,21 @@ def _enable_remote_registry(self): self.rrpstarted = True else: print_info("Trying to start RemoteRegistry service") - response = self._start_service('RemoteRegistry', bind=False) - self.rrpstarted = True - self.rrpshouldStop = True - print_good("Remote Registry service started") + self._connect('svcctl') + response = self._start_service('RemoteRegistry', bind=True) + if response == "DISABLED": + self.rrpshouldDisable = True + print_bad("Remote Registry service is disabled") + self._connect('svcctl') + print_info("Trying to enable RemoteRegistry service") + _ = self._enable_service("RemoteRegistry") + _ = self._start_service('RemoteRegistry', bind=False) + print_info("Checking the status of the RemoteRegistry service") + response = self._checkServiceStatus("RemoteRegistry") + if response: + self.rrpshouldStop = True + self.rrpstarted = True + print_good("Remote Registry service started") def _close_scm_handle(self, serviceHandle): try: @@ -128,6 +139,10 @@ def _disconnect(self): self._connect('svcctl') self._stop_service("RemoteRegistry") print_info("Remote Registy state restored -> STOPPED") + if self.rrpshouldDisable: + self._connect('svcctl') + self._disable_service("RemoteRegistry") + print_info("Remote Registy state restored -> DISABLED") self.dce.disconnect() self.is_connected = False @@ -270,6 +285,54 @@ def _enum_services(self): self._close_scm_handle(self.scManagerHandle) return response + def _disable_service(self, service_name): + if not self.is_connected: + raise Exception("Not connected to remote host") + self.bind_override = True + self._bind(scmr.MSRPC_UUID_SCMR) + ans = scmr.hROpenSCManagerW(self.dce) + self.scManagerHandle = ans['lpScHandle'] + ans = scmr.hROpenServiceW(self.dce, self.scManagerHandle, service_name + '\x00') + self.serviceHandle = ans['lpServiceHandle'] + try: + response = scmr.hRChangeServiceConfigW(self.dce, self.serviceHandle, dwStartType=scmr.SERVICE_DISABLED) + self._close_scm_handle(self.serviceHandle) + if response['ErrorCode'] == 0: + return True + else: + return False + except Exception as e: + print_debug(str(e), sys.exc_info()) + if "ERROR_ACCESS_DENIED" in str(e): + print_bad("Unable to change service configuration, access denied") + else: + print_bad("An error occurred: " + str(e)) + return False + + def _enable_service(self, service_name): + if not self.is_connected: + raise Exception("Not connected to remote host") + self.bind_override = True + self._bind(scmr.MSRPC_UUID_SCMR) + ans = scmr.hROpenSCManagerW(self.dce) + self.scManagerHandle = ans['lpScHandle'] + ans = scmr.hROpenServiceW(self.dce, self.scManagerHandle, service_name + '\x00') + self.serviceHandle = ans['lpServiceHandle'] + try: + response = scmr.hRChangeServiceConfigW(self.dce, self.serviceHandle, dwStartType=scmr.SERVICE_AUTO_START) + self._close_scm_handle(self.serviceHandle) + if response['ErrorCode'] == 0: + return True + else: + return False + except Exception as e: + print_debug(str(e), sys.exc_info()) + if "ERROR_ACCESS_DENIED" in str(e): + print_bad("Unable to change service configuration, access denied") + else: + print_bad("An error occurred: " + str(e)) + return False + def _get_service_details(self, service_name): if not self.is_connected: raise Exception("Not connected to remote host") @@ -303,11 +366,27 @@ def _start_service(self, service_name, bind=True): raise e return serviceHandle = ans['lpServiceHandle'] - response = scmr.hRStartServiceW(self.dce, serviceHandle) - self._close_scm_handle(serviceHandle) - if service_name == "RemoteRegistry": - self.rrpstarted = True - return response + try: + response = scmr.hRStartServiceW(self.dce, serviceHandle) + self._close_scm_handle(serviceHandle) + if service_name == "RemoteRegistry": + self.rrpstarted = True + if response['ErrorCode'] == 0: + + return True + except Exception as e: + if "ERROR_SERVICE_DISABLED" in str(e): + return "DISABLED" + elif "ERROR_SERVICE_ALREADY_RUNNING" in str(e): + return "RUNNING" + elif "ERROR_ACCESS_DENIED" in str(e): + print_bad("Unable to start service, access denied") + return False + else: + print_debug(str(e), sys.exc_info()) + return False + + def _stop_service(self, service_name): if not self.is_connected: diff --git a/src/slingerpkg/lib/scm.py b/src/slingerpkg/lib/scm.py index 9dee39e..efadf88 100755 --- a/src/slingerpkg/lib/scm.py +++ b/src/slingerpkg/lib/scm.py @@ -43,6 +43,90 @@ def start_service_handler(self, args): service_arg = args.serviceid if args.serviceid else args.service_name self.start_service(service_arg) + def enable_service_handler(self, args): + if not self.services_list and args.serviceid: + print_warning("No services have been enumerated. Run enumservices first.") + else: + service_arg = args.serviceid if args.serviceid else args.service_name + self.enable_service(service_arg) + + def disable_service_handler(self, args): + if not self.services_list and args.serviceid: + print_warning("No services have been enumerated. Run enumservices first.") + else: + service_arg = args.serviceid if args.serviceid else args.service_name + self.disable_service(service_arg) + + def disable_service(self, service_arg): + self.setup_dce_transport() + self.dce_transport._connect('svcctl') + + # lookup taskpath and task name from dict with task_id + service_name = None + if type(service_arg) is int: + print_info("Looking up service ID...") + count = 1 + #print_log("Searching through %d services" % len(self.services_list)) + for service in self.services_list: + #print_info("Checking service %d" % count) + if count == service_arg: + service_name = service[1] + break + count += 1 + else: + service_name = service_arg + + if service_name is None: + print_warning("Service name not found") + return + else: + print_info("Chosen Service: " + service_name) + try: + response = self.dce_transport._disable_service(service_name) + if response: + print_good("Service disabled successfully") + else: + print_log(f"Error disabling service '{service_name}': {response['ErrorCode']}") + except Exception as e: + print_bad("Unable to disable service: " + service_name) + print_bad("An error occurred:" + str(e)) + print_debug('', sys.exc_info()) + + def enable_service(self, service_arg): + self.setup_dce_transport() + self.dce_transport._connect('svcctl') + service_name = None + if type(service_arg) is int: + print_info("Looking up service ID...") + count = 1 + #print_log("Searching through %d services" % len(self.services_list)) + for service in self.services_list: + #print_info("Checking service %d" % count) + if count == service_arg: + service_name = service[1] + break + count += 1 + else: + service_name = service_arg + + if service_name is None: + print_warning("Service name not found") + return + else: + print_info("Chosen Service: " + service_name) + + try: + print_info(f"Trying to enable service {service_name}") + response = self.dce_transport._enable_service(service_name) + if response: + print_good("Service enabled successfully") + else: + print_log(f"Error enabling service '{service_name}': {response['ErrorCode']}") + except Exception as e: + print_bad("Unable to enable service: " + service_name) + print_bad("An error occurred:" + str(e)) + print_debug('', sys.exc_info()) + def start_service(self, service_arg): self.setup_dce_transport() self.dce_transport._connect('svcctl') @@ -70,7 +154,13 @@ def start_service(self, service_arg): print_info("Chosen Service: " + service_name) try: response = self.dce_transport._start_service(service_name) - if response['ErrorCode'] == 0: + if response == "DISABLED": + print_warning("Failed to start service: " + service_name) + print_warning("Service disabled") + return + elif response is False: + return + elif response is True: print_good("Service started successfully") else: print_log(f"Error starting service '{service_name}': {response['ErrorCode']}") diff --git a/src/slingerpkg/lib/winreg.py b/src/slingerpkg/lib/winreg.py index a71a1f2..1243fcc 100755 --- a/src/slingerpkg/lib/winreg.py +++ b/src/slingerpkg/lib/winreg.py @@ -96,7 +96,15 @@ def setup_remote_registry(self, args): try: print_info("Starting Remote Registry service") response = self.dce_transport._start_service('RemoteRegistry') - print_good("Remote Registry service started") + if response == "DISABLED": + print_info("Trying to enable the Remote Registry service") + self.dcetransport._connect('winreg') + ans = self.dce_transport._enable_service('RemoteRegistry') + + if ans != False: + print_good("Remote Registry service started") + else: + print_bad("Failed to start Remote Registry service") except Exception as e: diff --git a/src/slingerpkg/utils/cli.py b/src/slingerpkg/utils/cli.py index 4ee9717..8b9892d 100755 --- a/src/slingerpkg/utils/cli.py +++ b/src/slingerpkg/utils/cli.py @@ -191,6 +191,20 @@ def setup_cli_parser(slingerClient): svcstopgroup.add_argument('-i', '--serviceid', type=int, help='Specify the ID of the service to stop') svcstopgroup.add_argument('service_name', type=str, nargs='?', help='Specify the name of the service to stop') + # Subparser for 'serviceenable' command + parser_svcenable = subparsers.add_parser('serviceenable', help='Enable a service', description='Enable a specified service on the remote server', epilog='Example Usage: serviceenable -i 123 OR svcenable Spooler', aliases=['svcenable','enableservice', 'enablesvc']) + parser_svcenable.set_defaults(func=slingerClient.enable_service_handler) + svcenablegroup = parser_svcenable.add_mutually_exclusive_group(required=True) + svcenablegroup.add_argument('-i', '--serviceid', type=int, help='Specify the ID of the service to enable') + svcenablegroup.add_argument('service_name', type=str, nargs='?', help='Specify the name of the service to enable') + + # Subparser for 'servicedisable' command + parser_svcdisable = subparsers.add_parser('servicedisable', help='Disable a service', description='Disable a specified service on the remote server', epilog='Example Usage: servicedisable -i 123 OR svcdisable Spooler', aliases=['svcdisable','disableservice', 'disablesvc']) + parser_svcdisable.set_defaults(func=slingerClient.disable_service_handler) + svcdisablegroup = parser_svcdisable.add_mutually_exclusive_group(required=True) + svcdisablegroup.add_argument('-i', '--serviceid', type=int, help='Specify the ID of the service to disable') + svcdisablegroup.add_argument('service_name', type=str, nargs='?', help='Specify the name of the service to disable') + # Subparser for 'servicedel' command parser_svcdelete = subparsers.add_parser('servicedel', help='Delete a service', description='Delete a specified service on the remote server', epilog='Example Usage: servicedelete -i 123 OR svcdelete Spooler', aliases=['svcdelete','servicedelete']) svcdeletegroup = parser_svcdelete.add_mutually_exclusive_group(required=True)