summaryrefslogtreecommitdiff
path: root/foreign/client_handling/lazagne/config/DPAPI/credhist.py
diff options
context:
space:
mode:
Diffstat (limited to 'foreign/client_handling/lazagne/config/DPAPI/credhist.py')
-rw-r--r--foreign/client_handling/lazagne/config/DPAPI/credhist.py142
1 files changed, 142 insertions, 0 deletions
diff --git a/foreign/client_handling/lazagne/config/DPAPI/credhist.py b/foreign/client_handling/lazagne/config/DPAPI/credhist.py
new file mode 100644
index 0000000..2a1d8d7
--- /dev/null
+++ b/foreign/client_handling/lazagne/config/DPAPI/credhist.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Code based from these two awesome projects:
+- DPAPICK : https://bitbucket.org/jmichel/dpapick
+- DPAPILAB : https://github.com/dfirfpi/dpapilab
+"""
+
+import struct
+import hashlib
+
+from . import crypto
+from .eater import DataStruct
+
+
+class RPC_SID(DataStruct):
+ """
+ Represents a RPC_SID structure. See MSDN for documentation
+ """
+ def __init__(self, raw=None):
+ self.version = None
+ self.idAuth = None
+ self.subAuth = None
+ DataStruct.__init__(self, raw)
+
+ def parse(self, data):
+ self.version = data.eat("B")
+ n = data.eat("B")
+ self.idAuth = struct.unpack(">Q", "\0\0" + data.eat("6s"))[0]
+ self.subAuth = data.eat("%dL" % n)
+
+ def __str__(self):
+ s = ["S-%d-%d" % (self.version, self.idAuth)]
+ s += ["%d" % x for x in self.subAuth]
+ return "-".join(s)
+
+
+class CredhistEntry(DataStruct):
+
+ def __init__(self, raw=None):
+ self.pwdhash = None
+ self.hmac = None
+ self.revision = None
+ self.hashAlgo = None
+ self.rounds = None
+ self.cipherAlgo = None
+ self.shaHashLen = None
+ self.ntHashLen = None
+ self.iv = None
+ self.userSID = None
+ self.encrypted = None
+ self.revision2 = None
+ self.guid = None
+ self.ntlm = None
+ DataStruct.__init__(self, raw)
+
+ def parse(self, data):
+ self.revision = data.eat("L")
+ self.hashAlgo = crypto.CryptoAlgo(data.eat("L"))
+ self.rounds = data.eat("L")
+ data.eat("L")
+ self.cipherAlgo = crypto.CryptoAlgo(data.eat("L"))
+ self.shaHashLen = data.eat("L")
+ self.ntHashLen = data.eat("L")
+ self.iv = data.eat("16s")
+
+ self.userSID = RPC_SID()
+ self.userSID.parse(data)
+
+ n = self.shaHashLen + self.ntHashLen
+ n += -n % self.cipherAlgo.blockSize
+ self.encrypted = data.eat_string(n)
+
+ self.revision2 = data.eat("L")
+ self.guid = "%0x-%0x-%0x-%0x%0x-%0x%0x%0x%0x%0x%0x" % data.eat("L2H8B")
+
+ def decrypt_with_hash(self, pwdhash):
+ """
+ Decrypts this credhist entry with the given user's password hash.
+ Simply computes the encryption key with the given hash
+ then calls self.decrypt_with_key() to finish the decryption.
+ """
+ self.decrypt_with_key(crypto.derivePwdHash(pwdhash, str(self.userSID)))
+
+ def decrypt_with_key(self, enckey):
+ """
+ Decrypts this credhist entry using the given encryption key.
+ """
+ cleartxt = crypto.dataDecrypt(self.cipherAlgo, self.hashAlgo, self.encrypted, enckey,
+ self.iv, self.rounds)
+ self.pwdhash = cleartxt[:self.shaHashLen]
+ self.ntlm = cleartxt[self.shaHashLen:self.shaHashLen + self.ntHashLen].rstrip("\x00")
+ if len(self.ntlm) != 16:
+ self.ntlm = None
+
+
+class CredHistFile(DataStruct):
+
+ def __init__(self, raw=None):
+ self.entries_list = []
+ self.entries = {}
+ self.valid = False
+ self.footmagic = None
+ self.curr_guid = None
+ DataStruct.__init__(self, raw)
+
+ def parse(self, data):
+ while True:
+ l = data.pop("L")
+ if l == 0:
+ break
+ self.addEntry(data.pop_string(l - 4))
+
+ self.footmagic = data.eat("L")
+ self.curr_guid = "%0x-%0x-%0x-%0x%0x-%0x%0x%0x%0x%0x%0x" % data.eat("L2H8B")
+
+ def addEntry(self, blob):
+ """
+ Creates a CredhistEntry object with blob then adds it to the store
+ """
+ x = CredhistEntry(blob)
+ self.entries[x.guid] = x
+ self.entries_list.append(x)
+
+ def decrypt_with_hash(self, pwdhash):
+ """
+ Try to decrypt each entry with the given hash
+ """
+
+ if self.valid:
+ return
+
+ for entry in self.entries_list:
+ entry.decrypt_with_hash(pwdhash)
+
+ def decrypt_with_password(self, password):
+ """
+ Decrypts this credhist entry with the given user's password.
+ Simply computes the password hash then calls self.decrypt_with_hash()
+ """
+ self.decrypt_with_hash(hashlib.sha1(password.encode("UTF-16LE")).digest())