OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome_elf/blacklist/blacklist.h" | 5 #include "chrome_elf/blacklist/blacklist.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <string.h> | 8 #include <string.h> |
9 | 9 |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "chrome_elf/blacklist/blacklist_interceptions.h" | 12 #include "chrome_elf/blacklist/blacklist_interceptions.h" |
13 #include "chrome_elf/chrome_elf_constants.h" | 13 #include "chrome_elf/chrome_elf_constants.h" |
14 #include "chrome_elf/chrome_elf_reg.h" | |
14 #include "chrome_elf/chrome_elf_util.h" | 15 #include "chrome_elf/chrome_elf_util.h" |
15 #include "chrome_elf/thunk_getter.h" | 16 #include "chrome_elf/thunk_getter.h" |
16 #include "sandbox/win/src/interception_internal.h" | 17 #include "sandbox/win/src/interception_internal.h" |
17 #include "sandbox/win/src/internal_types.h" | 18 #include "sandbox/win/src/internal_types.h" |
18 #include "sandbox/win/src/service_resolver.h" | 19 #include "sandbox/win/src/service_resolver.h" |
19 | 20 |
20 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx | 21 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
21 extern "C" IMAGE_DOS_HEADER __ImageBase; | 22 extern "C" IMAGE_DOS_HEADER __ImageBase; |
22 | 23 |
23 namespace blacklist{ | 24 namespace blacklist{ |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 // an extra allocation at run time. | 82 // an extra allocation at run time. |
82 #pragma section(".crthunk",read,execute) | 83 #pragma section(".crthunk",read,execute) |
83 __declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage; | 84 __declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage; |
84 | 85 |
85 namespace { | 86 namespace { |
86 | 87 |
87 // Record if the blacklist was successfully initialized so processes can easily | 88 // Record if the blacklist was successfully initialized so processes can easily |
88 // determine if the blacklist is enabled for them. | 89 // determine if the blacklist is enabled for them. |
89 bool g_blacklist_initialized = false; | 90 bool g_blacklist_initialized = false; |
90 | 91 |
91 // Helper to set DWORD registry values. | |
92 DWORD SetDWValue(HKEY* key, const wchar_t* property, DWORD value) { | |
93 return ::RegSetValueEx(*key, | |
94 property, | |
95 0, | |
96 REG_DWORD, | |
97 reinterpret_cast<LPBYTE>(&value), | |
98 sizeof(value)); | |
99 } | |
100 | |
101 bool GenerateStateFromBeaconAndAttemptCount(HKEY* key, DWORD blacklist_state) { | |
102 LONG result = 0; | |
103 if (blacklist_state == blacklist::BLACKLIST_ENABLED) { | |
104 // If the blacklist succeeded on the previous run reset the failure | |
105 // counter. | |
106 return (SetDWValue(key, | |
107 blacklist::kBeaconAttemptCount, | |
108 static_cast<DWORD>(0)) == ERROR_SUCCESS); | |
109 } else { | |
110 // Some part of the blacklist setup failed last time. If this has occured | |
111 // blacklist::kBeaconMaxAttempts times in a row we switch the state to | |
112 // failed and skip setting up the blacklist. | |
113 DWORD attempt_count = 0; | |
114 DWORD attempt_count_size = sizeof(attempt_count); | |
115 result = ::RegQueryValueEx(*key, | |
116 blacklist::kBeaconAttemptCount, | |
117 0, | |
118 NULL, | |
119 reinterpret_cast<LPBYTE>(&attempt_count), | |
120 &attempt_count_size); | |
121 | |
122 if (result == ERROR_FILE_NOT_FOUND) | |
123 attempt_count = 0; | |
124 else if (result != ERROR_SUCCESS) | |
125 return false; | |
126 | |
127 ++attempt_count; | |
128 SetDWValue(key, blacklist::kBeaconAttemptCount, attempt_count); | |
129 | |
130 if (attempt_count >= blacklist::kBeaconMaxAttempts) { | |
131 blacklist_state = blacklist::BLACKLIST_SETUP_FAILED; | |
132 SetDWValue(key, blacklist::kBeaconState, blacklist_state); | |
133 } | |
134 | |
135 return false; | |
136 } | |
137 } | |
138 | |
139 } // namespace | 92 } // namespace |
140 | 93 |
141 namespace blacklist { | 94 namespace blacklist { |
142 | 95 |
143 #if defined(_WIN64) | 96 #if defined(_WIN64) |
144 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction. | 97 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction. |
145 #pragma section(".oldntmap",write,read) | 98 #pragma section(".oldntmap",write,read) |
146 __declspec(allocate(".oldntmap")) | 99 __declspec(allocate(".oldntmap")) |
147 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL; | 100 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL; |
148 #endif | 101 #endif |
149 | 102 |
150 bool LeaveSetupBeacon() { | 103 bool LeaveSetupBeacon() { |
151 HKEY key = NULL; | 104 HANDLE key_handle = INVALID_HANDLE_VALUE; |
152 DWORD disposition = 0; | 105 |
153 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, | 106 if (!nt::CreateRegKey(nt::HKCU, kRegistryBeaconPath, |
154 kRegistryBeaconPath, | 107 KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle)) |
155 0, | |
156 NULL, | |
157 REG_OPTION_NON_VOLATILE, | |
158 KEY_QUERY_VALUE | KEY_SET_VALUE, | |
159 NULL, | |
160 &key, | |
161 &disposition); | |
162 if (result != ERROR_SUCCESS) | |
163 return false; | 108 return false; |
164 | 109 |
165 // Retrieve the current blacklist state. | |
166 DWORD blacklist_state = BLACKLIST_STATE_MAX; | 110 DWORD blacklist_state = BLACKLIST_STATE_MAX; |
167 DWORD blacklist_state_size = sizeof(blacklist_state); | 111 if (!nt::GetRegValue_DWORD(key_handle, kBeaconState, &blacklist_state) || |
168 DWORD type = 0; | 112 blacklist_state == BLACKLIST_DISABLED) { |
169 result = ::RegQueryValueEx(key, | 113 nt::CloseRegKey(key_handle); |
170 kBeaconState, | |
171 0, | |
172 &type, | |
173 reinterpret_cast<LPBYTE>(&blacklist_state), | |
174 &blacklist_state_size); | |
175 | |
176 if (result != ERROR_SUCCESS || blacklist_state == BLACKLIST_DISABLED || | |
177 type != REG_DWORD) { | |
178 ::RegCloseKey(key); | |
179 return false; | 114 return false; |
180 } | 115 } |
181 | 116 |
182 if (!GenerateStateFromBeaconAndAttemptCount(&key, blacklist_state)) { | 117 // Handle attempt count. |
183 ::RegCloseKey(key); | 118 // Only return true if BL is enabled and succeeded on previous run. |
184 return false; | 119 bool success = false; |
120 if (blacklist_state == BLACKLIST_ENABLED) { | |
121 // If the blacklist succeeded on the previous run reset the failure | |
122 // counter. Then update the beacon state. | |
123 if (nt::SetRegValue_DWORD(key_handle, kBeaconAttemptCount, | |
124 static_cast<DWORD>(0))) { | |
125 if (nt::SetRegValue_DWORD(key_handle, kBeaconState, | |
126 BLACKLIST_SETUP_RUNNING)) | |
127 success = true; | |
128 } | |
129 } else { | |
130 // Some part of the blacklist setup failed last time. If this has occured | |
131 // blacklist::kBeaconMaxAttempts times in a row we switch the state to | |
132 // failed and skip setting up the blacklist. | |
133 DWORD attempt_count = 0; | |
134 | |
135 nt::GetRegValue_DWORD(key_handle, blacklist::kBeaconAttemptCount, | |
136 &attempt_count); | |
137 ++attempt_count; | |
138 nt::SetRegValue_DWORD(key_handle, blacklist::kBeaconAttemptCount, | |
139 attempt_count); | |
140 | |
141 if (attempt_count >= blacklist::kBeaconMaxAttempts) { | |
142 blacklist_state = blacklist::BLACKLIST_SETUP_FAILED; | |
143 nt::SetRegValue_DWORD(key_handle, blacklist::kBeaconState, | |
144 blacklist_state); | |
145 } | |
185 } | 146 } |
186 | 147 |
187 result = SetDWValue(&key, kBeaconState, BLACKLIST_SETUP_RUNNING); | 148 nt::CloseRegKey(key_handle); |
188 ::RegCloseKey(key); | 149 return success; |
189 | |
190 return (result == ERROR_SUCCESS); | |
191 } | 150 } |
192 | 151 |
193 bool ResetBeacon() { | 152 bool ResetBeacon() { |
194 HKEY key = NULL; | 153 HANDLE key_handle = INVALID_HANDLE_VALUE; |
195 DWORD disposition = 0; | 154 |
196 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, | 155 if (!nt::CreateRegKey(nt::HKCU, kRegistryBeaconPath, |
197 kRegistryBeaconPath, | 156 KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle)) |
198 0, | |
199 NULL, | |
200 REG_OPTION_NON_VOLATILE, | |
201 KEY_QUERY_VALUE | KEY_SET_VALUE, | |
202 NULL, | |
203 &key, | |
204 &disposition); | |
205 if (result != ERROR_SUCCESS) | |
206 return false; | 157 return false; |
207 | 158 |
208 DWORD blacklist_state = BLACKLIST_STATE_MAX; | 159 DWORD blacklist_state = BLACKLIST_STATE_MAX; |
209 DWORD blacklist_state_size = sizeof(blacklist_state); | 160 if (!nt::GetRegValue_DWORD(key_handle, kBeaconState, &blacklist_state)) { |
210 DWORD type = 0; | 161 nt::CloseRegKey(key_handle); |
211 result = ::RegQueryValueEx(key, | |
212 kBeaconState, | |
213 0, | |
214 &type, | |
215 reinterpret_cast<LPBYTE>(&blacklist_state), | |
216 &blacklist_state_size); | |
217 | |
218 if (result != ERROR_SUCCESS || type != REG_DWORD) { | |
219 ::RegCloseKey(key); | |
220 return false; | 162 return false; |
221 } | 163 } |
222 | 164 |
223 // Reaching this point with the setup running state means the setup did not | 165 // Reaching this point with the setup running state means the setup did not |
224 // crash, so we reset to enabled. Any other state indicates that setup was | 166 // crash, so we reset to enabled. Any other state indicates that setup was |
225 // skipped; in that case we leave the state alone for later recording. | 167 // skipped; in that case we leave the state alone for later recording. |
226 if (blacklist_state == BLACKLIST_SETUP_RUNNING) | 168 if (blacklist_state == BLACKLIST_SETUP_RUNNING) { |
227 result = SetDWValue(&key, kBeaconState, BLACKLIST_ENABLED); | 169 if (!nt::SetRegValue_DWORD(key_handle, kBeaconState, BLACKLIST_ENABLED)) { |
170 nt::CloseRegKey(key_handle); | |
171 return false; | |
172 } | |
173 } | |
228 | 174 |
229 ::RegCloseKey(key); | 175 nt::CloseRegKey(key_handle); |
230 return (result == ERROR_SUCCESS); | 176 return true; |
231 } | 177 } |
232 | 178 |
233 int BlacklistSize() { | 179 int BlacklistSize() { |
234 int size = -1; | 180 int size = -1; |
235 while (blacklist::g_troublesome_dlls[++size] != NULL) {} | 181 while (blacklist::g_troublesome_dlls[++size] != NULL) {} |
236 | 182 |
237 return size; | 183 return size; |
238 } | 184 } |
239 | 185 |
240 bool IsBlacklistInitialized() { | 186 bool IsBlacklistInitialized() { |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 sizeof(g_thunk_storage), | 355 sizeof(g_thunk_storage), |
410 PAGE_EXECUTE_READ, | 356 PAGE_EXECUTE_READ, |
411 &old_protect); | 357 &old_protect); |
412 | 358 |
413 AddDllsFromRegistryToBlacklist(); | 359 AddDllsFromRegistryToBlacklist(); |
414 | 360 |
415 return NT_SUCCESS(ret) && page_executable; | 361 return NT_SUCCESS(ret) && page_executable; |
416 } | 362 } |
417 | 363 |
418 void AddDllsFromRegistryToBlacklist() { | 364 void AddDllsFromRegistryToBlacklist() { |
419 HKEY key = NULL; | 365 std::vector<base::string16> dlls; |
420 LONG result = ::RegOpenKeyEx(HKEY_CURRENT_USER, | |
421 kRegistryFinchListPath, | |
422 0, | |
423 KEY_QUERY_VALUE | KEY_SET_VALUE, | |
424 &key); | |
425 | 366 |
426 if (result != ERROR_SUCCESS) | 367 if (!nt::GetRegValue_MULTI_SZ(nt::HKCU, kRegistryFinchListPath, |
368 kRegistryFinchListValueName, &dlls) || | |
369 dlls.size() == 0) | |
robertshield
2016/04/20 05:16:09
dlls.empty()
penny
2016/05/28 01:34:22
Done.
| |
427 return; | 370 return; |
428 | 371 |
429 // We add dlls from the registry to the blacklist. | 372 // Add each DLL to the BL in memory |
430 DWORD value_len; | 373 for (auto name : dlls) { |
431 DWORD name_len = MAX_PATH; | 374 AddDllToBlacklist(name.c_str()); |
432 std::vector<wchar_t> name_buffer(name_len); | |
433 for (int i = 0; result == ERROR_SUCCESS; ++i) { | |
434 name_len = MAX_PATH; | |
435 value_len = 0; | |
436 result = ::RegEnumValue( | |
437 key, i, &name_buffer[0], &name_len, NULL, NULL, NULL, &value_len); | |
438 if (result != ERROR_SUCCESS) | |
439 break; | |
440 | |
441 name_len = name_len + 1; | |
442 value_len = value_len + 1; | |
443 std::vector<wchar_t> value_buffer(value_len); | |
444 result = ::RegEnumValue(key, i, &name_buffer[0], &name_len, NULL, NULL, | |
445 reinterpret_cast<BYTE*>(&value_buffer[0]), | |
446 &value_len); | |
447 if (result != ERROR_SUCCESS) | |
448 break; | |
449 value_buffer[value_len - 1] = L'\0'; | |
450 AddDllToBlacklist(&value_buffer[0]); | |
451 } | 375 } |
452 | 376 |
453 ::RegCloseKey(key); | |
454 return; | 377 return; |
455 } | 378 } |
456 | 379 |
457 } // namespace blacklist | 380 } // namespace blacklist |
OLD | NEW |