├── CSkyDBK.h └── CSkyDBK.cpp /CSkyDBK.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma comment(lib, "Shlwapi.lib") 8 | 9 | #define SKYDBK_DEBUGPRINT(...) ((void)0) 10 | 11 | #ifndef _WIN64 12 | #error "Only win x64 is supported" 13 | #endif 14 | 15 | 16 | typedef struct _LSA_UNICODE_STRING { 17 | USHORT Length; 18 | USHORT MaximumLength; 19 | PWSTR Buffer; 20 | } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING; 21 | 22 | typedef NTSTATUS (__stdcall *tZwLoadDriver)( 23 | _In_ PUNICODE_STRING DriverServiceName 24 | ); 25 | typedef NTSTATUS (__stdcall *tZwUnloadDriver)( 26 | _In_ PUNICODE_STRING DriverServiceName 27 | ); 28 | typedef NTSTATUS(__stdcall *tRtlInitUnicodeString)( 29 | _Out_ PUNICODE_STRING DestinationString, 30 | _In_opt_ PCWSTR SourceString 31 | ); 32 | 33 | class CSkyDBK 34 | { 35 | private: 36 | 37 | HANDLE m_hDBK; 38 | HANDLE m_hCheatEngine; 39 | HDESK m_hCheatEngineDesktop; 40 | 41 | const wchar_t *m_szDBKPath; 42 | const wchar_t *m_szCheatEnginePath; 43 | 44 | std::wstring m_szServiceName; 45 | std::wstring m_szProcessEventName; 46 | std::wstring m_szThreadEventName; 47 | 48 | tZwLoadDriver m_ZwLoadDriver; 49 | tZwUnloadDriver m_ZwUnloadDriver; 50 | tRtlInitUnicodeString m_RtlInitUnicodeString; 51 | 52 | public: 53 | 54 | HANDLE LoadDriver(); 55 | 56 | bool UnloadDriver(); 57 | 58 | CSkyDBK(const wchar_t *szDBK, const wchar_t *szCE); 59 | 60 | ~CSkyDBK(); 61 | 62 | static std::wstring GetRandomWString(size_t len); 63 | 64 | private: 65 | 66 | static HMODULE GetRemoteModule(const char *szModuleName, DWORD dwProcessId); 67 | 68 | static bool GetRemoteModuleExportDirectory32(HMODULE hRemote, PIMAGE_EXPORT_DIRECTORY ExportDirectory, PIMAGE_DOS_HEADER DosHeader, PIMAGE_NT_HEADERS32 NtHeaders, HANDLE hProcess); 69 | 70 | static PVOID GetRemoteFuncAddress32(const char *module, const char *func, HANDLE hProcess); 71 | 72 | BYTE *GetCreateFileShellcode(HANDLE _In_ hProcess, const wchar_t _In_ *szDriverPipe, PVOID _Out_ *allocatedMemory); 73 | 74 | bool LoadDBK(); 75 | 76 | bool UnloadDBK(); 77 | 78 | LSTATUS PrepareDriverRegEntry(const std::wstring& svcName, const std::wstring& path, bool cleanup = false); 79 | 80 | static bool AttemptDebugPrivilege(HANDLE h); 81 | 82 | 83 | }; -------------------------------------------------------------------------------- /CSkyDBK.cpp: -------------------------------------------------------------------------------- 1 | #include "CSkyDBK.h" 2 | 3 | std::wstring CSkyDBK::GetRandomWString(size_t len) 4 | { 5 | std::wstring ustr = L""; 6 | 7 | const char begin1 = '\u0041'; 8 | const char end1 = '\u005A'; 9 | 10 | const char begin2 = '\u0061'; 11 | const char end2 = '\u007A'; 12 | 13 | const char begin3 = '\u0030'; 14 | const char end3 = '\u0039'; 15 | 16 | const char begin4 = '\u00A1'; 17 | const char end4 = '\u00FF'; 18 | 19 | for(auto i = 0; i < len; i++) { 20 | switch(rand() % 4) 21 | { 22 | default: 23 | case 0: 24 | ustr += begin1 + (rand() % (end1 - begin1)); 25 | break; 26 | case 1: 27 | ustr += begin2 + (rand() % (end2 - begin2)); 28 | break; 29 | case 2: 30 | ustr += begin3 + (rand() % (end3 - begin3)); 31 | break; 32 | case 3: 33 | ustr += begin4 + (rand() % (end4 - begin4)); 34 | break; 35 | } 36 | } 37 | 38 | return ustr; 39 | } 40 | 41 | HANDLE CSkyDBK::LoadDriver() 42 | { 43 | if(!this->LoadDBK()) 44 | { 45 | return INVALID_HANDLE_VALUE; 46 | } 47 | 48 | return this->m_hDBK; 49 | } 50 | 51 | bool CSkyDBK::UnloadDriver() 52 | { 53 | return this->UnloadDBK(); 54 | } 55 | 56 | CSkyDBK::CSkyDBK(const wchar_t * szDBK, const wchar_t * szCE) 57 | { 58 | this->AttemptDebugPrivilege(GetCurrentProcess()); 59 | 60 | this->m_szDBKPath = szDBK; 61 | this->m_szCheatEnginePath = szCE; 62 | this->m_hDBK = INVALID_HANDLE_VALUE; 63 | this->m_hCheatEngine = INVALID_HANDLE_VALUE; 64 | this->m_hCheatEngineDesktop = NULL; 65 | 66 | this->m_szProcessEventName = this->GetRandomWString(10 + (rand() % 15)); 67 | this->m_szThreadEventName = this->GetRandomWString(10 + (rand() % 15)); 68 | this->m_szServiceName = this->GetRandomWString(10 + (rand() % 15)); 69 | 70 | HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); 71 | this->m_ZwLoadDriver = reinterpret_cast(GetProcAddress(ntdll, "ZwLoadDriver")); 72 | this->m_ZwUnloadDriver = reinterpret_cast(GetProcAddress(ntdll, "ZwUnloadDriver")); 73 | this->m_RtlInitUnicodeString = reinterpret_cast(GetProcAddress(ntdll, "RtlInitUnicodeString")); 74 | 75 | wchar_t currentPath[MAX_PATH + 1] = L""; 76 | GetCurrentDirectoryW(MAX_PATH, currentPath); 77 | 78 | STARTUPINFOW startupInfo = { 0 }; 79 | PROCESS_INFORMATION processInfo = { 0 }; 80 | 81 | startupInfo.cb = sizeof(startupInfo); 82 | 83 | //Hide MessageBox approach #2: Create a new Desktop for the new process 84 | 85 | //After all I should probably just run the process in suspended state 86 | //and patch the entry point 87 | 88 | std::wstring desktopName = this->GetRandomWString(10 + (rand() % 15)); 89 | this->m_hCheatEngineDesktop = CreateDesktopW(desktopName.c_str(), NULL, NULL, 0, GENERIC_ALL, NULL); 90 | 91 | startupInfo.lpDesktop = const_cast(desktopName.c_str()); 92 | 93 | CreateProcessW(const_cast(szCE), NULL, NULL, NULL, FALSE, 0, NULL, currentPath, &startupInfo, &processInfo); 94 | this->m_hCheatEngine = processInfo.hProcess; 95 | this->AttemptDebugPrivilege(this->m_hCheatEngine); 96 | 97 | 98 | //Hide MessageBox approach #1: hide the MessageBox as soon as we find it, that's pretty dirty and bad 99 | /*HWND msgBox = NULL; 100 | do 101 | { 102 | msgBox = FindWindowW(NULL, L"dbk32.sys unloaded"); //will be shown if the driver isn't loaded (most cases) 103 | if(!msgBox) 104 | msgBox = FindWindowW(NULL, L"driver error"); //will be shown when the driver is loaded via CE 105 | if(!msgBox) 106 | msgBox = FindWindowW(NULL, L"DBK32.sys unloader"); //some other error, rarely happens 107 | 108 | Sleep(50); 109 | 110 | } while(msgBox == NULL); 111 | 112 | ShowWindow(msgBox, SW_HIDE);*/ 113 | } 114 | 115 | CSkyDBK::~CSkyDBK() 116 | { 117 | if(this->m_hDBK != INVALID_HANDLE_VALUE) 118 | { 119 | this->UnloadDBK(); 120 | this->m_hDBK = INVALID_HANDLE_VALUE; 121 | } 122 | 123 | if(this->m_hCheatEngine != INVALID_HANDLE_VALUE) 124 | { 125 | TerminateProcess(this->m_hCheatEngine, 0); 126 | this->m_hCheatEngine = INVALID_HANDLE_VALUE; 127 | } 128 | 129 | if(this->m_hCheatEngineDesktop != NULL) 130 | { 131 | CloseDesktop(this->m_hCheatEngineDesktop); 132 | this->m_hCheatEngineDesktop = NULL; 133 | } 134 | } 135 | 136 | 137 | HMODULE CSkyDBK::GetRemoteModule(const char *szModuleName, DWORD dwProcessId) 138 | { 139 | if(!szModuleName || !dwProcessId) { return NULL; } 140 | 141 | HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwProcessId); 142 | if(hSnap == INVALID_HANDLE_VALUE) { return NULL; } 143 | 144 | #if defined(MODULEENTRY32) 145 | #define SKYDBK_REDEF_FUNCS 146 | #undef MODULEENTRY32 147 | #undef Module32First 148 | #undef Module32Next 149 | #endif 150 | 151 | MODULEENTRY32 me; 152 | me.dwSize = sizeof(MODULEENTRY32); 153 | if(Module32First(hSnap, &me)) 154 | { 155 | do 156 | { 157 | if(!_stricmp(me.szModule, szModuleName)) 158 | { 159 | CloseHandle(hSnap); 160 | return me.hModule; 161 | } 162 | } while(Module32Next(hSnap, &me)); 163 | } 164 | CloseHandle(hSnap); 165 | 166 | #ifdef SKYDBK_REDEF_FUNCS 167 | #undef SKYDBK_REDEF_FUNCS 168 | #define Module32First Module32FirstW 169 | #define Module32Next Module32NextW 170 | #define MODULEENTRY32 MODULEENTRY32W 171 | #endif 172 | 173 | return NULL; 174 | } 175 | 176 | // https://github.com/EasyHook/EasyHook/blob/master/EasyHookDll/RemoteHook/thread.c#L710 177 | bool CSkyDBK::GetRemoteModuleExportDirectory32(HMODULE hRemote, PIMAGE_EXPORT_DIRECTORY ExportDirectory, PIMAGE_DOS_HEADER DosHeader, PIMAGE_NT_HEADERS32 NtHeaders, HANDLE hProcess) 178 | { 179 | if(!ExportDirectory) 180 | return false; 181 | 182 | memset(ExportDirectory, 0, sizeof(IMAGE_EXPORT_DIRECTORY)); 183 | 184 | PUCHAR ucAllocatedPEHeader = new UCHAR[1000]; 185 | 186 | if(!ReadProcessMemory(hProcess, (void*)hRemote, ucAllocatedPEHeader, (SIZE_T)1000, NULL)) 187 | return false; 188 | 189 | PIMAGE_SECTION_HEADER pImageSectionHeader = (PIMAGE_SECTION_HEADER)(ucAllocatedPEHeader + DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)); 190 | 191 | for(int i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++, pImageSectionHeader++) { 192 | if(!pImageSectionHeader) 193 | continue; 194 | 195 | if(_stricmp((char*)pImageSectionHeader->Name, ".edata") == 0) { 196 | if(!ReadProcessMemory(hProcess, (void*)pImageSectionHeader->VirtualAddress, ExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY), NULL)) 197 | continue; 198 | 199 | delete[] ucAllocatedPEHeader; 200 | return true; 201 | } 202 | 203 | } 204 | 205 | DWORD dwEATAddress = NtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress; 206 | if(!dwEATAddress) 207 | return false; 208 | 209 | if(!ReadProcessMemory(hProcess, (void*)((DWORD)hRemote + dwEATAddress), ExportDirectory, sizeof(IMAGE_EXPORT_DIRECTORY), NULL)) 210 | return false; 211 | 212 | delete[] ucAllocatedPEHeader; 213 | return true; 214 | } 215 | 216 | // https://github.com/EasyHook/EasyHook/blob/master/EasyHookDll/RemoteHook/thread.c#L837 217 | PVOID CSkyDBK::GetRemoteFuncAddress32(const char * module, const char * func, HANDLE hProcess) 218 | { 219 | HMODULE hRemote = GetRemoteModule(module, GetProcessId(hProcess)); 220 | 221 | if(!hRemote) 222 | return NULL; 223 | 224 | IMAGE_DOS_HEADER DosHeader; 225 | if(!ReadProcessMemory(hProcess, (void*)hRemote, &DosHeader, sizeof(IMAGE_DOS_HEADER), NULL) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE) 226 | return NULL; 227 | 228 | IMAGE_NT_HEADERS32 NtHeaders; 229 | void *dwNTHeaders = (PDWORD)((DWORD)hRemote + DosHeader.e_lfanew); 230 | if(!ReadProcessMemory(hProcess, dwNTHeaders, &NtHeaders, sizeof(IMAGE_NT_HEADERS32), NULL) || NtHeaders.Signature != IMAGE_NT_SIGNATURE) 231 | return NULL; 232 | 233 | IMAGE_EXPORT_DIRECTORY EATDirectory; 234 | if(!GetRemoteModuleExportDirectory32(hRemote, &EATDirectory, &DosHeader, &NtHeaders, hProcess)) 235 | return NULL; 236 | 237 | DWORD* AddressOfFunctions = (DWORD*)malloc(EATDirectory.NumberOfFunctions * sizeof(DWORD)); 238 | DWORD* AddressOfNames = (DWORD*)malloc(EATDirectory.NumberOfNames * sizeof(DWORD)); 239 | WORD* AddressOfOrdinals = (WORD*)malloc(EATDirectory.NumberOfNames * sizeof(WORD)); 240 | 241 | if(!ReadProcessMemory(hProcess, (void*)((DWORD)hRemote + (DWORD)EATDirectory.AddressOfFunctions), reinterpret_cast(AddressOfFunctions), EATDirectory.NumberOfFunctions * sizeof(DWORD), NULL)) { 242 | free(AddressOfFunctions); 243 | free(AddressOfNames); 244 | free(AddressOfOrdinals); 245 | return NULL; 246 | } 247 | 248 | if(!ReadProcessMemory(hProcess, (void*)((DWORD)hRemote + (DWORD)EATDirectory.AddressOfNames), reinterpret_cast(AddressOfNames), EATDirectory.NumberOfNames * sizeof(DWORD), NULL)) { 249 | free(AddressOfFunctions); 250 | free(AddressOfNames); 251 | free(AddressOfOrdinals); 252 | return NULL; 253 | } 254 | 255 | if(!ReadProcessMemory(hProcess, (void*)((DWORD)hRemote + (DWORD)EATDirectory.AddressOfNameOrdinals), reinterpret_cast(AddressOfOrdinals), EATDirectory.NumberOfNames * sizeof(WORD), NULL)) { 256 | free(AddressOfFunctions); 257 | free(AddressOfNames); 258 | free(AddressOfOrdinals); 259 | return NULL; 260 | } 261 | 262 | DWORD dwExportBase = ((DWORD)hRemote + NtHeaders.OptionalHeader.DataDirectory[0].VirtualAddress); 263 | DWORD dwExportSize = (dwExportBase + NtHeaders.OptionalHeader.DataDirectory[0].Size); 264 | 265 | for(DWORD i = 0; i < EATDirectory.NumberOfNames; ++i) 266 | { 267 | DWORD dwAddressOfFunction = ((DWORD)hRemote + (DWORD)AddressOfFunctions[i]); 268 | DWORD dwAddressOfName = ((DWORD)hRemote + (DWORD)AddressOfNames[i]); 269 | 270 | char pszFunctionName[256] = { 0 }; 271 | 272 | if(!ReadProcessMemory(hProcess, (void*)dwAddressOfName, pszFunctionName, 256, NULL)) 273 | continue; 274 | 275 | if(_stricmp(pszFunctionName, func) != 0) 276 | continue; 277 | 278 | if(dwAddressOfFunction >= dwExportBase && dwAddressOfFunction <= dwExportSize) { 279 | char pszRedirectName[256] = { 0 }; 280 | 281 | if(!ReadProcessMemory(hProcess, (void*)dwAddressOfFunction, pszRedirectName, 256, NULL)) 282 | continue; 283 | 284 | char pszModuleName[256] = { 0 }; 285 | char pszFunctionRedi[256] = { 0 }; 286 | 287 | int a = 0; 288 | for(; pszRedirectName[a] != '.'; a++) 289 | pszModuleName[a] = pszRedirectName[a]; 290 | a++; 291 | pszModuleName[a] = '\0'; 292 | 293 | int b = 0; 294 | for(; pszRedirectName[a] != '\0'; a++, b++) 295 | pszFunctionRedi[b] = pszRedirectName[a]; 296 | b++; 297 | pszFunctionRedi[b] = '\0'; 298 | 299 | strcat_s(pszModuleName, ".dll"); 300 | 301 | free(AddressOfFunctions); 302 | free(AddressOfNames); 303 | free(AddressOfOrdinals); 304 | 305 | return GetRemoteFuncAddress32(pszModuleName, pszFunctionRedi, hProcess); 306 | } 307 | 308 | WORD OrdinalValue = (reinterpret_cast(AddressOfOrdinals))[i]; 309 | 310 | if(OrdinalValue != i) { 311 | DWORD dwAddressOfRedirectedFunction = ((DWORD)hRemote + (DWORD)AddressOfFunctions[OrdinalValue]); 312 | DWORD dwAddressOfRedirectedName = ((DWORD)hRemote + (DWORD)AddressOfNames[OrdinalValue]); 313 | 314 | char pszRedirectedFunctionName[256] = { 0 }; 315 | 316 | free(AddressOfFunctions); 317 | free(AddressOfNames); 318 | free(AddressOfOrdinals); 319 | 320 | if(!ReadProcessMemory(hProcess, (void*)dwAddressOfRedirectedName, pszRedirectedFunctionName, 256, NULL)) 321 | return NULL; 322 | else 323 | return reinterpret_cast(dwAddressOfRedirectedFunction); 324 | } 325 | else { 326 | free(AddressOfFunctions); 327 | free(AddressOfNames); 328 | free(AddressOfOrdinals); 329 | 330 | return reinterpret_cast(dwAddressOfFunction); 331 | } 332 | } 333 | 334 | free(AddressOfFunctions); 335 | free(AddressOfNames); 336 | free(AddressOfOrdinals); 337 | 338 | return NULL; 339 | } 340 | 341 | 342 | BYTE * CSkyDBK::GetCreateFileShellcode(HANDLE _In_ hProcess, const wchar_t _In_ *szDriverPipe, PVOID _Out_ *allocatedMemory) 343 | { 344 | static BYTE shellcode[] = { 345 | 0x90, //NOP 346 | 0x90, //NOP 347 | 0x90, //NOP 348 | 0x90, //NOP 349 | 350 | 0xb8, 0xff, 0xff, 0xff, 0xff, //mov eax, 0xffffffff 351 | 0x6a, 0x00, //push 0 352 | 0x6a, 0x00, //push 0 353 | 0x6a, 0x03, //push OPEN_EXISTING 354 | 0x6a, 0x00, //push 0 355 | 0x6a, 0x03, //push FILE_SHARE_READ | FILE_SHARE_WRITE 356 | 0x68, 0x00, 0x00, 0x00, 0xc0, //push GENERIC_READ | GENERIC_WRITE 357 | 0x68, 0xff, 0xff, 0xff, 0xff, //push 0xffffffff 358 | 0xff, 0xd0, //call eax 359 | 0xba, 0xff, 0xff, 0xff, 0xff, //mov edx, 0xffffffff 360 | 0x89, 0x02, //mov [edx], eax 361 | 0xc3, //ret 362 | }; 363 | 364 | size_t pipeLen = wcslen(szDriverPipe); 365 | 366 | DWORD *shellcodeCreateFileW = reinterpret_cast(&shellcode[0x5]); 367 | DWORD *shellcodePipename = reinterpret_cast(&shellcode[0x19]); 368 | DWORD *shellcodeShellCodeStart = reinterpret_cast(&shellcode[0x20]); 369 | 370 | void *ptrCreateFileW = this->GetRemoteFuncAddress32("kernel32.dll", "CreateFileW", hProcess); 371 | 372 | void *ptrAllocatedShellcode = VirtualAllocEx(hProcess, 0, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 373 | void *ptrAllocatedPipeName = VirtualAllocEx(hProcess, 0, sizeof(wchar_t) * pipeLen, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 374 | 375 | *shellcodeCreateFileW = reinterpret_cast(ptrCreateFileW); 376 | *shellcodePipename = reinterpret_cast(ptrAllocatedPipeName); 377 | *shellcodeShellCodeStart = reinterpret_cast(ptrAllocatedShellcode); 378 | 379 | WriteProcessMemory(hProcess, ptrAllocatedPipeName, szDriverPipe, sizeof(wchar_t) * pipeLen, NULL); 380 | WriteProcessMemory(hProcess, ptrAllocatedShellcode, shellcode, sizeof(shellcode), NULL); 381 | 382 | *allocatedMemory = ptrAllocatedShellcode; 383 | 384 | return shellcode; 385 | } 386 | 387 | bool CSkyDBK::LoadDBK() 388 | { 389 | if(this->PrepareDriverRegEntry(this->m_szServiceName, this->m_szDBKPath) != 0) 390 | { 391 | return false; 392 | } 393 | 394 | std::wstring regPath = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\" + this->m_szServiceName; 395 | SKYDBK_DEBUGPRINT(L"%s\n", regPath.c_str()); 396 | 397 | UNICODE_STRING Ustr = { 0 }; 398 | this->m_RtlInitUnicodeString(&Ustr, regPath.c_str()); 399 | 400 | SKYDBK_DEBUGPRINT("Loading driver\n"); 401 | NTSTATUS result = this->m_ZwLoadDriver(&Ustr); 402 | if(result != 0) 403 | { 404 | SKYDBK_DEBUGPRINT("Failed: 0x%X\n", result); 405 | return false; 406 | } 407 | 408 | PVOID remoteShellcode = nullptr; 409 | DWORD dwThreadId = 0; 410 | HANDLE hThread = NULL, hCEHandle = NULL, hLocalHandle = NULL; 411 | BYTE *shellcode = this->GetCreateFileShellcode(this->m_hCheatEngine, (L"\\\\.\\" + this->m_szServiceName).c_str(), &remoteShellcode); 412 | 413 | SKYDBK_DEBUGPRINT("Creating thread...\n"); 414 | hThread = CreateRemoteThread(this->m_hCheatEngine, NULL, NULL, reinterpret_cast(remoteShellcode), NULL, NULL, &dwThreadId); 415 | WaitForSingleObject(hThread, INFINITE); 416 | ReadProcessMemory(this->m_hCheatEngine, remoteShellcode, &hCEHandle, 4, NULL); 417 | 418 | this->PrepareDriverRegEntry(this->m_szServiceName, this->m_szDBKPath, true); 419 | 420 | HANDLE ownProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); 421 | 422 | SKYDBK_DEBUGPRINT("CE Handle: 0x%X\n", this->m_hCheatEngine); 423 | BOOL b = DuplicateHandle(this->m_hCheatEngine, hCEHandle, ownProcess, &hLocalHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); 424 | SKYDBK_DEBUGPRINT("DuplicateHandle: 0x%X\nLocal Handle: 0x%X\n", b, hLocalHandle); 425 | 426 | this->m_hDBK = hLocalHandle; 427 | 428 | TerminateProcess(this->m_hCheatEngine, 0); 429 | this->m_hCheatEngine = INVALID_HANDLE_VALUE; 430 | 431 | CloseDesktop(this->m_hCheatEngineDesktop); 432 | this->m_hCheatEngineDesktop = NULL; 433 | 434 | return true; 435 | } 436 | 437 | bool CSkyDBK::UnloadDBK() 438 | { 439 | UNICODE_STRING Ustr = { 0 }; 440 | 441 | std::wstring regPath = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\" + this->m_szServiceName; 442 | this->m_RtlInitUnicodeString(&Ustr, regPath.c_str()); 443 | 444 | // Remove previously loaded instance, if any 445 | NTSTATUS status = this->m_ZwUnloadDriver(&Ustr); 446 | SHDeleteKeyW(HKEY_LOCAL_MACHINE, std::wstring(L"SYSTEM\\CurrentControlSet\\Services\\" + this->m_szServiceName).c_str()); 447 | 448 | if(status != 0) 449 | { 450 | return false; 451 | } 452 | 453 | return true; 454 | } 455 | 456 | //Credits: DarthTon 457 | LSTATUS CSkyDBK::PrepareDriverRegEntry(const std::wstring& svcName, const std::wstring& path, bool cleanup /* = false */) 458 | { 459 | HKEY key1, key2; 460 | DWORD dwType = 1; 461 | LSTATUS status = 0; 462 | WCHAR wszLocalPath[MAX_PATH] = { 0 }; 463 | 464 | swprintf_s(wszLocalPath, ARRAYSIZE(wszLocalPath), L"\\??\\%s", path.c_str()); 465 | 466 | status = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"system\\CurrentControlSet\\Services", &key1); 467 | if(status) 468 | return status; 469 | 470 | status = RegCreateKeyW(key1, svcName.c_str(), &key2); 471 | if(status) 472 | { 473 | RegCloseKey(key1); 474 | return status; 475 | } 476 | 477 | if(!cleanup) 478 | { 479 | status = RegSetValueExW( 480 | key2, L"ImagePath", 0, REG_SZ, 481 | reinterpret_cast(wszLocalPath), 482 | static_cast(sizeof(WCHAR)* (wcslen(wszLocalPath) + 1)) 483 | ); 484 | 485 | if(status) 486 | { 487 | RegCloseKey(key2); 488 | RegCloseKey(key1); 489 | return status; 490 | } 491 | 492 | status = RegSetValueExW(key2, L"Type", 0, REG_DWORD, reinterpret_cast(&dwType), sizeof(dwType)); 493 | if(status) 494 | { 495 | RegCloseKey(key2); 496 | RegCloseKey(key1); 497 | return status; 498 | } 499 | } 500 | 501 | std::wstring A = L"\\Device\\" + this->m_szServiceName; 502 | std::wstring B = L"\\DosDevices\\" + this->m_szServiceName; 503 | std::wstring C = L"\\BaseNamedObjects\\" + this->m_szProcessEventName; 504 | std::wstring D = L"\\BaseNamedObjects\\" + this->m_szThreadEventName; 505 | 506 | if(!cleanup) 507 | { 508 | status = RegSetValueExW(key2, L"A", 0, REG_SZ, reinterpret_cast(A.c_str()), A.length() * sizeof(WCHAR)); 509 | if(status) 510 | { 511 | RegCloseKey(key2); 512 | RegCloseKey(key1); 513 | return status; 514 | } 515 | 516 | status = RegSetValueExW(key2, L"B", 0, REG_SZ, reinterpret_cast(B.c_str()), B.length() * sizeof(WCHAR)); 517 | if(status) 518 | { 519 | RegCloseKey(key2); 520 | RegCloseKey(key1); 521 | return status; 522 | } 523 | 524 | status = RegSetValueExW(key2, L"C", 0, REG_SZ, reinterpret_cast(C.c_str()), C.length() * sizeof(WCHAR)); 525 | if(status) 526 | { 527 | RegCloseKey(key2); 528 | RegCloseKey(key1); 529 | return status; 530 | } 531 | 532 | status = RegSetValueExW(key2, L"D", 0, REG_SZ, reinterpret_cast(D.c_str()), D.length() * sizeof(WCHAR)); 533 | if(status) 534 | { 535 | RegCloseKey(key2); 536 | RegCloseKey(key1); 537 | return status; 538 | } 539 | } 540 | else 541 | { 542 | RegDeleteValueW(key2, L"A"); 543 | RegDeleteValueW(key2, L"B"); 544 | RegDeleteValueW(key2, L"C"); 545 | RegDeleteValueW(key2, L"D"); 546 | } 547 | 548 | RegCloseKey(key2); 549 | RegCloseKey(key1); 550 | 551 | return status; 552 | } 553 | 554 | bool CSkyDBK::AttemptDebugPrivilege(HANDLE h) 555 | { 556 | HANDLE hToken; 557 | bool res = false; 558 | 559 | if(OpenProcessToken(h, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 560 | { 561 | TOKEN_PRIVILEGES tp; 562 | 563 | tp.PrivilegeCount = 1; 564 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 565 | tp.Privileges[0].Luid.HighPart = 0; 566 | 567 | tp.Privileges[0].Luid.LowPart = 20; //Debug 568 | 569 | BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); 570 | res = result == TRUE ? true : false; 571 | 572 | tp.Privileges[0].Luid.LowPart = 10; //Load Driver 573 | 574 | result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); 575 | res = res && (result == TRUE); 576 | 577 | CloseHandle(hToken); 578 | } 579 | 580 | return res; 581 | } 582 | --------------------------------------------------------------------------------