OLD | NEW |
| (Empty) |
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/restricted_token.h" | |
6 #include "sandbox/win/src/restricted_token_utils.h" | |
7 #include "sandbox/win/tools/finder/finder.h" | |
8 #include "sandbox/win/tools/finder/ntundoc.h" | |
9 | |
10 #define BUFFER_SIZE 0x800 | |
11 #define CHECKPTR(x) if (!x) return ::GetLastError() | |
12 | |
13 // NT API | |
14 NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject; | |
15 NTOPENDIRECTORYOBJECT NtOpenDirectoryObject; | |
16 NTOPENEVENT NtOpenEvent; | |
17 NTOPENJOBOBJECT NtOpenJobObject; | |
18 NTOPENKEYEDEVENT NtOpenKeyedEvent; | |
19 NTOPENMUTANT NtOpenMutant; | |
20 NTOPENSECTION NtOpenSection; | |
21 NTOPENSEMAPHORE NtOpenSemaphore; | |
22 NTOPENSYMBOLICLINKOBJECT NtOpenSymbolicLinkObject; | |
23 NTOPENTIMER NtOpenTimer; | |
24 NTOPENFILE NtOpenFile; | |
25 NTCLOSE NtClose; | |
26 | |
27 DWORD Finder::InitNT() { | |
28 HMODULE ntdll_handle = ::LoadLibrary(L"ntdll.dll"); | |
29 CHECKPTR(ntdll_handle); | |
30 | |
31 NtOpenSymbolicLinkObject = (NTOPENSYMBOLICLINKOBJECT) ::GetProcAddress( | |
32 ntdll_handle, "NtOpenSymbolicLinkObject"); | |
33 CHECKPTR(NtOpenSymbolicLinkObject); | |
34 | |
35 NtQueryDirectoryObject = (NTQUERYDIRECTORYOBJECT) ::GetProcAddress( | |
36 ntdll_handle, "NtQueryDirectoryObject"); | |
37 CHECKPTR(NtQueryDirectoryObject); | |
38 | |
39 NtOpenDirectoryObject = (NTOPENDIRECTORYOBJECT) ::GetProcAddress( | |
40 ntdll_handle, "NtOpenDirectoryObject"); | |
41 CHECKPTR(NtOpenDirectoryObject); | |
42 | |
43 NtOpenKeyedEvent = (NTOPENKEYEDEVENT) ::GetProcAddress( | |
44 ntdll_handle, "NtOpenKeyedEvent"); | |
45 CHECKPTR(NtOpenKeyedEvent); | |
46 | |
47 NtOpenJobObject = (NTOPENJOBOBJECT) ::GetProcAddress( | |
48 ntdll_handle, "NtOpenJobObject"); | |
49 CHECKPTR(NtOpenJobObject); | |
50 | |
51 NtOpenSemaphore = (NTOPENSEMAPHORE) ::GetProcAddress( | |
52 ntdll_handle, "NtOpenSemaphore"); | |
53 CHECKPTR(NtOpenSemaphore); | |
54 | |
55 NtOpenSection = (NTOPENSECTION) ::GetProcAddress( | |
56 ntdll_handle, "NtOpenSection"); | |
57 CHECKPTR(NtOpenSection); | |
58 | |
59 NtOpenMutant= (NTOPENMUTANT) ::GetProcAddress(ntdll_handle, "NtOpenMutant"); | |
60 CHECKPTR(NtOpenMutant); | |
61 | |
62 NtOpenEvent = (NTOPENEVENT) ::GetProcAddress(ntdll_handle, "NtOpenEvent"); | |
63 CHECKPTR(NtOpenEvent); | |
64 | |
65 NtOpenTimer = (NTOPENTIMER) ::GetProcAddress(ntdll_handle, "NtOpenTimer"); | |
66 CHECKPTR(NtOpenTimer); | |
67 | |
68 NtOpenFile = (NTOPENFILE) ::GetProcAddress(ntdll_handle, "NtOpenFile"); | |
69 CHECKPTR(NtOpenFile); | |
70 | |
71 NtClose = (NTCLOSE) ::GetProcAddress(ntdll_handle, "NtClose"); | |
72 CHECKPTR(NtClose); | |
73 | |
74 return ERROR_SUCCESS; | |
75 } | |
76 | |
77 DWORD Finder::ParseKernelObjects(ATL::CString path) { | |
78 UNICODE_STRING unicode_str; | |
79 unicode_str.Length = (USHORT)path.GetLength()*2; | |
80 unicode_str.MaximumLength = (USHORT)path.GetLength()*2+2; | |
81 unicode_str.Buffer = path.GetBuffer(); | |
82 | |
83 OBJECT_ATTRIBUTES path_attributes; | |
84 InitializeObjectAttributes(&path_attributes, | |
85 &unicode_str, | |
86 0, // No Attributes | |
87 NULL, // No Root Directory | |
88 NULL); // No Security Descriptor | |
89 | |
90 | |
91 DWORD object_index = 0; | |
92 DWORD data_written = 0; | |
93 | |
94 // TODO(nsylvain): Do not use BUFFER_SIZE. Try to get the size | |
95 // dynamically. | |
96 OBJDIR_INFORMATION *object_directory_info = | |
97 (OBJDIR_INFORMATION*) ::HeapAlloc(GetProcessHeap(), | |
98 0, | |
99 BUFFER_SIZE); | |
100 | |
101 HANDLE file_handle; | |
102 NTSTATUS status_code = NtOpenDirectoryObject(&file_handle, | |
103 DIRECTORY_QUERY, | |
104 &path_attributes); | |
105 if (status_code != 0) | |
106 return ERROR_UNIDENTIFIED_ERROR; | |
107 | |
108 status_code = NtQueryDirectoryObject(file_handle, | |
109 object_directory_info, | |
110 BUFFER_SIZE, | |
111 TRUE, // Get Next Index | |
112 TRUE, // Ignore Input Index | |
113 &object_index, | |
114 &data_written); | |
115 | |
116 if (status_code != 0) | |
117 return ERROR_UNIDENTIFIED_ERROR; | |
118 | |
119 while (NtQueryDirectoryObject(file_handle, object_directory_info, | |
120 BUFFER_SIZE, TRUE, FALSE, &object_index, | |
121 &data_written) == 0 ) { | |
122 ATL::CString cur_path(object_directory_info->ObjectName.Buffer, | |
123 object_directory_info->ObjectName.Length / sizeof(WCHAR)); | |
124 | |
125 ATL::CString cur_type(object_directory_info->ObjectTypeName.Buffer, | |
126 object_directory_info->ObjectTypeName.Length / sizeof(WCHAR)); | |
127 | |
128 ATL::CString new_path; | |
129 if (path == L"\\") { | |
130 new_path = path + cur_path; | |
131 } else { | |
132 new_path = path + L"\\" + cur_path; | |
133 } | |
134 | |
135 TestKernelObjectAccess(new_path, cur_type); | |
136 | |
137 // Call the function recursively for all subdirectories | |
138 if (cur_type == L"Directory") { | |
139 ParseKernelObjects(new_path); | |
140 } | |
141 } | |
142 | |
143 NtClose(file_handle); | |
144 return ERROR_SUCCESS; | |
145 } | |
146 | |
147 DWORD Finder::TestKernelObjectAccess(ATL::CString path, ATL::CString type) { | |
148 Impersonater impersonate(token_handle_); | |
149 | |
150 kernel_object_stats_[PARSE]++; | |
151 | |
152 NTGENERICOPEN func = NULL; | |
153 GetFunctionForType(type, &func); | |
154 | |
155 if (!func) { | |
156 kernel_object_stats_[BROKEN]++; | |
157 Output(OBJ_ERR, type + L" Unsupported", path); | |
158 return ERROR_UNSUPPORTED_TYPE; | |
159 } | |
160 | |
161 UNICODE_STRING unicode_str; | |
162 unicode_str.Length = (USHORT)path.GetLength()*2; | |
163 unicode_str.MaximumLength = (USHORT)path.GetLength()*2+2; | |
164 unicode_str.Buffer = path.GetBuffer(); | |
165 | |
166 OBJECT_ATTRIBUTES path_attributes; | |
167 InitializeObjectAttributes(&path_attributes, | |
168 &unicode_str, | |
169 0, // No Attributes | |
170 NULL, // No Root Directory | |
171 NULL); // No Security Descriptor | |
172 | |
173 HANDLE handle; | |
174 NTSTATUS status_code = 0; | |
175 | |
176 if (access_type_ & kTestForAll) { | |
177 status_code = NtGenericOpen(GENERIC_ALL, &path_attributes, func, &handle); | |
178 if (STATUS_SUCCESS == status_code) { | |
179 kernel_object_stats_[ALL]++; | |
180 Output(OBJ, L"R/W", path); | |
181 NtClose(handle); | |
182 return GENERIC_ALL; | |
183 } else if (status_code != EXCEPTION_ACCESS_VIOLATION && | |
184 status_code != STATUS_ACCESS_DENIED) { | |
185 Output(OBJ_ERR, status_code, path); | |
186 kernel_object_stats_[BROKEN]++; | |
187 } | |
188 } | |
189 | |
190 if (access_type_ & kTestForWrite) { | |
191 status_code = NtGenericOpen(GENERIC_WRITE, &path_attributes, func, &handle); | |
192 if (STATUS_SUCCESS == status_code) { | |
193 kernel_object_stats_[WRITE]++; | |
194 Output(OBJ, L"W", path); | |
195 NtClose(handle); | |
196 return GENERIC_WRITE; | |
197 } else if (status_code != EXCEPTION_ACCESS_VIOLATION && | |
198 status_code != STATUS_ACCESS_DENIED) { | |
199 Output(OBJ_ERR, status_code, path); | |
200 kernel_object_stats_[BROKEN]++; | |
201 } | |
202 } | |
203 | |
204 if (access_type_ & kTestForRead) { | |
205 status_code = NtGenericOpen(GENERIC_READ, &path_attributes, func, &handle); | |
206 if (STATUS_SUCCESS == status_code) { | |
207 kernel_object_stats_[READ]++; | |
208 Output(OBJ, L"R", path); | |
209 NtClose(handle); | |
210 return GENERIC_READ; | |
211 } else if (status_code != EXCEPTION_ACCESS_VIOLATION && | |
212 status_code != STATUS_ACCESS_DENIED) { | |
213 Output(OBJ_ERR, status_code, path); | |
214 kernel_object_stats_[BROKEN]++; | |
215 } | |
216 } | |
217 | |
218 return 0; | |
219 } | |
220 | |
221 NTSTATUS Finder::NtGenericOpen(ACCESS_MASK desired_access, | |
222 OBJECT_ATTRIBUTES *object_attributes, | |
223 NTGENERICOPEN func_to_call, | |
224 HANDLE *handle) { | |
225 return func_to_call(handle, desired_access, object_attributes); | |
226 } | |
227 | |
228 bool Finder::GetFunctionForType(ATL::CString type, | |
229 NTGENERICOPEN * func_to_call) { | |
230 NTGENERICOPEN func = NULL; | |
231 | |
232 if (type == L"Event") func = NtOpenEvent; | |
233 else if (type == L"Job") func = NtOpenJobObject; | |
234 else if (type == L"KeyedEvent") func = NtOpenKeyedEvent; | |
235 else if (type == L"Mutant") func = NtOpenMutant; | |
236 else if (type == L"Section") func = NtOpenSection; | |
237 else if (type == L"Semaphore") func = NtOpenSemaphore; | |
238 else if (type == L"Timer") func = NtOpenTimer; | |
239 else if (type == L"SymbolicLink") func = NtOpenSymbolicLinkObject; | |
240 else if (type == L"Directory") func = NtOpenDirectoryObject; | |
241 | |
242 if (func) { | |
243 *func_to_call = func; | |
244 return true; | |
245 } | |
246 | |
247 return false; | |
248 } | |
OLD | NEW |