Home | History | Annotate | Download | only in pocdll
      1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "sandbox/win/sandbox_poc/pocdll/exports.h"
      6 #include "sandbox/win/sandbox_poc/pocdll/utils.h"
      7 #include "sandbox/win/tools/finder/ntundoc.h"
      8 
      9 // This file contains the tests used to verify the security of handles in
     10 // the process
     11 
     12 NTQUERYOBJECT NtQueryObject;
     13 NTQUERYINFORMATIONFILE NtQueryInformationFile;
     14 NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
     15 
     16 void POCDLL_API TestGetHandle(HANDLE log) {
     17   HandleToFile handle2file;
     18   FILE *output = handle2file.Translate(log, "w");
     19 
     20   // Initialize the NTAPI functions we need
     21   HMODULE ntdll_handle = ::GetModuleHandle(L"ntdll.dll");
     22   if (!ntdll_handle) {
     23     fprintf(output, "[ERROR] Cannot load ntdll.dll. Error %d\r\n",
     24             ::GetLastError());
     25     return;
     26   }
     27 
     28   NtQueryObject = reinterpret_cast<NTQUERYOBJECT>(
     29                       GetProcAddress(ntdll_handle, "NtQueryObject"));
     30   NtQueryInformationFile = reinterpret_cast<NTQUERYINFORMATIONFILE>(
     31                       GetProcAddress(ntdll_handle, "NtQueryInformationFile"));
     32   NtQuerySystemInformation = reinterpret_cast<NTQUERYSYSTEMINFORMATION>(
     33                       GetProcAddress(ntdll_handle, "NtQuerySystemInformation"));
     34 
     35   if (!NtQueryObject || !NtQueryInformationFile || !NtQuerySystemInformation) {
     36     fprintf(output, "[ERROR] Cannot load all NT functions. Error %d\r\n",
     37                     ::GetLastError());
     38     return;
     39   }
     40 
     41   // Get the number of handles on the system
     42   DWORD buffer_size = 0;
     43   SYSTEM_HANDLE_INFORMATION_EX temp_info;
     44   NTSTATUS status = NtQuerySystemInformation(
     45       SystemHandleInformation, &temp_info, sizeof(temp_info),
     46       &buffer_size);
     47   if (!buffer_size) {
     48     fprintf(output, "[ERROR] Get the number of handles. Error 0x%X\r\n",
     49                     status);
     50     return;
     51   }
     52 
     53   SYSTEM_HANDLE_INFORMATION_EX *system_handles =
     54       reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(new BYTE[buffer_size]);
     55 
     56   status = NtQuerySystemInformation(SystemHandleInformation, system_handles,
     57                                     buffer_size, &buffer_size);
     58   if (STATUS_SUCCESS != status) {
     59     fprintf(output, "[ERROR] Failed to get the handle list. Error 0x%X\r\n",
     60                     status);
     61     delete [] system_handles;
     62     return;
     63   }
     64 
     65   for (ULONG i = 0; i < system_handles->NumberOfHandles; ++i) {
     66     USHORT h = system_handles->Information[i].Handle;
     67     if (system_handles->Information[i].ProcessId != ::GetCurrentProcessId())
     68       continue;
     69 
     70     OBJECT_NAME_INFORMATION *name = NULL;
     71     ULONG name_size = 0;
     72     // Query the name information a first time to get the size of the name.
     73     status = NtQueryObject(reinterpret_cast<HANDLE>(h),
     74                            ObjectNameInformation,
     75                            name,
     76                            name_size,
     77                            &name_size);
     78 
     79     if (name_size) {
     80       name = reinterpret_cast<OBJECT_NAME_INFORMATION *>(new BYTE[name_size]);
     81 
     82       // Query the name information a second time to get the name of the
     83       // object referenced by the handle.
     84       status = NtQueryObject(reinterpret_cast<HANDLE>(h),
     85                              ObjectNameInformation,
     86                              name,
     87                              name_size,
     88                              &name_size);
     89     }
     90 
     91     PUBLIC_OBJECT_TYPE_INFORMATION *type = NULL;
     92     ULONG type_size = 0;
     93 
     94     // Query the object to get the size of the object type name.
     95     status = NtQueryObject(reinterpret_cast<HANDLE>(h),
     96                            ObjectTypeInformation,
     97                            type,
     98                            type_size,
     99                            &type_size);
    100     if (type_size) {
    101       type = reinterpret_cast<PUBLIC_OBJECT_TYPE_INFORMATION *>(
    102           new BYTE[type_size]);
    103 
    104       // Query the type information a second time to get the object type
    105       // name.
    106       status = NtQueryObject(reinterpret_cast<HANDLE>(h),
    107                              ObjectTypeInformation,
    108                              type,
    109                              type_size,
    110                              &type_size);
    111     }
    112 
    113     // NtQueryObject cannot return the name for a file. In this case we
    114     // need to ask NtQueryInformationFile
    115     FILE_NAME_INFORMATION *file_name = NULL;
    116     if (type && wcsncmp(L"File", type->TypeName.Buffer,
    117                         (type->TypeName.Length /
    118                         sizeof(type->TypeName.Buffer[0]))) == 0)  {
    119       // This function does not return the size of the buffer. We need to
    120       // iterate and always increase the buffer size until the function
    121       // succeeds. (Or at least does not fail with STATUS_BUFFER_OVERFLOW)
    122       ULONG size_file = MAX_PATH;
    123       IO_STATUS_BLOCK status_block = {0};
    124       do {
    125         // Delete the previous buffer create. The buffer was too small
    126         if (file_name) {
    127           delete[] reinterpret_cast<BYTE*>(file_name);
    128           file_name = NULL;
    129         }
    130 
    131         // Increase the buffer and do the call agan
    132         size_file += MAX_PATH;
    133         file_name = reinterpret_cast<FILE_NAME_INFORMATION *>(
    134             new BYTE[size_file]);
    135         status = NtQueryInformationFile(reinterpret_cast<HANDLE>(h),
    136                                         &status_block,
    137                                         file_name,
    138                                         size_file,
    139                                         FileNameInformation);
    140       } while (status == STATUS_BUFFER_OVERFLOW);
    141 
    142       if (STATUS_SUCCESS != status) {
    143         if (file_name) {
    144           delete[] file_name;
    145           file_name = NULL;
    146         }
    147       }
    148     }
    149 
    150     if (file_name) {
    151       UNICODE_STRING file_name_string;
    152       file_name_string.Buffer = file_name->FileName;
    153       file_name_string.Length = (USHORT)file_name->FileNameLength;
    154       file_name_string.MaximumLength = (USHORT)file_name->FileNameLength;
    155       fprintf(output, "[GRANTED] Handle 0x%4.4X Access: 0x%8.8X "
    156                       "Type: %-13.13wZ Path: %wZ\r\n",
    157                       h,
    158                       system_handles->Information[i].GrantedAccess,
    159                       type ? &type->TypeName : NULL,
    160                       &file_name_string);
    161     } else {
    162       fprintf(output, "[GRANTED] Handle 0x%4.4X Access: 0x%8.8X "
    163                       "Type: %-13.13wZ Path: %wZ\r\n",
    164                       h,
    165                       system_handles->Information[i].GrantedAccess,
    166                       type ? &type->TypeName : NULL,
    167                       name ? &name->ObjectName : NULL);
    168     }
    169 
    170     if (type) {
    171       delete[] type;
    172     }
    173 
    174     if (file_name) {
    175       delete[] file_name;
    176     }
    177 
    178     if (name) {
    179       delete [] name;
    180     }
    181   }
    182 
    183   if (system_handles) {
    184     delete [] system_handles;
    185   }
    186 }
    187