summaryrefslogtreecommitdiffstats
path: root/sandbox/tools/finder/finder_kernel.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/tools/finder/finder_kernel.cc')
-rw-r--r--sandbox/tools/finder/finder_kernel.cc273
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