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