From ed0b5f4350acbe1840a0e74e1eaae9193b9dcf04 Mon Sep 17 00:00:00 2001 From: ghost-ng Date: Thu, 4 Jan 2024 17:57:03 -0500 Subject: [PATCH] added todo task, fixed setup, minor message fixes, minor func fixes --- README.md | 5 ++++ setup.py | 5 ---- src/slinger.py | 18 +++++++-------- src/slingerpkg/__init__.py | 2 +- src/slingerpkg/lib/dcetransport.py | 2 +- src/slingerpkg/lib/schtasks.py | 1 + src/slingerpkg/lib/smblib.py | 37 ++++++++++++++++++++++++++++-- src/slingerpkg/utils/cli.py | 4 +++- 8 files changed, 55 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 880c0b2..10e3cc2 100644 --- a/README.md +++ b/README.md @@ -180,13 +180,18 @@ pip install slinger-_._._.tar.gz ### Task Scheduler - all in one (create, execute, delete) +- add task run modifiers (run every X min/hour) ### Registry - uptime +- process enumeration (inspired by nmap ns script) ### Service Control - sc modify +### Test +- test on a domain + ## Contributing ### Creating Your Own Plugin for Slinger diff --git a/setup.py b/setup.py index 0a3e16e..0e42211 100644 --- a/setup.py +++ b/setup.py @@ -22,10 +22,5 @@ def parse_requirements(filename): url="https://github.com/ghost-ng/slinger", python_requires='>=3.10', scripts=['src/slinger.py'], - entry_points={ - 'console_scripts': [ - 'slinger=slinger.slinger:main', - ], - }, data_files=[('src/slingerpkg/plugins', ['src/slingerpkg/plugins/my_plugin.py'])], ) diff --git a/src/slinger.py b/src/slinger.py index 3f69a15..f06f5e8 100755 --- a/src/slinger.py +++ b/src/slinger.py @@ -45,17 +45,17 @@ def main(): original_settings = termios.tcgetattr(0) parser = argparse.ArgumentParser(description='impacket swiss army knife (sort of)') - parser.add_argument('--host', required=True, help='Host to connect to') - parser.add_argument('-u', '--username', required=True, help='Username for authentication') - parser.add_argument('-d', '--domain', default='', help='Domain for authentication') - parser.add_argument('-p', '--port', type=int, default=445, help='Port to connect to') - parser.add_argument('--nojoy', action='store_true', help='Turn off emojis') + parser.add_argument('-host', required=True, help='Host to connect to') + parser.add_argument('-user', '--username', required=True, help='Username for authentication') + parser.add_argument('-domain', '--domain', default='', help='Domain for authentication') + parser.add_argument('-port', type=int, default=445, help='Port to connect to') + parser.add_argument('-nojoy', action='store_true', help='Turn off emojis') # authentication mutually exclusive group auth_group = parser.add_mutually_exclusive_group(required=True) auth_group.add_argument('-pass', '--password', help='Password for authentication') - auth_group.add_argument('--ntlm', help='NTLM hash for authentication') - auth_group.add_argument('--kerberos', action='store_true', help='Use Kerberos for authentication') - parser.add_argument('--debug', action='store_true', help='Turn on debug output') + auth_group.add_argument('-ntlm', help='NTLM hash for authentication') + auth_group.add_argument('-kerberos', action='store_true', help='Use Kerberos for authentication') + parser.add_argument('-debug', action='store_true', help='Turn on debug output') if len(sys.argv) == 1: parser.print_help() @@ -142,7 +142,7 @@ def main(): continue except Exception as e: print_debug(str(e), sys.exc_info()) - print_bad(f"Error: {e}: {sys.exc_info()}") + continue except argparse.ArgumentError as e: #print("Unknown command") diff --git a/src/slingerpkg/__init__.py b/src/slingerpkg/__init__.py index c933bc6..1738eb0 100755 --- a/src/slingerpkg/__init__.py +++ b/src/slingerpkg/__init__.py @@ -1,2 +1,2 @@ -__version__ = '0.2.0' +__version__ = '0.3.0' __package__ = 'slinger' \ No newline at end of file diff --git a/src/slingerpkg/lib/dcetransport.py b/src/slingerpkg/lib/dcetransport.py index d7f0b53..a4f252a 100755 --- a/src/slingerpkg/lib/dcetransport.py +++ b/src/slingerpkg/lib/dcetransport.py @@ -346,7 +346,7 @@ def _checkServiceStatus(self, serviceName): # Let's check its status ans = scmr.hRQueryServiceStatus(self.dce, svcHandle) if ans['lpServiceStatus']['dwCurrentState'] == scmr.SERVICE_STOPPED: - print_info('Service %s is in stopped state' % serviceName) + print_info('Service %s is in a stopped state' % serviceName) return False elif ans['lpServiceStatus']['dwCurrentState'] == scmr.SERVICE_RUNNING: print_info('Service %s is already running' % serviceName) diff --git a/src/slingerpkg/lib/schtasks.py b/src/slingerpkg/lib/schtasks.py index 83eacb5..22134f7 100755 --- a/src/slingerpkg/lib/schtasks.py +++ b/src/slingerpkg/lib/schtasks.py @@ -79,6 +79,7 @@ def enum_task_folders_recursive(self, args): folder (str): The folder to start the enumeration from. Defaults to "\\". start_index (int): The starting index for the enumeration. Defaults to 0. """ + print_info("Getting all tasks, this might take a while...") folder="\\" start_index=0 print_info("Enumerating Task Scheduler...") diff --git a/src/slingerpkg/lib/smblib.py b/src/slingerpkg/lib/smblib.py index 9a5ff97..c00e04f 100755 --- a/src/slingerpkg/lib/smblib.py +++ b/src/slingerpkg/lib/smblib.py @@ -31,6 +31,7 @@ def connect_share(self, args): self.share = share print_good(f"Connected to share {share}") self.is_connected_to_share = True + self.relative_path = "" self.update_current_path() except Exception as e: print_debug(str(e), sys.exc_info()) @@ -348,13 +349,45 @@ def dir_list(self, args=None): if f.is_system(): attributes += 'S' if f.is_archive(): attributes += 'A' long_name = f.get_longname() - dirList.append([file_type, creation_time, last_access_time, last_write_time, filesize, attributes, long_name]) + # attributes is file type - attributes (if not empty) + attribs = file_type if attributes == '' else file_type + "," + attributes + dirList.append([attribs, creation_time, last_access_time, last_write_time, filesize, long_name]) if path == "\\": suffix = "" else: suffix = path + "\\" print_info("Showing directory listing for: " + os.path.normpath(self.share + "\\" + suffix)) - print_log(tabulate(dirList, headers=['Type', 'Created', 'Last Access', 'Last Write', 'Size', 'Attribs', 'Name'], tablefmt='psql')) + + # get sort option from arg.sort + sort_option = args.sort + reverse_sort_option = args.sort_reverse + if sort_option == "name": + if reverse_sort_option: + dirList.sort(key=lambda x: x[5], reverse=True) + else: + dirList.sort(key=lambda x: x[5]) + elif sort_option == "created": + if reverse_sort_option: + dirList.sort(key=lambda x: x[1], reverse=True) + else: + dirList.sort(key=lambda x: x[1]) + elif sort_option == "lastaccess": + if reverse_sort_option: + dirList.sort(key=lambda x: x[2], reverse=True) + else: + dirList.sort(key=lambda x: x[2]) + elif sort_option == "lastwrite": + if reverse_sort_option: + dirList.sort(key=lambda x: x[3], reverse=True) + else: + dirList.sort(key=lambda x: x[3]) + elif sort_option == "size": + if reverse_sort_option: + dirList.sort(key=lambda x: x[4], reverse=True) + else: + dirList.sort(key=lambda x: x[4]) + + print_log(tabulate(dirList, headers=['Attribs', 'Created', 'LastAccess', 'LastWrite', 'Size', 'Name'], tablefmt='psql')) except Exception as e: print_debug(f"Failed to list directory {path} on share {self.share}: {e}", sys.exc_info()) print_bad(f"Failed to list directory {path} on share {self.share}: {e}") diff --git a/src/slingerpkg/utils/cli.py b/src/slingerpkg/utils/cli.py index b39427b..5326f47 100755 --- a/src/slingerpkg/utils/cli.py +++ b/src/slingerpkg/utils/cli.py @@ -110,6 +110,8 @@ def setup_cli_parser(slingerClient): # Subparser for 'ls' command parser_dir = subparsers.add_parser('ls', help='List directory contents', description='List contents of a directory at a specified path', epilog='Example Usage: ls /path/to/directory') parser_dir.add_argument('path', nargs='?', default=".", help='Path to list contents, defaults to current path') + parser_dir.add_argument('-s', '--sort', choices=['name','size','created','lastaccess','lastwrite'], default="date", help='Sort the directory contents by name, size, or date') + parser_dir.add_argument('-sr', '--sort-reverse', action='store_true', help='Reverse the sort order', default=False) parser_dir.set_defaults(func=slingerClient.dir_list) # Subparser for 'shares' command @@ -425,7 +427,7 @@ def get_prompt(client, nojoy): preamble = slinger_emoji + " " emoji = preamble if not nojoy else "" - prompt = f"{emoji}{colors.OKGREEN}({client.host}):{client.current_path}>{colors.ENDC} " + prompt = f"{emoji}{colors.OKGREEN}({client.host}):\\\\{client.current_path}>{colors.ENDC} " return prompt