1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This file implements PEImage, a generic class to manipulate PE files. 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This file was adapted from GreenBorder's Code. 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/pe_image.h" 9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace base { 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace win { 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(_WIN64) && !defined(NACL_WIN64) 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(rvargas): Bug 27218. Make sure this is ok. 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#error This code is not tested on x64. Please make sure all the base unit tests\ 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pass before doing any real work. The current unit tests don't test the\ 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott differences between 32- and 64-bits implementations. Bugs may slip through.\ 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott You need to improve the coverage before continuing. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Structure to perform imports enumerations. 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct EnumAllImportsStorage { 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PEImage::EnumImportsFunction callback; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID cookie; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compare two strings byte by byte on an unsigned basis. 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if s1 == s2, return 0 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if s1 < s2, return negative 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if s1 > s2, return positive 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Exception if inputs are invalid. 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int StrCmpByByte(LPCSTR s1, LPCSTR s2) { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (*s1 != '\0' && *s1 == *s2) { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++s1; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++s2; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (*reinterpret_cast<const unsigned char*>(s1) - 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *reinterpret_cast<const unsigned char*>(s2)); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Callback used to enumerate imports. See EnumImportChunksFunction. 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ProcessImportChunk(const PEImage &image, LPCSTR module, 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA name_table, 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA iat, PVOID cookie) { 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cookie); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return image.EnumOneImportChunk(storage.callback, module, name_table, iat, 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott storage.cookie); 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction. 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ProcessDelayImportChunk(const PEImage &image, 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PImgDelayDescr delay_descriptor, 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR module, PIMAGE_THUNK_DATA name_table, 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat, 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA unload_iat, PVOID cookie) { 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cookie); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor, 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott module, name_table, iat, bound_iat, 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unload_iat, storage.cookie); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid PEImage::set_module(HMODULE module) { 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott module_ = module; 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_DOS_HEADER PEImage::GetDosHeader() const { 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return reinterpret_cast<PIMAGE_DOS_HEADER>(module_); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_NT_HEADERS PEImage::GetNTHeaders() const { 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_DOS_HEADER dos_header = GetDosHeader(); 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return reinterpret_cast<PIMAGE_NT_HEADERS>( 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew); 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const { 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (section < nt_headers->FileHeader.NumberOfSections) 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return first_section + section; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottWORD PEImage::GetNumSections() const { 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GetNTHeaders()->FileHeader.NumberOfSections; 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottDWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const { 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return nt_headers->OptionalHeader.DataDirectory[directory].Size; 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const { 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return RVAToAddr( 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress); 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const { 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PBYTE target = reinterpret_cast<PBYTE>(address); 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_SECTION_HEADER section; 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) { 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't use the virtual RVAToAddr. 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PBYTE start = reinterpret_cast<PBYTE>( 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PEImage::RVAToAddr(section->VirtualAddress)); 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = section->Misc.VirtualSize; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((start <= target) && (start + size > target)) 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return section; 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName( 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR section_name) const { 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == section_name) 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_SECTION_HEADER ret = NULL; 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int num_sections = GetNumSections(); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < num_sections; i++) { 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_SECTION_HEADER section = GetSectionHeader(i); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name, 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(section->Name))) { 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ret = section; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ret; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPDWORD PEImage::GetExportEntry(LPCSTR name) const { 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == exports) 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WORD ordinal = 0; 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!GetProcOrdinal(name, &ordinal)) 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD functions = reinterpret_cast<PDWORD>( 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(exports->AddressOfFunctions)); 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return functions + ordinal - exports->Base; 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFARPROC PEImage::GetProcAddress(LPCSTR function_name) const { 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD export_entry = GetExportEntry(function_name); 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == export_entry) 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry)); 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PBYTE exports = reinterpret_cast<PBYTE>( 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check for forwarded exports as a special case. 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (exports <= function && exports + size > function) 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push) 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4312) 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This cast generates a warning because it is 32 bit specific. 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return reinterpret_cast<FARPROC>(0xFFFFFFFF); 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop) 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return reinterpret_cast<FARPROC>(function); 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const { 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == ordinal) 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == exports) 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsOrdinal(function_name)) { 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *ordinal = ToOrdinal(function_name); 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD lower = names; 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD upper = names + exports->NumberOfNames; 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int cmp = -1; 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Binary Search for the name. 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (lower != upper) { 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD middle = lower + (upper - lower) / 2; 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle)); 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This may be called by sandbox before MSVCRT dll loads, so can't use 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CRT function here. 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmp = StrCmpByByte(function_name, name); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cmp == 0) { 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lower = middle; 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cmp > 0) 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lower = middle + 1; 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott upper = middle; 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cmp != 0) 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PWORD ordinals = reinterpret_cast<PWORD>( 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(exports->AddressOfNameOrdinals)); 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base); 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const { 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UINT num_sections = nt_headers->FileHeader.NumberOfSections; 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_SECTION_HEADER section = GetSectionHeader(0); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (UINT i = 0; i < num_sections; i++, section++) { 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID section_start = RVAToAddr(section->VirtualAddress); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = section->Misc.VirtualSize; 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, section, section_start, size, cookie)) 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const { 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT); 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if there are any exports at all. 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == directory || 0 == size) 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott directory); 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UINT ordinal_base = exports->Base; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UINT num_funcs = exports->NumberOfFunctions; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UINT num_names = exports->NumberOfNames; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD functions = reinterpret_cast<PDWORD>(RVAToAddr( 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exports->AddressOfFunctions)); 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr( 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exports->AddressOfNameOrdinals)); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (UINT count = 0; count < num_funcs; count++) { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID func = RVAToAddr(functions[count]); 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == func) 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check for a name. 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR name = NULL; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UINT hint; 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (hint = 0; hint < num_names; hint++) { 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ordinals[hint] == count) { 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint])); 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (name == NULL) 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hint = 0; 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check for forwarded exports. 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR forward = NULL; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) && 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) + 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size) { 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott forward = reinterpret_cast<LPCSTR>(func); 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott func = 0; 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, ordinal_base + count, hint, name, func, forward, 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cookie)) 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const { 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC); 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC); 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott directory); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (directory == NULL || size < sizeof(IMAGE_BASE_RELOCATION)) 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (base->SizeOfBlock) { 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PWORD reloc = reinterpret_cast<PWORD>(base + 1); 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(WORD); 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (UINT i = 0; i < num_relocs; i++, reloc++) { 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WORD type = *reloc >> 12; 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF)); 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, type, address, cookie)) 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<char*>(base) + base->SizeOfBlock); 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumImportChunks(EnumImportChunksFunction callback, 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID cookie) const { 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT); 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk(); 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR)) 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; import->FirstThunk; import++) { 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name)); 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(import->OriginalFirstThunk)); 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(import->FirstThunk)); 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, module_name, name_table, iat, cookie)) 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumOneImportChunk(EnumImportsFunction callback, 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR module_name, 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA name_table, 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA iat, PVOID cookie) const { 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == name_table) 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; name_table && name_table->u1.Ordinal; name_table++, iat++) { 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR name = NULL; 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WORD ordinal = 0; 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WORD hint = 0; 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(name_table->u1.ForwarderString)); 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hint = import->Hint; 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name = reinterpret_cast<LPCSTR>(&import->Name); 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const { 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnumAllImportsStorage temp = { callback, cookie }; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return EnumImportChunks(ProcessImportChunk, &temp); 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback, 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID cookie) const { 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID directory = GetImageDirectoryEntryAddr( 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory); 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (directory == NULL || size == 0) 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; delay_descriptor->rvaHmod; delay_descriptor++) { 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA name_table; 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA iat; 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA bound_iat; // address of the optional bound IAT 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA unload_iat; // address of optional copy of original IAT 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR module_name; 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // check if VC7-style imports, using RVAs instead of 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // VC6-style addresses. 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rvas) { 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott module_name = reinterpret_cast<LPCSTR>( 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(delay_descriptor->rvaDLLName)); 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(delay_descriptor->rvaINT)); 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(delay_descriptor->rvaIAT)); 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(delay_descriptor->rvaBoundIAT)); 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(delay_descriptor->rvaUnloadIAT)); 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push) 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4312) 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // These casts generate warnings because they are 32 bit specific. 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott module_name = reinterpret_cast<LPCSTR>(delay_descriptor->rvaDLLName); 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delay_descriptor->rvaINT); 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott iat = reinterpret_cast<PIMAGE_THUNK_DATA>(delay_descriptor->rvaIAT); 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delay_descriptor->rvaBoundIAT); 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delay_descriptor->rvaUnloadIAT); 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop) 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, delay_descriptor, module_name, name_table, iat, 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bound_iat, unload_iat, cookie)) 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback, 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PImgDelayDescr delay_descriptor, 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR module_name, 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA name_table, 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA iat, 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA bound_iat, 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_THUNK_DATA unload_iat, 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID cookie) const { 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UNREFERENCED_PARAMETER(bound_iat); 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UNREFERENCED_PARAMETER(unload_iat); 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; name_table->u1.Ordinal; name_table++, iat++) { 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPCSTR name = NULL; 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WORD ordinal = 0; 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WORD hint = 0; 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_IMPORT_BY_NAME import; 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rvas) { 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RVAToAddr(name_table->u1.ForwarderString)); 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push) 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4312) 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This cast generates a warning because it is 32 bit specific. 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_table->u1.ForwarderString); 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop) 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hint = import->Hint; 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name = reinterpret_cast<LPCSTR>(&import->Name); 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::EnumAllDelayImports(EnumImportsFunction callback, 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID cookie) const { 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnumAllImportsStorage temp = { callback, cookie }; 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return EnumDelayImportChunks(ProcessDelayImportChunk, &temp); 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::VerifyMagic() const { 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_DOS_HEADER dos_header = GetDosHeader(); 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (nt_headers->Signature != IMAGE_NT_SIGNATURE) 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (nt_headers->FileHeader.SizeOfOptionalHeader != 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(IMAGE_OPTIONAL_HEADER)) 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const { 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LPVOID address = RVAToAddr(rva); 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ImageAddrToOnDiskOffset(address, on_disk_offset); 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool PEImage::ImageAddrToOnDiskOffset(LPVOID address, 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD *on_disk_offset) const { 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == address) 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Get the section that this address belongs to. 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address); 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (NULL == section_header) 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(push) 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable: 4311) 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // These casts generate warnings because they are 32 bit specific. 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't follow the virtual RVAToAddr, use the one on the base. 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD offset_within_section = reinterpret_cast<DWORD>(address) - 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<DWORD>(PEImage::RVAToAddr( 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott section_header->VirtualAddress)); 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(pop) 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *on_disk_offset = section_header->PointerToRawData + offset_within_section; 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPVOID PEImage::RVAToAddr(DWORD rva) const { 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rva == 0) 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return reinterpret_cast<char*>(module_) + rva; 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottPVOID PEImageAsData::RVAToAddr(DWORD rva) const { 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rva == 0) 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PVOID in_memory = PEImage::RVAToAddr(rva); 561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DWORD disk_offset; 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset)) 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return PEImage::RVAToAddr(disk_offset); 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 568731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 569731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace win 570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace base 571