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