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
[] = {
28 #endif // !defined(_WIN64)
30 bool AddressBeyondRange(const ModuleInfo
& module
, uintptr_t address
) {
31 return module
.base_address
+ module
.size
< address
;
34 void ScanImportAddressTable(
35 HMODULE module_handle
,
36 const std::set
<ModuleInfo
>& loaded_modules
,
37 std::set
<base::string16
>* imported_modules
) {
38 DCHECK(module_handle
);
39 DCHECK(imported_modules
);
41 // To find the Import Address Table address, we start from the DOS header.
42 // The module handle is actually the base address where the header is.
43 IMAGE_DOS_HEADER
* dos_header
=
44 reinterpret_cast<IMAGE_DOS_HEADER
*>(module_handle
);
45 // The e_lfanew is an offset from the DOS header to the NT header. It should
47 DCHECK(dos_header
->e_lfanew
);
48 IMAGE_NT_HEADERS
* nt_headers
= reinterpret_cast<IMAGE_NT_HEADERS
*>(
49 module_handle
+ dos_header
->e_lfanew
/ sizeof(uintptr_t));
50 // For modules that have an import address table, its offset from the
51 // DOS header is stored in the second data directory's VirtualAddress.
52 if (!nt_headers
->OptionalHeader
.DataDirectory
[1].VirtualAddress
)
54 IMAGE_IMPORT_DESCRIPTOR
* image_descriptor
=
55 reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR
*>(module_handle
+
56 nt_headers
->OptionalHeader
.DataDirectory
[1].VirtualAddress
/
58 // The list of Import Address Tables ends with an empty {0} descriptor.
59 while (image_descriptor
->Characteristics
) {
60 uintptr_t* address
= reinterpret_cast<uintptr_t*>(
61 module_handle
+ image_descriptor
->FirstThunk
/ sizeof(uintptr_t));
62 // Each section of the Import Address Table ends with a NULL funcpointer.
64 std::set
<ModuleInfo
>::const_iterator lower_bound
= std::lower_bound(
65 loaded_modules
.begin(), loaded_modules
.end(), *address
,
67 if (lower_bound
!= loaded_modules
.end() &&
68 lower_bound
->ContainsAddress(*address
)) {
69 imported_modules
->insert(lower_bound
->name
);
73 image_descriptor
+= sizeof(image_descriptor
) / sizeof(uintptr_t);
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
);