target_interceptions.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "sandbox/win/src/target_interceptions.h"
  5. #include "base/win/static_constants.h"
  6. #include "sandbox/win/src/interception_agent.h"
  7. #include "sandbox/win/src/sandbox_factory.h"
  8. #include "sandbox/win/src/sandbox_nt_util.h"
  9. namespace sandbox {
  10. const char KERNEL32_DLL_NAME[] = "kernel32.dll";
  11. enum SectionLoadState {
  12. kBeforeKernel32,
  13. kAfterKernel32,
  14. };
  15. // Hooks NtMapViewOfSection to detect the load of DLLs. If hot patching is
  16. // required for this dll, this functions patches it.
  17. NTSTATUS WINAPI
  18. TargetNtMapViewOfSection(NtMapViewOfSectionFunction orig_MapViewOfSection,
  19. HANDLE section,
  20. HANDLE process,
  21. PVOID* base,
  22. ULONG_PTR zero_bits,
  23. SIZE_T commit_size,
  24. PLARGE_INTEGER offset,
  25. PSIZE_T view_size,
  26. SECTION_INHERIT inherit,
  27. ULONG allocation_type,
  28. ULONG protect) {
  29. NTSTATUS ret = orig_MapViewOfSection(section, process, base, zero_bits,
  30. commit_size, offset, view_size, inherit,
  31. allocation_type, protect);
  32. static SectionLoadState s_state = kBeforeKernel32;
  33. do {
  34. if (!NT_SUCCESS(ret))
  35. break;
  36. if (!IsSameProcess(process))
  37. break;
  38. // Only check for verifier.dll or kernel32.dll loading if we haven't moved
  39. // past that state yet.
  40. if (s_state == kBeforeKernel32) {
  41. const char* ansi_module_name =
  42. GetAnsiImageInfoFromModule(reinterpret_cast<HMODULE>(*base));
  43. // _strnicmp below may hit read access violations for some sections. We
  44. // find what looks like a valid export directory for a PE module but the
  45. // pointer to the module name will be pointing to invalid memory.
  46. __try {
  47. // Don't initialize the heap if verifier.dll is being loaded. This
  48. // indicates Application Verifier is enabled and we should wait until
  49. // the next module is loaded.
  50. if (ansi_module_name &&
  51. (GetNtExports()->_strnicmp(
  52. ansi_module_name, base::win::kApplicationVerifierDllName,
  53. GetNtExports()->strlen(
  54. base::win::kApplicationVerifierDllName) +
  55. 1) == 0)) {
  56. break;
  57. }
  58. if (ansi_module_name &&
  59. (GetNtExports()->_strnicmp(ansi_module_name, KERNEL32_DLL_NAME,
  60. sizeof(KERNEL32_DLL_NAME)) == 0)) {
  61. s_state = kAfterKernel32;
  62. }
  63. } __except (EXCEPTION_EXECUTE_HANDLER) {
  64. }
  65. }
  66. if (!InitHeap())
  67. break;
  68. if (!IsValidImageSection(section, base, offset, view_size))
  69. break;
  70. UINT image_flags;
  71. UNICODE_STRING* module_name =
  72. GetImageInfoFromModule(reinterpret_cast<HMODULE>(*base), &image_flags);
  73. UNICODE_STRING* file_name = GetBackingFilePath(*base);
  74. if ((!module_name) && (image_flags & MODULE_HAS_CODE)) {
  75. // If the module has no exports we retrieve the module name from the
  76. // full path of the mapped section.
  77. module_name = ExtractModuleName(file_name);
  78. }
  79. InterceptionAgent* agent = InterceptionAgent::GetInterceptionAgent();
  80. if (agent) {
  81. if (!agent->OnDllLoad(file_name, module_name, *base)) {
  82. // Interception agent is demanding to un-map the module.
  83. GetNtExports()->UnmapViewOfSection(process, *base);
  84. *base = nullptr;
  85. ret = STATUS_UNSUCCESSFUL;
  86. }
  87. }
  88. if (module_name)
  89. operator delete(module_name, NT_ALLOC);
  90. if (file_name)
  91. operator delete(file_name, NT_ALLOC);
  92. } while (false);
  93. return ret;
  94. }
  95. NTSTATUS WINAPI
  96. TargetNtUnmapViewOfSection(NtUnmapViewOfSectionFunction orig_UnmapViewOfSection,
  97. HANDLE process,
  98. PVOID base) {
  99. NTSTATUS ret = orig_UnmapViewOfSection(process, base);
  100. if (!NT_SUCCESS(ret))
  101. return ret;
  102. if (!IsSameProcess(process))
  103. return ret;
  104. InterceptionAgent* agent = InterceptionAgent::GetInterceptionAgent();
  105. if (agent)
  106. agent->OnDllUnload(base);
  107. return ret;
  108. }
  109. } // namespace sandbox