Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / install_verification / win / imported_module_verification.cc
blob2eebc9985bfb5def4cfa6eeca698c3948632e2b5
1 // Copyright 2013 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.
5 #include "chrome/browser/install_verification/win/imported_module_verification.h"
7 #include <Windows.h>
9 #include <algorithm>
10 #include <iterator>
11 #include <string>
12 #include <vector>
13 #include "base/logging.h"
14 #include "base/strings/string16.h"
15 #include "chrome/browser/install_verification/win/module_info.h"
17 namespace {
19 #if !defined(_WIN64)
20 // We must make sure not to include modules here that are likely to get unloaded
21 // because the scanning of the module is not done within a loader lock, so is
22 // not resilient to changes made to the modules list.
23 const wchar_t* const kModulesToScan[] = {
24 L"chrome.dll",
25 L"kernel32.dll",
26 L"user32.dll"
29 bool AddressBeyondRange(const ModuleInfo& module, uintptr_t address) {
30 return module.base_address + module.size < address;
33 void ScanImportAddressTable(
34 HMODULE module_handle,
35 const std::set<ModuleInfo>& loaded_modules,
36 std::set<base::string16>* imported_modules) {
37 DCHECK(module_handle);
38 DCHECK(imported_modules);
40 // To find the Import Address Table address, we start from the DOS header.
41 // The module handle is actually the base address where the header is.
42 IMAGE_DOS_HEADER* dos_header =
43 reinterpret_cast<IMAGE_DOS_HEADER*>(module_handle);
44 // The e_lfanew is an offset from the DOS header to the NT header. It should
45 // never be 0.
46 DCHECK(dos_header->e_lfanew);
47 IMAGE_NT_HEADERS* nt_headers = reinterpret_cast<IMAGE_NT_HEADERS*>(
48 module_handle + dos_header->e_lfanew / sizeof(uintptr_t));
49 // For modules that have an import address table, its offset from the
50 // DOS header is stored in the second data directory's VirtualAddress.
51 if (!nt_headers->OptionalHeader.DataDirectory[1].VirtualAddress)
52 return;
53 IMAGE_IMPORT_DESCRIPTOR* image_descriptor =
54 reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(module_handle +
55 nt_headers->OptionalHeader.DataDirectory[1].VirtualAddress /
56 sizeof(uintptr_t));
57 // The list of Import Address Tables ends with an empty {0} descriptor.
58 while (image_descriptor->Characteristics) {
59 uintptr_t* address = reinterpret_cast<uintptr_t*>(
60 module_handle + image_descriptor->FirstThunk / sizeof(uintptr_t));
61 // Each section of the Import Address Table ends with a NULL funcpointer.
62 while (*address) {
63 std::set<ModuleInfo>::const_iterator lower_bound = std::lower_bound(
64 loaded_modules.begin(), loaded_modules.end(), *address,
65 AddressBeyondRange);
66 if (lower_bound != loaded_modules.end() &&
67 lower_bound->ContainsAddress(*address)) {
68 imported_modules->insert(lower_bound->name);
70 ++address;
72 image_descriptor += sizeof(image_descriptor) / sizeof(uintptr_t);
75 #endif // !defined(_WIN64)
77 } // namespace
79 void VerifyImportedModules(const std::set<ModuleInfo>& loaded_modules,
80 const ModuleIDs& module_ids,
81 ModuleVerificationDelegate* delegate){
82 // Note that module verification is temporarily disabled for 64-bit builds.
83 // See crbug.com/316274.
84 #if !defined(_WIN64)
85 std::set<base::string16> imported_module_names;
86 for (size_t i = 0; i < arraysize(kModulesToScan); ++i) {
87 HMODULE module_handle = ::GetModuleHandle(kModulesToScan[i]);
88 if (module_handle) {
89 ScanImportAddressTable(module_handle,
90 loaded_modules,
91 &imported_module_names);
95 std::vector<std::string> module_name_digests;
96 std::transform(imported_module_names.begin(),
97 imported_module_names.end(),
98 std::back_inserter(module_name_digests),
99 &CalculateModuleNameDigest);
100 ReportModuleMatches(module_name_digests, module_ids, delegate);
101 #endif