Skip to content

Commit

Permalink
Merge pull request #80 from Hackndo/3.1.7
Browse files Browse the repository at this point in the history
3.1.7
  • Loading branch information
Hackndo authored Apr 6, 2023
2 parents 33fb1be + f55ddb4 commit 4e4b4e5
Show file tree
Hide file tree
Showing 25 changed files with 256 additions and 239 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# lsassy

[![PyPI version](https://badge.fury.io/py/lsassy.svg)](https://pypi.org/project/lsassy)
[![PyPI version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=py&type=6&v=v3.1.7&x2=0)](https://pypi.org/project/lsassy)
[![PyPI Statistics](https://img.shields.io/pypi/dm/lsassy.svg)](https://pypistats.org/packages/lsassy)
[![Tests](https://github.com/hackndo/lsassy/workflows/Tests/badge.svg)](https://github.com/hackndo/lsassy/actions?workflow=Tests)
[![Twitter](https://img.shields.io/twitter/follow/hackanddo?label=HackAndDo&style=social)](https://twitter.com/intent/follow?screen_name=hackanddo)
Expand Down
2 changes: 1 addition & 1 deletion lsassy/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '3.1.6'
__version__ = '3.1.7'
10 changes: 10 additions & 0 deletions lsassy/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from lsassy import __version__
from lsassy.core import ThreadPool
from lsassy.dumper import Dumper
from lsassy.logger import lsassy_logger
import logging


def main():
Expand Down Expand Up @@ -82,6 +84,14 @@ def main():

args = parser.parse_args()

if args.v == 1:
lsassy_logger.setLevel(logging.INFO)
elif args.v >= 2:
lsassy_logger.setLevel(logging.DEBUG)
lsassy_logger.info("lsassy v {}".format(__version__))
else:
lsassy_logger.setLevel(logging.ERROR)

ThreadPool(args.target, args).run()


Expand Down
72 changes: 32 additions & 40 deletions lsassy/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
import time
from queue import Queue

from lsassy import logger, __version__
from lsassy import __version__
from lsassy.dumper import Dumper
from lsassy.impacketfile import ImpacketFile
from lsassy.parser import Parser
from lsassy.session import Session
from lsassy.utils import get_targets
from lsassy.writer import Writer
from lsassy.logger import lsassy_logger

lock = threading.RLock()

Expand Down Expand Up @@ -43,12 +44,13 @@ def __init__(self, targets, arguments):
self.arguments = arguments
self.threads = []
self.max_threads = arguments.threads
self.task_q = Queue(self.max_threads+10)
self.task_q = Queue(self.max_threads)
lsassy_logger.no_color = self.arguments.no_color
signal.signal(signal.SIGINT, self.interrupt_event)
signal.signal(signal.SIGTERM, self.interrupt_event)

def interrupt_event(self, signum, stack):
logging.error("**CTRL+C** QUITTING GRACEFULLY")
lsassy_logger.error("**CTRL+C** QUITTING GRACEFULLY")
self.stop()
raise KeyboardInterrupt

Expand All @@ -62,19 +64,8 @@ def isRunning(self):
return any(thread.is_alive() for thread in self.threads)

def run(self):
logger.init(no_color=self.arguments.no_color)
threading.current_thread().name = "[Core]"

if self.arguments.v == 1:
logging.getLogger().setLevel(logging.INFO)
elif self.arguments.v >= 2:
logging.getLogger().setLevel(logging.DEBUG)
threading.current_thread().name = "[DEBUG]"
logging.info("lsassy v {}".format(__version__))
else:
logging.getLogger().setLevel(logging.ERROR)

threading.current_thread().name = "[Core]"
try:
# Turn-on the worker threads
for i in range(self.max_threads):
Expand All @@ -84,15 +75,16 @@ def run(self):
thread.start()

instance_id = 1
lsassy_logger.debug(f"Targets: {self.targets}")
for target in self.targets:
self.task_q.put(Lsassy(target, self.arguments, instance_id))
lsassy_logger.debug(f"Created target: {instance_id}: {target}")
instance_id += 1

# Block until all tasks are done
self.task_q.join()

except KeyboardInterrupt as e:
logging.error("Au revoir.")
lsassy_logger.error("Au revoir.")


class Lsassy:
Expand Down Expand Up @@ -134,7 +126,7 @@ def run(self):
dump_path = dump_path.replace('/', '\\')
if len(dump_path) > 1 and dump_path[1] == ":":
if dump_path[0] != "C":
logging.error("Drive '{}' is not supported. 'C' drive only.".format(dump_path[0]))
lsassy_logger.error("Drive '{}' is not supported. 'C' drive only.".format(dump_path[0]))
return False
dump_path = dump_path[2:]
if dump_path[-1] != "\\":
Expand All @@ -146,7 +138,7 @@ def run(self):
masterkeys_file = self.args.masterkeys_file

if parse_only and (dump_path is None or self.args.dump_name is None):
logging.error("--dump-path and --dump-name required for --parse-only option")
lsassy_logger.error("--dump-path and --dump-name required for --parse-only option")
return False

try:
Expand All @@ -167,20 +159,20 @@ def run(self):
)

if session.smb_session is None:
logging.warning("Couldn't connect to remote host")
lsassy_logger.warning("Couldn't connect to remote host")
return False

if not parse_only:
dumper = Dumper(session, self.args.timeout, self.args.time_between_commands).load(self.args.dump_method)
if dumper is None:
logging.error("Unable to load dump module")
lsassy_logger.error("Unable to load dump module")
return False

file = dumper.dump(no_powershell=self.args.no_powershell, exec_methods=exec_methods,
copy=self.args.copy, dump_path=dump_path,
dump_name=self.args.dump_name, **options)
if file is None:
logging.error("Unable to dump lsass.")
lsassy_logger.error("Unable to dump lsass.")
return False
else:
file = ImpacketFile(session).open(
Expand All @@ -190,20 +182,20 @@ def run(self):
timeout=self.args.timeout
)
if file is None:
logging.error("Unable to open lsass dump.")
lsassy_logger.error("Unable to open lsass dump.")
return False

credentials, tickets, masterkeys = Parser(file).parse()
file.close()

if not parse_only and not keep_dump:
ImpacketFile.delete(session, file.get_file_path(), timeout=self.args.timeout)
logging.success("Lsass dump deleted")
lsassy_logger.debug("Lsass dump deleted")
else:
logging.debug("Not deleting lsass dump as --parse-only was provided")
lsassy_logger.debug("Not deleting lsass dump as --parse-only was provided")

if credentials is None:
logging.error("Unable to extract credentials from lsass. Cleaning.")
lsassy_logger.error("Unable to extract credentials from lsass. Cleaning.")
return False

with lock:
Expand All @@ -222,38 +214,38 @@ def run(self):
except KeyboardInterrupt:
pass
except Exception as e:
logging.error("An unknown error has occurred.", exc_info=True)
lsassy_logger.error("An unknown error has occurred.", exc_info=True)
finally:
logging.debug("Cleaning...")
logging.debug("dumper: {}".format(dumper))
logging.debug("file: {}".format(file))
logging.debug("session: {}".format(session))
lsassy_logger.debug("Cleaning...")
lsassy_logger.debug("dumper: {}".format(dumper))
lsassy_logger.debug("file: {}".format(file))
lsassy_logger.debug("session: {}".format(session))
try:
dumper.clean()
logging.debug("Dumper cleaned")
lsassy_logger.debug("Dumper cleaned")
except Exception as e:
logging.debug("Potential issue while cleaning dumper: {}".format(str(e)))
lsassy_logger.debug("Potential issue while cleaning dumper: {}".format(str(e)))

try:
file.close()
logging.debug("File closed")
lsassy_logger.debug("File closed")
except Exception as e:
logging.debug("Potential issue while closing file: {}".format(str(e)))
lsassy_logger.debug("Potential issue while closing file: {}".format(str(e)))

if not parse_only and not keep_dump:
try:
if ImpacketFile.delete(session, file_path=file.get_file_path(), timeout=self.args.timeout):
logging.debug("Lsass dump deleted")
lsassy_logger.debug("Lsass dump deleted")
except Exception as e:
try:
logging.debug("Couldn't delete lsass dump using file. Trying dump object...")
lsassy_logger.debug("Couldn't delete lsass dump using file. Trying dump object...")
if ImpacketFile.delete(session, file_path=dumper.dump_path + dumper.dump_name, timeout=self.args.timeout):
logging.debug("Lsass dump deleted")
lsassy_logger.debug("Lsass dump deleted")
except Exception as e:
logging.debug("Potential issue while deleting lsass dump: {}".format(str(e)))
lsassy_logger.debug("Potential issue while deleting lsass dump: {}".format(str(e)))

try:
session.smb_session.close()
logging.debug("SMB session closed")
lsassy_logger.debug("SMB session closed")
except Exception as e:
logging.debug("Potential issue while closing SMB session: {}".format(str(e)))
lsassy_logger.debug("Potential issue while closing SMB session: {}".format(str(e)))
7 changes: 3 additions & 4 deletions lsassy/dumper.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import logging
import importlib
import pkgutil

from lsassy import dumpmethod, exec
from lsassy.logger import lsassy_logger


class Dumper:
Expand All @@ -13,7 +13,6 @@ class Dumper:
Returns None if doesn't exist.
"""
def __init__(self, session, timeout, time_between_commands):

self._session = session
self._timeout = timeout
self._time_between_commands = time_between_commands
Expand All @@ -27,10 +26,10 @@ def load(self, dump_module):
try:
return importlib.import_module("lsassy.dumpmethod.{}".format(dump_module.lower()), "DumpMethod").DumpMethod(self._session, self._timeout, self._time_between_commands)
except ModuleNotFoundError:
logging.warning("Dump module '{}' doesn't exist".format(dump_module))
lsassy_logger.warning("Dump module '{}' doesn't exist".format(dump_module))
return None
except Exception:
logging.warning("Unknown error while loading '{}'".format(dump_module), exc_info=True)
lsassy_logger.warning("Unknown error while loading '{}'".format(dump_module), exc_info=True)
return None

@staticmethod
Expand Down
Loading

0 comments on commit 4e4b4e5

Please sign in to comment.