mirror of
https://github.com/login-securite/DonPAPI
synced 2025-01-05 05:59:43 +00:00
716 lines
20 KiB
Python
716 lines
20 KiB
Python
# Vault Structure has been taken from mimikatz
|
|
from ctypes.wintypes import *
|
|
from ctypes import *
|
|
|
|
import sys
|
|
import os
|
|
|
|
try:
|
|
import _winreg as winreg
|
|
except ImportError:
|
|
import winreg
|
|
|
|
LPTSTR = LPSTR
|
|
LPCTSTR = LPSTR
|
|
PHANDLE = POINTER(HANDLE)
|
|
HANDLE = LPVOID
|
|
LPDWORD = POINTER(DWORD)
|
|
PVOID = c_void_p
|
|
INVALID_HANDLE_VALUE = c_void_p(-1).value
|
|
NTSTATUS = ULONG()
|
|
PWSTR = c_wchar_p
|
|
LPWSTR = c_wchar_p
|
|
PBYTE = POINTER(BYTE)
|
|
LPBYTE = POINTER(BYTE)
|
|
PSID = PVOID
|
|
LONG = c_long
|
|
WORD = c_uint16
|
|
|
|
# #############################- Constants ##############################
|
|
|
|
# Credential Manager
|
|
CRYPTPROTECT_UI_FORBIDDEN = 0x01
|
|
CRED_TYPE_GENERIC = 0x1
|
|
CRED_TYPE_DOMAIN_VISIBLE_PASSWORD = 0x4
|
|
|
|
# Regedit
|
|
HKEY_CURRENT_USER = -2147483647
|
|
HKEY_LOCAL_MACHINE = -2147483646
|
|
KEY_READ = 131097
|
|
KEY_ENUMERATE_SUB_KEYS = 8
|
|
KEY_QUERY_VALUE = 1
|
|
|
|
# custom key to read registry (not from msdn)
|
|
ACCESS_READ = KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE
|
|
|
|
# Token manipulation
|
|
PROCESS_QUERY_INFORMATION = 0x0400
|
|
STANDARD_RIGHTS_REQUIRED = 0x000F0000
|
|
READ_CONTROL = 0x00020000
|
|
STANDARD_RIGHTS_READ = READ_CONTROL
|
|
TOKEN_ASSIGN_PRIMARY = 0x0001
|
|
TOKEN_DUPLICATE = 0x0002
|
|
TOKEN_IMPERSONATE = 0x0004
|
|
TOKEN_QUERY = 0x0008
|
|
TOKEN_QUERY_SOURCE = 0x0010
|
|
TOKEN_ADJUST_PRIVILEGES = 0x0020
|
|
TOKEN_ADJUST_GROUPS = 0x0040
|
|
TOKEN_ADJUST_DEFAULT = 0x0080
|
|
TOKEN_ADJUST_SESSIONID = 0x0100
|
|
TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY)
|
|
tokenprivs = (
|
|
TOKEN_QUERY | TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_QUERY_SOURCE | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | (
|
|
131072 | 4))
|
|
TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
|
|
TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
|
|
TOKEN_ADJUST_SESSIONID)
|
|
|
|
SE_DEBUG_PRIVILEGE = 20
|
|
|
|
|
|
# ############################# Structures ##############################
|
|
|
|
class CREDENTIAL_ATTRIBUTE(Structure):
|
|
_fields_ = [
|
|
('Keyword', LPSTR),
|
|
('Flags', DWORD),
|
|
('ValueSize', DWORD),
|
|
('Value', LPBYTE)
|
|
]
|
|
|
|
|
|
PCREDENTIAL_ATTRIBUTE = POINTER(CREDENTIAL_ATTRIBUTE)
|
|
|
|
|
|
class CREDENTIAL(Structure):
|
|
_fields_ = [
|
|
('Flags', DWORD),
|
|
('Type', DWORD),
|
|
('TargetName', LPSTR),
|
|
('Comment', LPSTR),
|
|
('LastWritten', FILETIME),
|
|
('CredentialBlobSize', DWORD),
|
|
# ('CredentialBlob', POINTER(BYTE)),
|
|
('CredentialBlob', POINTER(c_char)),
|
|
('Persist', DWORD),
|
|
('AttributeCount', DWORD),
|
|
('Attributes', PCREDENTIAL_ATTRIBUTE),
|
|
('TargetAlias', LPSTR),
|
|
('UserName', LPSTR)
|
|
]
|
|
|
|
|
|
PCREDENTIAL = POINTER(CREDENTIAL)
|
|
|
|
|
|
class DATA_BLOB(Structure):
|
|
_fields_ = [
|
|
('cbData', DWORD),
|
|
('pbData', POINTER(c_char))
|
|
]
|
|
|
|
|
|
class GUID(Structure):
|
|
_fields_ = [
|
|
("data1", DWORD),
|
|
("data2", WORD),
|
|
("data3", WORD),
|
|
("data4", BYTE * 6)
|
|
]
|
|
|
|
|
|
LPGUID = POINTER(GUID)
|
|
|
|
|
|
class VAULT_CREDENTIAL_ATTRIBUTEW(Structure):
|
|
_fields_ = [
|
|
('keyword', LPWSTR),
|
|
('flags', DWORD),
|
|
('badAlign', DWORD),
|
|
('valueSize', DWORD),
|
|
('value', LPBYTE),
|
|
]
|
|
|
|
|
|
PVAULT_CREDENTIAL_ATTRIBUTEW = POINTER(VAULT_CREDENTIAL_ATTRIBUTEW)
|
|
|
|
|
|
class VAULT_BYTE_BUFFER(Structure):
|
|
_fields_ = [
|
|
('length', DWORD),
|
|
('value', PBYTE),
|
|
]
|
|
|
|
|
|
class DATA(Structure):
|
|
_fields_ = [
|
|
# ('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', DWORD)
|
|
]
|
|
|
|
|
|
class Flag(Structure):
|
|
_fields_ = [
|
|
('0x00', DWORD),
|
|
('0x01', DWORD),
|
|
('0x02', DWORD),
|
|
('0x03', DWORD),
|
|
('0x04', DWORD),
|
|
('0x05', DWORD),
|
|
('0x06', DWORD),
|
|
('0x07', DWORD),
|
|
('0x08', DWORD),
|
|
('0x09', DWORD),
|
|
('0x0a', DWORD),
|
|
('0x0b', DWORD),
|
|
('0x0c', DWORD),
|
|
('0x0d', DWORD)
|
|
]
|
|
|
|
|
|
class VAULT_ITEM_DATA(Structure):
|
|
_fields_ = [
|
|
# ('schemaElementId', DWORD),
|
|
# ('unk0', DWORD),
|
|
# ('Type', DWORD),
|
|
# ('unk1', DWORD),
|
|
('data', DATA),
|
|
]
|
|
|
|
|
|
PVAULT_ITEM_DATA = POINTER(VAULT_ITEM_DATA)
|
|
|
|
|
|
# From https://github.com/gentilkiwi/mimikatz/blob/b008188f9fe5668b5dae80c210290c7efa872ffa/mimikatz/modules/kuhl_m_vault.h#L157
|
|
class VAULT_ITEM_WIN8(Structure):
|
|
_fields_ = [
|
|
('id', GUID),
|
|
('pName', PWSTR),
|
|
('pResource', PVAULT_ITEM_DATA),
|
|
('pUsername', PVAULT_ITEM_DATA),
|
|
('pPassword', PVAULT_ITEM_DATA),
|
|
('pPackageSid', PVAULT_ITEM_DATA),
|
|
('LastWritten', FILETIME),
|
|
('Flags', DWORD),
|
|
('cbProperties', DWORD),
|
|
('Properties', PVAULT_ITEM_DATA),
|
|
]
|
|
|
|
|
|
PVAULT_ITEM_WIN8 = POINTER(VAULT_ITEM_WIN8)
|
|
|
|
|
|
# From https://github.com/gentilkiwi/mimikatz/blob/b008188f9fe5668b5dae80c210290c7efa872ffa/mimikatz/modules/kuhl_m_vault.h#L145
|
|
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),
|
|
]
|
|
|
|
|
|
PVAULT_ITEM_WIN7 = POINTER(VAULT_ITEM_WIN7)
|
|
|
|
class OSVERSIONINFOEXW(Structure):
|
|
_fields_ = [
|
|
('dwOSVersionInfoSize', c_ulong),
|
|
('dwMajorVersion', c_ulong),
|
|
('dwMinorVersion', c_ulong),
|
|
('dwBuildNumber', c_ulong),
|
|
('dwPlatformId', c_ulong),
|
|
('szCSDVersion', c_wchar * 128),
|
|
('wServicePackMajor', c_ushort),
|
|
('wServicePackMinor', c_ushort),
|
|
('wSuiteMask', c_ushort),
|
|
('wProductType', c_byte),
|
|
('wReserved', c_byte)
|
|
]
|
|
|
|
|
|
class CRYPTPROTECT_PROMPTSTRUCT(Structure):
|
|
_fields_ = [
|
|
('cbSize', DWORD),
|
|
('dwPromptFlags', DWORD),
|
|
('hwndApp', HWND),
|
|
('szPrompt', LPCWSTR),
|
|
]
|
|
|
|
|
|
PCRYPTPROTECT_PROMPTSTRUCT = POINTER(CRYPTPROTECT_PROMPTSTRUCT)
|
|
|
|
|
|
class LUID(Structure):
|
|
_fields_ = [
|
|
("LowPart", DWORD),
|
|
("HighPart", LONG),
|
|
]
|
|
|
|
|
|
PLUID = POINTER(LUID)
|
|
|
|
|
|
class SID_AND_ATTRIBUTES(Structure):
|
|
_fields_ = [
|
|
("Sid", PSID),
|
|
("Attributes", DWORD),
|
|
]
|
|
|
|
|
|
class TOKEN_USER(Structure):
|
|
_fields_ = [
|
|
("User", SID_AND_ATTRIBUTES), ]
|
|
|
|
|
|
class LUID_AND_ATTRIBUTES(Structure):
|
|
_fields_ = [
|
|
("Luid", LUID),
|
|
("Attributes", DWORD),
|
|
]
|
|
|
|
|
|
class TOKEN_PRIVILEGES(Structure):
|
|
_fields_ = [
|
|
("PrivilegeCount", DWORD),
|
|
("Privileges", LUID_AND_ATTRIBUTES),
|
|
]
|
|
|
|
|
|
PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)
|
|
|
|
|
|
class SECURITY_ATTRIBUTES(Structure):
|
|
_fields_ = [
|
|
("nLength", DWORD),
|
|
("lpSecurityDescriptor", LPVOID),
|
|
("bInheritHandle", BOOL),
|
|
]
|
|
|
|
|
|
PSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
|
|
|
|
|
|
class SID_NAME_USE(DWORD):
|
|
_sid_types = dict(enumerate('''
|
|
User Group Domain Alias WellKnownGroup DeletedAccount
|
|
Invalid Unknown Computer Label'''.split(), 1))
|
|
|
|
def __init__(self, value=None):
|
|
if value is not None:
|
|
if value not in self.sid_types:
|
|
raise ValueError('invalid SID type')
|
|
DWORD.__init__(value)
|
|
|
|
def __str__(self):
|
|
if self.value not in self._sid_types:
|
|
raise ValueError('invalid SID type')
|
|
return self._sid_types[self.value]
|
|
|
|
def __repr__(self):
|
|
return 'SID_NAME_USE(%s)' % self.value
|
|
|
|
|
|
PSID_NAME_USE = POINTER(SID_NAME_USE)
|
|
|
|
# ############################# Load dlls ##############################
|
|
|
|
advapi32 = WinDLL('advapi32', use_last_error=True)
|
|
crypt32 = WinDLL('crypt32', use_last_error=True)
|
|
kernel32 = WinDLL('kernel32', use_last_error=True)
|
|
psapi = WinDLL('psapi', use_last_error=True)
|
|
ntdll = WinDLL('ntdll', use_last_error=True)
|
|
|
|
# ############################# Functions ##############################
|
|
|
|
RevertToSelf = advapi32.RevertToSelf
|
|
RevertToSelf.restype = BOOL
|
|
RevertToSelf.argtypes = []
|
|
|
|
ImpersonateLoggedOnUser = advapi32.ImpersonateLoggedOnUser
|
|
ImpersonateLoggedOnUser.restype = BOOL
|
|
ImpersonateLoggedOnUser.argtypes = [HANDLE]
|
|
|
|
DuplicateTokenEx = advapi32.DuplicateTokenEx
|
|
DuplicateTokenEx.restype = BOOL
|
|
DuplicateTokenEx.argtypes = [HANDLE, DWORD, PSECURITY_ATTRIBUTES, DWORD, DWORD, POINTER(HANDLE)]
|
|
|
|
AdjustTokenPrivileges = advapi32.AdjustTokenPrivileges
|
|
AdjustTokenPrivileges.restype = BOOL
|
|
AdjustTokenPrivileges.argtypes = [HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, POINTER(DWORD)]
|
|
|
|
LookupPrivilegeValueA = advapi32.LookupPrivilegeValueA
|
|
LookupPrivilegeValueA.restype = BOOL
|
|
LookupPrivilegeValueA.argtypes = [LPCTSTR, LPCTSTR, PLUID]
|
|
|
|
ConvertSidToStringSid = advapi32.ConvertSidToStringSidW
|
|
ConvertSidToStringSid.restype = BOOL
|
|
ConvertSidToStringSid.argtypes = [DWORD, POINTER(LPWSTR)]
|
|
|
|
LookupAccountSid = advapi32.LookupAccountSidW
|
|
LookupAccountSid.restype = BOOL
|
|
LookupAccountSid.argtypes = [LPCWSTR, PSID, LPCWSTR, LPDWORD, LPCWSTR, LPDWORD, PSID_NAME_USE]
|
|
|
|
LocalAlloc = kernel32.LocalAlloc
|
|
LocalAlloc.restype = HANDLE
|
|
LocalAlloc.argtypes = [PSID, DWORD]
|
|
|
|
GetTokenInformation = advapi32.GetTokenInformation
|
|
GetTokenInformation.restype = BOOL
|
|
GetTokenInformation.argtypes = [HANDLE, DWORD, LPVOID, DWORD, POINTER(DWORD)]
|
|
|
|
OpenProcess = kernel32.OpenProcess
|
|
OpenProcess.restype = HANDLE
|
|
OpenProcess.argtypes = [DWORD, BOOL, DWORD]
|
|
|
|
OpenProcessToken = advapi32.OpenProcessToken
|
|
OpenProcessToken.restype = BOOL
|
|
OpenProcessToken.argtypes = [HANDLE, DWORD, POINTER(HANDLE)]
|
|
|
|
CloseHandle = kernel32.CloseHandle
|
|
CloseHandle.restype = BOOL
|
|
CloseHandle.argtypes = [HANDLE]
|
|
|
|
CredEnumerate = advapi32.CredEnumerateA
|
|
CredEnumerate.restype = BOOL
|
|
CredEnumerate.argtypes = [LPCTSTR, DWORD, POINTER(DWORD), POINTER(POINTER(PCREDENTIAL))]
|
|
|
|
CredFree = advapi32.CredFree
|
|
CredFree.restype = PVOID
|
|
CredFree.argtypes = [PVOID]
|
|
|
|
LocalFree = kernel32.LocalFree
|
|
LocalFree.restype = HANDLE
|
|
LocalFree.argtypes = [HANDLE]
|
|
|
|
CryptUnprotectData = crypt32.CryptUnprotectData
|
|
CryptUnprotectData.restype = BOOL
|
|
CryptUnprotectData.argtypes = [POINTER(DATA_BLOB), POINTER(LPWSTR), POINTER(DATA_BLOB), PVOID,
|
|
PCRYPTPROTECT_PROMPTSTRUCT, DWORD, POINTER(DATA_BLOB)]
|
|
|
|
# these functions do not exist on XP workstations
|
|
try:
|
|
prototype = WINFUNCTYPE(ULONG, DWORD, LPDWORD, POINTER(LPGUID))
|
|
vaultEnumerateVaults = prototype(("VaultEnumerateVaults", windll.vaultcli))
|
|
|
|
prototype = WINFUNCTYPE(ULONG, LPGUID, DWORD, HANDLE)
|
|
vaultOpenVault = prototype(("VaultOpenVault", windll.vaultcli))
|
|
|
|
prototype = WINFUNCTYPE(ULONG, HANDLE, DWORD, LPDWORD, POINTER(c_char_p))
|
|
vaultEnumerateItems = prototype(("VaultEnumerateItems", windll.vaultcli))
|
|
|
|
prototype = WINFUNCTYPE(ULONG, HANDLE, LPGUID, PVAULT_ITEM_DATA, PVAULT_ITEM_DATA, PVAULT_ITEM_DATA, HWND, DWORD,
|
|
POINTER(PVAULT_ITEM_WIN8))
|
|
vaultGetItem8 = prototype(("VaultGetItem", windll.vaultcli))
|
|
|
|
prototype = WINFUNCTYPE(ULONG, HANDLE, LPGUID, PVAULT_ITEM_DATA, PVAULT_ITEM_DATA, HWND, DWORD, POINTER(PVAULT_ITEM_WIN7))
|
|
vaultGetItem7 = prototype(("VaultGetItem", windll.vaultcli))
|
|
|
|
prototype = WINFUNCTYPE(ULONG, LPVOID)
|
|
vaultFree = prototype(("VaultFree", windll.vaultcli))
|
|
|
|
prototype = WINFUNCTYPE(ULONG, PHANDLE)
|
|
vaultCloseVault = prototype(("VaultCloseVault", windll.vaultcli))
|
|
|
|
def get_vault_objects_for_this_version_of_windows():
|
|
"""
|
|
@return: Tuple[
|
|
Type of vault item,
|
|
Pointer to type of vault item,
|
|
VaultGetItem function as Callable[[vault_handle, vault_item_prt, password_vault_item_ptr], int]
|
|
]
|
|
"""
|
|
os_version_float = float(get_os_version())
|
|
if os_version_float == 6.1:
|
|
# Windows 7
|
|
return (
|
|
VAULT_ITEM_WIN7,
|
|
PVAULT_ITEM_WIN7,
|
|
lambda hVault, pVaultItem, pPasswordVaultItem:
|
|
vaultGetItem7(hVault, byref(pVaultItem.id), pVaultItem.pResource, pVaultItem.pUsername,
|
|
None, 0, byref(pPasswordVaultItem))
|
|
)
|
|
elif os_version_float > 6.1:
|
|
# Later than Windows7
|
|
return (
|
|
VAULT_ITEM_WIN8,
|
|
PVAULT_ITEM_WIN8,
|
|
lambda hVault, pVaultItem, pPasswordVaultItem:
|
|
vaultGetItem8(hVault, byref(pVaultItem.id), pVaultItem.pResource, pVaultItem.pUsername,
|
|
pVaultItem.pPackageSid, # additional parameter compared to Windows 7
|
|
None, 0, byref(pPasswordVaultItem))
|
|
)
|
|
|
|
raise Exception("Vault is not supported for this version of OS")
|
|
|
|
except Exception:
|
|
pass
|
|
|
|
GetModuleFileNameEx = psapi.GetModuleFileNameExW
|
|
GetModuleFileNameEx.restype = DWORD
|
|
GetModuleFileNameEx.argtypes = [HANDLE, HMODULE, LPWSTR, DWORD]
|
|
|
|
|
|
# ############################# Custom functions ##############################
|
|
|
|
|
|
def EnumProcesses():
|
|
_EnumProcesses = psapi.EnumProcesses
|
|
_EnumProcesses.argtypes = [LPVOID, DWORD, LPDWORD]
|
|
_EnumProcesses.restype = bool
|
|
|
|
size = 0x1000
|
|
cbBytesReturned = DWORD()
|
|
unit = sizeof(DWORD)
|
|
dwOwnPid = os.getpid()
|
|
while 1:
|
|
ProcessIds = (DWORD * (size // unit))()
|
|
cbBytesReturned.value = size
|
|
_EnumProcesses(byref(ProcessIds), cbBytesReturned, byref(cbBytesReturned))
|
|
returned = cbBytesReturned.value
|
|
if returned < size:
|
|
break
|
|
size = size + 0x1000
|
|
ProcessIdList = list()
|
|
for ProcessId in ProcessIds:
|
|
if ProcessId is None:
|
|
break
|
|
if ProcessId == dwOwnPid:
|
|
continue
|
|
ProcessIdList.append(ProcessId)
|
|
return ProcessIdList
|
|
|
|
|
|
def LookupAccountSidW(lpSystemName, lpSid):
|
|
# From https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/win32/advapi32.py
|
|
_LookupAccountSidW = advapi32.LookupAccountSidW
|
|
_LookupAccountSidW.argtypes = [LPSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPDWORD]
|
|
_LookupAccountSidW.restype = BOOL
|
|
|
|
ERROR_INSUFFICIENT_BUFFER = 122
|
|
cchName = DWORD(0)
|
|
cchReferencedDomainName = DWORD(0)
|
|
peUse = DWORD(0)
|
|
success = _LookupAccountSidW(lpSystemName, lpSid, None, byref(cchName), None, byref(cchReferencedDomainName),
|
|
byref(peUse))
|
|
error = GetLastError()
|
|
if not success or error == ERROR_INSUFFICIENT_BUFFER:
|
|
lpName = create_unicode_buffer(u'', cchName.value + 1)
|
|
lpReferencedDomainName = create_unicode_buffer(u'', cchReferencedDomainName.value + 1)
|
|
success = _LookupAccountSidW(lpSystemName, lpSid, lpName, byref(cchName), lpReferencedDomainName,
|
|
byref(cchReferencedDomainName), byref(peUse))
|
|
if success:
|
|
return lpName.value, lpReferencedDomainName.value, peUse.value
|
|
|
|
return None, None, None
|
|
|
|
|
|
def QueryFullProcessImageNameW(hProcess, dwFlags=0):
|
|
_QueryFullProcessImageNameW = kernel32.QueryFullProcessImageNameW
|
|
_QueryFullProcessImageNameW.argtypes = [HANDLE, DWORD, LPWSTR, POINTER(DWORD)]
|
|
_QueryFullProcessImageNameW.restype = bool
|
|
ERROR_INSUFFICIENT_BUFFER = 122
|
|
|
|
dwSize = MAX_PATH
|
|
while 1:
|
|
lpdwSize = DWORD(dwSize)
|
|
lpExeName = create_unicode_buffer('', lpdwSize.value + 1)
|
|
success = _QueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, byref(lpdwSize))
|
|
if success and 0 < lpdwSize.value < dwSize:
|
|
break
|
|
error = GetLastError()
|
|
if error != ERROR_INSUFFICIENT_BUFFER:
|
|
return False
|
|
dwSize = dwSize + 256
|
|
if dwSize > 0x1000:
|
|
# this prevents an infinite loop in Windows 2008 when the path has spaces,
|
|
# see http://msdn.microsoft.com/en-us/library/ms684919(VS.85).aspx#4
|
|
return False
|
|
return lpExeName.value
|
|
|
|
|
|
def RtlAdjustPrivilege(privilege_id):
|
|
"""
|
|
privilege_id: int
|
|
"""
|
|
_RtlAdjustPrivilege = ntdll.RtlAdjustPrivilege
|
|
_RtlAdjustPrivilege.argtypes = [ULONG, BOOL, BOOL, POINTER(BOOL)]
|
|
_RtlAdjustPrivilege.restype = LONG
|
|
|
|
Enable = True
|
|
CurrentThread = False # enable for whole process
|
|
Enabled = BOOL()
|
|
|
|
status = _RtlAdjustPrivilege(privilege_id, Enable, CurrentThread, byref(Enabled))
|
|
if status != 0:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def getData(blobOut):
|
|
cbData = blobOut.cbData
|
|
pbData = blobOut.pbData
|
|
buffer = create_string_buffer(cbData)
|
|
memmove(buffer, pbData, sizeof(buffer))
|
|
LocalFree(pbData);
|
|
return buffer.raw
|
|
|
|
|
|
def get_full_path_from_pid(pid):
|
|
if pid:
|
|
filename = create_unicode_buffer("", 256)
|
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, int(pid))
|
|
if not hProcess:
|
|
return False
|
|
|
|
size = GetModuleFileNameEx(hProcess, None, filename, 256)
|
|
CloseHandle(hProcess)
|
|
if size:
|
|
return filename.value
|
|
else:
|
|
return False
|
|
|
|
|
|
python_version = 2
|
|
if sys.version_info[0]:
|
|
python_version = sys.version_info[0]
|
|
|
|
|
|
def Win32CryptUnprotectData(cipherText, entropy=False, is_current_user=True, user_dpapi=False):
|
|
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)
|
|
blobOut = DATA_BLOB()
|
|
|
|
if entropy:
|
|
bufferEntropy = c_buffer(entropy, len(entropy))
|
|
blobEntropy = DATA_BLOB(len(entropy), bufferEntropy)
|
|
|
|
if CryptUnprotectData(byref(blobIn), None, byref(blobEntropy), None, None, 0, byref(blobOut)):
|
|
decrypted = getData(blobOut)
|
|
|
|
else:
|
|
if CryptUnprotectData(byref(blobIn), None, None, None, None, 0, byref(blobOut)):
|
|
decrypted = getData(blobOut)
|
|
|
|
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:
|
|
try:
|
|
decrypted = user_dpapi.decrypt_encrypted_blob(cipherText)
|
|
except:
|
|
# The encrypted blob cannot be parsed - weird (could happen with chrome v80)
|
|
return None
|
|
if decrypted is False:
|
|
decrypted = None
|
|
else:
|
|
# raise ValueError('MasterKeys not found')
|
|
pass
|
|
|
|
if not decrypted:
|
|
if not user_dpapi:
|
|
# raise ValueError('DPApi unavailable')
|
|
pass
|
|
elif not user_dpapi.unlocked:
|
|
# raise ValueError('DPApi locked')
|
|
pass
|
|
|
|
return decrypted
|
|
|
|
|
|
def get_os_version():
|
|
"""
|
|
return major anr minor version
|
|
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx
|
|
"""
|
|
os_version = OSVERSIONINFOEXW()
|
|
os_version.dwOSVersionInfoSize = sizeof(os_version)
|
|
retcode = windll.Ntdll.RtlGetVersion(byref(os_version))
|
|
if retcode != 0:
|
|
return False
|
|
|
|
return '%s.%s' % (str(os_version.dwMajorVersion.real), str(os_version.dwMinorVersion.real))
|
|
|
|
|
|
def isx64machine():
|
|
archi = os.environ.get("PROCESSOR_ARCHITEW6432", '')
|
|
if '64' in archi:
|
|
return True
|
|
|
|
archi = os.environ.get("PROCESSOR_ARCHITECTURE", '')
|
|
if '64' in archi:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def OpenKey(key, path, index=0, access=KEY_READ):
|
|
if isx64:
|
|
return winreg.OpenKey(key, path, index, access | winreg.KEY_WOW64_64KEY)
|
|
else:
|
|
return winreg.OpenKey(key, path, index, access)
|
|
|
|
|
|
isx64 = isx64machine()
|
|
|
|
|
|
def string_to_unicode(string):
|
|
if python_version == 2:
|
|
return unicode(string)
|
|
else:
|
|
return string # String on python 3 are already unicode
|
|
|
|
|
|
def chr_or_byte(integer):
|
|
if python_version == 2:
|
|
return chr(integer)
|
|
else:
|
|
return bytes([integer]) # Python 3
|
|
|
|
|
|
def int_or_bytes(integer):
|
|
if python_version == 2:
|
|
return integer
|
|
else:
|
|
return bytes([integer]) # Python 3
|
|
|
|
|
|
def char_to_int(string):
|
|
if python_version == 2 or isinstance(string, str):
|
|
return ord(string)
|
|
else:
|
|
return string # Python 3
|
|
|
|
|
|
def convert_to_byte(string):
|
|
if python_version == 2:
|
|
return string
|
|
else:
|
|
return string.encode() # Python 3
|