Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.1.13 #102

Merged
merged 13 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/lsassy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.10'

- name: Install dependencies
run: |
Expand All @@ -46,15 +46,15 @@ jobs:
max-parallel: 4
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ['3.9']
python-version: ['3.10']
steps:
- name: Checking out
uses: actions/checkout@v2

- name: Setup on ${{ matrix.os }}
uses: actions/setup-python@v2
with:
python-version: 3.9
python-version: '3.10'
architecture: x64

- name: Building binary with pyinstaller
Expand Down
16 changes: 10 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/python-poetry/poetry
rev: 1.8.3
hooks:
- id: poetry-check
- id: poetry-lock
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# lsassy
[![PyPI version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=py&type=6&v=v3.1.12&x2=0)](https://pypi.org/project/lsassy)
[![PyPI version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=py&type=6&v=v3.1.13&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/actions/workflows/lsassy.yml/badge.svg)](https://github.com/hackndo/lsassy/actions?workflow=lsassy)
[![Twitter](https://img.shields.io/twitter/follow/hackanddo?label=HackAndDo&style=social)](https://twitter.com/intent/follow?screen_name=hackanddo)
Expand Down
10 changes: 7 additions & 3 deletions hooks/hook-lsassy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
Note that output "table_output" has been removed. There's a bug regarding pyinstaller and
rich library which prevents compiling lsassy if this lib is somehow imported.
"""
hiddenimports = (collect_submodules('lsassy.exec') + collect_submodules('lsassy.output') + collect_submodules('lsassy.dumpmethod'))
hiddenimports.remove('lsassy.output.table_output')
hiddenimports.append('unicrypto.backends.pycryptodomex')
hiddenimports = (
collect_submodules("lsassy.exec")
+ collect_submodules("lsassy.output")
+ collect_submodules("lsassy.dumpmethod")
)
hiddenimports.remove("lsassy.output.table_output")
hiddenimports.append("unicrypto.backends.pycryptodomex")
2 changes: 1 addition & 1 deletion lsassy/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '3.1.12'
__version__ = "3.1.13"
240 changes: 179 additions & 61 deletions lsassy/console.py
Original file line number Diff line number Diff line change
@@ -1,83 +1,201 @@
import argparse
import logging
import sys

from lsassy import __version__
from lsassy.core import ThreadPool
from lsassy.dumper import Dumper
from lsassy.logger import lsassy_logger, LsassyLogger
import logging
from lsassy.logger import lsassy_logger


def main():
"""
Command line function to call lsassy
"""
Command line function to call lsassy
"""
version = __version__
parser = argparse.ArgumentParser(
prog="lsassy",
description='lsassy v{} - Remote lsass dump reader'.format(__version__)
description="lsassy v{} - Remote lsass dump reader".format(__version__),
)

group_dump = parser.add_argument_group('dump')
group_dump.add_argument('-m', '--dump-method', action='store', default="comsvcs",
help="Dumping method ({})".format(', '.join(Dumper.list_dump_methods())))
group_dump.add_argument('--dump-path', action='store',
help='Path to store lsass dumpfile (Default: \\Windows\\Temp)')
group_dump.add_argument('--dump-name', action='store', help='Name given to lsass dumpfile (Default: Random)')
group_dump.add_argument('-e', '--exec', action='store',
help='List of execution methods, comma separated (From {})'.format(', '.join(Dumper.list_exec_methods())))
group_dump.add_argument('--no-powershell', action='store_true', help='Disable PowerShell')
group_dump.add_argument('--copy', action='store_true', help='Copies cmd or powershell with random name before using it')
group_dump.add_argument('-O', '--options', action='store',
help='Dump module options (Example procdump_path=/opt/procdump.exe,procdump=procdump.exe')
group_dump.add_argument('--timeout', action='store', type=int, default=5,
help='Max time to wait for lsass dump (Default 5s)')
group_dump.add_argument('--time-between-commands', action='store', type=int, default=1,
help='Time to wait between dump methods commands (Default 1s)')
group_dump.add_argument('--parse-only', action='store_true', help='Parse dump without dumping')
group_dump.add_argument('--dump-only', action='store_true', help='Dump lsass without parsing it')
group_dump.add_argument('--keep-dump', action='store_true', help='Do not delete lsass dump on remote host')
group_dump = parser.add_argument_group("dump")
group_dump.add_argument(
"-m",
"--dump-method",
action="store",
default="comsvcs",
help="Dumping method ({})".format(", ".join(Dumper.list_dump_methods())),
)
group_dump.add_argument(
"--dump-path",
action="store",
help="Path to store lsass dumpfile (Default: \\Windows\\Temp)",
)
group_dump.add_argument(
"--dump-name",
action="store",
help="Name given to lsass dumpfile (Default: Random)",
)
group_dump.add_argument(
"-e",
"--exec",
action="store",
help="List of execution methods, comma separated (From {})".format(
", ".join(Dumper.list_exec_methods())
),
)
group_dump.add_argument(
"--no-powershell", action="store_true", help="Disable PowerShell"
)
group_dump.add_argument(
"--copy",
action="store_true",
help="Copies cmd or powershell with random name before using it",
)
group_dump.add_argument(
"-O",
"--options",
action="store",
help="Dump module options (Example procdump_path=/opt/procdump.exe,procdump=procdump.exe",
)
group_dump.add_argument(
"--timeout",
action="store",
type=int,
default=5,
help="Max time to wait for lsass dump (Default 5s)",
)
group_dump.add_argument(
"--time-between-commands",
action="store",
type=int,
default=1,
help="Time to wait between dump methods commands (Default 1s)",
)
group_dump.add_argument(
"--parse-only", action="store_true", help="Parse dump without dumping"
)
group_dump.add_argument(
"--dump-only", action="store_true", help="Dump lsass without parsing it"
)
group_dump.add_argument(
"--keep-dump",
action="store_true",
help="Do not delete lsass dump on remote host",
)

group_auth = parser.add_argument_group('authentication')
group_auth.add_argument('-u', '--username', action='store', help='Username')
group_auth.add_argument('-p', '--password', action='store', help='Plaintext password')
group_auth.add_argument('-d', '--domain', default="", action='store', help='Domain name')
group_auth.add_argument('--port', default=445, type=int, action='store', help='Port (Default: 445)')
group_auth.add_argument('--no-pass', action='store_true', help='Do not provide password (Default: False)')
group_auth.add_argument('-H', '--hashes', action='store', help='[LM:]NT hash')
group_auth.add_argument('-k', '--kerberos', action="store_true",
help='Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on '
'target parameters. If valid credentials '
'cannot be found, it will use the ones specified in the command line')
group_auth.add_argument('-dc-ip', action='store', metavar="ip address",
help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) '
'specified in the target parameter')
group_auth.add_argument('-aesKey', action="store", metavar="hex key",
help='AES key to use for Kerberos Authentication '
'(128 or 256 bits)')
group_auth = parser.add_argument_group("authentication")
group_auth.add_argument("-u", "--username", action="store", help="Username")
group_auth.add_argument(
"-p", "--password", action="store", help="Plaintext password"
)
group_auth.add_argument(
"-d", "--domain", default="", action="store", help="Domain name"
)
group_auth.add_argument(
"--port", default=445, type=int, action="store", help="Port (Default: 445)"
)
group_auth.add_argument(
"--no-pass",
action="store_true",
help="Do not provide password (Default: False)",
)
group_auth.add_argument("-H", "--hashes", action="store", help="[LM:]NT hash")
group_auth.add_argument(
"-k",
"--kerberos",
action="store_true",
help="Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on "
"target parameters. If valid credentials "
"cannot be found, it will use the ones specified in the command line",
)
group_auth.add_argument(
"-dc-ip",
action="store",
metavar="ip address",
help="IP Address of the domain controller. If omitted it will use the domain part (FQDN) "
"specified in the target parameter",
)
group_auth.add_argument(
"-aesKey",
action="store",
metavar="hex key",
help="AES key to use for Kerberos Authentication " "(128 or 256 bits)",
)

group_out = parser.add_argument_group('output')
group_out.add_argument('-K', '--kerberos-dir', action='store', help='Save kerberos tickets to a directory')
group_out.add_argument('-M', '--masterkeys-file', action='store', help='Save masterkeys in format {GUID}:SHA1 to a file')
group_out.add_argument('-o', '--outfile', action='store', help='Output credentials to file')
group_out.add_argument('-f', '--format', choices=["pretty", "json", "grep", "table"], action='store', default="pretty",
help='Output format (Default pretty)')
group_out.add_argument('-ff', '--file-format', choices=["pretty", "json", "grep", "table"], action='store',
help='File format (Default same value as --format)')
group_out.add_argument('-nc', '--no-color', action='store_true', help='No colors in output')

group_out = parser.add_argument_group("output")
group_out.add_argument(
"-K",
"--kerberos-dir",
action="store",
help="Save kerberos tickets to a directory",
)
group_out.add_argument(
"-M",
"--masterkeys-file",
action="store",
help="Save masterkeys in format {GUID}:SHA1 to a file",
)
group_out.add_argument(
"-o", "--outfile", action="store", help="Output credentials to file"
)
group_out.add_argument(
"-f",
"--format",
choices=["pretty", "json", "grep", "table"],
action="store",
default="pretty",
help="Output format (Default pretty)",
)
group_out.add_argument(
"-ff",
"--file-format",
choices=["pretty", "json", "grep", "table"],
action="store",
help="File format (Default same value as --format)",
)
group_out.add_argument(
"-nc", "--no-color", action="store_true", help="No colors in output"
)

group_out.add_argument('--users', action='store_true', help='Only display user accounts (No computer accounts)')
group_out.add_argument('--no-tickets', action='store_true', help='Do not display valid TGT')
group_out.add_argument('--masterkeys', action='store_true', help='Display valid masterkeys')
group_out.add_argument(
"--users",
action="store_true",
help="Only display user accounts (No computer accounts)",
)
group_out.add_argument(
"--no-tickets", action="store_true", help="Do not display valid TGT"
)
group_out.add_argument(
"--masterkeys", action="store_true", help="Display valid masterkeys"
)

parser.add_argument('-v', action='count', default=0, help='Verbosity level (-v or -vv)')
parser.add_argument('--threads', default=10, type=int, action='store', help='Threads number')
parser.add_argument('-q', '--quiet', action='store_true', help='Quiet mode, only display credentials')
parser.add_argument('-V', '--version', action='version', version='%(prog)s (version {})'.format(version))
parser.add_argument('target', nargs='*', type=str, action='store',
help='The target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) '
'containing a list of targets')
parser.add_argument(
"-v", action="count", default=0, help="Verbosity level (-v or -vv)"
)
parser.add_argument(
"--threads", default=10, type=int, action="store", help="Threads number"
)
parser.add_argument(
"-q",
"--quiet",
action="store_true",
help="Quiet mode, only display credentials",
)
parser.add_argument(
"-V",
"--version",
action="version",
version="%(prog)s (version {})".format(version),
)
parser.add_argument(
"target",
nargs="*",
type=str,
action="store",
help="The target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) "
"containing a list of targets",
)

if len(sys.argv) == 1:
parser.print_help()
Expand Down
Loading
Loading