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. 4 5 #include "chrome/browser/install_verification/win/imported_module_verification.h" 6 7 #include <Windows.h> 8 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" 16 17 namespace { 18 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" 26 }; 27 28 bool AddressBeyondRange(const ModuleInfo& module, uintptr_t address) { 29 return module.base_address + module.size < address; 30 } 31 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); 38 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); 68 } 69 ++address; 70 } 71 image_descriptor += sizeof(image_descriptor) / sizeof(uintptr_t); 72 } 73 } 74 75 } // namespace 76 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); 90 } 91 } 92 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 100 } 101