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.

210 lines
5.4 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. NotifyCallback.c
  5. Abstract:
  6. This module implements the code that (on win2k) implements
  7. the callback into the shim DLLs to notify them that all the
  8. static linked modules have run their init routines.
  9. Author:
  10. clupu created 19 February 2001
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <string.h>
  17. #include <windef.h>
  18. #include <winbase.h>
  19. #include "ShimEng.h"
  20. //
  21. // The structure of the code for injection must be byte aligned.
  22. //
  23. #pragma pack(push)
  24. #pragma pack(1)
  25. typedef struct tagINJECTION_CODE
  26. {
  27. BYTE PUSH_RETURN;
  28. PVOID retAddr;
  29. BYTE JMP;
  30. PVOID injCodeStart;
  31. } INJECTION_CODE, *PINJECTION_CODE;
  32. #pragma pack(pop)
  33. BYTE g_originalCode[sizeof(INJECTION_CODE)];
  34. PVOID g_entryPoint;
  35. void
  36. InitInjectionCode(
  37. IN PVOID entryPoint,
  38. IN PVOID injCodeStart,
  39. OUT PINJECTION_CODE pInjCode
  40. )
  41. /*++
  42. Return: void
  43. Desc: This function initializes the structure that contains
  44. the code to be injected at the entry point.
  45. --*/
  46. {
  47. //
  48. // Push the return address first so the ret in
  49. // the cleanup function will remove it from the stack and use it
  50. // as the return address.
  51. //
  52. pInjCode->PUSH_RETURN = 0x68;
  53. pInjCode->retAddr = entryPoint;
  54. pInjCode->JMP = 0xE9;
  55. //
  56. // The DWORD used in the JMP opcode is relative to the EIP after the JMP.
  57. // That's why we need to subtract sizeof(ONJECTION_CODE).
  58. //
  59. pInjCode->injCodeStart = (PVOID)((ULONG)injCodeStart -
  60. (ULONG)entryPoint -
  61. sizeof(INJECTION_CODE));
  62. }
  63. void
  64. RestoreOriginalCode(
  65. void
  66. )
  67. /*++
  68. Return: void
  69. Desc: This function restores the code that was injected at
  70. the entry point.
  71. --*/
  72. {
  73. NTSTATUS status;
  74. SIZE_T codeSize = sizeof(INJECTION_CODE);
  75. ULONG uOldProtect, uOldProtect2;
  76. PVOID entryPoint = g_entryPoint;
  77. //
  78. // WARNING: NtProtectVirtualMemory will change the second parameter so
  79. // we need to keep a copy of it on the stack.
  80. //
  81. status = NtProtectVirtualMemory(NtCurrentProcess(),
  82. &entryPoint,
  83. &codeSize,
  84. PAGE_READWRITE,
  85. &uOldProtect);
  86. if (!NT_SUCCESS(status)) {
  87. DPF(dlError,
  88. "[RestoreOriginalCode] Failed 0x%x to change the protection.\n",
  89. status);
  90. return;
  91. }
  92. //
  93. // Copy back the original code the the entry point.
  94. //
  95. RtlCopyMemory(g_entryPoint, g_originalCode, sizeof(INJECTION_CODE));
  96. entryPoint = g_entryPoint;
  97. codeSize = sizeof(INJECTION_CODE);
  98. status = NtProtectVirtualMemory(NtCurrentProcess(),
  99. &entryPoint,
  100. &codeSize,
  101. uOldProtect,
  102. &uOldProtect2);
  103. if (!NT_SUCCESS(status)) {
  104. DPF(dlError,
  105. "[RestoreOriginalCode] Failed 0x%x to change back the protection.\n",
  106. status);
  107. return;
  108. }
  109. }
  110. BOOL
  111. InjectNotificationCode(
  112. IN PVOID entryPoint
  113. )
  114. /*++
  115. Return: void
  116. Desc: This function places a trampoline at the EXE's entry point so
  117. that we can notify the shim DLLs that all the static linked
  118. modules have run their init routines.
  119. --*/
  120. {
  121. INJECTION_CODE injectionCode;
  122. SIZE_T nBytes;
  123. NTSTATUS status;
  124. SIZE_T codeSize = sizeof(INJECTION_CODE);
  125. ULONG uOldProtect = 0;
  126. ULONG uOldProtect2 = 0;
  127. g_entryPoint = entryPoint;
  128. InitInjectionCode(entryPoint, NotifyShimDlls, &injectionCode);
  129. status = NtProtectVirtualMemory(NtCurrentProcess(),
  130. &g_entryPoint,
  131. &codeSize,
  132. PAGE_READWRITE,
  133. &uOldProtect);
  134. if (!NT_SUCCESS(status)) {
  135. DPF(dlError,
  136. "[InjectNotificationCode] Failed 0x%x to change the protection.\n",
  137. status);
  138. return FALSE;
  139. }
  140. //
  141. // Save the code that was originally at the entry point.
  142. //
  143. RtlCopyMemory(g_originalCode, entryPoint, sizeof(INJECTION_CODE));
  144. //
  145. // Place the trampoline at the entry point.
  146. //
  147. RtlCopyMemory(entryPoint, &injectionCode, sizeof(INJECTION_CODE));
  148. g_entryPoint = entryPoint;
  149. //
  150. // Restore the protection.
  151. //
  152. codeSize = sizeof(INJECTION_CODE);
  153. status = NtProtectVirtualMemory(NtCurrentProcess(),
  154. &g_entryPoint,
  155. &codeSize,
  156. uOldProtect,
  157. &uOldProtect2);
  158. if (!NT_SUCCESS(status)) {
  159. DPF(dlError,
  160. "[InjectNotificationCode] Failed 0x%x to change back the protection.\n",
  161. status);
  162. return FALSE;
  163. }
  164. g_entryPoint = entryPoint;
  165. return TRUE;
  166. }