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 |