15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome_elf/blacklist/blacklist.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <assert.h>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string.h>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <vector>
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome_elf/blacklist/blacklist_interceptions.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome_elf/chrome_elf_constants.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome_elf/chrome_elf_util.h"
1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome_elf/thunk_getter.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sandbox/win/src/interception_internal.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sandbox/win/src/internal_types.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sandbox/win/src/service_resolver.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern "C" IMAGE_DOS_HEADER __ImageBase;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace blacklist{
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The DLLs listed here are known (or under strong suspicion) of causing crashes
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// when they are loaded in the browser. DLLs should only be added to this list
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// if there is nothing else Chrome can do to prevent those crashes.
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// For more information about how this list is generated, and how to get off
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// of it, see:
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// https://sites.google.com/a/chromium.org/dev/Home/third-party-developers
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// NOTE: Please remember to update the DllHash enum in histograms.xml when
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       adding a new value to the blacklist.
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = {
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"activedetect32.dll",                // Lenovo One Key Theater.
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        // See crbug.com/379218.
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"activedetect64.dll",                // Lenovo One Key Theater.
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"bitguard.dll",                      // Unknown (suspected malware).
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"chrmxtn.dll",                       // Unknown (keystroke logger).
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  L"cplushook.dll",                     // Unknown (suspected malware).
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  L"datamngr.dll",                      // Unknown (suspected adware).
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  L"hk.dll",                            // Unknown (keystroke logger).
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  L"libapi2hook.dll",                   // V-Bates.
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  L"libinject.dll",                     // V-Bates.
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  L"libinject2.dll",                    // V-Bates.
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  L"libredir2.dll",                     // V-Bates.
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  L"libsvn_tsvn32.dll",                 // TortoiseSVN.
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  L"libwinhook.dll",                    // V-Bates.
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  L"lmrn.dll",                          // Unknown.
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  L"minisp.dll",                        // Unknown (suspected malware).
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  L"scdetour.dll",                      // Quick Heal Antivirus.
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        // See crbug.com/382561.
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"systemk.dll",                       // Unknown (suspected adware).
545b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  L"wajam_goblin_64.dll",               // Wajam Internet Technologies.
555b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  L"wajam_goblin.dll",                  // Wajam Internet Technologies.
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"windowsapihookdll32.dll",           // Lenovo One Key Theater.
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        // See crbug.com/379218.
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  L"windowsapihookdll64.dll",           // Lenovo One Key Theater.
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Keep this null pointer here to mark the end of the list.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NULL,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool g_blocked_dlls[kTroublesomeDllsMaxCount] = {};
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int g_num_blocked_dlls = 0;
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace blacklist
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Allocate storage for thunks in a page of this module to save on doing
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// an extra allocation at run time.
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma section(".crthunk",read,execute)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)__declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Record if the blacklist was successfully initialized so processes can easily
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// determine if the blacklist is enabled for them.
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool g_blacklist_initialized = false;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper to set DWORD registry values.
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)DWORD SetDWValue(HKEY* key, const wchar_t* property, DWORD value) {
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ::RegSetValueEx(*key,
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         property,
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         0,
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         REG_DWORD,
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         reinterpret_cast<LPBYTE>(&value),
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         sizeof(value));
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool GenerateStateFromBeaconAndAttemptCount(HKEY* key, DWORD blacklist_state) {
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LONG result = 0;
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (blacklist_state == blacklist::BLACKLIST_ENABLED) {
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the blacklist succeeded on the previous run reset the failure
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // counter.
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return (SetDWValue(key,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       blacklist::kBeaconAttemptCount,
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       static_cast<DWORD>(0)) == ERROR_SUCCESS);
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Some part of the blacklist setup failed last time.  If this has occured
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // blacklist::kBeaconMaxAttempts times in a row we switch the state to
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // failed and skip setting up the blacklist.
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DWORD attempt_count = 0;
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DWORD attempt_count_size = sizeof(attempt_count);
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    result = ::RegQueryValueEx(*key,
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               blacklist::kBeaconAttemptCount,
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               0,
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               NULL,
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               reinterpret_cast<LPBYTE>(&attempt_count),
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               &attempt_count_size);
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (result == ERROR_FILE_NOT_FOUND)
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      attempt_count = 0;
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    else if (result != ERROR_SUCCESS)
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ++attempt_count;
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SetDWValue(key, blacklist::kBeaconAttemptCount, attempt_count);
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (attempt_count >= blacklist::kBeaconMaxAttempts) {
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      blacklist_state = blacklist::BLACKLIST_SETUP_FAILED;
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SetDWValue(key, blacklist::kBeaconState, blacklist_state);
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace blacklist {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(_WIN64)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Allocate storage for the pointer to the old NtMapViewOfSectionFunction.
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma section(".oldntmap",write,read)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  __declspec(allocate(".oldntmap"))
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool LeaveSetupBeacon() {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HKEY key = NULL;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD disposition = 0;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 kRegistryBeaconPath,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 0,
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 NULL,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 REG_OPTION_NON_VOLATILE,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 KEY_QUERY_VALUE | KEY_SET_VALUE,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 NULL,
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &key,
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &disposition);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != ERROR_SUCCESS)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Retrieve the current blacklist state.
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DWORD blacklist_state = BLACKLIST_STATE_MAX;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD blacklist_state_size = sizeof(blacklist_state);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD type = 0;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result = ::RegQueryValueEx(key,
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             kBeaconState,
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             0,
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             &type,
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             reinterpret_cast<LPBYTE>(&blacklist_state),
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             &blacklist_state_size);
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (blacklist_state == BLACKLIST_DISABLED || result != ERROR_SUCCESS ||
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      type != REG_DWORD) {
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ::RegCloseKey(key);
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!GenerateStateFromBeaconAndAttemptCount(&key, blacklist_state)) {
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ::RegCloseKey(key);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  result = SetDWValue(&key, kBeaconState, BLACKLIST_SETUP_RUNNING);
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ::RegCloseKey(key);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (result == ERROR_SUCCESS);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ResetBeacon() {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HKEY key = NULL;
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD disposition = 0;
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 kRegistryBeaconPath,
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 0,
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 NULL,
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 REG_OPTION_NON_VOLATILE,
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 KEY_QUERY_VALUE | KEY_SET_VALUE,
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 NULL,
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &key,
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &disposition);
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != ERROR_SUCCESS)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DWORD blacklist_state = BLACKLIST_STATE_MAX;
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DWORD blacklist_state_size = sizeof(blacklist_state);
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DWORD type = 0;
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  result = ::RegQueryValueEx(key,
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             kBeaconState,
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             0,
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             &type,
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             reinterpret_cast<LPBYTE>(&blacklist_state),
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             &blacklist_state_size);
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (result != ERROR_SUCCESS || type != REG_DWORD) {
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ::RegCloseKey(key);
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Reaching this point with the setup running state means the setup did not
2126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // crash, so we reset to enabled.  Any other state indicates that setup was
2136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // skipped; in that case we leave the state alone for later recording.
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (blacklist_state == BLACKLIST_SETUP_RUNNING)
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    result = SetDWValue(&key, kBeaconState, BLACKLIST_ENABLED);
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ::RegCloseKey(key);
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (result == ERROR_SUCCESS);
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int BlacklistSize() {
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int size = -1;
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (blacklist::g_troublesome_dlls[++size] != NULL) {}
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return size;
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsBlacklistInitialized() {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_blacklist_initialized;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GetBlacklistIndex(const wchar_t* dll_name) {
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (int i = 0; i < kTroublesomeDllsMaxCount, g_troublesome_dlls[i]; ++i) {
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (_wcsicmp(dll_name, g_troublesome_dlls[i]) == 0)
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return i;
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return -1;
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AddDllToBlacklist(const wchar_t* dll_name) {
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int blacklist_size = BlacklistSize();
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We need to leave one space at the end for the null pointer.
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (blacklist_size + 1 >= kTroublesomeDllsMaxCount)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < blacklist_size; ++i) {
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!_wcsicmp(g_troublesome_dlls[i], dll_name))
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Copy string to blacklist.
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  wchar_t* str_buffer = new wchar_t[wcslen(dll_name) + 1];
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  wcscpy(str_buffer, dll_name);
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_troublesome_dlls[blacklist_size] = str_buffer;
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  g_blocked_dlls[blacklist_size] = false;
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool RemoveDllFromBlacklist(const wchar_t* dll_name) {
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int blacklist_size = BlacklistSize();
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < blacklist_size; ++i) {
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!_wcsicmp(g_troublesome_dlls[i], dll_name)) {
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Found the thing to remove. Delete it then replace it with the last
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // element.
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delete[] g_troublesome_dlls[i];
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_troublesome_dlls[i] = g_troublesome_dlls[blacklist_size - 1];
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_troublesome_dlls[blacklist_size - 1] = NULL;
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Also update the stats recording if we have blocked this dll or not.
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (g_blocked_dlls[i])
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        --g_num_blocked_dlls;
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      g_blocked_dlls[i] = g_blocked_dlls[blacklist_size - 1];
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TODO(csharp): Maybe store these values in the registry so we can
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// still report them if Chrome crashes early.
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SuccessfullyBlocked(const wchar_t** blocked_dlls, int* size) {
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (size == NULL)
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If the array isn't valid or big enough, just report the size it needs to
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // be and return.
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (blocked_dlls == NULL && *size < g_num_blocked_dlls) {
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *size = g_num_blocked_dlls;
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *size = g_num_blocked_dlls;
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int strings_to_fill = 0;
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (int i = 0; strings_to_fill < g_num_blocked_dlls && g_troublesome_dlls[i];
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       ++i) {
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (g_blocked_dlls[i]) {
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      blocked_dlls[strings_to_fill] = g_troublesome_dlls[i];
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ++strings_to_fill;
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BlockedDll(size_t blocked_index) {
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  assert(blocked_index < kTroublesomeDllsMaxCount);
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!g_blocked_dlls[blocked_index] &&
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      blocked_index < kTroublesomeDllsMaxCount) {
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ++g_num_blocked_dlls;
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    g_blocked_dlls[blocked_index] = true;
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool Initialize(bool force) {
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check to see that we found the functions we need in ntdll.
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!InitializeInterceptImports())
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check to see if this is a non-browser process, abort if so.
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsNonBrowserProcess())
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Check to see if the blacklist beacon is still set to running (indicating a
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // failure) or disabled, and abort if so.
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!force && !LeaveSetupBeacon())
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // It is possible for other dlls to have already patched code by now and
329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // attempting to patch their code might result in crashes.
330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const bool kRelaxed = false;
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
33223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Create a thunk via the appropriate ServiceResolver instance.
33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  sandbox::ServiceResolverThunk* thunk = GetThunk(kRelaxed);
33423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
33523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Don't try blacklisting on unsupported OS versions.
33623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!thunk)
33723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
33823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage);
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Mark the thunk storage as readable and writeable, since we
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ready to write to it.
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DWORD old_protect = 0;
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!VirtualProtect(&g_thunk_storage,
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      sizeof(g_thunk_storage),
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      PAGE_EXECUTE_READWRITE,
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      &old_protect)) {
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  thunk->AllowLocalPatches();
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We declare this early so it can be used in the 64-bit block below and
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // still work on 32-bit build when referenced at the end of the function.
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BOOL page_executable = false;
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Replace the default NtMapViewOfSection with our patched version.
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(_WIN64)
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName),
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              reinterpret_cast<void*>(&__ImageBase),
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              "NtMapViewOfSection",
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              NULL,
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              &blacklist::BlNtMapViewOfSection64,
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              thunk_storage,
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              sizeof(sandbox::ThunkData),
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              NULL);
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Keep a pointer to the original code, we don't have enough space to
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // add it directly to the call.
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  g_nt_map_view_of_section_func = reinterpret_cast<NtMapViewOfSectionFunction>(
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      thunk_storage);
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ensure that the pointer to the old function can't be changed.
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) page_executable = VirtualProtect(&g_nt_map_view_of_section_func,
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  sizeof(g_nt_map_view_of_section_func),
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  PAGE_EXECUTE_READ,
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  &old_protect);
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName),
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              reinterpret_cast<void*>(&__ImageBase),
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              "NtMapViewOfSection",
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              NULL,
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              &blacklist::BlNtMapViewOfSection,
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              thunk_storage,
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              sizeof(sandbox::ThunkData),
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              NULL);
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete thunk;
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Record if we have initialized the blacklist.
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  g_blacklist_initialized = NT_SUCCESS(ret);
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Mark the thunk storage as executable and prevent any future writes to it.
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  page_executable = page_executable && VirtualProtect(&g_thunk_storage,
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      sizeof(g_thunk_storage),
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      PAGE_EXECUTE_READ,
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &old_protect);
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AddDllsFromRegistryToBlacklist();
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NT_SUCCESS(ret) && page_executable;
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid AddDllsFromRegistryToBlacklist() {
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  HKEY key = NULL;
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  LONG result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                               kRegistryFinchListPath,
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                               0,
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                               KEY_QUERY_VALUE | KEY_SET_VALUE,
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                               &key);
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (result != ERROR_SUCCESS)
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // We add dlls from the registry to the blacklist.
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DWORD value_len;
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DWORD name_len = MAX_PATH;
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::vector<wchar_t> name_buffer(name_len);
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (int i = 0; result == ERROR_SUCCESS; ++i) {
42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    name_len = MAX_PATH;
42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    value_len = 0;
42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    result = ::RegEnumValue(
42346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        key, i, &name_buffer[0], &name_len, NULL, NULL, NULL, &value_len);
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (result != ERROR_SUCCESS)
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    name_len = name_len + 1;
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    value_len = value_len + 1;
42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::vector<wchar_t> value_buffer(value_len);
43046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    result = ::RegEnumValue(key, i, &name_buffer[0], &name_len, NULL, NULL,
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            reinterpret_cast<BYTE*>(&value_buffer[0]),
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            &value_len);
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (result != ERROR_SUCCESS)
434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
43546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    value_buffer[value_len - 1] = L'\0';
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    AddDllToBlacklist(&value_buffer[0]);
43746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
43846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
43946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ::RegCloseKey(key);
440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return;
44146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
44246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace blacklist
444