Skip to content

Commit

Permalink
fixed download upload paths, refactorred dce transport, fixed cli cmd…
Browse files Browse the repository at this point in the history
…s, fixed portfwd rules
  • Loading branch information
ghost-ng committed Dec 27, 2023
1 parent 8b50730 commit dc9e2c6
Show file tree
Hide file tree
Showing 12 changed files with 737 additions and 422 deletions.
17 changes: 3 additions & 14 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,10 @@ task scheduler

registry
- uptime
- processes

service control
- sc modify

- sc delete
- sc add


factor encoding
if sys.stdout.encoding is None:
# Output is redirected to a file
sys.stdout = codecs.getwriter('utf8')(sys.stdout)

- properly disconnect dce
- move None checks for transport to function
- clean up unused imports

fix error reporting
command chaining
run slinger script file (from folder)
244 changes: 41 additions & 203 deletions main.py

Large diffs are not rendered by default.

54 changes: 49 additions & 5 deletions slinger/lib/dcetransport.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,7 @@ def _start_service(self, service_name, bind=True):
if "rpc_s_access_denied" in str(e):
print_bad("Unable to connect to service, access denied")
else:
print_bad("An error occurred:")
traceback.print_exc()
raise e
return
serviceHandle = ans['lpServiceHandle']
response = scmr.hRStartServiceW(self.dce, serviceHandle)
Expand All @@ -322,8 +321,8 @@ def _stop_service(self, service_name):
if "rpc_s_access_denied" in str(e):
print_bad("Unable to connect to service, access denied")
else:
print_bad("An error occurred:")
traceback.print_exc()
print_bad("An error occurred: " + str(e))
print_debug('', sys.exc_info())
return
serviceHandle = ans['lpServiceHandle']
response = scmr.hRControlService(self.dce, serviceHandle, scmr.SERVICE_CONTROL_STOP)
Expand Down Expand Up @@ -355,6 +354,51 @@ def _checkServiceStatus(self, serviceName):
else:
raise Exception('Unknown service state 0x%x - Aborting' % ans['CurrentState'])

def _delete_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']
try:
ans = scmr.hROpenServiceW(self.dce, self.scManagerHandle, service_name + '\x00')
except Exception as e:
if "rpc_s_access_denied" in str(e):
print_bad("Unable to connect to service, access denied")
else:
print_bad("An error occurred: " + str(e))
print_debug('', sys.exc_info())
return
serviceHandle = ans['lpServiceHandle']
response = scmr.hRDeleteService(self.dce, serviceHandle)
self._close_scm_handle(serviceHandle)
return response

def _create_service(self, service_name, bin_path, start_type, display_name=None):
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']
if display_name is None:
display_name = service_name

try:
if start_type == 'auto':
start_type = scmr.SERVICE_AUTO_START
elif start_type == 'demand':
start_type = scmr.SERVICE_DEMAND_START
elif start_type == 'system':
start_type = scmr.SERVICE_SYSTEM_START
except AttributeError:
start_type = scmr.SERVICE_DEMAND_START

response = scmr.hRCreateServiceW(self.dce, self.scManagerHandle, service_name, display_name,
dwServiceType=scmr.SERVICE_WIN32_OWN_PROCESS, dwErrorControl=scmr.SERVICE_ERROR_IGNORE, lpBinaryPathName=bin_path, dwStartType=start_type)
return response

def _get_root_key(self, keyName):
# Let's strip the root key
try:
Expand Down Expand Up @@ -398,7 +442,7 @@ def _enum_subkeys(self, keyName, bind=True):
i += 1

except Exception as e:
print_debug(str(e))
print_debug(str(e), sys.exc_info())
break
return subkeys

Expand Down
88 changes: 51 additions & 37 deletions slinger/lib/schtasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ def __init__(self):


def enum_folders_old(self, folder_path="\\", start_index=0):
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
self.setup_dce_transport()
self.dce_transport._connect('atsvc')

# Call SchRpcEnumFolders
Expand All @@ -43,9 +42,7 @@ def enum_folders_old(self, folder_path="\\", start_index=0):
if folder_name is not None and full_folder_path not in self.folder_list:
print_info("Found Folder: " + full_folder_path)
self.folder_list.append(full_folder_path)

#print_info("Found Folders: " + ' '.join(self.folder_list))
#self.enum_folders_recursive(self.folder_list, start_index)


def enum_folders(self, folder_path="\\", start_index=0):
"""
Expand All @@ -58,8 +55,7 @@ def enum_folders(self, folder_path="\\", start_index=0):
Returns:
None
"""
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
self.setup_dce_transport()
self.dce_transport._connect('atsvc')
response = self.dce_transport._enum_folders(folder_path, start_index)
if response['ErrorCode'] == 0:
Expand All @@ -75,14 +71,16 @@ def enum_folders(self, folder_path="\\", start_index=0):
else:
return

def enum_folders_recursive(self, folder="\\", start_index=0):
def enum_task_folders_recursive(self, args):
"""
Enumerates the Task Scheduler folders recursively.
Args:
folder (str): The folder to start the enumeration from. Defaults to "\\".
start_index (int): The starting index for the enumeration. Defaults to 0.
"""
folder="\\"
start_index=0
print_info("Enumerating Task Scheduler...")
self.folder_list = ["\\"]
self.folder_list_dict = {}
Expand Down Expand Up @@ -139,8 +137,7 @@ def parse_folder_tasks(self, response, folder):
return None

def view_tasks_in_folder(self, folder=None):
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
self.setup_dce_transport()
#self.dce_transport.connect('atsvc')

folder_paths = self.folder_list if folder is None else [folder]
Expand All @@ -149,7 +146,7 @@ def view_tasks_in_folder(self, folder=None):
self.dce_transport._connect('atsvc')
folder_path = folder_path.rstrip("\\")
try:
#print_info(f"Enumerating tasks in folder: {folder_path}")
print_info(f"Enumerating tasks in folder: {folder_path}")
response = self.dce_transport._view_tasks_in_folder(folder_path)
#print_log(response.dump())
#print_info(f"Parsing Tasks in {folder_path}:")
Expand All @@ -165,17 +162,21 @@ def view_tasks_in_folder(self, folder=None):
print_bad("Unable to view tasks in folder: " + folder_path)
print_log(e)

def task_run(self, abs_path):
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
def task_run(self, args):
abs_path = args.task_path
self.setup_dce_transport()
self.dce_transport._connect('atsvc')
response = self.dce_transport._run_task(abs_path)
if response['ErrorCode'] == 0:
print_good(f"Task '{abs_path}' run successfully.")
else:
print_bad(f"Error running task '{abs_path}': {response['ErrorCode']}")

def task_create(self, task_name, program, arguments, folder_path):
def task_create(self, args):
task_name = args.name
program = args.program
arguments = args.arguments
folder_path = args.folder
# generate random date in last year using format 2023-01-01T08:00:00
new_date = generate_random_date()
task_xml = f"""<?xml version="1.0" encoding="UTF-16"?>
Expand Down Expand Up @@ -228,8 +229,7 @@ def task_create(self, task_name, program, arguments, folder_path):
</Task>
"""
#validate_xml(task_xml)
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
self.setup_dce_transport()
self.dce_transport._connect('atsvc')

print_info(f"Creating task '{task_name}' in folder '{folder_path}'")
Expand All @@ -250,11 +250,15 @@ def task_create(self, task_name, program, arguments, folder_path):
print_log(f"Error creating task '{task_name}': {response['ErrorCode']}")



def task_delete_handler(self, args):
if not self.folder_list_dict and args.taskid:
print_warning("No tasks have been enumerated. Run enumtasks first.")
else:
task_arg = args.taskid if args.taskid else args.task_path
self.task_delete(task_arg)

def task_delete(self, task_arg):
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
self.setup_dce_transport()
self.dce_transport._connect('atsvc')

task_name = None
Expand All @@ -279,12 +283,21 @@ def task_delete(self, task_arg):
print_warning("Task ID not found")
return
else:
print_info(f"Chosen Task:\nTask Path: {task_path}\nTask Name: {task_name}")
response = self.dce_transport._delete_task(task_abs_path)
if response['ErrorCode'] == 0:
print_good(f"Task '{task_abs_path}' deleted successfully.")
else:
print_bad(f"Error deleting task '{task_abs_path}': {response['ErrorCode']}")
#print_info(f"Chosen Task:\nTask Path: {task_path}\nTask Name: {task_name}")
try:
response = self.dce_transport._delete_task(task_abs_path)
if response['ErrorCode'] == 0:
print_good(f"Task '{task_abs_path}' deleted successfully.")
else:
print_bad(f"Error deleting task '{task_abs_path}': {response['ErrorCode']}")
except Exception as e:
if "ERROR_FILE_NOT_FOUND" in str(e) or "ERROR_INVALID_NAME" in str(e):
print_warning(f"Task '{task_abs_path}' does not exist.")
return
else:
print_bad(f"Error deleting task '{task_abs_path}': {e}")
return

except Exception as e:
task_arg = str(task_arg)
if "Bind context rejected: reason_not_specified" in str(e):
Expand All @@ -293,21 +306,22 @@ def task_delete(self, task_arg):
print_warning("Unable to delete task: " + task_arg +" - invalid name")
else:
print_bad("Unable to delete task: " + task_arg)
print_bad("An error occurred:")
traceback.print_exc()

print_debug("An error occurred:", sys.exc_info())

def task_show_handler(self, args):

if not self.folder_list_dict and args.taskid:
print_warning("No tasks have been enumerated. Run enumtasks first.")
else:
task_arg = args.taskid if args.taskid else args.task_path
self.view_task_details(task_arg)


def task_manager(self):
pass





def view_task_details(self, task_arg):
if self.dce_transport is None:
self.dce_transport = DCETransport(self.host, self.username, self.port, self.conn)
self.setup_dce_transport()
self.dce_transport._connect('atsvc')
# lookup taskpath and task name from dict with task_id
task_name = None
Expand All @@ -333,7 +347,7 @@ def view_task_details(self, task_arg):
return
else:
print_info(f"Chosen Task:\nTask Path: {task_path}\nTask Name: {task_name}")
response = self.dce_transport._view_tasks(task_name, task_path)
response = self.dce_transport._view_tasks(task_name, task_path)
if response['ErrorCode'] == 0:
task_xml = response['pXml']
print_log(f"{task_xml}")
Expand All @@ -343,7 +357,7 @@ def view_task_details(self, task_arg):
except Exception as e:
if "Bind context rejected: reason_not_specified" in str(e):
print_warning("Unable to view task: " + task_arg +" - invalid context")
elif "ERROR_INVALID_NAME" in str(e):
elif "ERROR_INVALID_NAME" in str(e) or "ERROR_FILE_NOT_FOUND" in str(e):
print_warning("Unable to view task: " + task_arg +" - invalid name")
else:
print_bad("Unable to view task: " + task_arg)
Expand Down
Loading

0 comments on commit dc9e2c6

Please sign in to comment.