diff options
Diffstat (limited to 'sandbox/tools/finder/finder_kernel.cc')
-rw-r--r-- | sandbox/tools/finder/finder_kernel.cc | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/sandbox/tools/finder/finder_kernel.cc b/sandbox/tools/finder/finder_kernel.cc new file mode 100644 index 0000000..4ab17e7 --- /dev/null +++ b/sandbox/tools/finder/finder_kernel.cc @@ -0,0 +1,273 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#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; +}
\ No newline at end of file |