Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(671)

Side by Side Diff: chrome/browser/safe_browsing/incident_reporting/module_load_analyzer_win.cc

Issue 1643573002: Add a ModuleLoadAnalyzer which checks modules against a whitelist (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/soon when/soon as Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/incident_reporting/module_load_analyzer.h "
6
7 #include "base/file_version_info.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
rkaplow 2016/02/09 20:45:52 should be using histogram_macros.h
proberge 2016/02/10 14:21:41 Done.
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/install_verification/win/module_info.h"
16 #include "chrome/browser/install_verification/win/module_verification_common.h"
17 #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h"
18 #include "chrome/browser/safe_browsing/incident_reporting/suspicious_module_inci dent.h"
19 #include "chrome/browser/safe_browsing/path_sanitizer.h"
20 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
21 #include "chrome/common/safe_browsing/binary_feature_extractor.h"
22 #include "chrome/common/safe_browsing/csd.pb.h"
23 #include "crypto/sha2.h"
24
25 #if defined(SAFE_BROWSING_DB_LOCAL)
26 #include "chrome/browser/safe_browsing/local_database_manager.h"
27 #elif defined(SAFE_BROWSING_DB_REMOTE)
28 #include "chrome/browser/safe_browsing/remote_database_manager.h"
29 #endif
30
31 namespace safe_browsing {
32
33 static bool g_stop_module_load_analysis_ = false;
34
35 // Enables incident reporting when non-whitelisted modules are found.
36 const base::Feature kIncidentReportingModuleLoadAnalysis{
37 "IncidentReportingModuleLoadAnalysis", base::FEATURE_DISABLED_BY_DEFAULT};
38
39 ModuleLoadAnalyzer::~ModuleLoadAnalyzer() {
40 g_stop_module_load_analysis_ = true;
41 }
42
43 void ModuleLoadAnalyzer::Initialize() {
44 DCHECK(database_manager_);
45 // For testing only. In practice, Initialize should ever only be called once.
46 g_stop_module_load_analysis_ = false;
47 if (base::FeatureList::IsEnabled(kIncidentReportingModuleLoadAnalysis)) {
48 scoped_refptr<SafeBrowsingService> safe_browsing_service(
49 g_browser_process->safe_browsing_service());
50
51 if (safe_browsing_service) {
52 safe_browsing_service
53 ->RegisterExtendedReportingOnlyDelayedAnalysisCallback(
54 base::Bind(&ModuleLoadAnalyzer::VerifyModuleLoadState,
55 base::Unretained(this)));
56 }
57 }
58 }
59
60 // Retrieves the set of suspicious modules that are loaded in the process.
61 void ModuleLoadAnalyzer::GetLoadedSuspiciousModulesOnIOThread(
62 scoped_ptr<IncidentReceiver> incident_receiver) {
63 std::set<ModuleInfo> module_info_set;
64 base::TimeTicks start_time = base::TimeTicks::Now();
65 scoped_ptr<std::set<base::string16>> suspicious_names(
66 new std::set<base::string16>);
67
68 if (!GetLoadedModules(&module_info_set))
69 return;
70
71 std::set<ModuleInfo>::const_iterator module_iter(module_info_set.begin());
72 for (; module_iter != module_info_set.end(); ++module_iter) {
73 base::string16 module_file_name(base::ToLowerASCII(
74 base::FilePath(module_iter->name).BaseName().value()));
75
76 // If not whitelisted.
77 if (!database_manager_->MatchModuleWhitelistString(
78 base::UTF16ToUTF8(module_file_name)))
79 suspicious_names->insert(module_iter->name);
80 }
81
82 UMA_HISTOGRAM_TIMES("SBIRS.SuspiciousModuleDetectionTime",
83 base::TimeTicks::Now() - start_time);
84
85 if (!suspicious_names->empty()) {
86 // Note that we use BLOCK_SHUTDOWN here but manually end the processing as
87 // soon as the analyzer is destroyed.
88 scoped_refptr<base::TaskRunner> task_runner =
89 content::BrowserThread::GetBlockingPool()
90 ->GetTaskRunnerWithShutdownBehavior(
91 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
92
93 task_runner->PostTask(
94 FROM_HERE,
95 base::Bind(&ModuleLoadAnalyzer::ReportIncidentsForSuspiciousModules,
96 base::Passed(std::move(suspicious_names)),
97 base::Passed(std::move(incident_receiver))));
98 }
99 }
100
101 // static
102 void ModuleLoadAnalyzer::ReportIncidentsForSuspiciousModules(
103 scoped_ptr<std::set<base::string16>> module_names,
104 scoped_ptr<IncidentReceiver> incident_receiver) {
105 PathSanitizer path_sanitizer;
106 base::TimeTicks start_time = base::TimeTicks::Now();
107
108 UMA_HISTOGRAM_COUNTS("SBIRS.SuspiciousModuleReportCount",
109 module_names->size());
110
111 for (const auto& module_name : *module_names) {
112 if (g_stop_module_load_analysis_)
113 return;
114 // TODO(proberge): Skip over modules that have already been reported.
115
116 scoped_ptr<ClientIncidentReport_IncidentData_SuspiciousModuleIncident>
117 suspicious_module(
118 new ClientIncidentReport_IncidentData_SuspiciousModuleIncident());
119
120 const base::FilePath module_path(module_name);
121
122 // Sanitized path.
123 base::FilePath sanitized_path(module_path);
124 path_sanitizer.StripHomeDirectory(&sanitized_path);
125 suspicious_module->set_path(base::WideToUTF8(sanitized_path.value()));
126
127 // Digest.
128 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor(
129 new BinaryFeatureExtractor());
130
131 binary_feature_extractor->ExtractDigest(
132 module_path, suspicious_module->mutable_digest());
133
134 // Version.
135 scoped_ptr<FileVersionInfo> version_info(
136 FileVersionInfo::CreateFileVersionInfo(module_path));
137 if (version_info) {
138 std::wstring file_version = version_info->file_version();
139 if (!file_version.empty())
140 suspicious_module->set_version(base::WideToUTF8(file_version));
141 }
142
143 // Signature.
144 binary_feature_extractor->CheckSignature(
145 module_path, suspicious_module->mutable_signature());
146
147 // Image headers.
148 if (!binary_feature_extractor->ExtractImageFeatures(
149 module_path, BinaryFeatureExtractor::kDefaultOptions,
150 suspicious_module->mutable_image_headers(),
151 nullptr /* signed_data */)) {
152 suspicious_module->clear_image_headers();
153 }
154
155 // Send the report.
156 incident_receiver->AddIncidentForProcess(make_scoped_ptr(
157 new SuspiciousModuleIncident(std::move(suspicious_module))));
158 }
159
160 UMA_HISTOGRAM_TIMES("SBIRS.SuspiciousModuleReportingTime",
rkaplow 2016/02/09 20:45:52 you can use SCOPED_UMA_HISTOGRAM_TIMER
proberge 2016/02/10 14:21:41 Done.
161 base::TimeTicks::Now() - start_time);
162 }
163
164 void ModuleLoadAnalyzer::VerifyModuleLoadState(
165 scoped_ptr<IncidentReceiver> incident_receiver) {
166 // PostTaskAndReply doesn't work here because we're in a sequenced blocking
167 // thread pool.
168 content::BrowserThread::PostTask(
169 content::BrowserThread::IO, FROM_HERE,
170 base::Bind(&ModuleLoadAnalyzer::GetLoadedSuspiciousModulesOnIOThread,
171 base::Unretained(this),
172 base::Passed(std::move(incident_receiver))));
173 }
174
175 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698