Index: sandbox/win/tools/finder/finder_kernel.cc |
diff --git a/sandbox/win/tools/finder/finder_kernel.cc b/sandbox/win/tools/finder/finder_kernel.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..430a4c08ab478519590e6275d0298379095a7af5 |
--- /dev/null |
+++ b/sandbox/win/tools/finder/finder_kernel.cc |
@@ -0,0 +1,248 @@ |
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sandbox/win/src/restricted_token.h" |
+#include "sandbox/win/src/restricted_token_utils.h" |
+#include "sandbox/win/tools/finder/finder.h" |
+#include "sandbox/win/tools/finder/ntundoc.h" |
+ |
+#define BUFFER_SIZE 0x800 |
+#define CHECKPTR(x) if (!x) return ::GetLastError() |
+ |
+// NT API |
+NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject; |
+NTOPENDIRECTORYOBJECT NtOpenDirectoryObject; |
+NTOPENEVENT NtOpenEvent; |
+NTOPENJOBOBJECT NtOpenJobObject; |
+NTOPENKEYEDEVENT NtOpenKeyedEvent; |
+NTOPENMUTANT NtOpenMutant; |
+NTOPENSECTION NtOpenSection; |
+NTOPENSEMAPHORE NtOpenSemaphore; |
+NTOPENSYMBOLICLINKOBJECT NtOpenSymbolicLinkObject; |
+NTOPENTIMER NtOpenTimer; |
+NTOPENFILE NtOpenFile; |
+NTCLOSE NtClose; |
+ |
+DWORD Finder::InitNT() { |
+ HMODULE ntdll_handle = ::LoadLibrary(L"ntdll.dll"); |
+ CHECKPTR(ntdll_handle); |
+ |
+ NtOpenSymbolicLinkObject = (NTOPENSYMBOLICLINKOBJECT) ::GetProcAddress( |
+ ntdll_handle, "NtOpenSymbolicLinkObject"); |
+ CHECKPTR(NtOpenSymbolicLinkObject); |
+ |
+ NtQueryDirectoryObject = (NTQUERYDIRECTORYOBJECT) ::GetProcAddress( |
+ ntdll_handle, "NtQueryDirectoryObject"); |
+ CHECKPTR(NtQueryDirectoryObject); |
+ |
+ NtOpenDirectoryObject = (NTOPENDIRECTORYOBJECT) ::GetProcAddress( |
+ ntdll_handle, "NtOpenDirectoryObject"); |
+ CHECKPTR(NtOpenDirectoryObject); |
+ |
+ NtOpenKeyedEvent = (NTOPENKEYEDEVENT) ::GetProcAddress( |
+ ntdll_handle, "NtOpenKeyedEvent"); |
+ CHECKPTR(NtOpenKeyedEvent); |
+ |
+ NtOpenJobObject = (NTOPENJOBOBJECT) ::GetProcAddress( |
+ ntdll_handle, "NtOpenJobObject"); |
+ CHECKPTR(NtOpenJobObject); |
+ |
+ NtOpenSemaphore = (NTOPENSEMAPHORE) ::GetProcAddress( |
+ ntdll_handle, "NtOpenSemaphore"); |
+ CHECKPTR(NtOpenSemaphore); |
+ |
+ NtOpenSection = (NTOPENSECTION) ::GetProcAddress( |
+ ntdll_handle, "NtOpenSection"); |
+ CHECKPTR(NtOpenSection); |
+ |
+ NtOpenMutant= (NTOPENMUTANT) ::GetProcAddress(ntdll_handle, "NtOpenMutant"); |
+ CHECKPTR(NtOpenMutant); |
+ |
+ NtOpenEvent = (NTOPENEVENT) ::GetProcAddress(ntdll_handle, "NtOpenEvent"); |
+ CHECKPTR(NtOpenEvent); |
+ |
+ NtOpenTimer = (NTOPENTIMER) ::GetProcAddress(ntdll_handle, "NtOpenTimer"); |
+ CHECKPTR(NtOpenTimer); |
+ |
+ NtOpenFile = (NTOPENFILE) ::GetProcAddress(ntdll_handle, "NtOpenFile"); |
+ CHECKPTR(NtOpenFile); |
+ |
+ NtClose = (NTCLOSE) ::GetProcAddress(ntdll_handle, "NtClose"); |
+ CHECKPTR(NtClose); |
+ |
+ return ERROR_SUCCESS; |
+} |
+ |
+DWORD Finder::ParseKernelObjects(ATL::CString path) { |
+ UNICODE_STRING unicode_str; |
+ unicode_str.Length = (USHORT)path.GetLength()*2; |
+ unicode_str.MaximumLength = (USHORT)path.GetLength()*2+2; |
+ unicode_str.Buffer = path.GetBuffer(); |
+ |
+ OBJECT_ATTRIBUTES path_attributes; |
+ InitializeObjectAttributes(&path_attributes, |
+ &unicode_str, |
+ 0, // No Attributes |
+ NULL, // No Root Directory |
+ NULL); // No Security Descriptor |
+ |
+ |
+ DWORD object_index = 0; |
+ DWORD data_written = 0; |
+ |
+ // TODO(nsylvain): Do not use BUFFER_SIZE. Try to get the size |
+ // dynamically. |
+ OBJDIR_INFORMATION *object_directory_info = |
+ (OBJDIR_INFORMATION*) ::HeapAlloc(GetProcessHeap(), |
+ 0, |
+ BUFFER_SIZE); |
+ |
+ HANDLE file_handle; |
+ NTSTATUS status_code = NtOpenDirectoryObject(&file_handle, |
+ DIRECTORY_QUERY, |
+ &path_attributes); |
+ if (status_code != 0) |
+ return ERROR_UNIDENTIFIED_ERROR; |
+ |
+ status_code = NtQueryDirectoryObject(file_handle, |
+ object_directory_info, |
+ BUFFER_SIZE, |
+ TRUE, // Get Next Index |
+ TRUE, // Ignore Input Index |
+ &object_index, |
+ &data_written); |
+ |
+ if (status_code != 0) |
+ return ERROR_UNIDENTIFIED_ERROR; |
+ |
+ while (NtQueryDirectoryObject(file_handle, object_directory_info, |
+ BUFFER_SIZE, TRUE, FALSE, &object_index, |
+ &data_written) == 0 ) { |
+ ATL::CString cur_path(object_directory_info->ObjectName.Buffer, |
+ object_directory_info->ObjectName.Length / sizeof(WCHAR)); |
+ |
+ ATL::CString cur_type(object_directory_info->ObjectTypeName.Buffer, |
+ object_directory_info->ObjectTypeName.Length / sizeof(WCHAR)); |
+ |
+ ATL::CString new_path; |
+ if (path == L"\\") { |
+ new_path = path + cur_path; |
+ } else { |
+ new_path = path + L"\\" + cur_path; |
+ } |
+ |
+ TestKernelObjectAccess(new_path, cur_type); |
+ |
+ // Call the function recursively for all subdirectories |
+ if (cur_type == L"Directory") { |
+ ParseKernelObjects(new_path); |
+ } |
+ } |
+ |
+ NtClose(file_handle); |
+ return ERROR_SUCCESS; |
+} |
+ |
+DWORD Finder::TestKernelObjectAccess(ATL::CString path, ATL::CString type) { |
+ Impersonater impersonate(token_handle_); |
+ |
+ kernel_object_stats_[PARSE]++; |
+ |
+ NTGENERICOPEN func = NULL; |
+ GetFunctionForType(type, &func); |
+ |
+ if (!func) { |
+ kernel_object_stats_[BROKEN]++; |
+ Output(OBJ_ERR, type + L" Unsupported", path); |
+ return ERROR_UNSUPPORTED_TYPE; |
+ } |
+ |
+ UNICODE_STRING unicode_str; |
+ unicode_str.Length = (USHORT)path.GetLength()*2; |
+ unicode_str.MaximumLength = (USHORT)path.GetLength()*2+2; |
+ unicode_str.Buffer = path.GetBuffer(); |
+ |
+ OBJECT_ATTRIBUTES path_attributes; |
+ InitializeObjectAttributes(&path_attributes, |
+ &unicode_str, |
+ 0, // No Attributes |
+ NULL, // No Root Directory |
+ NULL); // No Security Descriptor |
+ |
+ HANDLE handle; |
+ NTSTATUS status_code = 0; |
+ |
+ if (access_type_ & kTestForAll) { |
+ status_code = NtGenericOpen(GENERIC_ALL, &path_attributes, func, &handle); |
+ if (STATUS_SUCCESS == status_code) { |
+ kernel_object_stats_[ALL]++; |
+ Output(OBJ, L"R/W", path); |
+ NtClose(handle); |
+ return GENERIC_ALL; |
+ } else if (status_code != EXCEPTION_ACCESS_VIOLATION && |
+ status_code != STATUS_ACCESS_DENIED) { |
+ Output(OBJ_ERR, status_code, path); |
+ kernel_object_stats_[BROKEN]++; |
+ } |
+ } |
+ |
+ if (access_type_ & kTestForWrite) { |
+ status_code = NtGenericOpen(GENERIC_WRITE, &path_attributes, func, &handle); |
+ if (STATUS_SUCCESS == status_code) { |
+ kernel_object_stats_[WRITE]++; |
+ Output(OBJ, L"W", path); |
+ NtClose(handle); |
+ return GENERIC_WRITE; |
+ } else if (status_code != EXCEPTION_ACCESS_VIOLATION && |
+ status_code != STATUS_ACCESS_DENIED) { |
+ Output(OBJ_ERR, status_code, path); |
+ kernel_object_stats_[BROKEN]++; |
+ } |
+ } |
+ |
+ if (access_type_ & kTestForRead) { |
+ status_code = NtGenericOpen(GENERIC_READ, &path_attributes, func, &handle); |
+ if (STATUS_SUCCESS == status_code) { |
+ kernel_object_stats_[READ]++; |
+ Output(OBJ, L"R", path); |
+ NtClose(handle); |
+ return GENERIC_READ; |
+ } else if (status_code != EXCEPTION_ACCESS_VIOLATION && |
+ status_code != STATUS_ACCESS_DENIED) { |
+ Output(OBJ_ERR, status_code, path); |
+ kernel_object_stats_[BROKEN]++; |
+ } |
+ } |
+ |
+ return 0; |
+} |
+ |
+NTSTATUS Finder::NtGenericOpen(ACCESS_MASK desired_access, |
+ OBJECT_ATTRIBUTES *object_attributes, |
+ NTGENERICOPEN func_to_call, |
+ HANDLE *handle) { |
+ return func_to_call(handle, desired_access, object_attributes); |
+} |
+ |
+bool Finder::GetFunctionForType(ATL::CString type, |
+ NTGENERICOPEN * func_to_call) { |
+ NTGENERICOPEN func = NULL; |
+ |
+ if (type == L"Event") func = NtOpenEvent; |
+ else if (type == L"Job") func = NtOpenJobObject; |
+ else if (type == L"KeyedEvent") func = NtOpenKeyedEvent; |
+ else if (type == L"Mutant") func = NtOpenMutant; |
+ else if (type == L"Section") func = NtOpenSection; |
+ else if (type == L"Semaphore") func = NtOpenSemaphore; |
+ else if (type == L"Timer") func = NtOpenTimer; |
+ else if (type == L"SymbolicLink") func = NtOpenSymbolicLinkObject; |
+ else if (type == L"Directory") func = NtOpenDirectoryObject; |
+ |
+ if (func) { |
+ *func_to_call = func; |
+ return true; |
+ } |
+ |
+ return false; |
+} |