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
5 #include "sandbox/win/src/target_interceptions.h"
6
7 #include "sandbox/win/src/interception_agent.h"
8 #include "sandbox/win/src/sandbox_factory.h"
9 #include "sandbox/win/src/sandbox_nt_util.h"
10 #include "sandbox/win/src/target_services.h"
11
12 namespace sandbox {
13
14 SANDBOX_INTERCEPT NtExports g_nt;
15
16 const char VERIFIER_DLL_NAME[] = "verifier.dll";
17 const char KERNEL32_DLL_NAME[] = "kernel32.dll";
18
19 enum SectionLoadState {
20 kBeforeKernel32,
21 kAfterKernel32,
22 };
23
24 // Hooks NtMapViewOfSection to detect the load of DLLs. If hot patching is
25 // required for this dll, this functions patches it.
26 NTSTATUS WINAPI
TargetNtMapViewOfSection(NtMapViewOfSectionFunction orig_MapViewOfSection,HANDLE section,HANDLE process,PVOID * base,ULONG_PTR zero_bits,SIZE_T commit_size,PLARGE_INTEGER offset,PSIZE_T view_size,SECTION_INHERIT inherit,ULONG allocation_type,ULONG protect)27 TargetNtMapViewOfSection(NtMapViewOfSectionFunction orig_MapViewOfSection,
28 HANDLE section,
29 HANDLE process,
30 PVOID* base,
31 ULONG_PTR zero_bits,
32 SIZE_T commit_size,
33 PLARGE_INTEGER offset,
34 PSIZE_T view_size,
35 SECTION_INHERIT inherit,
36 ULONG allocation_type,
37 ULONG protect) {
38 NTSTATUS ret = orig_MapViewOfSection(section, process, base, zero_bits,
39 commit_size, offset, view_size, inherit,
40 allocation_type, protect);
41 static SectionLoadState s_state = kBeforeKernel32;
42
43 do {
44 if (!NT_SUCCESS(ret))
45 break;
46
47 if (!IsSameProcess(process))
48 break;
49
50 // Only check for verifier.dll or kernel32.dll loading if we haven't moved
51 // past that state yet.
52 if (s_state == kBeforeKernel32) {
53 const char* ansi_module_name =
54 GetAnsiImageInfoFromModule(reinterpret_cast<HMODULE>(*base));
55
56 // _strnicmp below may hit read access violations for some sections. We
57 // find what looks like a valid export directory for a PE module but the
58 // pointer to the module name will be pointing to invalid memory.
59 __try {
60 // Don't initialize the heap if verifier.dll is being loaded. This
61 // indicates Application Verifier is enabled and we should wait until
62 // the next module is loaded.
63 if (ansi_module_name &&
64 (g_nt._strnicmp(ansi_module_name, VERIFIER_DLL_NAME,
65 sizeof(VERIFIER_DLL_NAME)) == 0))
66 break;
67
68 if (ansi_module_name &&
69 (g_nt._strnicmp(ansi_module_name, KERNEL32_DLL_NAME,
70 sizeof(KERNEL32_DLL_NAME)) == 0)) {
71 SandboxFactory::GetTargetServices()->GetState()->SetKernel32Loaded();
72 s_state = kAfterKernel32;
73 }
74 } __except (EXCEPTION_EXECUTE_HANDLER) {
75 }
76 }
77
78 if (!InitHeap())
79 break;
80
81 if (!IsValidImageSection(section, base, offset, view_size))
82 break;
83
84 UINT image_flags;
85 UNICODE_STRING* module_name =
86 GetImageInfoFromModule(reinterpret_cast<HMODULE>(*base), &image_flags);
87 UNICODE_STRING* file_name = GetBackingFilePath(*base);
88
89 if ((!module_name) && (image_flags & MODULE_HAS_CODE)) {
90 // If the module has no exports we retrieve the module name from the
91 // full path of the mapped section.
92 module_name = ExtractModuleName(file_name);
93 }
94
95 InterceptionAgent* agent = InterceptionAgent::GetInterceptionAgent();
96
97 if (agent) {
98 if (!agent->OnDllLoad(file_name, module_name, *base)) {
99 // Interception agent is demanding to un-map the module.
100 g_nt.UnmapViewOfSection(process, *base);
101 *base = nullptr;
102 ret = STATUS_UNSUCCESSFUL;
103 }
104 }
105
106 if (module_name)
107 operator delete(module_name, NT_ALLOC);
108
109 if (file_name)
110 operator delete(file_name, NT_ALLOC);
111
112 } while (false);
113
114 return ret;
115 }
116
117 NTSTATUS WINAPI
TargetNtUnmapViewOfSection(NtUnmapViewOfSectionFunction orig_UnmapViewOfSection,HANDLE process,PVOID base)118 TargetNtUnmapViewOfSection(NtUnmapViewOfSectionFunction orig_UnmapViewOfSection,
119 HANDLE process,
120 PVOID base) {
121 NTSTATUS ret = orig_UnmapViewOfSection(process, base);
122
123 if (!NT_SUCCESS(ret))
124 return ret;
125
126 if (!IsSameProcess(process))
127 return ret;
128
129 InterceptionAgent* agent = InterceptionAgent::GetInterceptionAgent();
130
131 if (agent)
132 agent->OnDllUnload(base);
133
134 return ret;
135 }
136
137 } // namespace sandbox
138