15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/sandbox_poc/pocdll/exports.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/sandbox_poc/pocdll/utils.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/tools/finder/ntundoc.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains the tests used to verify the security of handles in
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the process
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTQUERYOBJECT NtQueryObject;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTQUERYINFORMATIONFILE NtQueryInformationFile;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void POCDLL_API TestGetHandle(HANDLE log) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandleToFile handle2file;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE *output = handle2file.Translate(log, "w");
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the NTAPI functions we need
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE ntdll_handle = ::GetModuleHandle(L"ntdll.dll");
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ntdll_handle) {
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    fprintf(output, "[ERROR] Cannot load ntdll.dll. Error %ld\r\n",
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ::GetLastError());
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NtQueryObject = reinterpret_cast<NTQUERYOBJECT>(
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      GetProcAddress(ntdll_handle, "NtQueryObject"));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NtQueryInformationFile = reinterpret_cast<NTQUERYINFORMATIONFILE>(
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      GetProcAddress(ntdll_handle, "NtQueryInformationFile"));
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NtQuerySystemInformation = reinterpret_cast<NTQUERYSYSTEMINFORMATION>(
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      GetProcAddress(ntdll_handle, "NtQuerySystemInformation"));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NtQueryObject || !NtQueryInformationFile || !NtQuerySystemInformation) {
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    fprintf(output, "[ERROR] Cannot load all NT functions. Error %ld\r\n",
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ::GetLastError());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the number of handles on the system
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD buffer_size = 0;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SYSTEM_HANDLE_INFORMATION_EX temp_info;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = NtQuerySystemInformation(
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SystemHandleInformation, &temp_info, sizeof(temp_info),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &buffer_size);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buffer_size) {
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    fprintf(output, "[ERROR] Get the number of handles. Error 0x%lX\r\n",
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    status);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SYSTEM_HANDLE_INFORMATION_EX *system_handles =
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(new BYTE[buffer_size]);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = NtQuerySystemInformation(SystemHandleInformation, system_handles,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    buffer_size, &buffer_size);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (STATUS_SUCCESS != status) {
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    fprintf(output, "[ERROR] Failed to get the handle list. Error 0x%lX\r\n",
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    status);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] system_handles;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ULONG i = 0; i < system_handles->NumberOfHandles; ++i) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    USHORT h = system_handles->Information[i].Handle;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (system_handles->Information[i].ProcessId != ::GetCurrentProcessId())
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OBJECT_NAME_INFORMATION *name = NULL;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG name_size = 0;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Query the name information a first time to get the size of the name.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status = NtQueryObject(reinterpret_cast<HANDLE>(h),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ObjectNameInformation,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           name,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           name_size,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &name_size);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name_size) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = reinterpret_cast<OBJECT_NAME_INFORMATION *>(new BYTE[name_size]);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Query the name information a second time to get the name of the
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // object referenced by the handle.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status = NtQueryObject(reinterpret_cast<HANDLE>(h),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ObjectNameInformation,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             name,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             name_size,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &name_size);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PUBLIC_OBJECT_TYPE_INFORMATION *type = NULL;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG type_size = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Query the object to get the size of the object type name.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status = NtQueryObject(reinterpret_cast<HANDLE>(h),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ObjectTypeInformation,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           type,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           type_size,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &type_size);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type_size) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      type = reinterpret_cast<PUBLIC_OBJECT_TYPE_INFORMATION *>(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new BYTE[type_size]);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Query the type information a second time to get the object type
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // name.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status = NtQueryObject(reinterpret_cast<HANDLE>(h),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ObjectTypeInformation,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             type,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             type_size,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &type_size);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NtQueryObject cannot return the name for a file. In this case we
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // need to ask NtQueryInformationFile
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_NAME_INFORMATION *file_name = NULL;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type && wcsncmp(L"File", type->TypeName.Buffer,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        (type->TypeName.Length /
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(type->TypeName.Buffer[0]))) == 0)  {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This function does not return the size of the buffer. We need to
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // iterate and always increase the buffer size until the function
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // succeeds. (Or at least does not fail with STATUS_BUFFER_OVERFLOW)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ULONG size_file = MAX_PATH;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IO_STATUS_BLOCK status_block = {0};
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      do {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Delete the previous buffer create. The buffer was too small
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (file_name) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete[] reinterpret_cast<BYTE*>(file_name);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file_name = NULL;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Increase the buffer and do the call agan
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_file += MAX_PATH;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_name = reinterpret_cast<FILE_NAME_INFORMATION *>(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new BYTE[size_file]);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        status = NtQueryInformationFile(reinterpret_cast<HANDLE>(h),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &status_block,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        file_name,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        size_file,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        FileNameInformation);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } while (status == STATUS_BUFFER_OVERFLOW);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (STATUS_SUCCESS != status) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (file_name) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delete[] file_name;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file_name = NULL;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_name) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UNICODE_STRING file_name_string;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_name_string.Buffer = file_name->FileName;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_name_string.Length = (USHORT)file_name->FileNameLength;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_name_string.MaximumLength = (USHORT)file_name->FileNameLength;
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      fprintf(output, "[GRANTED] Handle 0x%4.4X Access: 0x%8.8lX "
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      "Type: %-13wZ Path: %wZ\r\n",
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      h,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      system_handles->Information[i].GrantedAccess,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      type ? &type->TypeName : NULL,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      &file_name_string);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      fprintf(output, "[GRANTED] Handle 0x%4.4X Access: 0x%8.8lX "
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      "Type: %-13wZ Path: %wZ\r\n",
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      h,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      system_handles->Information[i].GrantedAccess,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      type ? &type->TypeName : NULL,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      name ? &name->ObjectName : NULL);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete[] type;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_name) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete[] file_name;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete [] name;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (system_handles) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] system_handles;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
187