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"
13 #include "base/logging.h"
14 #include "base/strings/string16.h"
15 #include "chrome/browser/install_verification/win/module_info.h"
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
[] = {
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
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
)
53 IMAGE_IMPORT_DESCRIPTOR
* image_descriptor
=
54 reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR
*>(module_handle
+
55 nt_headers
->OptionalHeader
.DataDirectory
[1].VirtualAddress
/
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.
63 std::set
<ModuleInfo
>::const_iterator lower_bound
= std::lower_bound(
64 loaded_modules
.begin(), loaded_modules
.end(), *address
,
66 if (lower_bound
!= loaded_modules
.end() &&
67 lower_bound
->ContainsAddress(*address
)) {
68 imported_modules
->insert(lower_bound
->name
);
72 image_descriptor
+= sizeof(image_descriptor
) / sizeof(uintptr_t);
75 #endif // !defined(_WIN64)
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.
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
]);
89 ScanImportAddressTable(module_handle
,
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
);