• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
MyThreadBombimgFunction(void * param)16 DWORD WINAPI MyThreadBombimgFunction(void *param) {
17   UNREFERENCED_PARAMETER(param);
18   Sleep(INFINITE);
19   return 0;
20 }
21 
TestThreadBombing(HANDLE log)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%lX\r\n", tid);
39       ::CloseHandle(thread);
40       number_errors = 0;
41     } else {
42       fprintf(output, "[BLOCKED] Creating thread. Error %ld\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.
TakeAllCpu(void * param)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 
TestTakeAllCpu(HANDLE log)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(%ld) priority to Realtime\r\n",
94                 tid);
95       } else {
96         fprintf(output, "[BLOCKED] Set thread(%ld) 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 %ld\r\n",
107            ::GetLastError());
108   }
109 }
110 
TestUseAllMemory(HANDLE log)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 
TestCreateObjects(HANDLE log)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 
EnumWindowCallback(HWND hwnd,LPARAM output)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.
TestCloseHWND(HANDLE log)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