Skip to content

Commit

Permalink
Merge pull request #91 from Hackndo/3.1.9
Browse files Browse the repository at this point in the history
3.1.9
  • Loading branch information
Hackndo committed Apr 17, 2024
2 parents 0f858a1 + f3f081a commit edf117e
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 16 deletions.
2 changes: 1 addition & 1 deletion lsassy/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def run(self):
return False

if not dump_only:
credentials, tickets, masterkeys = Parser(file).parse()
credentials, tickets, masterkeys = Parser(self.target, file).parse()
file.close()

if not parse_only and not keep_dump:
Expand Down
11 changes: 10 additions & 1 deletion lsassy/credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ class Credential:
"""
Credential class to hold extracted credentials from remote hosts
"""
def __init__(self, username, password=None, domain=None, lmhash=None, nthash=None, sha1=None, ticket=None, ssp=None, masterkey=None):
def __init__(self, hostname, username, password=None, domain=None, lmhash=None, nthash=None, sha1=None, ticket=None, ssp=None, masterkey=None):
self.hostname = hostname
self.username = username
self.password = password
self.domain = domain
Expand All @@ -13,6 +14,13 @@ def __init__(self, username, password=None, domain=None, lmhash=None, nthash=Non
self.ssp = ssp
self.masterkey = masterkey

def get_hostname(self):
"""
Get hostname where credential was found
:return: hostname
"""
return self.hostname

def get_username(self):
"""
Get credential username
Expand Down Expand Up @@ -51,6 +59,7 @@ def get_object(self):
:return: dict with credentials information
"""
return {
"hostname": self.hostname,
"username": self.username,
"password": self.password,
"domain": self.domain,
Expand Down
6 changes: 4 additions & 2 deletions lsassy/output/pretty_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_output(self) -> str:
# Step 3: Calculate the maximum size for padding.
# This ensures proper alignment in the output.
max_size = max(
len(c.get("domain") or "") + len(c.get("username") or "")
len(c.get("hostname") or "") + len(c.get("domain") or "") + len(c.get("username") or "")
for c in self._credentials
if c is not None
)
Expand Down Expand Up @@ -105,6 +105,7 @@ def _format_output_line(
Returns:
str: A formatted string representing a single line of the output.
"""
hostname = cred.get("hostname") or ""
domain = "{}\\".format(cred.get("domain")) if cred.get("domain") else " "
username = cred.get("username") or ""
padding = " " * (max_size - len(domain) - len(username) + 2)
Expand All @@ -118,7 +119,8 @@ def _format_output_line(
else ""
)

output_line = "{}{}{}{}{}{}".format(
output_line = "{} - {}{}{}{}{}{}".format(
hostname,
domain,
username,
padding,
Expand Down
8 changes: 5 additions & 3 deletions lsassy/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class Parser:
Parse remote lsass dump file using impacketfile and pypykatz
"""

def __init__(self, dumpfile):
def __init__(self, target, dumpfile):
self._target = target
self._dumpfile = dumpfile


Expand Down Expand Up @@ -48,7 +49,7 @@ def parse(self):
or (NThash and NThash != "00000000000000000000000000000000")
or (LMHash and LMHash != "00000000000000000000000000000000")):
credentials.append(
Credential(ssp=ssp, domain=domain, username=username, password=password, lmhash=LMHash,
Credential(hostname=self._target, ssp=ssp, domain=domain, username=username, password=password, lmhash=LMHash,
nthash=NThash, sha1=SHA1))

for kcred in pypy_parse.logon_sessions[luid].kerberos_creds:
Expand All @@ -60,7 +61,7 @@ def parse(self):
if m not in masterkeys:
masterkeys.append(m)
credentials.append(
Credential(ssp='dpapi', domain='', username='', masterkey=m)
Credential(hostname=self._target, ssp='dpapi', domain='', username='', masterkey=m)
)

for cred in pypy_parse.orphaned_creds:
Expand All @@ -79,6 +80,7 @@ def parse(self):
if ticket.EndTime > datetime.now(ticket.EndTime.tzinfo):

credentials.append(Credential(
hostname=self._target,
ssp="kerberos",
domain=ticket.DomainName,
username=ticket.EClientName[0],
Expand Down
13 changes: 4 additions & 9 deletions tests/test_lsassy.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import unittest
import logging
from argparse import Namespace

from lsassy.core import ThreadPool
from lsassy.dumper import Dumper
from lsassy.parser import Parser
from lsassy.session import Session
from lsassy.writer import Writer
from lsassy.logger import lsassy_logger

USERNAME = "pixis"
PASSWORD = 'P4ssw0rd'
Expand Down Expand Up @@ -85,7 +83,8 @@ def test_workflow(self):
file = dumper.dump(exec_methods=["smb"])
self.assertIsNotNone(file)

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

file.close()
self.assertTrue(len(credentials) > 0)

Expand All @@ -104,7 +103,6 @@ def setUp(self) -> None:
username=USERNAME,
password=PASSWORD
)
lsassy_logger.setLevel(logging.DEBUG)

def dump_lsass(self, exec):
dumper = Dumper(self.session, 5, 1).load("comsvcs")
Expand All @@ -123,14 +121,10 @@ def test_smb_stealth(self):

"""
@TODO To fix
def test_mmc(self):
self.dump_lsass("mmc")
"""
"""
@TODO To fix
def test_wmi(self):
self.dump_lsass("wmi")
"""
Expand Down Expand Up @@ -206,7 +200,8 @@ def setUp(self) -> None:
file = dumper.dump(exec_methods=["smb"])
self.assertIsNotNone(file)

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

file.close()
self.assertTrue(len(credentials) > 0)

Expand Down

0 comments on commit edf117e

Please sign in to comment.