Commit 5379f172 authored by pennymac's avatar pennymac Committed by Commit bot

NTRegistry - added wow64 redirection support.

TESTS=chrome_elf_unittests: NtRegistryTest*
BUG=641169
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.win:win10_chromium_x64_rel_ng

Review-Url: https://codereview.chromium.org/2345913003
Cr-Commit-Position: refs/heads/master@{#422919}
parent 546e56fe
...@@ -11,7 +11,7 @@ assert(is_win) ...@@ -11,7 +11,7 @@ assert(is_win)
# Please don't add dependencies on other system libraries. # Please don't add dependencies on other system libraries.
static_library("install_static_util") { static_library("install_static_util") {
public_deps = [ public_deps = [
"//chrome_elf/nt_registry:nt_registry", "//chrome_elf:nt_registry",
] ]
sources = [ sources = [
......
...@@ -270,8 +270,9 @@ bool GetCollectStatsConsentImpl(const std::wstring& exe_path) { ...@@ -270,8 +270,9 @@ bool GetCollectStatsConsentImpl(const std::wstring& exe_path) {
std::wstring full_key_path(kRegPathClientStateMedium); std::wstring full_key_path(kRegPathClientStateMedium);
full_key_path.append(1, L'\\'); full_key_path.append(1, L'\\');
full_key_path.append(app_guid); full_key_path.append(app_guid);
if (system_install && nt::QueryRegValueDWORD(nt::HKLM, full_key_path.c_str(), if (system_install &&
kRegValueUsageStats, &out_value)) nt::QueryRegValueDWORD(nt::HKLM, nt::WOW6432, full_key_path.c_str(),
kRegValueUsageStats, &out_value))
return (out_value == 1); return (out_value == 1);
// Second, try kRegPathClientState. // Second, try kRegPathClientState.
...@@ -279,8 +280,8 @@ bool GetCollectStatsConsentImpl(const std::wstring& exe_path) { ...@@ -279,8 +280,8 @@ bool GetCollectStatsConsentImpl(const std::wstring& exe_path) {
full_key_path.append(1, L'\\'); full_key_path.append(1, L'\\');
full_key_path.append(app_guid); full_key_path.append(app_guid);
return (nt::QueryRegValueDWORD((system_install ? nt::HKLM : nt::HKCU), return (nt::QueryRegValueDWORD((system_install ? nt::HKLM : nt::HKCU),
full_key_path.c_str(), kRegValueUsageStats, nt::WOW6432, full_key_path.c_str(),
&out_value) && kRegValueUsageStats, &out_value) &&
out_value == 1); out_value == 1);
} }
...@@ -410,8 +411,8 @@ bool IsMultiInstall(bool is_system_install) { ...@@ -410,8 +411,8 @@ bool IsMultiInstall(bool is_system_install) {
full_key_path.append(1, L'\\'); full_key_path.append(1, L'\\');
full_key_path.append(kAppGuidGoogleChrome); full_key_path.append(kAppGuidGoogleChrome);
if (!nt::QueryRegValueSZ((is_system_install ? nt::HKLM : nt::HKCU), if (!nt::QueryRegValueSZ((is_system_install ? nt::HKLM : nt::HKCU),
full_key_path.c_str(), kUninstallArgumentsField, nt::WOW6432, full_key_path.c_str(),
&args)) kUninstallArgumentsField, &args))
return false; return false;
return (args.find(L"--multi-install") != std::wstring::npos); return (args.find(L"--multi-install") != std::wstring::npos);
...@@ -429,7 +430,7 @@ bool GetCollectStatsInSample() { ...@@ -429,7 +430,7 @@ bool GetCollectStatsInSample() {
std::wstring registry_path = GetChromeInstallRegistryPath(); std::wstring registry_path = GetChromeInstallRegistryPath();
DWORD out_value = 0; DWORD out_value = 0;
if (!nt::QueryRegValueDWORD(nt::HKCU, registry_path.c_str(), if (!nt::QueryRegValueDWORD(nt::HKCU, nt::WOW6432, registry_path.c_str(),
kRegValueChromeStatsSample, &out_value)) { kRegValueChromeStatsSample, &out_value)) {
// If reading the value failed, treat it as though sampling isn't in effect, // If reading the value failed, treat it as though sampling isn't in effect,
// implicitly meaning this install is in the sample. // implicitly meaning this install is in the sample.
...@@ -442,8 +443,8 @@ bool SetCollectStatsInSample(bool in_sample) { ...@@ -442,8 +443,8 @@ bool SetCollectStatsInSample(bool in_sample) {
std::wstring registry_path = GetChromeInstallRegistryPath(); std::wstring registry_path = GetChromeInstallRegistryPath();
HANDLE key_handle = INVALID_HANDLE_VALUE; HANDLE key_handle = INVALID_HANDLE_VALUE;
if (!nt::CreateRegKey(nt::HKCU, registry_path.c_str(), KEY_SET_VALUE, if (!nt::CreateRegKey(nt::HKCU, registry_path.c_str(),
&key_handle)) { KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) {
nt::CloseRegKey(key_handle); nt::CloseRegKey(key_handle);
return false; return false;
} }
...@@ -456,14 +457,14 @@ bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) { ...@@ -456,14 +457,14 @@ bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) {
DWORD value = 0; DWORD value = 0;
// First, try HKLM. // First, try HKLM.
if (nt::QueryRegValueDWORD(nt::HKLM, kRegPathChromePolicy, if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, kRegPathChromePolicy,
kMetricsReportingEnabled, &value)) { kMetricsReportingEnabled, &value)) {
*crash_reporting_enabled = (value != 0); *crash_reporting_enabled = (value != 0);
return true; return true;
} }
// Second, try HKCU. // Second, try HKCU.
if (nt::QueryRegValueDWORD(nt::HKCU, kRegPathChromePolicy, if (nt::QueryRegValueDWORD(nt::HKCU, nt::NONE, kRegPathChromePolicy,
kMetricsReportingEnabled, &value)) { kMetricsReportingEnabled, &value)) {
*crash_reporting_enabled = (value != 0); *crash_reporting_enabled = (value != 0);
return true; return true;
...@@ -643,13 +644,13 @@ void GetChromeChannelName(bool is_per_user_install, ...@@ -643,13 +644,13 @@ void GetChromeChannelName(bool is_per_user_install,
std::wstring full_key_path(kRegPathClientState); std::wstring full_key_path(kRegPathClientState);
full_key_path.append(1, L'\\'); full_key_path.append(1, L'\\');
full_key_path.append(kAppGuidGoogleBinaries); full_key_path.append(kAppGuidGoogleBinaries);
nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, nt::WOW6432,
full_key_path.c_str(), kRegApField, &value); full_key_path.c_str(), kRegApField, &value);
} else { } else {
std::wstring full_key_path(kRegPathClientState); std::wstring full_key_path(kRegPathClientState);
full_key_path.append(1, L'\\'); full_key_path.append(1, L'\\');
full_key_path.append(kAppGuidGoogleChrome); full_key_path.append(kAppGuidGoogleChrome);
nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, nt::WOW6432,
full_key_path.c_str(), kRegApField, &value); full_key_path.c_str(), kRegApField, &value);
} }
...@@ -695,7 +696,7 @@ std::string GetGoogleUpdateVersion() { ...@@ -695,7 +696,7 @@ std::string GetGoogleUpdateVersion() {
// Consider whether Chromium should connect to Google update to manage // Consider whether Chromium should connect to Google update to manage
// updates. Should this be returning an empty string for Chromium builds?. // updates. Should this be returning an empty string for Chromium builds?.
std::wstring update_version; std::wstring update_version;
if (nt::QueryRegValueSZ(nt::AUTO, kRegPathGoogleUpdate, if (nt::QueryRegValueSZ(nt::AUTO, nt::WOW6432, kRegPathGoogleUpdate,
kRegGoogleUpdateVersion, &update_version)) kRegGoogleUpdateVersion, &update_version))
return UTF16ToUTF8(update_version); return UTF16ToUTF8(update_version);
......
...@@ -43,10 +43,10 @@ shared_library("chrome_elf") { ...@@ -43,10 +43,10 @@ shared_library("chrome_elf") {
":constants", ":constants",
":crash", ":crash",
":hook_util", ":hook_util",
":nt_registry",
":security", ":security",
"//build/config/sanitizers:deps", "//build/config/sanitizers:deps",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
] ]
configs += [ "//build/config/win:windowed" ] configs += [ "//build/config/win:windowed" ]
configs -= [ "//build/config/win:console" ] configs -= [ "//build/config/win:console" ]
...@@ -76,7 +76,7 @@ source_set("security") { ...@@ -76,7 +76,7 @@ source_set("security") {
] ]
deps = [ deps = [
":constants", ":constants",
"//chrome_elf/nt_registry:nt_registry", ":nt_registry",
] ]
} }
...@@ -126,9 +126,9 @@ static_library("blacklist") { ...@@ -126,9 +126,9 @@ static_library("blacklist") {
":constants", ":constants",
":crash", ":crash",
":hook_util", ":hook_util",
":nt_registry",
"//base:base_static", # pe_image "//base:base_static", # pe_image
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
] ]
} }
...@@ -159,11 +159,24 @@ static_library("hook_util") { ...@@ -159,11 +159,24 @@ static_library("hook_util") {
"hook_util/hook_util.h", "hook_util/hook_util.h",
] ]
deps = [ deps = [
":nt_registry", # utils
"//base:base_static", # pe_image "//base:base_static", # pe_image
"//sandbox", "//sandbox",
] ]
} }
# This target contains utility functions which must only depend on
# kernel32. Please don't add dependencies on other system libraries.
static_library("nt_registry") {
sources = [
"../sandbox/win/src/nt_internals.h",
"nt_registry/nt_registry.cc",
"nt_registry/nt_registry.h",
]
libs = [ "kernel32.lib" ]
}
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## tests ## tests
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
...@@ -175,6 +188,7 @@ test("chrome_elf_unittests") { ...@@ -175,6 +188,7 @@ test("chrome_elf_unittests") {
"chrome_elf_util_unittest.cc", "chrome_elf_util_unittest.cc",
"elf_imports_unittest.cc", "elf_imports_unittest.cc",
"hook_util/test/hook_util_test.cc", "hook_util/test/hook_util_test.cc",
"nt_registry/nt_registry_unittest.cc",
"run_all_unittests.cc", "run_all_unittests.cc",
] ]
include_dirs = [ "$target_gen_dir" ] include_dirs = [ "$target_gen_dir" ]
...@@ -185,13 +199,13 @@ test("chrome_elf_unittests") { ...@@ -185,13 +199,13 @@ test("chrome_elf_unittests") {
":crash", ":crash",
":hook_util", ":hook_util",
":hook_util_test_dll", ":hook_util_test_dll",
":nt_registry",
":security", ":security",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//chrome", "//chrome",
"//chrome/common:version_header", "//chrome/common:version_header",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
"//sandbox", "//sandbox",
"//testing/gtest", "//testing/gtest",
] ]
...@@ -222,20 +236,22 @@ test("chrome_elf_unittests") { ...@@ -222,20 +236,22 @@ test("chrome_elf_unittests") {
} }
shared_library("blacklist_test_main_dll") { shared_library("blacklist_test_main_dll") {
testonly = true
sources = [ sources = [
"blacklist/test/blacklist_test_main_dll.cc", "blacklist/test/blacklist_test_main_dll.cc",
"blacklist/test/blacklist_test_main_dll.def", "blacklist/test/blacklist_test_main_dll.def",
] ]
deps = [ deps = [
":blacklist", ":blacklist",
":nt_registry",
"//base", "//base",
"//build/config/sanitizers:deps", "//build/config/sanitizers:deps",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
] ]
} }
loadable_module("blacklist_test_dll_1") { loadable_module("blacklist_test_dll_1") {
testonly = true
sources = [ sources = [
"blacklist/test/blacklist_test_dll_1.cc", "blacklist/test/blacklist_test_dll_1.cc",
"blacklist/test/blacklist_test_dll_1.def", "blacklist/test/blacklist_test_dll_1.def",
...@@ -246,6 +262,7 @@ loadable_module("blacklist_test_dll_1") { ...@@ -246,6 +262,7 @@ loadable_module("blacklist_test_dll_1") {
} }
loadable_module("blacklist_test_dll_2") { loadable_module("blacklist_test_dll_2") {
testonly = true
sources = [ sources = [
"blacklist/test/blacklist_test_dll_2.cc", "blacklist/test/blacklist_test_dll_2.cc",
"blacklist/test/blacklist_test_dll_2.def", "blacklist/test/blacklist_test_dll_2.def",
...@@ -261,6 +278,7 @@ loadable_module("blacklist_test_dll_2") { ...@@ -261,6 +278,7 @@ loadable_module("blacklist_test_dll_2") {
# which does), Ninja would get confused and always rebuild this target because # which does), Ninja would get confused and always rebuild this target because
# it sees a declared output file but that file doesn't exist on disk. # it sees a declared output file but that file doesn't exist on disk.
loadable_module("blacklist_test_dll_3") { loadable_module("blacklist_test_dll_3") {
testonly = true
sources = [ sources = [
"blacklist/test/blacklist_test_dll_3.cc", "blacklist/test/blacklist_test_dll_3.cc",
] ]
...@@ -270,6 +288,7 @@ loadable_module("blacklist_test_dll_3") { ...@@ -270,6 +288,7 @@ loadable_module("blacklist_test_dll_3") {
} }
shared_library("hook_util_test_dll") { shared_library("hook_util_test_dll") {
testonly = true
sources = [ sources = [
"hook_util/test/hook_util_test_dll.cc", "hook_util/test/hook_util_test_dll.cc",
"hook_util/test/hook_util_test_dll.h", "hook_util/test/hook_util_test_dll.h",
......
...@@ -133,20 +133,18 @@ class BlacklistTest : public testing::Test { ...@@ -133,20 +133,18 @@ class BlacklistTest : public testing::Test {
// process-specific environment variables, for our test DLLs to access. // process-specific environment variables, for our test DLLs to access.
// This will only work as long as the IPC is within the same process. // This will only work as long as the IPC is within the same process.
void IpcOverrides() { void IpcOverrides() {
if (::wcslen(nt::HKCU_override) != 0) { base::string16 temp = nt::GetTestingOverride(nt::HKCU);
ASSERT_TRUE( if (!temp.empty())
::SetEnvironmentVariableW(L"hkcu_override", nt::HKCU_override)); ASSERT_TRUE(::SetEnvironmentVariableW(L"hkcu_override", temp.c_str()));
} temp = nt::GetTestingOverride(nt::HKLM);
if (::wcslen(nt::HKLM_override) != 0) { if (!temp.empty())
ASSERT_TRUE( ASSERT_TRUE(::SetEnvironmentVariableW(L"hklm_override", temp.c_str()));
::SetEnvironmentVariableW(L"hklm_override", nt::HKLM_override));
}
} }
void SetUp() override { void SetUp() override {
base::string16 temp; base::string16 temp;
override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp); override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp);
::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); ASSERT_TRUE(nt::SetTestingOverride(nt::HKCU, temp));
// Make the override path available to our test DLL. // Make the override path available to our test DLL.
IpcOverrides(); IpcOverrides();
...@@ -203,10 +201,9 @@ class BlacklistTest : public testing::Test { ...@@ -203,10 +201,9 @@ class BlacklistTest : public testing::Test {
TestDll_RemoveDllFromBlacklist(kTestDllName1); TestDll_RemoveDllFromBlacklist(kTestDllName1);
TestDll_RemoveDllFromBlacklist(kTestDllName2); TestDll_RemoveDllFromBlacklist(kTestDllName2);
TestDll_RemoveDllFromBlacklist(kTestDllName3); TestDll_RemoveDllFromBlacklist(kTestDllName3);
}
// A scoped temporary directory to be destroyed with this test. ASSERT_TRUE(nt::SetTestingOverride(nt::HKCU, base::string16()));
base::ScopedTempDir reg_override_dir_; }
}; };
TEST_F(BlacklistTest, Beacon) { TEST_F(BlacklistTest, Beacon) {
......
...@@ -14,22 +14,20 @@ namespace { ...@@ -14,22 +14,20 @@ namespace {
void GetIpcOverrides() { void GetIpcOverrides() {
DWORD buffer_size = ::GetEnvironmentVariableW(L"hkcu_override", nullptr, 0); DWORD buffer_size = ::GetEnvironmentVariableW(L"hkcu_override", nullptr, 0);
if (buffer_size > 0) { if (buffer_size > 0) {
wchar_t* content = new wchar_t[buffer_size]; std::wstring content(buffer_size, L'\0');
buffer_size = buffer_size =
::GetEnvironmentVariableW(L"hkcu_override", content, buffer_size); ::GetEnvironmentVariableW(L"hkcu_override", &content[0], buffer_size);
if (buffer_size) if (buffer_size)
::wcsncpy(nt::HKCU_override, content, nt::g_kRegMaxPathLen - 1); nt::SetTestingOverride(nt::HKCU, content);
delete[] content;
} }
buffer_size = ::GetEnvironmentVariableW(L"hklm_override", nullptr, 0); buffer_size = ::GetEnvironmentVariableW(L"hklm_override", nullptr, 0);
if (buffer_size > 0) { if (buffer_size > 0) {
wchar_t* content = new wchar_t[buffer_size]; std::wstring content(buffer_size, L'\0');
buffer_size = buffer_size =
::GetEnvironmentVariableW(L"hklm_override", content, buffer_size); ::GetEnvironmentVariableW(L"hklm_override", &content[0], buffer_size);
if (buffer_size) if (buffer_size)
::wcsncpy(nt::HKLM_override, content, nt::g_kRegMaxPathLen - 1); nt::SetTestingOverride(nt::HKLM, content);
delete[] content;
} }
return; return;
......
...@@ -72,17 +72,25 @@ bool IsSecuritySet() { ...@@ -72,17 +72,25 @@ bool IsSecuritySet() {
} }
void RegRedirect(nt::ROOT_KEY key, void RegRedirect(nt::ROOT_KEY key,
registry_util::RegistryOverrideManager& rom) { registry_util::RegistryOverrideManager* rom) {
ASSERT_NE(key, nt::AUTO);
base::string16 temp; base::string16 temp;
if (key == nt::HKCU) { if (key == nt::HKCU) {
rom.OverrideRegistry(HKEY_CURRENT_USER, &temp); rom->OverrideRegistry(HKEY_CURRENT_USER, &temp);
::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); ASSERT_TRUE(nt::SetTestingOverride(nt::HKCU, temp));
} else if (key == nt::HKLM) { } else {
rom.OverrideRegistry(HKEY_LOCAL_MACHINE, &temp); rom->OverrideRegistry(HKEY_LOCAL_MACHINE, &temp);
::wcsncpy(nt::HKLM_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); ASSERT_TRUE(nt::SetTestingOverride(nt::HKLM, temp));
} }
// nt::AUTO should not be passed into this function. }
void CancelRegRedirect(nt::ROOT_KEY key) {
ASSERT_NE(key, nt::AUTO);
if (key == nt::HKCU)
ASSERT_TRUE(nt::SetTestingOverride(nt::HKCU, base::string16()));
else
ASSERT_TRUE(nt::SetTestingOverride(nt::HKLM, base::string16()));
} }
TEST(ChromeElfUtilTest, CanaryTest) { TEST(ChromeElfUtilTest, CanaryTest) {
...@@ -108,7 +116,7 @@ TEST(ChromeElfUtilTest, BrowserProcessSecurityTest) { ...@@ -108,7 +116,7 @@ TEST(ChromeElfUtilTest, BrowserProcessSecurityTest) {
// Set up registry override for this test. // Set up registry override for this test.
registry_util::RegistryOverrideManager override_manager; registry_util::RegistryOverrideManager override_manager;
RegRedirect(nt::HKCU, override_manager); RegRedirect(nt::HKCU, &override_manager);
// First, ensure that the emergency-off finch signal works. // First, ensure that the emergency-off finch signal works.
EXPECT_TRUE(SetSecurityFinchFlag(true)); EXPECT_TRUE(SetSecurityFinchFlag(true));
...@@ -119,112 +127,8 @@ TEST(ChromeElfUtilTest, BrowserProcessSecurityTest) { ...@@ -119,112 +127,8 @@ TEST(ChromeElfUtilTest, BrowserProcessSecurityTest) {
// Second, test that the process mitigation is set when no finch signal. // Second, test that the process mitigation is set when no finch signal.
elf_security::EarlyBrowserSecurity(); elf_security::EarlyBrowserSecurity();
EXPECT_TRUE(IsSecuritySet()); EXPECT_TRUE(IsSecuritySet());
}
//------------------------------------------------------------------------------
// NT registry API tests (chrome_elf_reg)
//------------------------------------------------------------------------------
TEST(ChromeElfUtilTest, NTRegistry) {
HANDLE key_handle;
const wchar_t* dword_val_name = L"DwordTestValue";
DWORD dword_val = 1234;
const wchar_t* sz_val_name = L"SzTestValue";
base::string16 sz_val = L"blah de blah de blahhhhh.";
const wchar_t* sz_val_name2 = L"SzTestValueEmpty";
base::string16 sz_val2 = L"";
const wchar_t* multisz_val_name = L"SzmultiTestValue";
std::vector<base::string16> multisz_val;
base::string16 multi1 = L"one";
base::string16 multi2 = L"two";
base::string16 multi3 = L"three";
const wchar_t* multisz_val_name2 = L"SzmultiTestValueBad";
base::string16 multi_empty = L"";
const wchar_t* sz_new_key_1 = L"test\\new\\subkey";
const wchar_t* sz_new_key_2 = L"test\\new\\subkey\\blah\\";
const wchar_t* sz_new_key_3 = L"\\test\\new\\subkey\\\\blah2";
// Set up registry override for this test.
registry_util::RegistryOverrideManager override_manager;
RegRedirect(nt::HKCU, override_manager);
// Create a temp key to play under.
ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, elf_sec::kRegSecurityPath,
KEY_ALL_ACCESS, &key_handle));
// Exercise the supported getter & setter functions.
EXPECT_TRUE(nt::SetRegValueDWORD(key_handle, dword_val_name, dword_val));
EXPECT_TRUE(nt::SetRegValueSZ(key_handle, sz_val_name, sz_val));
EXPECT_TRUE(nt::SetRegValueSZ(key_handle, sz_val_name2, sz_val2));
DWORD get_dword = 0;
base::string16 get_sz;
EXPECT_TRUE(nt::QueryRegValueDWORD(key_handle, dword_val_name, &get_dword) &&
get_dword == dword_val);
EXPECT_TRUE(nt::QueryRegValueSZ(key_handle, sz_val_name, &get_sz) &&
get_sz.compare(sz_val) == 0);
EXPECT_TRUE(nt::QueryRegValueSZ(key_handle, sz_val_name2, &get_sz) &&
get_sz.compare(sz_val2) == 0);
multisz_val.push_back(multi1);
multisz_val.push_back(multi2);
multisz_val.push_back(multi3);
EXPECT_TRUE(
nt::SetRegValueMULTISZ(key_handle, multisz_val_name, multisz_val));
multisz_val.clear();
multisz_val.push_back(multi_empty);
EXPECT_TRUE(
nt::SetRegValueMULTISZ(key_handle, multisz_val_name2, multisz_val));
multisz_val.clear();
EXPECT_TRUE(
nt::QueryRegValueMULTISZ(key_handle, multisz_val_name, &multisz_val));
if (multisz_val.size() == 3) {
EXPECT_TRUE(multi1.compare(multisz_val.at(0)) == 0);
EXPECT_TRUE(multi2.compare(multisz_val.at(1)) == 0);
EXPECT_TRUE(multi3.compare(multisz_val.at(2)) == 0);
} else {
EXPECT_TRUE(false);
}
multisz_val.clear();
EXPECT_TRUE( CancelRegRedirect(nt::HKCU);
nt::QueryRegValueMULTISZ(key_handle, multisz_val_name2, &multisz_val));
if (multisz_val.size() == 1) {
EXPECT_TRUE(multi_empty.compare(multisz_val.at(0)) == 0);
} else {
EXPECT_TRUE(false);
}
multisz_val.clear();
// Clean up
EXPECT_TRUE(nt::DeleteRegKey(key_handle));
nt::CloseRegKey(key_handle);
// More tests for CreateRegKey recursion.
ASSERT_TRUE(
nt::CreateRegKey(nt::HKCU, sz_new_key_1, KEY_ALL_ACCESS, nullptr));
EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, sz_new_key_1, KEY_ALL_ACCESS,
&key_handle, nullptr));
EXPECT_TRUE(nt::DeleteRegKey(key_handle));
nt::CloseRegKey(key_handle);
ASSERT_TRUE(
nt::CreateRegKey(nt::HKCU, sz_new_key_2, KEY_ALL_ACCESS, nullptr));
EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, sz_new_key_2, KEY_ALL_ACCESS,
&key_handle, nullptr));
EXPECT_TRUE(nt::DeleteRegKey(key_handle));
nt::CloseRegKey(key_handle);
ASSERT_TRUE(
nt::CreateRegKey(nt::HKCU, sz_new_key_3, KEY_ALL_ACCESS, nullptr));
EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, L"test\\new\\subkey\\blah2",
KEY_ALL_ACCESS, &key_handle, nullptr));
EXPECT_TRUE(nt::DeleteRegKey(key_handle));
nt::CloseRegKey(key_handle);
ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, nullptr, KEY_ALL_ACCESS, &key_handle));
nt::CloseRegKey(key_handle);
} }
// Parameterized test with paramters: // Parameterized test with paramters:
...@@ -237,8 +141,8 @@ class ChromeElfUtilTest ...@@ -237,8 +141,8 @@ class ChromeElfUtilTest
protected: protected:
void SetUp() override { void SetUp() override {
// Set up registry override for these tests. // Set up registry override for these tests.
RegRedirect(nt::HKLM, override_manager_); RegRedirect(nt::HKLM, &override_manager_);
RegRedirect(nt::HKCU, override_manager_); RegRedirect(nt::HKCU, &override_manager_);
const char* app; const char* app;
const char* level; const char* level;
...@@ -263,6 +167,11 @@ class ChromeElfUtilTest ...@@ -263,6 +167,11 @@ class ChromeElfUtilTest
} }
} }
void TearDown() override {
CancelRegRedirect(nt::HKCU);
CancelRegRedirect(nt::HKLM);
}
base::string16 BuildKey(const wchar_t* path, const wchar_t* guid) { base::string16 BuildKey(const wchar_t* path, const wchar_t* guid) {
base::string16 full_key_path(path); base::string16 full_key_path(path);
full_key_path.append(1, L'\\'); full_key_path.append(1, L'\\');
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <versionhelpers.h> // windows.h must be before #include <versionhelpers.h> // windows.h must be before
#include "base/win/pe_image.h" #include "base/win/pe_image.h"
#include "chrome_elf/nt_registry/nt_registry.h" // utils
#include "sandbox/win/src/interception_internal.h" #include "sandbox/win/src/interception_internal.h"
#include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/sandbox_utils.h" #include "sandbox/win/src/sandbox_utils.h"
...@@ -18,31 +19,6 @@ namespace { ...@@ -18,31 +19,6 @@ namespace {
// Common hooking utility functions - LOCAL // Common hooking utility functions - LOCAL
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if !defined(_WIN64)
// Whether a process is running under WOW64 (the wrapper that allows 32-bit
// processes to run on 64-bit versions of Windows). This will return
// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit
// Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g.
// the process does not have sufficient access rights to determine this.
enum WOW64Status {
WOW64_DISABLED,
WOW64_ENABLED,
WOW64_UNKNOWN,
};
WOW64Status GetWOW64StatusForCurrentProcess() {
typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL);
IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
if (!is_wow64_process)
return WOW64_DISABLED;
BOOL is_wow64 = FALSE;
if (!is_wow64_process(GetCurrentProcess(), &is_wow64))
return WOW64_UNKNOWN;
return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
}
#endif // !defined(_WIN64)
// Change the page protections to writable, copy the data, // Change the page protections to writable, copy the data,
// restore protections. Returns a winerror code. // restore protections. Returns a winerror code.
DWORD PatchMem(void* target, void* new_bytes, size_t length) { DWORD PatchMem(void* target, void* new_bytes, size_t length) {
...@@ -246,7 +222,7 @@ sandbox::ServiceResolverThunk* HookSystemService(bool relaxed) { ...@@ -246,7 +222,7 @@ sandbox::ServiceResolverThunk* HookSystemService(bool relaxed) {
// handling one like it does in 32-bit versions). // handling one like it does in 32-bit versions).
thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); thunk = new sandbox::ServiceResolverThunk(current_process, relaxed);
#else #else
if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) { if (nt::IsCurrentProcWow64()) {
if (::IsWindows10OrGreater()) if (::IsWindows10OrGreater())
thunk = new sandbox::Wow64W10ResolverThunk(current_process, relaxed); thunk = new sandbox::Wow64W10ResolverThunk(current_process, relaxed);
else if (::IsWindows8OrGreater()) else if (::IsWindows8OrGreater())
......
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/chrome_build.gni")
import("//testing/test.gni")
assert(is_win)
# This target only contains utility functions which must only depend on
# kernel32. Please don't add dependencies on other system libraries.
static_library("nt_registry") {
sources = [
"../../sandbox/win/src/nt_internals.h",
"nt_registry.cc",
"nt_registry.h",
]
libs = [ "kernel32.lib" ]
}
...@@ -6,3 +6,8 @@ include_rules = [ ...@@ -6,3 +6,8 @@ include_rules = [
"-chrome_elf", "-chrome_elf",
"+chrome_elf/nt_registry/nt_registry.h", "+chrome_elf/nt_registry/nt_registry.h",
] ]
specific_include_rules = {
".*_unittest\.cc": [
"+base",
]
}
\ No newline at end of file
This diff is collapsed.
...@@ -28,16 +28,27 @@ ...@@ -28,16 +28,27 @@
namespace nt { namespace nt {
// These globals are only used in test suites that use reg redirection // Windows registry maximum lengths (in chars). Not including null char.
// of HKLM and/or HKCU. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
extern const size_t g_kRegMaxPathLen; constexpr size_t g_kRegMaxPathLen = 255;
extern wchar_t HKLM_override[]; constexpr size_t g_kRegMaxValueName = 16383;
extern wchar_t HKCU_override[];
// AUTO will choose depending on system install or not. // AUTO will choose depending on system install or not.
// Use HKLM or HKCU to override. // Use HKLM or HKCU to override.
typedef enum _ROOT_KEY { AUTO = 0, HKLM, HKCU } ROOT_KEY; typedef enum _ROOT_KEY { AUTO = 0, HKLM, HKCU } ROOT_KEY;
// Used with wrapper functions to request registry redirection override.
// Maps to KEY_WOW64_32KEY and KEY_WOW64_64KEY access flags.
enum WOW64_OVERRIDE {
NONE = 0L,
WOW6432 = KEY_WOW64_32KEY,
WOW6464 = KEY_WOW64_64KEY
};
//------------------------------------------------------------------------------
// Create, open, delete, close functions
//------------------------------------------------------------------------------
// Create and/or open a registry key. // Create and/or open a registry key.
// - This function will recursively create multiple sub-keys if required for // - This function will recursively create multiple sub-keys if required for
// |key_path|. // |key_path|.
...@@ -66,7 +77,10 @@ bool DeleteRegKey(HANDLE key); ...@@ -66,7 +77,10 @@ bool DeleteRegKey(HANDLE key);
// Delete a registry key. // Delete a registry key.
// - WRAPPER: Function opens and closes the target key for caller. // - WRAPPER: Function opens and closes the target key for caller.
bool DeleteRegKey(ROOT_KEY root, const wchar_t* key_path); // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool DeleteRegKey(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path);
// Close a registry key handle that was opened with CreateRegKey or OpenRegKey. // Close a registry key handle that was opened with CreateRegKey or OpenRegKey.
void CloseRegKey(HANDLE key); void CloseRegKey(HANDLE key);
...@@ -96,7 +110,9 @@ bool QueryRegValueDWORD(HANDLE key, ...@@ -96,7 +110,9 @@ bool QueryRegValueDWORD(HANDLE key,
// Query DWORD value. // Query DWORD value.
// - WRAPPER: Function opens and closes the target key for caller, and works // - WRAPPER: Function opens and closes the target key for caller, and works
// with DWORD data type. // with DWORD data type.
// - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool QueryRegValueDWORD(ROOT_KEY root, bool QueryRegValueDWORD(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path, const wchar_t* key_path,
const wchar_t* value_name, const wchar_t* value_name,
DWORD* out_dword); DWORD* out_dword);
...@@ -112,7 +128,9 @@ bool QueryRegValueSZ(HANDLE key, ...@@ -112,7 +128,9 @@ bool QueryRegValueSZ(HANDLE key,
// Query SZ (string) value. // Query SZ (string) value.
// - WRAPPER: Function opens and closes the target key for caller, and works // - WRAPPER: Function opens and closes the target key for caller, and works
// with SZ data type. // with SZ data type.
// - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool QueryRegValueSZ(ROOT_KEY root, bool QueryRegValueSZ(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path, const wchar_t* key_path,
const wchar_t* value_name, const wchar_t* value_name,
std::wstring* out_sz); std::wstring* out_sz);
...@@ -128,7 +146,9 @@ bool QueryRegValueMULTISZ(HANDLE key, ...@@ -128,7 +146,9 @@ bool QueryRegValueMULTISZ(HANDLE key,
// Query MULTI_SZ (multiple strings) value. // Query MULTI_SZ (multiple strings) value.
// - WRAPPER: Function opens and closes the target key for caller, and works // - WRAPPER: Function opens and closes the target key for caller, and works
// with MULTI_SZ data type. // with MULTI_SZ data type.
// - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool QueryRegValueMULTISZ(ROOT_KEY root, bool QueryRegValueMULTISZ(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path, const wchar_t* key_path,
const wchar_t* value_name, const wchar_t* value_name,
std::vector<std::wstring>* out_multi_sz); std::vector<std::wstring>* out_multi_sz);
...@@ -155,7 +175,9 @@ bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value); ...@@ -155,7 +175,9 @@ bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value);
// Set DWORD value. // Set DWORD value.
// - WRAPPER: Function opens and closes the target key for caller, and works // - WRAPPER: Function opens and closes the target key for caller, and works
// with DWORD data type. // with DWORD data type.
// - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool SetRegValueDWORD(ROOT_KEY root, bool SetRegValueDWORD(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path, const wchar_t* key_path,
const wchar_t* value_name, const wchar_t* value_name,
DWORD value); DWORD value);
...@@ -171,7 +193,9 @@ bool SetRegValueSZ(HANDLE key, ...@@ -171,7 +193,9 @@ bool SetRegValueSZ(HANDLE key,
// Set SZ (string) value. // Set SZ (string) value.
// - WRAPPER: Function opens and closes the target key for caller, and works // - WRAPPER: Function opens and closes the target key for caller, and works
// with SZ data type. // with SZ data type.
// - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool SetRegValueSZ(ROOT_KEY root, bool SetRegValueSZ(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path, const wchar_t* key_path,
const wchar_t* value_name, const wchar_t* value_name,
const std::wstring& value); const std::wstring& value);
...@@ -187,7 +211,9 @@ bool SetRegValueMULTISZ(HANDLE key, ...@@ -187,7 +211,9 @@ bool SetRegValueMULTISZ(HANDLE key,
// Set MULTI_SZ (multiple strings) value. // Set MULTI_SZ (multiple strings) value.
// - WRAPPER: Function opens and closes the target key for caller, and works // - WRAPPER: Function opens and closes the target key for caller, and works
// with MULTI_SZ data type. // with MULTI_SZ data type.
// - Use |wow64_override| to force redirection behaviour, or pass nt::NONE.
bool SetRegValueMULTISZ(ROOT_KEY root, bool SetRegValueMULTISZ(ROOT_KEY root,
WOW64_OVERRIDE wow64_override,
const wchar_t* key_path, const wchar_t* key_path,
const wchar_t* value_name, const wchar_t* value_name,
const std::vector<std::wstring>& values); const std::vector<std::wstring>& values);
...@@ -199,6 +225,15 @@ bool SetRegValueMULTISZ(ROOT_KEY root, ...@@ -199,6 +225,15 @@ bool SetRegValueMULTISZ(ROOT_KEY root,
// Returns the current user SID in string form. // Returns the current user SID in string form.
const wchar_t* GetCurrentUserSidString(); const wchar_t* GetCurrentUserSidString();
// Returns true if this process is WOW64.
bool IsCurrentProcWow64();
// Setter function for test suites that use reg redirection.
bool SetTestingOverride(ROOT_KEY root, const std::wstring& new_path);
// Getter function for test suites that use reg redirection.
std::wstring GetTestingOverride(ROOT_KEY root);
}; // namespace nt }; // namespace nt
#endif // CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_ #endif // CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment