| 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;
|
| +}
|
|
|