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