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"
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
[] = {
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
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
)
52 IMAGE_IMPORT_DESCRIPTOR
* image_descriptor
=
53 reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR
*>(module_handle
+
54 nt_headers
->OptionalHeader
.DataDirectory
[1].VirtualAddress
/
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.
62 std::set
<ModuleInfo
>::const_iterator lower_bound
= std::lower_bound(
63 loaded_modules
.begin(), loaded_modules
.end(), *address
,
65 if (lower_bound
!= loaded_modules
.end() &&
66 lower_bound
->ContainsAddress(*address
)) {
67 imported_modules
->insert(lower_bound
->name
);
71 image_descriptor
+= sizeof(image_descriptor
) / sizeof(uintptr_t);
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.
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
]);
87 ScanImportAddressTable(module_handle
,
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
);