Home | History | Annotate | Download | only in win
      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