|
1 | 1 | import argparse |
| 2 | +import logging |
2 | 3 | import sys |
3 | 4 |
|
4 | 5 | from lsassy import __version__ |
5 | 6 | from lsassy.core import ThreadPool |
6 | 7 | from lsassy.dumper import Dumper |
7 | | -from lsassy.logger import lsassy_logger, LsassyLogger |
8 | | -import logging |
| 8 | +from lsassy.logger import lsassy_logger |
9 | 9 |
|
10 | 10 |
|
11 | 11 | def main(): |
12 | 12 | """ |
13 | | - Command line function to call lsassy |
14 | | - """ |
| 13 | + Command line function to call lsassy |
| 14 | + """ |
15 | 15 | version = __version__ |
16 | 16 | parser = argparse.ArgumentParser( |
17 | 17 | prog="lsassy", |
18 | | - description='lsassy v{} - Remote lsass dump reader'.format(__version__) |
| 18 | + description="lsassy v{} - Remote lsass dump reader".format(__version__), |
19 | 19 | ) |
20 | 20 |
|
21 | | - group_dump = parser.add_argument_group('dump') |
22 | | - group_dump.add_argument('-m', '--dump-method', action='store', default="comsvcs", |
23 | | - help="Dumping method ({})".format(', '.join(Dumper.list_dump_methods()))) |
24 | | - group_dump.add_argument('--dump-path', action='store', |
25 | | - help='Path to store lsass dumpfile (Default: \\Windows\\Temp)') |
26 | | - group_dump.add_argument('--dump-name', action='store', help='Name given to lsass dumpfile (Default: Random)') |
27 | | - group_dump.add_argument('-e', '--exec', action='store', |
28 | | - help='List of execution methods, comma separated (From {})'.format(', '.join(Dumper.list_exec_methods()))) |
29 | | - group_dump.add_argument('--no-powershell', action='store_true', help='Disable PowerShell') |
30 | | - group_dump.add_argument('--copy', action='store_true', help='Copies cmd or powershell with random name before using it') |
31 | | - group_dump.add_argument('-O', '--options', action='store', |
32 | | - help='Dump module options (Example procdump_path=/opt/procdump.exe,procdump=procdump.exe') |
33 | | - group_dump.add_argument('--timeout', action='store', type=int, default=5, |
34 | | - help='Max time to wait for lsass dump (Default 5s)') |
35 | | - group_dump.add_argument('--time-between-commands', action='store', type=int, default=1, |
36 | | - help='Time to wait between dump methods commands (Default 1s)') |
37 | | - group_dump.add_argument('--parse-only', action='store_true', help='Parse dump without dumping') |
38 | | - group_dump.add_argument('--dump-only', action='store_true', help='Dump lsass without parsing it') |
39 | | - group_dump.add_argument('--keep-dump', action='store_true', help='Do not delete lsass dump on remote host') |
| 21 | + group_dump = parser.add_argument_group("dump") |
| 22 | + group_dump.add_argument( |
| 23 | + "-m", |
| 24 | + "--dump-method", |
| 25 | + action="store", |
| 26 | + default="comsvcs", |
| 27 | + help="Dumping method ({})".format(", ".join(Dumper.list_dump_methods())), |
| 28 | + ) |
| 29 | + group_dump.add_argument( |
| 30 | + "--dump-path", |
| 31 | + action="store", |
| 32 | + help="Path to store lsass dumpfile (Default: \\Windows\\Temp)", |
| 33 | + ) |
| 34 | + group_dump.add_argument( |
| 35 | + "--dump-name", |
| 36 | + action="store", |
| 37 | + help="Name given to lsass dumpfile (Default: Random)", |
| 38 | + ) |
| 39 | + group_dump.add_argument( |
| 40 | + "-e", |
| 41 | + "--exec", |
| 42 | + action="store", |
| 43 | + help="List of execution methods, comma separated (From {})".format( |
| 44 | + ", ".join(Dumper.list_exec_methods()) |
| 45 | + ), |
| 46 | + ) |
| 47 | + group_dump.add_argument( |
| 48 | + "--no-powershell", action="store_true", help="Disable PowerShell" |
| 49 | + ) |
| 50 | + group_dump.add_argument( |
| 51 | + "--copy", |
| 52 | + action="store_true", |
| 53 | + help="Copies cmd or powershell with random name before using it", |
| 54 | + ) |
| 55 | + group_dump.add_argument( |
| 56 | + "-O", |
| 57 | + "--options", |
| 58 | + action="store", |
| 59 | + help="Dump module options (Example procdump_path=/opt/procdump.exe,procdump=procdump.exe", |
| 60 | + ) |
| 61 | + group_dump.add_argument( |
| 62 | + "--timeout", |
| 63 | + action="store", |
| 64 | + type=int, |
| 65 | + default=5, |
| 66 | + help="Max time to wait for lsass dump (Default 5s)", |
| 67 | + ) |
| 68 | + group_dump.add_argument( |
| 69 | + "--time-between-commands", |
| 70 | + action="store", |
| 71 | + type=int, |
| 72 | + default=1, |
| 73 | + help="Time to wait between dump methods commands (Default 1s)", |
| 74 | + ) |
| 75 | + group_dump.add_argument( |
| 76 | + "--parse-only", action="store_true", help="Parse dump without dumping" |
| 77 | + ) |
| 78 | + group_dump.add_argument( |
| 79 | + "--dump-only", action="store_true", help="Dump lsass without parsing it" |
| 80 | + ) |
| 81 | + group_dump.add_argument( |
| 82 | + "--keep-dump", |
| 83 | + action="store_true", |
| 84 | + help="Do not delete lsass dump on remote host", |
| 85 | + ) |
40 | 86 |
|
41 | | - group_auth = parser.add_argument_group('authentication') |
42 | | - group_auth.add_argument('-u', '--username', action='store', help='Username') |
43 | | - group_auth.add_argument('-p', '--password', action='store', help='Plaintext password') |
44 | | - group_auth.add_argument('-d', '--domain', default="", action='store', help='Domain name') |
45 | | - group_auth.add_argument('--port', default=445, type=int, action='store', help='Port (Default: 445)') |
46 | | - group_auth.add_argument('--no-pass', action='store_true', help='Do not provide password (Default: False)') |
47 | | - group_auth.add_argument('-H', '--hashes', action='store', help='[LM:]NT hash') |
48 | | - group_auth.add_argument('-k', '--kerberos', action="store_true", |
49 | | - help='Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on ' |
50 | | - 'target parameters. If valid credentials ' |
51 | | - 'cannot be found, it will use the ones specified in the command line') |
52 | | - group_auth.add_argument('-dc-ip', action='store', metavar="ip address", |
53 | | - help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) ' |
54 | | - 'specified in the target parameter') |
55 | | - group_auth.add_argument('-aesKey', action="store", metavar="hex key", |
56 | | - help='AES key to use for Kerberos Authentication ' |
57 | | - '(128 or 256 bits)') |
| 87 | + group_auth = parser.add_argument_group("authentication") |
| 88 | + group_auth.add_argument("-u", "--username", action="store", help="Username") |
| 89 | + group_auth.add_argument( |
| 90 | + "-p", "--password", action="store", help="Plaintext password" |
| 91 | + ) |
| 92 | + group_auth.add_argument( |
| 93 | + "-d", "--domain", default="", action="store", help="Domain name" |
| 94 | + ) |
| 95 | + group_auth.add_argument( |
| 96 | + "--port", default=445, type=int, action="store", help="Port (Default: 445)" |
| 97 | + ) |
| 98 | + group_auth.add_argument( |
| 99 | + "--no-pass", |
| 100 | + action="store_true", |
| 101 | + help="Do not provide password (Default: False)", |
| 102 | + ) |
| 103 | + group_auth.add_argument("-H", "--hashes", action="store", help="[LM:]NT hash") |
| 104 | + group_auth.add_argument( |
| 105 | + "-k", |
| 106 | + "--kerberos", |
| 107 | + action="store_true", |
| 108 | + help="Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on " |
| 109 | + "target parameters. If valid credentials " |
| 110 | + "cannot be found, it will use the ones specified in the command line", |
| 111 | + ) |
| 112 | + group_auth.add_argument( |
| 113 | + "-dc-ip", |
| 114 | + action="store", |
| 115 | + metavar="ip address", |
| 116 | + help="IP Address of the domain controller. If omitted it will use the domain part (FQDN) " |
| 117 | + "specified in the target parameter", |
| 118 | + ) |
| 119 | + group_auth.add_argument( |
| 120 | + "-aesKey", |
| 121 | + action="store", |
| 122 | + metavar="hex key", |
| 123 | + help="AES key to use for Kerberos Authentication " "(128 or 256 bits)", |
| 124 | + ) |
58 | 125 |
|
59 | | - group_out = parser.add_argument_group('output') |
60 | | - group_out.add_argument('-K', '--kerberos-dir', action='store', help='Save kerberos tickets to a directory') |
61 | | - group_out.add_argument('-M', '--masterkeys-file', action='store', help='Save masterkeys in format {GUID}:SHA1 to a file') |
62 | | - group_out.add_argument('-o', '--outfile', action='store', help='Output credentials to file') |
63 | | - group_out.add_argument('-f', '--format', choices=["pretty", "json", "grep", "table"], action='store', default="pretty", |
64 | | - help='Output format (Default pretty)') |
65 | | - group_out.add_argument('-ff', '--file-format', choices=["pretty", "json", "grep", "table"], action='store', |
66 | | - help='File format (Default same value as --format)') |
67 | | - group_out.add_argument('-nc', '--no-color', action='store_true', help='No colors in output') |
68 | | - |
| 126 | + group_out = parser.add_argument_group("output") |
| 127 | + group_out.add_argument( |
| 128 | + "-K", |
| 129 | + "--kerberos-dir", |
| 130 | + action="store", |
| 131 | + help="Save kerberos tickets to a directory", |
| 132 | + ) |
| 133 | + group_out.add_argument( |
| 134 | + "-M", |
| 135 | + "--masterkeys-file", |
| 136 | + action="store", |
| 137 | + help="Save masterkeys in format {GUID}:SHA1 to a file", |
| 138 | + ) |
| 139 | + group_out.add_argument( |
| 140 | + "-o", "--outfile", action="store", help="Output credentials to file" |
| 141 | + ) |
| 142 | + group_out.add_argument( |
| 143 | + "-f", |
| 144 | + "--format", |
| 145 | + choices=["pretty", "json", "grep", "table"], |
| 146 | + action="store", |
| 147 | + default="pretty", |
| 148 | + help="Output format (Default pretty)", |
| 149 | + ) |
| 150 | + group_out.add_argument( |
| 151 | + "-ff", |
| 152 | + "--file-format", |
| 153 | + choices=["pretty", "json", "grep", "table"], |
| 154 | + action="store", |
| 155 | + help="File format (Default same value as --format)", |
| 156 | + ) |
| 157 | + group_out.add_argument( |
| 158 | + "-nc", "--no-color", action="store_true", help="No colors in output" |
| 159 | + ) |
69 | 160 |
|
70 | | - group_out.add_argument('--users', action='store_true', help='Only display user accounts (No computer accounts)') |
71 | | - group_out.add_argument('--no-tickets', action='store_true', help='Do not display valid TGT') |
72 | | - group_out.add_argument('--masterkeys', action='store_true', help='Display valid masterkeys') |
| 161 | + group_out.add_argument( |
| 162 | + "--users", |
| 163 | + action="store_true", |
| 164 | + help="Only display user accounts (No computer accounts)", |
| 165 | + ) |
| 166 | + group_out.add_argument( |
| 167 | + "--no-tickets", action="store_true", help="Do not display valid TGT" |
| 168 | + ) |
| 169 | + group_out.add_argument( |
| 170 | + "--masterkeys", action="store_true", help="Display valid masterkeys" |
| 171 | + ) |
73 | 172 |
|
74 | | - parser.add_argument('-v', action='count', default=0, help='Verbosity level (-v or -vv)') |
75 | | - parser.add_argument('--threads', default=10, type=int, action='store', help='Threads number') |
76 | | - parser.add_argument('-q', '--quiet', action='store_true', help='Quiet mode, only display credentials') |
77 | | - parser.add_argument('-V', '--version', action='version', version='%(prog)s (version {})'.format(version)) |
78 | | - parser.add_argument('target', nargs='*', type=str, action='store', |
79 | | - help='The target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) ' |
80 | | - 'containing a list of targets') |
| 173 | + parser.add_argument( |
| 174 | + "-v", action="count", default=0, help="Verbosity level (-v or -vv)" |
| 175 | + ) |
| 176 | + parser.add_argument( |
| 177 | + "--threads", default=10, type=int, action="store", help="Threads number" |
| 178 | + ) |
| 179 | + parser.add_argument( |
| 180 | + "-q", |
| 181 | + "--quiet", |
| 182 | + action="store_true", |
| 183 | + help="Quiet mode, only display credentials", |
| 184 | + ) |
| 185 | + parser.add_argument( |
| 186 | + "-V", |
| 187 | + "--version", |
| 188 | + action="version", |
| 189 | + version="%(prog)s (version {})".format(version), |
| 190 | + ) |
| 191 | + parser.add_argument( |
| 192 | + "target", |
| 193 | + nargs="*", |
| 194 | + type=str, |
| 195 | + action="store", |
| 196 | + help="The target IP(s), range(s), CIDR(s), hostname(s), FQDN(s), file(s) " |
| 197 | + "containing a list of targets", |
| 198 | + ) |
81 | 199 |
|
82 | 200 | if len(sys.argv) == 1: |
83 | 201 | parser.print_help() |
|
0 commit comments