| Index: chrome/browser/enumerate_modules_model_win.cc
|
| ===================================================================
|
| --- chrome/browser/enumerate_modules_model_win.cc (revision 66756)
|
| +++ chrome/browser/enumerate_modules_model_win.cc (working copy)
|
| @@ -13,10 +13,12 @@
|
| #include "base/environment.h"
|
| #include "base/file_path.h"
|
| #include "base/file_version_info_win.h"
|
| +#include "base/metrics/histogram.h"
|
| #include "base/scoped_handle.h"
|
| #include "base/sha2.h"
|
| #include "base/string_number_conversions.h"
|
| #include "base/string_util.h"
|
| +#include "base/time.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "base/values.h"
|
| #include "base/version.h"
|
| @@ -53,6 +55,21 @@
|
| // from both the UI thread and the FILE thread.
|
| Lock* lock = NULL;
|
|
|
| +// A struct to help de-duping modules before adding them to the enumerated
|
| +// modules vector.
|
| +struct FindModule {
|
| + public:
|
| + explicit FindModule(const ModuleEnumerator::Module& x)
|
| + : module(x) {}
|
| + bool operator()(ModuleEnumerator::Module module_in) const {
|
| + return (module.type == module_in.type) &&
|
| + (module.location == module_in.location) &&
|
| + (module.name == module_in.name);
|
| + }
|
| +
|
| + const ModuleEnumerator::Module& module;
|
| +};
|
| +
|
| }
|
|
|
| // The browser process module blacklist. This lists all modules that are known
|
| @@ -226,15 +243,28 @@
|
| }
|
|
|
| void ModuleEnumerator::ScanOnFileThread() {
|
| + base::TimeTicks start_time = base::TimeTicks::Now();
|
| +
|
| enumerated_modules_->clear();
|
|
|
| // Make sure the path mapping vector is setup so we can collapse paths.
|
| PreparePathMappings();
|
|
|
| + base::TimeTicks checkpoint = base::TimeTicks::Now();
|
| EnumerateLoadedModules();
|
| + HISTOGRAM_TIMES("Conflicts.EnumerateLoadedModules",
|
| + base::TimeTicks::Now() - checkpoint);
|
| +
|
| + checkpoint = base::TimeTicks::Now();
|
| EnumerateShellExtensions();
|
| - EnumerateWinsockModule();
|
| + HISTOGRAM_TIMES("Conflicts.EnumerateShellExtensions",
|
| + base::TimeTicks::Now() - checkpoint);
|
|
|
| + checkpoint = base::TimeTicks::Now();
|
| + EnumerateWinsockModules();
|
| + HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules",
|
| + base::TimeTicks::Now() - checkpoint);
|
| +
|
| MatchAgainstBlacklist();
|
|
|
| std::sort(enumerated_modules_->begin(),
|
| @@ -244,6 +274,9 @@
|
| BrowserThread::PostTask(
|
| callback_thread_id_, FROM_HERE,
|
| NewRunnableMethod(this, &ModuleEnumerator::ReportBack));
|
| +
|
| + HISTOGRAM_TIMES("Conflicts.EnumerationTotalTime",
|
| + base::TimeTicks::Now() - start_time);
|
| }
|
|
|
| void ModuleEnumerator::EnumerateLoadedModules() {
|
| @@ -303,13 +336,13 @@
|
|
|
| NormalizeModule(&entry);
|
| CollapsePath(&entry);
|
| - enumerated_modules_->push_back(entry);
|
| + AddToListWithoutDuplicating(entry);
|
|
|
| ++registration;
|
| }
|
| }
|
|
|
| -void ModuleEnumerator::EnumerateWinsockModule() {
|
| +void ModuleEnumerator::EnumerateWinsockModules() {
|
| // Add to this list the Winsock LSP DLLs.
|
| WinsockLayeredServiceProviderList layered_providers;
|
| GetWinsockLayeredServiceProviders(&layered_providers);
|
| @@ -321,6 +354,7 @@
|
| entry.location = layered_providers[i].path;
|
| entry.description = layered_providers[i].name;
|
| entry.recommended_action = NONE;
|
| + entry.duplicate_count = 0;
|
|
|
| wchar_t expanded[MAX_PATH];
|
| DWORD size = ExpandEnvironmentStrings(
|
| @@ -333,12 +367,13 @@
|
|
|
| // Paths have already been collapsed.
|
| NormalizeModule(&entry);
|
| - enumerated_modules_->push_back(entry);
|
| + AddToListWithoutDuplicating(entry);
|
| }
|
| }
|
|
|
| void ModuleEnumerator::PopulateModuleInformation(Module* module) {
|
| module->status = NOT_MATCHED;
|
| + module->duplicate_count = 0;
|
| module->normalized = false;
|
| module->digital_signer =
|
| GetSubjectNameFromDigitalSignature(FilePath(module->location));
|
| @@ -358,6 +393,22 @@
|
| }
|
| }
|
|
|
| +void ModuleEnumerator::AddToListWithoutDuplicating(const Module& module) {
|
| + DCHECK(module.normalized);
|
| + // These are registered modules, not loaded modules so the same module
|
| + // can be registered multiple times, often dozens of times. There is no need
|
| + // to list each registration, so we just increment the count for each module
|
| + // that is counted multiple times.
|
| + ModulesVector::iterator iter;
|
| + iter = std::find_if(enumerated_modules_->begin(),
|
| + enumerated_modules_->end(),
|
| + FindModule(module));
|
| + if (iter != enumerated_modules_->end())
|
| + iter->duplicate_count++;
|
| + else
|
| + enumerated_modules_->push_back(module);
|
| +}
|
| +
|
| void ModuleEnumerator::PreparePathMappings() {
|
| path_mapping_.clear();
|
|
|
| @@ -368,6 +419,7 @@
|
| env_vars.push_back(L"USERPROFILE");
|
| env_vars.push_back(L"SystemRoot");
|
| env_vars.push_back(L"TEMP");
|
| + env_vars.push_back(L"TMP");
|
| for (std::vector<string16>::const_iterator variable = env_vars.begin();
|
| variable != env_vars.end(); ++variable) {
|
| std::string path;
|
| @@ -420,6 +472,17 @@
|
| break;
|
| }
|
| }
|
| +
|
| + // Modules loaded from these locations are frequently malicious
|
| + // and notorious for changing frequently so they are not good candidates
|
| + // for blacklising individually. Mark them as suspicious if we haven't
|
| + // classified them as bad yet.
|
| + if (module->status == NOT_MATCHED || module->status == GOOD) {
|
| + if (StartsWith(module->location, L"%temp%", false) ||
|
| + StartsWith(module->location, L"%tmp%", false)) {
|
| + module->status = SUSPECTED_BAD;
|
| + }
|
| + }
|
| }
|
| }
|
|
|
| @@ -646,6 +709,11 @@
|
| scanning_ = false;
|
| lock->Release();
|
|
|
| + HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules",
|
| + suspected_bad_modules_detected_);
|
| + HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules",
|
| + confirmed_bad_modules_detected_);
|
| +
|
| NotificationService::current()->Notify(
|
| NotificationType::MODULE_LIST_ENUMERATED,
|
| Source<EnumerateModulesModel>(this),
|
|
|