1 // Copyright (c) 2006-2008 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 // This file was adapted from GreenBorder's Code. 6 // To understand what this class is about (for other than well known functions 7 // as GetProcAddress), a good starting point is "An In-Depth Look into the 8 // Win32 Portable Executable File Format" by Matt Pietrek: 9 // http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx 10 11 #ifndef BASE_PE_IMAGE_H_ 12 #define BASE_PE_IMAGE_H_ 13 14 #include <windows.h> 15 #include <DelayIMP.h> 16 17 // This class is a wrapper for the Portable Executable File Format (PE). 18 // It's main purpose is to provide an easy way to work with imports and exports 19 // from a file, mapped in memory as image. 20 class PEImage { 21 public: 22 // Callback to enumerate sections. 23 // cookie is the value passed to the enumerate method. 24 // Returns true to continue the enumeration. 25 typedef bool (*EnumSectionsFunction)(const PEImage &image, 26 PIMAGE_SECTION_HEADER header, 27 PVOID section_start, DWORD section_size, 28 PVOID cookie); 29 30 // Callback to enumerate exports. 31 // function is the actual address of the symbol. If forward is not null, it 32 // contains the dll and symbol to forward this export to. cookie is the value 33 // passed to the enumerate method. 34 // Returns true to continue the enumeration. 35 typedef bool (*EnumExportsFunction)(const PEImage &image, DWORD ordinal, 36 DWORD hint, LPCSTR name, PVOID function, 37 LPCSTR forward, PVOID cookie); 38 39 // Callback to enumerate import blocks. 40 // name_table and iat point to the imports name table and address table for 41 // this block. cookie is the value passed to the enumerate method. 42 // Returns true to continue the enumeration. 43 typedef bool (*EnumImportChunksFunction)(const PEImage &image, LPCSTR module, 44 PIMAGE_THUNK_DATA name_table, 45 PIMAGE_THUNK_DATA iat, PVOID cookie); 46 47 // Callback to enumerate imports. 48 // module is the dll that exports this symbol. cookie is the value passed to 49 // the enumerate method. 50 // Returns true to continue the enumeration. 51 typedef bool (*EnumImportsFunction)(const PEImage &image, LPCSTR module, 52 DWORD ordinal, LPCSTR name, DWORD hint, 53 PIMAGE_THUNK_DATA iat, PVOID cookie); 54 55 // Callback to enumerate dalayed import blocks. 56 // module is the dll that exports this block of symbols. cookie is the value 57 // passed to the enumerate method. 58 // Returns true to continue the enumeration. 59 typedef bool (*EnumDelayImportChunksFunction)(const PEImage &image, 60 PImgDelayDescr delay_descriptor, 61 LPCSTR module, 62 PIMAGE_THUNK_DATA name_table, 63 PIMAGE_THUNK_DATA iat, 64 PIMAGE_THUNK_DATA bound_iat, 65 PIMAGE_THUNK_DATA unload_iat, 66 PVOID cookie); 67 68 // Callback to enumerate relocations. 69 // cookie is the value passed to the enumerate method. 70 // Returns true to continue the enumeration. 71 typedef bool (*EnumRelocsFunction)(const PEImage &image, WORD type, 72 PVOID address, PVOID cookie); 73 74 explicit PEImage(HMODULE module) : module_(module) {} 75 explicit PEImage(const void* module) { 76 module_ = reinterpret_cast<HMODULE>(const_cast<void*>(module)); 77 } 78 79 // Gets the HMODULE for this object. 80 HMODULE module() const; 81 82 // Sets this object's HMODULE. 83 void set_module(HMODULE module); 84 85 // Checks if this symbol is actually an ordinal. 86 static bool IsOrdinal(LPCSTR name); 87 88 // Converts a named symbol to the corresponding ordinal. 89 static WORD ToOrdinal(LPCSTR name); 90 91 // Returns the DOS_HEADER for this PE. 92 PIMAGE_DOS_HEADER GetDosHeader() const; 93 94 // Returns the NT_HEADER for this PE. 95 PIMAGE_NT_HEADERS GetNTHeaders() const; 96 97 // Returns number of sections of this PE. 98 WORD GetNumSections() const; 99 100 // Returns the header for a given section. 101 // returns NULL if there is no such section. 102 PIMAGE_SECTION_HEADER GetSectionHeader(UINT section) const; 103 104 // Returns the size of a given directory entry. 105 DWORD GetImageDirectoryEntrySize(UINT directory) const; 106 107 // Returns the address of a given directory entry. 108 PVOID GetImageDirectoryEntryAddr(UINT directory) const; 109 110 // Returns the section header for a given address. 111 // Use: s = image.GetImageSectionFromAddr(a); 112 // Post: 's' is the section header of the section that contains 'a' 113 // or NULL if there is no such section. 114 PIMAGE_SECTION_HEADER GetImageSectionFromAddr(PVOID address) const; 115 116 // Returns the section header for a given section. 117 PIMAGE_SECTION_HEADER GetImageSectionHeaderByName(LPCSTR section_name) const; 118 119 // Returns the first block of imports. 120 PIMAGE_IMPORT_DESCRIPTOR GetFirstImportChunk() const; 121 122 // Returns the exports directory. 123 PIMAGE_EXPORT_DIRECTORY GetExportDirectory() const; 124 125 // Returns a given export entry. 126 // Use: e = image.GetExportEntry(f); 127 // Pre: 'f' is either a zero terminated string or ordinal 128 // Post: 'e' is a pointer to the export directory entry 129 // that contains 'f's export RVA, or NULL if 'f' 130 // is not exported from this image 131 PDWORD GetExportEntry(LPCSTR name) const; 132 133 // Returns the address for a given exported symbol. 134 // Use: p = image.GetProcAddress(f); 135 // Pre: 'f' is either a zero terminated string or ordinal. 136 // Post: if 'f' is a non-forwarded export from image, 'p' is 137 // the exported function. If 'f' is a forwarded export 138 // then p is the special value 0xFFFFFFFF. In this case 139 // RVAToAddr(*GetExportEntry) can be used to resolve 140 // the string that describes the forward. 141 FARPROC GetProcAddress(LPCSTR function_name) const; 142 143 // Retrieves the ordinal for a given exported symbol. 144 // Returns true if the symbol was found. 145 bool GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const; 146 147 // Enumerates PE sections. 148 // cookie is a generic cookie to pass to the callback. 149 // Returns true on success. 150 bool EnumSections(EnumSectionsFunction callback, PVOID cookie) const; 151 152 // Enumerates PE exports. 153 // cookie is a generic cookie to pass to the callback. 154 // Returns true on success. 155 bool EnumExports(EnumExportsFunction callback, PVOID cookie) const; 156 157 // Enumerates PE imports. 158 // cookie is a generic cookie to pass to the callback. 159 // Returns true on success. 160 bool EnumAllImports(EnumImportsFunction callback, PVOID cookie) const; 161 162 // Enumerates PE import blocks. 163 // cookie is a generic cookie to pass to the callback. 164 // Returns true on success. 165 bool EnumImportChunks(EnumImportChunksFunction callback, PVOID cookie) const; 166 167 // Enumerates the imports from a single PE import block. 168 // cookie is a generic cookie to pass to the callback. 169 // Returns true on success. 170 bool EnumOneImportChunk(EnumImportsFunction callback, LPCSTR module_name, 171 PIMAGE_THUNK_DATA name_table, PIMAGE_THUNK_DATA iat, 172 PVOID cookie) const; 173 174 175 // Enumerates PE delay imports. 176 // cookie is a generic cookie to pass to the callback. 177 // Returns true on success. 178 bool EnumAllDelayImports(EnumImportsFunction callback, PVOID cookie) const; 179 180 // Enumerates PE delay import blocks. 181 // cookie is a generic cookie to pass to the callback. 182 // Returns true on success. 183 bool EnumDelayImportChunks(EnumDelayImportChunksFunction callback, 184 PVOID cookie) const; 185 186 // Enumerates imports from a single PE delay import block. 187 // cookie is a generic cookie to pass to the callback. 188 // Returns true on success. 189 bool EnumOneDelayImportChunk(EnumImportsFunction callback, 190 PImgDelayDescr delay_descriptor, 191 LPCSTR module_name, 192 PIMAGE_THUNK_DATA name_table, 193 PIMAGE_THUNK_DATA iat, 194 PIMAGE_THUNK_DATA bound_iat, 195 PIMAGE_THUNK_DATA unload_iat, 196 PVOID cookie) const; 197 198 // Enumerates PE relocation entries. 199 // cookie is a generic cookie to pass to the callback. 200 // Returns true on success. 201 bool EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const; 202 203 // Verifies the magic values on the PE file. 204 // Returns true if all values are correct. 205 bool VerifyMagic() const; 206 207 // Converts an rva value to the appropriate address. 208 virtual PVOID RVAToAddr(DWORD rva) const; 209 210 // Converts an rva value to an offset on disk. 211 // Returns true on success. 212 bool ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const; 213 214 // Converts an address to an offset on disk. 215 // Returns true on success. 216 bool ImageAddrToOnDiskOffset(LPVOID address, DWORD *on_disk_offset) const; 217 218 private: 219 HMODULE module_; 220 }; 221 222 // This class is an extension to the PEImage class that allows working with PE 223 // files mapped as data instead of as image file. 224 class PEImageAsData : public PEImage { 225 public: 226 explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {} 227 228 virtual PVOID RVAToAddr(DWORD rva) const; 229 }; 230 231 inline bool PEImage::IsOrdinal(LPCSTR name) { 232 #pragma warning(push) 233 #pragma warning(disable: 4311) 234 // This cast generates a warning because it is 32 bit specific. 235 return reinterpret_cast<DWORD>(name) <= 0xFFFF; 236 #pragma warning(pop) 237 } 238 239 inline WORD PEImage::ToOrdinal(LPCSTR name) { 240 return reinterpret_cast<WORD>(name); 241 } 242 243 inline HMODULE PEImage::module() const { 244 return module_; 245 } 246 247 inline PIMAGE_IMPORT_DESCRIPTOR PEImage::GetFirstImportChunk() const { 248 return reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>( 249 GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_IMPORT)); 250 } 251 252 inline PIMAGE_EXPORT_DIRECTORY PEImage::GetExportDirectory() const { 253 return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( 254 GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); 255 } 256 257 #endif // BASE_PE_IMAGE_H_ 258