1 // Copyright (c) 2006-2008 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 <malloc.h> 6 #include "sandbox/win/sandbox_poc/pocdll/exports.h" 7 #include "sandbox/win/sandbox_poc/pocdll/utils.h" 8 9 // This file contains the tests used to verify if it's possible to DOS or crash 10 // the machine. All tests that can impact the stability of the machine should 11 // be in this file. 12 13 // Sleeps forever. this function is used to be the 14 // entry point for the threads created by the thread bombing function. 15 // This function never returns. 16 DWORD WINAPI MyThreadBombimgFunction(void *param) { 17 UNREFERENCED_PARAMETER(param); 18 Sleep(INFINITE); 19 return 0; 20 } 21 22 void POCDLL_API TestThreadBombing(HANDLE log) { 23 HandleToFile handle2file; 24 FILE *output = handle2file.Translate(log, "w"); 25 26 // we stop after 5 errors in a row 27 int number_errors = 0; 28 for (int i = 0; i < 100000; ++i) { 29 DWORD tid; 30 // Create the thread and leak the handle. 31 HANDLE thread = ::CreateThread(NULL, // Default security attributes 32 NULL, // Stack size 33 MyThreadBombimgFunction, 34 NULL, // Parameter 35 0, // No creation flags 36 &tid); 37 if (thread) { 38 fprintf(output, "[GRANTED] Creating thread with tid 0x%X\r\n", tid); 39 ::CloseHandle(thread); 40 number_errors = 0; 41 } else { 42 fprintf(output, "[BLOCKED] Creating thread. Error %d\r\n", 43 ::GetLastError()); 44 number_errors++; 45 } 46 47 if (number_errors >= 5) { 48 break; 49 } 50 } 51 } 52 53 54 // Executes a complex mathematical operation forever in a loop. This function 55 // is used as entry point for the threads created by TestTakeAllCpu. It it 56 // designed to take all CPU on the processor where the thread is running. 57 // The return value is always 0. 58 DWORD WINAPI TakeAllCpu(void *param) { 59 UNREFERENCED_PARAMETER(param); 60 int cpt = 0; 61 for (;;) { 62 cpt += 2; 63 cpt /= 2; 64 cpt *= cpt; 65 cpt = cpt % 100; 66 cpt = cpt | (cpt * cpt); 67 } 68 } 69 70 void POCDLL_API TestTakeAllCpu(HANDLE log) { 71 HandleToFile handle2file; 72 FILE *output = handle2file.Translate(log, "w"); 73 74 DWORD_PTR process_mask = 0; 75 DWORD_PTR system_mask = 0; 76 if (::GetProcessAffinityMask(::GetCurrentProcess(), 77 &process_mask, 78 &system_mask)) { 79 DWORD_PTR affinity_mask = 1; 80 81 while (system_mask) { 82 DWORD tid = 0; 83 84 HANDLE thread = ::CreateThread(NULL, // Default security attributes. 85 NULL, // Stack size. 86 TakeAllCpu, 87 NULL, // Parameter. 88 0, // No creation flags. 89 &tid); 90 ::SetThreadAffinityMask(thread, affinity_mask); 91 92 if (::SetThreadPriority(thread, REALTIME_PRIORITY_CLASS)) { 93 fprintf(output, "[GRANTED] Set thread(%d) priority to Realtime\r\n", 94 tid); 95 } else { 96 fprintf(output, "[BLOCKED] Set thread(%d) priority to Realtime\r\n", 97 tid); 98 } 99 100 ::CloseHandle(thread); 101 102 affinity_mask = affinity_mask << 1; 103 system_mask = system_mask >> 1; 104 } 105 } else { 106 fprintf(output, "[ERROR] Cannot get affinity mask. Error %d\r\n", 107 ::GetLastError()); 108 } 109 } 110 111 void POCDLL_API TestUseAllMemory(HANDLE log) { 112 HandleToFile handle2file; 113 FILE *output = handle2file.Translate(log, "w"); 114 115 int number_errors = 0; 116 unsigned long memory_size = 0; 117 for (;;) { 118 DWORD *ptr_to_leak = reinterpret_cast<DWORD *>(malloc(1024*256)); 119 if (ptr_to_leak) { 120 memory_size += (256); 121 number_errors = 0; 122 } else { 123 number_errors++; 124 } 125 126 // check if we have more than 5 errors in a row. If so, quit. 127 if (number_errors >= 5) { 128 fprintf(output, "[INFO] Created %lu kb of memory\r\n", memory_size); 129 return; 130 } 131 132 Sleep(5); // 5ms to be able to see the progression easily with taskmgr. 133 } 134 } 135 136 void POCDLL_API TestCreateObjects(HANDLE log) { 137 HandleToFile handle2file; 138 FILE *output = handle2file.Translate(log, "w"); 139 140 int mutexes = 0; 141 int jobs = 0; 142 int events = 0; 143 for (int i = 0; i < 1000000; ++i) { 144 if (::CreateMutex(NULL, // Default security attributes. 145 TRUE, // We are the initial owner. 146 NULL)) { // No name. 147 mutexes++; 148 } 149 150 if (::CreateJobObject(NULL, // Default security attributes. 151 NULL)) { // No name. 152 jobs++; 153 } 154 155 if (::CreateEvent(NULL, // Default security attributes. 156 TRUE, // Manual Reset. 157 TRUE, // Object is signaled. 158 NULL)) { // No name. 159 events++; 160 } 161 } 162 163 fprintf(output, "[GRANTED] Created %d mutexes, %d jobs and %d events for " 164 "a total of %d objects out of 3 000 000\r\n", mutexes, jobs, 165 events, mutexes + jobs + events); 166 } 167 168 BOOL CALLBACK EnumWindowCallback(HWND hwnd, LPARAM output) { 169 DWORD pid; 170 ::GetWindowThreadProcessId(hwnd, &pid); 171 if (pid != ::GetCurrentProcessId()) { 172 wchar_t window_title[100 + 1] = {0}; 173 ::GetWindowText(hwnd, window_title, 100); 174 fprintf(reinterpret_cast<FILE*>(output), 175 "[GRANTED] Found window 0x%p with title %S\r\n", 176 hwnd, 177 window_title); 178 ::CloseWindow(hwnd); 179 } 180 181 return TRUE; 182 } 183 184 // Enumerates all the windows on the system and call the function to try to 185 // close them. The goal of this function is to try to kill the system by 186 // closing all windows. 187 // "output" is the stream used for logging. 188 void POCDLL_API TestCloseHWND(HANDLE log) { 189 HandleToFile handle2file; 190 FILE *output = handle2file.Translate(log, "w"); 191 192 ::EnumWindows(EnumWindowCallback, PtrToLong(output)); 193 // TODO(nsylvain): find a way to know when the enum is finished 194 // before returning. 195 ::Sleep(3000); 196 } 197