Skip to content

Commit

Permalink
DPAPI: try harder to decrypt blobs
Browse files Browse the repository at this point in the history
  • Loading branch information
alxchk committed May 15, 2019
1 parent 9e9a0e0 commit 83619e8
Showing 1 changed file with 50 additions and 30 deletions.
80 changes: 50 additions & 30 deletions Windows/lazagne/config/winstructure.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Vault Structure has been taken from mimikatz
from ctypes.wintypes import *
from ctypes import *

import sys
import os

Expand Down Expand Up @@ -32,7 +33,7 @@
CRED_TYPE_GENERIC = 0x1
CRED_TYPE_DOMAIN_VISIBLE_PASSWORD = 0x4

# Regedit
# Regedit
HKEY_CURRENT_USER = -2147483647
HKEY_LOCAL_MACHINE = -2147483646
KEY_READ = 131097
Expand Down Expand Up @@ -144,18 +145,18 @@ class VAULT_BYTE_BUFFER(Structure):

class DATA(Structure):
_fields_ = [
# ('boolean', BOOL),
# ('short', SHORT),
# ('unsignedShort', WORD),
# ('int', LONG),
# ('unsignedInt', ULONG),
# ('double', DOUBLE),
# ('boolean', BOOL),
# ('short', SHORT),
# ('unsignedShort', WORD),
# ('int', LONG),
# ('unsignedInt', ULONG),
# ('double', DOUBLE),
('guid', GUID),
('string', LPWSTR),
('byteArray', VAULT_BYTE_BUFFER),
('protectedArray', VAULT_BYTE_BUFFER),
('attribute', PVAULT_CREDENTIAL_ATTRIBUTEW),
# ('Sid', PSID)
# ('Sid', PSID)
('sid', DWORD)
]

Expand All @@ -181,12 +182,12 @@ class Flag(Structure):

class VAULT_ITEM_DATA(Structure):
_fields_ = [
# ('schemaElementId', DWORD),
# ('unk0', DWORD),
# ('Type', VAULT_ELEMENT_TYPE),
# ('type', Flag),
# ('type', DWORD * 14),
# ('unk1', DWORD),
# ('schemaElementId', DWORD),
# ('unk0', DWORD),
# ('Type', VAULT_ELEMENT_TYPE),
# ('type', Flag),
# ('type', DWORD * 14),
# ('unk1', DWORD),
('data', DATA),
]

Expand All @@ -213,17 +214,17 @@ class VAULT_ITEM_WIN8(Structure):


# class VAULT_ITEM_WIN7(Structure):
# _fields_ = [
# ('id', GUID),
# ('pName', PWSTR),
# ('pResource', PVAULT_ITEM_DATA),
# ('pUsername', PVAULT_ITEM_DATA),
# ('pPassword', PVAULT_ITEM_DATA),
# ('LastWritten', FILETIME),
# ('Flags', DWORD),
# ('cbProperties', DWORD),
# ('Properties', PVAULT_ITEM_DATA),
# ]
# _fields_ = [
# ('id', GUID),
# ('pName', PWSTR),
# ('pResource', PVAULT_ITEM_DATA),
# ('pUsername', PVAULT_ITEM_DATA),
# ('pPassword', PVAULT_ITEM_DATA),
# ('LastWritten', FILETIME),
# ('Flags', DWORD),
# ('cbProperties', DWORD),
# ('Properties', PVAULT_ITEM_DATA),
# ]
# PVAULT_ITEM_WIN7 = POINTER(VAULT_ITEM_WIN7)

class OSVERSIONINFOEXW(Structure):
Expand Down Expand Up @@ -567,6 +568,8 @@ def Win32CryptUnprotectData(cipherText, entropy=False, is_current_user=True, use
if python_version == 2:
cipherText = str(cipherText)

decrypted = None

if is_current_user:
bufferIn = c_buffer(cipherText, len(cipherText))
blobIn = DATA_BLOB(len(cipherText), bufferIn)
Expand All @@ -577,15 +580,32 @@ def Win32CryptUnprotectData(cipherText, entropy=False, is_current_user=True, use
blobEntropy = DATA_BLOB(len(entropy), bufferEntropy)

if CryptUnprotectData(byref(blobIn), None, byref(blobEntropy), None, None, 0, byref(blobOut)):
return getData(blobOut).decode("utf-8")
decrypted = getData(blobOut).decode("utf-8")

else:
if CryptUnprotectData(byref(blobIn), None, None, None, None, 0, byref(blobOut)):
return getData(blobOut).decode("utf-8")
decrypted = getData(blobOut).decode("utf-8")

if not decrypted:
can_decrypt = True
if not (user_dpapi and user_dpapi.unlocked):
from lazagne.config.dpapi_structure import are_masterkeys_retrieved
can_decrypt = are_masterkeys_retrieved()

if can_decrypt:
decrypted = user_dpapi.decrypt_encrypted_blob(cipherText)
if decrypted is False:
decrypted = None
else:
raise ValueError('MasterKeys not found')

if not decrypted:
if not user_dpapi:
raise ValueError('DPApi unavailable')
elif not user_dpapi.unlocked:
raise ValueError('DPApi locked')

elif user_dpapi and user_dpapi.unlocked:
# entropy should be an hex value
return user_dpapi.decrypt_encrypted_blob(cipherText, entropy_hex=entropy)
return decrypted


def get_os_version():
Expand Down

0 comments on commit 83619e8

Please sign in to comment.