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.
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"
10 #define BUFFER_SIZE 0x800
11 #define CHECKPTR(x) if (!x) return ::GetLastError()
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
;
27 DWORD
Finder::InitNT() {
28 HMODULE ntdll_handle
= ::LoadLibrary(L
"ntdll.dll");
29 CHECKPTR(ntdll_handle
);
31 NtOpenSymbolicLinkObject
= (NTOPENSYMBOLICLINKOBJECT
) ::GetProcAddress(
32 ntdll_handle
, "NtOpenSymbolicLinkObject");
33 CHECKPTR(NtOpenSymbolicLinkObject
);
35 NtQueryDirectoryObject
= (NTQUERYDIRECTORYOBJECT
) ::GetProcAddress(
36 ntdll_handle
, "NtQueryDirectoryObject");
37 CHECKPTR(NtQueryDirectoryObject
);
39 NtOpenDirectoryObject
= (NTOPENDIRECTORYOBJECT
) ::GetProcAddress(
40 ntdll_handle
, "NtOpenDirectoryObject");
41 CHECKPTR(NtOpenDirectoryObject
);
43 NtOpenKeyedEvent
= (NTOPENKEYEDEVENT
) ::GetProcAddress(
44 ntdll_handle
, "NtOpenKeyedEvent");
45 CHECKPTR(NtOpenKeyedEvent
);
47 NtOpenJobObject
= (NTOPENJOBOBJECT
) ::GetProcAddress(
48 ntdll_handle
, "NtOpenJobObject");
49 CHECKPTR(NtOpenJobObject
);
51 NtOpenSemaphore
= (NTOPENSEMAPHORE
) ::GetProcAddress(
52 ntdll_handle
, "NtOpenSemaphore");
53 CHECKPTR(NtOpenSemaphore
);
55 NtOpenSection
= (NTOPENSECTION
) ::GetProcAddress(
56 ntdll_handle
, "NtOpenSection");
57 CHECKPTR(NtOpenSection
);
59 NtOpenMutant
= (NTOPENMUTANT
) ::GetProcAddress(ntdll_handle
, "NtOpenMutant");
60 CHECKPTR(NtOpenMutant
);
62 NtOpenEvent
= (NTOPENEVENT
) ::GetProcAddress(ntdll_handle
, "NtOpenEvent");
63 CHECKPTR(NtOpenEvent
);
65 NtOpenTimer
= (NTOPENTIMER
) ::GetProcAddress(ntdll_handle
, "NtOpenTimer");
66 CHECKPTR(NtOpenTimer
);
68 NtOpenFile
= (NTOPENFILE
) ::GetProcAddress(ntdll_handle
, "NtOpenFile");
71 NtClose
= (NTCLOSE
) ::GetProcAddress(ntdll_handle
, "NtClose");
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();
83 OBJECT_ATTRIBUTES path_attributes
;
84 InitializeObjectAttributes(&path_attributes
,
87 NULL
, // No Root Directory
88 NULL
); // No Security Descriptor
91 DWORD object_index
= 0;
92 DWORD data_written
= 0;
94 // TODO(nsylvain): Do not use BUFFER_SIZE. Try to get the size
96 OBJDIR_INFORMATION
*object_directory_info
=
97 (OBJDIR_INFORMATION
*) ::HeapAlloc(GetProcessHeap(),
102 NTSTATUS status_code
= NtOpenDirectoryObject(&file_handle
,
105 if (status_code
!= 0)
106 return ERROR_UNIDENTIFIED_ERROR
;
108 status_code
= NtQueryDirectoryObject(file_handle
,
109 object_directory_info
,
111 TRUE
, // Get Next Index
112 TRUE
, // Ignore Input Index
116 if (status_code
!= 0)
117 return ERROR_UNIDENTIFIED_ERROR
;
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
));
125 ATL::CString
cur_type(object_directory_info
->ObjectTypeName
.Buffer
,
126 object_directory_info
->ObjectTypeName
.Length
/ sizeof(WCHAR
));
128 ATL::CString new_path
;
130 new_path
= path
+ cur_path
;
132 new_path
= path
+ L
"\\" + cur_path
;
135 TestKernelObjectAccess(new_path
, cur_type
);
137 // Call the function recursively for all subdirectories
138 if (cur_type
== L
"Directory") {
139 ParseKernelObjects(new_path
);
143 NtClose(file_handle
);
144 return ERROR_SUCCESS
;
147 DWORD
Finder::TestKernelObjectAccess(ATL::CString path
, ATL::CString type
) {
148 Impersonater
impersonate(token_handle_
);
150 kernel_object_stats_
[PARSE
]++;
152 NTGENERICOPEN func
= NULL
;
153 GetFunctionForType(type
, &func
);
156 kernel_object_stats_
[BROKEN
]++;
157 Output(OBJ_ERR
, type
+ L
" Unsupported", path
);
158 return ERROR_UNSUPPORTED_TYPE
;
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();
166 OBJECT_ATTRIBUTES path_attributes
;
167 InitializeObjectAttributes(&path_attributes
,
170 NULL
, // No Root Directory
171 NULL
); // No Security Descriptor
174 NTSTATUS status_code
= 0;
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
);
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
]++;
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
);
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
]++;
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
);
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
]++;
221 NTSTATUS
Finder::NtGenericOpen(ACCESS_MASK desired_access
,
222 OBJECT_ATTRIBUTES
*object_attributes
,
223 NTGENERICOPEN func_to_call
,
225 return func_to_call(handle
, desired_access
, object_attributes
);
228 bool Finder::GetFunctionForType(ATL::CString type
,
229 NTGENERICOPEN
* func_to_call
) {
230 NTGENERICOPEN func
= NULL
;
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
;
243 *func_to_call
= func
;