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