import base64, hashlib, binascii, sys, re
sys.path.insert(0, 'venv/lib/python3.10/site-packages')
from impacket.examples.secretsdump import CryptoCommon, LSA_SECRET, LSA_SECRET_BLOB, NL_RECORD

d = {}
for line in open('blob.txt', errors='replace'):
    line = line.strip()
    if '=' in line:
        k, v = line.split('=', 1)
        d[k] = v

def b64(k):
    return base64.b64decode(d[k])

def sha1000(key, value):
    s = hashlib.sha256()
    s.update(key)
    for i in range(1000):
        s.update(value)
    return s.digest()

def ustrs(b):
    out = []
    for m in re.finditer(rb'(?:[\x20-\x7e]\x00){3,}', b):
        out.append(m.group().decode('utf-16le', 'replace'))
    return out

boot = binascii.unhexlify(d['BOOT'])
perm = [8,5,4,2,11,9,13,3,0,6,1,12,14,10,15,7]
bootKey = bytes(boot[perm[i]] for i in range(16))
print('bootKey', binascii.hexlify(bootKey).decode())

polek = b64('POLEK')
print('poleklen', len(polek))
rec = LSA_SECRET(polek)
enc = rec['EncryptedData']
print('enc off', len(polek) - len(enc))
tmp = sha1000(bootKey, enc[:32])
pt = CryptoCommon.decryptAES(tmp, enc[32:])
blob = LSA_SECRET_BLOB(pt)
lsakey = blob['Secret'][52:][:32]
print('lsakey', binascii.hexlify(lsakey).decode())

nlkm_raw = b64('NLKM')
rec2 = LSA_SECRET(nlkm_raw)
enc2 = rec2['EncryptedData']
tmp2 = sha1000(lsakey, enc2[:32])
nklm = CryptoCommon.decryptAES(tmp2, enc2[32:])
print('nklm', binascii.hexlify(nklm).decode())
key = nklm[16:32]

for i in range(1, 11):
    kk = 'NL%d' % i
    if kk not in d or not d[kk] or d[kk] in ('NA', 'NULL'):
        print(kk, 'none', d.get(kk)); continue
    raw = b64(kk)
    r = NL_RECORD(raw)
    ivz = (r['IV'] == b'\x00' * 16)
    print(kk, 'len', len(raw), 'iv0', ivz, 'flags', r['Flags'], 'ul', r['UserLength'], 'dl', r['DomainNameLength'], 'sids', r['SidCount'])
    if not ivz and (r['Flags'] & 1):
        p = CryptoCommon.decryptAES(key, r['EncryptedData'], r['IV'])
        print('   hash', binascii.hexlify(p[:0x10]).decode())
        print('   strs', ustrs(p))
    else:
        print('   RAWstrs', ustrs(raw))
        print('   RAWhex', binascii.hexlify(raw[64:112]).decode())
