// Modifies PatchGuard context (its value field and code) to disarm them. // Note that this function is not necessary if you just want to stop PatchGuard. // Thus, a lots of magic numbers in this function is just for presentation. EXTERN_C static void Win8pPatchPgContext( __inout PgContext_8_1* PgContext) { // There are several condition checks in FsRtlMdlReadCompleteDevEx and // Pg_SelfValidation to see the result of validation check. Following // addresses are these addresses and will be modified. auto fsRtlUninitializeSmallMcb = reinterpret_cast<ULONG_PTR>(PgContext) + PgContext->offsetToFsUninitializeSmallMcbInBytes; auto fsRtlMdlReadCompleteDevEx = fsRtlUninitializeSmallMcb - 0xa000; auto fsResultCheck1 = fsRtlMdlReadCompleteDevEx + 0x90cd; auto fsResultCheck2 = fsRtlMdlReadCompleteDevEx + 0x92e1; auto pgSelfValidation = reinterpret_cast<ULONG_PTR>(PgContext) + PgContext->offsetToPg_SelfValidationInBytes; auto pgResultCheck = pgSelfValidation + 0x423; //DBG_BREAK(); // Install patches on PatchGuard code static const UCHAR patch1[] = { WIN8_PG_CONTEXT_HOOK_ENTRY_CODE, 0x90, 0x90, 0x90, 0x90, 0x90, }; PatchReal(reinterpret_cast<void*>(fsResultCheck1), patch1, sizeof(patch1)); static const UCHAR patch2[] = { WIN8_PG_CONTEXT_HOOK_ENTRY_CODE, 0x0F, 0x85, 0x6D, 0x04, }; PatchReal(reinterpret_cast<void*>(fsResultCheck2), patch2, sizeof(patch2)); static const UCHAR patch3[] = { WIN8_PG_CONTEXT_HOOK_ENTRY_CODE, 0xe9, 0x09, 0x02, }; PatchReal(reinterpret_cast<void*>(pgResultCheck), patch3, sizeof(patch3)); // When ((the value & 2) == true), PatchGuard does self runtime // en(de)cryption. I do not want PatchGuard to do that for the sake of // debugging. It can be deleted. //PgContext->onTheFlyEnDecryptionFlag &= 0xFFFFFFFD; // When the value is not 0xFFFFFFFF, PatchGuard does Win32k verification. // I do not want PatchGuard to do that because when an error is detected // during Win32k validation, PatchGuard goes to BugCheck without calling // a necessary function (to be precise, MmDetachSession) to be a neutral // state. PgContext->checkWin32kIfNotNegativeOne = 0xFFFFFFFF; }
EXTERN_C static void Win8pInstallHook2( __in ULONG_PTR PatchAddress, __in ULONG_PTR AsmHandler) { UCHAR patchCode[] = { WIN8_HOOK_ENTRY_CODE, // nop or int 3 0x48, 0xbb, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // mov rbx, 0FFFFFFFFFFFFFFFFh 0xFF, 0xe3, // jmp rbx }; C_ASSERT(sizeof(patchCode) == 13); // Replace placeholder (0xffffffffffffffff) located at offset 3 of patchCode // with AsmHandler *reinterpret_cast<ULONG_PTR*>(patchCode + 3) = AsmHandler; // And install patch PatchReal(reinterpret_cast<void*>(PatchAddress), patchCode, sizeof(patchCode)); }
EXTERN_C static void WinXpInstallPatchForDecryptedPatchGuardContext( __in PatchGuardContextInfo& Info) { // Do not do anything for a patched context, just in case. auto pgContext = reinterpret_cast<PgContextBase*>(Info.PgContext); if (WinXpIsPatchGuardContextPatched(*pgContext)) { return; } // Install hook static const auto HEADER_SIZE = FIELD_OFFSET(PgContextBase, ExAcquireResourceSharedLite); const auto searchSizeInBytes = pgContext->ContextSizeInQWord * sizeof(ULONG64)+HEADER_SIZE; auto pgSdbpCheckDll = MemMem(pgContext, searchSizeInBytes, &WINX_SdbpCheckDll_PATTERN[0], sizeof(WINX_SdbpCheckDll_PATTERN)); ASSERT(pgSdbpCheckDll); // Make r13 and r14 zero. These are used as PgContext pointer later, and if // values are zero, PatchGuard gracefully ends its activity. static const UCHAR PATCH_CODE[] = { WINX_HOOK_CODE, // nop or int 3 0x4D, 0x33, 0xED, // xor r13, r13 0x4D, 0x33, 0xF6, // xor r14, r14 0xc3, // ret }; PatchReal(pgSdbpCheckDll, PATCH_CODE, sizeof(PATCH_CODE)); // Also, install hook at CmpAppendDllSection because it may be called at // the next time as we disabled SdbpCheckDll. pgContext->CmpAppendDllSection[WINX_HOOK_OFFSET + 0] = WINX_HOOK_CODE; pgContext->CmpAppendDllSection[WINX_HOOK_OFFSET + 1] = 0xc3; // RET ASSERT(WinXpIsPatchGuardContextPatched(*pgContext)); }