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