Chromium Code Reviews| 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 |