| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/safe_browsing/environment_data_collection_win.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/base_paths.h" | |
| 10 #include "base/files/file_path.h" | |
| 11 #include "base/path_service.h" | |
| 12 #include "base/scoped_native_library.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | |
| 14 #include "base/test/test_reg_util_win.h" | |
| 15 #include "base/win/registry.h" | |
| 16 #include "chrome/browser/safe_browsing/module_integrity_unittest_util_win.h" | |
| 17 #include "chrome/browser/safe_browsing/module_integrity_verifier_win.h" | |
| 18 #include "chrome/browser/safe_browsing/path_sanitizer.h" | |
| 19 #include "chrome/common/safe_browsing/csd.pb.h" | |
| 20 #include "chrome_elf/chrome_elf_constants.h" | |
| 21 #include "net/base/winsock_init.h" | |
| 22 #include "testing/gtest/include/gtest/gtest.h" | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 const wchar_t test_dll[] = L"test_name.dll"; | |
| 27 | |
| 28 // Helper function that returns true if a dll with filename |dll_name| is | |
| 29 // found in |process_report|. | |
| 30 bool ProcessReportContainsDll( | |
| 31 const safe_browsing::ClientIncidentReport_EnvironmentData_Process& | |
| 32 process_report, | |
| 33 const base::FilePath& dll_name) { | |
| 34 for (int i = 0; i < process_report.dll_size(); ++i) { | |
| 35 base::FilePath current_dll = | |
| 36 base::FilePath::FromUTF8Unsafe(process_report.dll(i).path()); | |
| 37 | |
| 38 if (current_dll.BaseName() == dll_name) | |
| 39 return true; | |
| 40 } | |
| 41 | |
| 42 return false; | |
| 43 } | |
| 44 | |
| 45 // Look through dll entries and check for the presence of the LSP feature for | |
| 46 // |dll|. | |
| 47 bool DllEntryContainsLspFeature( | |
| 48 const safe_browsing::ClientIncidentReport_EnvironmentData_Process& | |
| 49 process_report, | |
| 50 const std::string& dll) { | |
| 51 for (int i = 0; i < process_report.dll_size(); ++i) { | |
| 52 if (process_report.dll(i).path() == dll) { | |
| 53 // Verify each feature of |dll|. | |
| 54 for (int j = 0; j < process_report.dll(i).feature_size(); ++j) { | |
| 55 if (process_report.dll(i).feature(j) == | |
| 56 safe_browsing::ClientIncidentReport_EnvironmentData_Process_Dll:: | |
| 57 LSP) | |
| 58 // LSP feature found. | |
| 59 return true; | |
| 60 } | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 return false; | |
| 65 } | |
| 66 | |
| 67 } // namespace | |
| 68 | |
| 69 TEST(SafeBrowsingEnvironmentDataCollectionWinTest, CollectDlls) { | |
| 70 // This test will check if the CollectDlls method works by loading | |
| 71 // a dll and then checking if we can find it within the process report. | |
| 72 // Pick msvidc32.dll as it is present from WinXP to Win8 and yet rarely used. | |
| 73 // msvidc32.dll exists in both 32 and 64 bit versions. | |
| 74 base::FilePath msvdc32_dll(L"msvidc32.dll"); | |
| 75 | |
| 76 safe_browsing::ClientIncidentReport_EnvironmentData_Process process_report; | |
| 77 safe_browsing::CollectDlls(&process_report); | |
| 78 | |
| 79 ASSERT_FALSE(ProcessReportContainsDll(process_report, msvdc32_dll)); | |
| 80 | |
| 81 // Redo the same verification after loading a new dll. | |
| 82 base::ScopedNativeLibrary library(msvdc32_dll); | |
| 83 | |
| 84 process_report.clear_dll(); | |
| 85 safe_browsing::CollectDlls(&process_report); | |
| 86 | |
| 87 ASSERT_TRUE(ProcessReportContainsDll(process_report, msvdc32_dll)); | |
| 88 } | |
| 89 | |
| 90 TEST(SafeBrowsingEnvironmentDataCollectionWinTest, RecordLspFeature) { | |
| 91 net::EnsureWinsockInit(); | |
| 92 | |
| 93 // Populate our incident report with loaded modules. | |
| 94 safe_browsing::ClientIncidentReport_EnvironmentData_Process process_report; | |
| 95 safe_browsing::CollectDlls(&process_report); | |
| 96 | |
| 97 // We'll test RecordLspFeatures against a real dll registered as a LSP. All | |
| 98 // dll paths are expected to be lowercase in the process report. | |
| 99 std::string lsp = "c:\\windows\\system32\\mswsock.dll"; | |
| 100 int base_address = 0x77770000; | |
| 101 int length = 0x180000; | |
| 102 | |
| 103 safe_browsing::RecordLspFeature(&process_report); | |
| 104 | |
| 105 // Return successfully if LSP feature is found. | |
| 106 if (DllEntryContainsLspFeature(process_report, lsp)) | |
| 107 return; | |
| 108 | |
| 109 // |lsp| was not already loaded into the current process. Manually add it | |
| 110 // to the process report so that it will get marked as a LSP. | |
| 111 safe_browsing::ClientIncidentReport_EnvironmentData_Process_Dll* dll = | |
| 112 process_report.add_dll(); | |
| 113 dll->set_path(lsp); | |
| 114 dll->set_base_address(base_address); | |
| 115 dll->set_length(length); | |
| 116 | |
| 117 safe_browsing::RecordLspFeature(&process_report); | |
| 118 | |
| 119 // Return successfully if LSP feature is found. | |
| 120 if (DllEntryContainsLspFeature(process_report, lsp)) | |
| 121 return; | |
| 122 | |
| 123 FAIL() << "No LSP feature found for " << lsp; | |
| 124 } | |
| 125 | |
| 126 TEST(SafeBrowsingEnvironmentDataCollectionWinTest, CollectDllBlacklistData) { | |
| 127 // Ensure that CollectDllBlacklistData correctly adds the set of sanitized dll | |
| 128 // names currently stored in the registry to the report. | |
| 129 registry_util::RegistryOverrideManager override_manager; | |
| 130 override_manager.OverrideRegistry(HKEY_CURRENT_USER, L"safe_browsing_test"); | |
| 131 | |
| 132 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER, | |
| 133 blacklist::kRegistryFinchListPath, | |
| 134 KEY_QUERY_VALUE | KEY_SET_VALUE); | |
| 135 | |
| 136 // Check that with an empty registry the blacklisted dlls field is left empty. | |
| 137 safe_browsing::ClientIncidentReport_EnvironmentData_Process process_report; | |
| 138 safe_browsing::CollectDllBlacklistData(&process_report); | |
| 139 EXPECT_EQ(0, process_report.blacklisted_dll_size()); | |
| 140 | |
| 141 // Check that after adding exactly one dll to the registry it appears in the | |
| 142 // process report. | |
| 143 blacklist_registry_key.WriteValue(test_dll, test_dll); | |
| 144 safe_browsing::CollectDllBlacklistData(&process_report); | |
| 145 ASSERT_EQ(1, process_report.blacklisted_dll_size()); | |
| 146 | |
| 147 base::string16 process_report_dll = | |
| 148 base::UTF8ToWide(process_report.blacklisted_dll(0)); | |
| 149 EXPECT_EQ(base::string16(test_dll), process_report_dll); | |
| 150 | |
| 151 // Check that if the registry contains the full path to a dll it is properly | |
| 152 // sanitized before being reported. | |
| 153 blacklist_registry_key.DeleteValue(test_dll); | |
| 154 process_report.clear_blacklisted_dll(); | |
| 155 | |
| 156 base::FilePath path; | |
| 157 ASSERT_TRUE(PathService::Get(base::DIR_HOME, &path)); | |
| 158 base::string16 input_path = | |
| 159 path.Append(FILE_PATH_LITERAL("test_path.dll")).value(); | |
| 160 | |
| 161 std::string path_expected = base::FilePath(FILE_PATH_LITERAL("~")) | |
| 162 .Append(FILE_PATH_LITERAL("test_path.dll")) | |
| 163 .AsUTF8Unsafe(); | |
| 164 | |
| 165 blacklist_registry_key.WriteValue(input_path.c_str(), input_path.c_str()); | |
| 166 safe_browsing::CollectDllBlacklistData(&process_report); | |
| 167 | |
| 168 ASSERT_EQ(1, process_report.blacklisted_dll_size()); | |
| 169 std::string process_report_path = process_report.blacklisted_dll(0); | |
| 170 EXPECT_EQ(path_expected, process_report_path); | |
| 171 } | |
| 172 | |
| 173 TEST(SafeBrowsingEnvironmentDataCollectionWinTest, VerifyLoadedModules) { | |
| 174 // Load the test modules. | |
| 175 std::vector<base::ScopedNativeLibrary> test_dlls( | |
| 176 safe_browsing::kTestDllNamesCount); | |
| 177 for (size_t i = 0; i < safe_browsing::kTestDllNamesCount; ++i) { | |
| 178 test_dlls[i].Reset(LoadNativeLibrary( | |
| 179 base::FilePath(safe_browsing::kTestDllNames[i]), NULL)); | |
| 180 } | |
| 181 | |
| 182 // Edit the first byte of the function exported by the first module. | |
| 183 HMODULE module_handle = GetModuleHandle(safe_browsing::kTestDllNames[0]); | |
| 184 EXPECT_NE(reinterpret_cast<HANDLE>(NULL), module_handle); | |
| 185 uint8_t* export_addr = reinterpret_cast<uint8_t*>( | |
| 186 GetProcAddress(module_handle, safe_browsing::kTestExportName)); | |
| 187 EXPECT_NE(reinterpret_cast<uint8_t*>(NULL), export_addr); | |
| 188 | |
| 189 uint8_t new_val = (*export_addr) + 1; | |
| 190 SIZE_T bytes_written = 0; | |
| 191 WriteProcessMemory(GetCurrentProcess(), | |
| 192 export_addr, | |
| 193 reinterpret_cast<void*>(&new_val), | |
| 194 1, | |
| 195 &bytes_written); | |
| 196 EXPECT_EQ(1, bytes_written); | |
| 197 | |
| 198 safe_browsing::ClientIncidentReport_EnvironmentData_Process process_report; | |
| 199 safe_browsing::CollectModuleVerificationData( | |
| 200 safe_browsing::kTestDllNames, | |
| 201 safe_browsing::kTestDllNamesCount, | |
| 202 &process_report); | |
| 203 | |
| 204 // CollectModuleVerificationData should return the single modified module and | |
| 205 // its modified export. The other module, being unmodified, is omitted from | |
| 206 // the returned list of modules. | |
| 207 EXPECT_EQ(1, process_report.module_state_size()); | |
| 208 | |
| 209 EXPECT_EQ(base::WideToUTF8(std::wstring(safe_browsing::kTestDllNames[0])), | |
| 210 process_report.module_state(0).name()); | |
| 211 EXPECT_EQ( | |
| 212 safe_browsing::ClientIncidentReport_EnvironmentData_Process_ModuleState:: | |
| 213 MODULE_STATE_MODIFIED, | |
| 214 process_report.module_state(0).modified_state()); | |
| 215 EXPECT_EQ(1, process_report.module_state(0).modified_export_size()); | |
| 216 EXPECT_EQ(std::string(safe_browsing::kTestExportName), | |
| 217 process_report.module_state(0).modified_export(0)); | |
| 218 } | |
| OLD | NEW |