/** * @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__