diff options
Diffstat (limited to 'sandbox/win/tools/finder/finder_kernel.cc')
-rw-r--r-- | sandbox/win/tools/finder/finder_kernel.cc | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/sandbox/win/tools/finder/finder_kernel.cc b/sandbox/win/tools/finder/finder_kernel.cc new file mode 100644 index 0000000..66ab454 --- /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/src/restricted_token.h" +#include "sandbox/src/restricted_token_utils.h" +#include "sandbox/tools/finder/finder.h" +#include "sandbox/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; +} |