Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
4.5 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. DominantSpecies.cpp
  5. Abstract:
  6. See Force21 shim - almost exactly the same problem.
  7. DominantSpecies contains an invalid check code that looks like the following:
  8. mov esi,A
  9. mov eax,B
  10. sub eax,esi
  11. cmp eax,ebp
  12. jle @@Loc
  13. mov eax,ebp
  14. @@Loc:
  15. In a particular case: B=-1 and A<0x80000000 this jump will be incorrectly
  16. taken. The reason this works on Win9x is that A>0x80000000 because it's a
  17. memory mapped file. On NT, no user mode address can normally be >2GB.
  18. This shim patches the app with a 'cli' instruction so that it can perform
  19. some logic when the exception gets hit. This is admittedly slow.
  20. Note we didn't use the in memory patching facility of the shim because we
  21. still needed logic. It didn't make sense to split the shim from the patch.
  22. Also, we can't have a general shim which makes all memory addresses high and
  23. catches the fallout, because game performance suffers too much.
  24. Notes:
  25. This is an app specific shim.
  26. History:
  27. 06/30/2001 linstev Created
  28. --*/
  29. #include "precomp.h"
  30. IMPLEMENT_SHIM_BEGIN(DominantSpecies)
  31. #include "ShimHookMacro.h"
  32. APIHOOK_ENUM_BEGIN
  33. APIHOOK_ENUM_END
  34. /*++
  35. In memory patch the executable with a cli instruction. This patch works
  36. for both the release version and a patch.
  37. --*/
  38. VOID
  39. ExecutePatch()
  40. {
  41. BYTE bPatchMatch[] = {
  42. 0x2b, 0xc6, 0x3b, 0xc5, 0x7c, 0x02, 0x8b, 0xc5, 0x85, 0xc0 };
  43. LPBYTE pPatchAddress[] = {
  44. (LPBYTE)0x53f543, // the shipping version
  45. (LPBYTE)0x000000}; // placeholder for a vendor patch in case they get it wrong again
  46. BYTE bPatch = 0xFA; // cli - to cause an exception
  47. //
  48. // Run through the patches and see which one matches
  49. //
  50. for (UINT j=0; j<sizeof(pPatchAddress)/sizeof(LPBYTE); j++)
  51. {
  52. LPBYTE pb = pPatchAddress[j];
  53. // Make sure it's an OK address.
  54. if (!IsBadReadPtr(pb, sizeof(bPatchMatch)))
  55. {
  56. // Check the bytes match
  57. for (UINT i=0; i < sizeof(bPatchMatch); i++)
  58. {
  59. if (*pb != bPatchMatch[i])
  60. {
  61. break;
  62. }
  63. pb++;
  64. }
  65. // In memory patch
  66. if (i == sizeof(bPatchMatch))
  67. {
  68. DWORD dwOldProtect;
  69. if (VirtualProtect(
  70. (PVOID)pPatchAddress[j],
  71. 1,
  72. PAGE_READWRITE,
  73. &dwOldProtect))
  74. {
  75. *pPatchAddress[j] = bPatch;
  76. LOGN(
  77. eDbgLevelError,
  78. "Successfully patched\n");
  79. return;
  80. }
  81. }
  82. }
  83. }
  84. }
  85. /*++
  86. Handle the cli in such a way that the correct logic is performed.
  87. --*/
  88. LONG
  89. ExceptionFilter(
  90. struct _EXCEPTION_POINTERS *ExceptionInfo
  91. )
  92. {
  93. CONTEXT *lpContext = ExceptionInfo->ContextRecord;
  94. if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION)
  95. {
  96. // Looks like we've hit our cli instruction
  97. if ((LONG)lpContext->Eax < 0) // Boundary condition, EDI<0
  98. {
  99. // Jump past the invalid check
  100. lpContext->Eip = lpContext->Eip + 6;
  101. }
  102. else
  103. {
  104. // Replace the 'sub edi,eax' and continue
  105. lpContext->Eax = lpContext->Eax - lpContext->Esi;
  106. lpContext->Eip = lpContext->Eip + 2;
  107. }
  108. return EXCEPTION_CONTINUE_EXECUTION;
  109. }
  110. return EXCEPTION_CONTINUE_SEARCH;
  111. }
  112. /*++
  113. Register hooked functions
  114. --*/
  115. BOOL
  116. NOTIFY_FUNCTION(
  117. DWORD fdwReason)
  118. {
  119. if (fdwReason == DLL_PROCESS_ATTACH)
  120. {
  121. ExecutePatch();
  122. // Try to find new exception handler
  123. _pfn_RtlAddVectoredExceptionHandler pfnExcept;
  124. pfnExcept = (_pfn_RtlAddVectoredExceptionHandler)
  125. GetProcAddress(
  126. GetModuleHandle(L"NTDLL.DLL"),
  127. "RtlAddVectoredExceptionHandler");
  128. if (pfnExcept)
  129. {
  130. (_pfn_RtlAddVectoredExceptionHandler) pfnExcept(
  131. 0,
  132. (PVOID)ExceptionFilter);
  133. }
  134. }
  135. return TRUE;
  136. }
  137. HOOK_BEGIN
  138. CALL_NOTIFY_FUNCTION
  139. HOOK_END
  140. IMPLEMENT_SHIM_END