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