-
-
Notifications
You must be signed in to change notification settings - Fork 261
Expand file tree
/
Copy pathparser.py
More file actions
133 lines (121 loc) · 5.22 KB
/
Copy pathparser.py
File metadata and controls
133 lines (121 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from datetime import datetime
from pypykatz.pypykatz import pypykatz
from lsassy.credential import Credential
from lsassy.logger import lsassy_logger
class Parser:
"""
Parse remote lsass dump file using impacketfile and pypykatz
"""
def __init__(self, target, dumpfile):
self._target = target
self._dumpfile = dumpfile
def parse(self):
"""
Parse remote dump file and delete it after parsing
:return: List of Credentials
"""
credentials = []
tickets = []
masterkeys = []
try:
pypy_parse = pypykatz.parse_minidump_external(
self._dumpfile, chunksize=60 * 1024
)
except Exception:
lsassy_logger.error(
"An error occurred while parsing lsass dump", exc_info=True
)
return None
ssps = [
"msv_creds",
"wdigest_creds",
"ssp_creds",
"livessp_creds",
"kerberos_creds",
"credman_creds",
"tspkg_creds",
"dpapi_creds",
]
for luid in pypy_parse.logon_sessions:
for ssp in ssps:
for cred in getattr(pypy_parse.logon_sessions[luid], ssp, []):
domain = getattr(cred, "domainname", None)
username = getattr(cred, "username", None)
password = getattr(cred, "password", None)
LMHash = getattr(cred, "LMHash", None)
NThash = getattr(cred, "NThash", None)
SHA1 = getattr(cred, "SHAHash", None)
if LMHash is not None:
LMHash = LMHash.hex()
if NThash is not None:
NThash = NThash.hex()
if SHA1 is not None:
SHA1 = SHA1.hex()
if username and (
password
or (NThash and NThash != "00000000000000000000000000000000")
or (LMHash and LMHash != "00000000000000000000000000000000")
):
credentials.append(
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:
for ticket in kcred.tickets:
tickets.append(ticket)
for dpapicred in pypy_parse.logon_sessions[luid].dpapi_creds:
m = "{%s}:%s" % (dpapicred.key_guid, dpapicred.sha1_masterkey)
if m not in masterkeys:
masterkeys.append(m)
credentials.append(
Credential(
hostname=self._target,
ssp="dpapi",
domain="",
username="",
masterkey=m,
)
)
for cred in pypy_parse.orphaned_creds:
if cred.credtype == "kerberos":
for ticket in cred.tickets:
tickets.append(ticket)
for ticket in tickets:
if ticket.ServiceName is not None and ticket.ServiceName[0] == "krbtgt":
if ticket.EClientName is not None and ticket.DomainName is not None:
if (
ticket.TargetDomainName is not None
and ticket.TargetDomainName != ticket.DomainName
):
target_domain = ticket.TargetDomainName
else:
target_domain = ticket.DomainName
# Keep only valid tickets
if ticket.EndTime > datetime.now(ticket.EndTime.tzinfo):
credentials.append(
Credential(
hostname=self._target,
ssp="kerberos",
domain=ticket.DomainName,
username=ticket.EClientName[0],
ticket={
"file": list(ticket.kirbi_data)[0].split(".kirbi")[
0
]
+ "_"
+ ticket.EndTime.strftime("%Y%m%d%H%M%S")
+ ".ccache",
"domain": target_domain,
"endtime": ticket.EndTime,
},
)
)
return credentials, tickets, masterkeys