1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/chromium/base/win/pe_image.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,571 @@ 1.4 +// Copyright (c) 2010 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +// This file implements PEImage, a generic class to manipulate PE files. 1.9 +// This file was adapted from GreenBorder's Code. 1.10 + 1.11 +#include "base/win/pe_image.h" 1.12 + 1.13 +namespace base { 1.14 +namespace win { 1.15 + 1.16 +#if defined(_WIN64) && !defined(NACL_WIN64) 1.17 +// TODO(jschuh): crbug.com/167707 Make sure this is ok. 1.18 +#pragma message ("Warning: \ 1.19 + This code is not tested on x64. Please make sure all the base unit tests\ 1.20 + pass before doing any real work. The current unit tests don't test the\ 1.21 + differences between 32- and 64-bits implementations. Bugs may slip through.\ 1.22 + You need to improve the coverage before continuing.") 1.23 +#endif 1.24 + 1.25 +// Structure to perform imports enumerations. 1.26 +struct EnumAllImportsStorage { 1.27 + PEImage::EnumImportsFunction callback; 1.28 + PVOID cookie; 1.29 +}; 1.30 + 1.31 +namespace { 1.32 + 1.33 + // Compare two strings byte by byte on an unsigned basis. 1.34 + // if s1 == s2, return 0 1.35 + // if s1 < s2, return negative 1.36 + // if s1 > s2, return positive 1.37 + // Exception if inputs are invalid. 1.38 + int StrCmpByByte(LPCSTR s1, LPCSTR s2) { 1.39 + while (*s1 != '\0' && *s1 == *s2) { 1.40 + ++s1; 1.41 + ++s2; 1.42 + } 1.43 + 1.44 + return (*reinterpret_cast<const unsigned char*>(s1) - 1.45 + *reinterpret_cast<const unsigned char*>(s2)); 1.46 + } 1.47 + 1.48 +} // namespace 1.49 + 1.50 +// Callback used to enumerate imports. See EnumImportChunksFunction. 1.51 +bool ProcessImportChunk(const PEImage &image, LPCSTR module, 1.52 + PIMAGE_THUNK_DATA name_table, 1.53 + PIMAGE_THUNK_DATA iat, PVOID cookie) { 1.54 + EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( 1.55 + cookie); 1.56 + 1.57 + return image.EnumOneImportChunk(storage.callback, module, name_table, iat, 1.58 + storage.cookie); 1.59 +} 1.60 + 1.61 +// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction. 1.62 +bool ProcessDelayImportChunk(const PEImage &image, 1.63 + PImgDelayDescr delay_descriptor, 1.64 + LPCSTR module, PIMAGE_THUNK_DATA name_table, 1.65 + PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat, 1.66 + PIMAGE_THUNK_DATA unload_iat, PVOID cookie) { 1.67 + EnumAllImportsStorage &storage = *reinterpret_cast<EnumAllImportsStorage*>( 1.68 + cookie); 1.69 + 1.70 + return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor, 1.71 + module, name_table, iat, bound_iat, 1.72 + unload_iat, storage.cookie); 1.73 +} 1.74 + 1.75 +void PEImage::set_module(HMODULE module) { 1.76 + module_ = module; 1.77 +} 1.78 + 1.79 +PIMAGE_DOS_HEADER PEImage::GetDosHeader() const { 1.80 + return reinterpret_cast<PIMAGE_DOS_HEADER>(module_); 1.81 +} 1.82 + 1.83 +PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const { 1.84 + PIMAGE_DOS_HEADER dos_header = GetDosHeader(); 1.85 + 1.86 + return reinterpret_cast<PIMAGE_NT_HEADERS>( 1.87 + reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew); 1.88 +} 1.89 + 1.90 +PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const { 1.91 + PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 1.92 + PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers); 1.93 + 1.94 + if (section < nt_headers->FileHeader.NumberOfSections) 1.95 + return first_section + section; 1.96 + else 1.97 + return NULL; 1.98 +} 1.99 + 1.100 +WORD PEImage::GetNumSections() const { 1.101 + return GetNTHeaders()->FileHeader.NumberOfSections; 1.102 +} 1.103 + 1.104 +DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const { 1.105 + PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 1.106 + 1.107 + return nt_headers->OptionalHeader.DataDirectory[directory].Size; 1.108 +} 1.109 + 1.110 +PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const { 1.111 + PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 1.112 + 1.113 + return RVAToAddr( 1.114 + nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress); 1.115 +} 1.116 + 1.117 +PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const { 1.118 + PBYTE target = reinterpret_cast<PBYTE>(address); 1.119 + PIMAGE_SECTION_HEADER section; 1.120 + 1.121 + for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) { 1.122 + // Don't use the virtual RVAToAddr. 1.123 + PBYTE start = reinterpret_cast<PBYTE>( 1.124 + PEImage::RVAToAddr(section->VirtualAddress)); 1.125 + 1.126 + DWORD size = section->Misc.VirtualSize; 1.127 + 1.128 + if ((start <= target) && (start + size > target)) 1.129 + return section; 1.130 + } 1.131 + 1.132 + return NULL; 1.133 +} 1.134 + 1.135 +PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName( 1.136 + LPCSTR section_name) const { 1.137 + if (NULL == section_name) 1.138 + return NULL; 1.139 + 1.140 + PIMAGE_SECTION_HEADER ret = NULL; 1.141 + int num_sections = GetNumSections(); 1.142 + 1.143 + for (int i = 0; i < num_sections; i++) { 1.144 + PIMAGE_SECTION_HEADER section = GetSectionHeader(i); 1.145 + if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name, 1.146 + sizeof(section->Name))) { 1.147 + ret = section; 1.148 + break; 1.149 + } 1.150 + } 1.151 + 1.152 + return ret; 1.153 +} 1.154 + 1.155 +PDWORD PEImage::GetExportEntry(LPCSTR name) const { 1.156 + PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); 1.157 + 1.158 + if (NULL == exports) 1.159 + return NULL; 1.160 + 1.161 + WORD ordinal = 0; 1.162 + if (!GetProcOrdinal(name, &ordinal)) 1.163 + return NULL; 1.164 + 1.165 + PDWORD functions = reinterpret_cast<PDWORD>( 1.166 + RVAToAddr(exports->AddressOfFunctions)); 1.167 + 1.168 + return functions + ordinal - exports->Base; 1.169 +} 1.170 + 1.171 +FARPROC PEImage::GetProcAddress(LPCSTR function_name) const { 1.172 + PDWORD export_entry = GetExportEntry(function_name); 1.173 + if (NULL == export_entry) 1.174 + return NULL; 1.175 + 1.176 + PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry)); 1.177 + 1.178 + PBYTE exports = reinterpret_cast<PBYTE>( 1.179 + GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); 1.180 + DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); 1.181 + 1.182 + // Check for forwarded exports as a special case. 1.183 + if (exports <= function && exports + size > function) 1.184 +#pragma warning(push) 1.185 +#pragma warning(disable: 4312) 1.186 + // This cast generates a warning because it is 32 bit specific. 1.187 + return reinterpret_cast<FARPROC>(0xFFFFFFFF); 1.188 +#pragma warning(pop) 1.189 + 1.190 + return reinterpret_cast<FARPROC>(function); 1.191 +} 1.192 + 1.193 +bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const { 1.194 + if (NULL == ordinal) 1.195 + return false; 1.196 + 1.197 + PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); 1.198 + 1.199 + if (NULL == exports) 1.200 + return false; 1.201 + 1.202 + if (IsOrdinal(function_name)) { 1.203 + *ordinal = ToOrdinal(function_name); 1.204 + } else { 1.205 + PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); 1.206 + PDWORD lower = names; 1.207 + PDWORD upper = names + exports->NumberOfNames; 1.208 + int cmp = -1; 1.209 + 1.210 + // Binary Search for the name. 1.211 + while (lower != upper) { 1.212 + PDWORD middle = lower + (upper - lower) / 2; 1.213 + LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle)); 1.214 + 1.215 + // This may be called by sandbox before MSVCRT dll loads, so can't use 1.216 + // CRT function here. 1.217 + cmp = StrCmpByByte(function_name, name); 1.218 + 1.219 + if (cmp == 0) { 1.220 + lower = middle; 1.221 + break; 1.222 + } 1.223 + 1.224 + if (cmp > 0) 1.225 + lower = middle + 1; 1.226 + else 1.227 + upper = middle; 1.228 + } 1.229 + 1.230 + if (cmp != 0) 1.231 + return false; 1.232 + 1.233 + 1.234 + PWORD ordinals = reinterpret_cast<PWORD>( 1.235 + RVAToAddr(exports->AddressOfNameOrdinals)); 1.236 + 1.237 + *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base); 1.238 + } 1.239 + 1.240 + return true; 1.241 +} 1.242 + 1.243 +bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const { 1.244 + PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 1.245 + UINT num_sections = nt_headers->FileHeader.NumberOfSections; 1.246 + PIMAGE_SECTION_HEADER section = GetSectionHeader(0); 1.247 + 1.248 + for (UINT i = 0; i < num_sections; i++, section++) { 1.249 + PVOID section_start = RVAToAddr(section->VirtualAddress); 1.250 + DWORD size = section->Misc.VirtualSize; 1.251 + 1.252 + if (!callback(*this, section, section_start, size, cookie)) 1.253 + return false; 1.254 + } 1.255 + 1.256 + return true; 1.257 +} 1.258 + 1.259 +bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const { 1.260 + PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT); 1.261 + DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); 1.262 + 1.263 + // Check if there are any exports at all. 1.264 + if (NULL == directory || 0 == size) 1.265 + return true; 1.266 + 1.267 + PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( 1.268 + directory); 1.269 + UINT ordinal_base = exports->Base; 1.270 + UINT num_funcs = exports->NumberOfFunctions; 1.271 + UINT num_names = exports->NumberOfNames; 1.272 + PDWORD functions = reinterpret_cast<PDWORD>(RVAToAddr( 1.273 + exports->AddressOfFunctions)); 1.274 + PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); 1.275 + PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr( 1.276 + exports->AddressOfNameOrdinals)); 1.277 + 1.278 + for (UINT count = 0; count < num_funcs; count++) { 1.279 + PVOID func = RVAToAddr(functions[count]); 1.280 + if (NULL == func) 1.281 + continue; 1.282 + 1.283 + // Check for a name. 1.284 + LPCSTR name = NULL; 1.285 + UINT hint; 1.286 + for (hint = 0; hint < num_names; hint++) { 1.287 + if (ordinals[hint] == count) { 1.288 + name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint])); 1.289 + break; 1.290 + } 1.291 + } 1.292 + 1.293 + if (name == NULL) 1.294 + hint = 0; 1.295 + 1.296 + // Check for forwarded exports. 1.297 + LPCSTR forward = NULL; 1.298 + if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) && 1.299 + reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) + 1.300 + size) { 1.301 + forward = reinterpret_cast<LPCSTR>(func); 1.302 + func = 0; 1.303 + } 1.304 + 1.305 + if (!callback(*this, ordinal_base + count, hint, name, func, forward, 1.306 + cookie)) 1.307 + return false; 1.308 + } 1.309 + 1.310 + return true; 1.311 +} 1.312 + 1.313 +bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const { 1.314 + PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC); 1.315 + DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC); 1.316 + PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( 1.317 + directory); 1.318 + 1.319 + if (directory == NULL || size < sizeof(IMAGE_BASE_RELOCATION)) 1.320 + return true; 1.321 + 1.322 + while (base->SizeOfBlock) { 1.323 + PWORD reloc = reinterpret_cast<PWORD>(base + 1); 1.324 + UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 1.325 + sizeof(WORD); 1.326 + 1.327 + for (UINT i = 0; i < num_relocs; i++, reloc++) { 1.328 + WORD type = *reloc >> 12; 1.329 + PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF)); 1.330 + 1.331 + if (!callback(*this, type, address, cookie)) 1.332 + return false; 1.333 + } 1.334 + 1.335 + base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( 1.336 + reinterpret_cast<char*>(base) + base->SizeOfBlock); 1.337 + } 1.338 + 1.339 + return true; 1.340 +} 1.341 + 1.342 +bool PEImage::EnumImportChunks(EnumImportChunksFunction callback, 1.343 + PVOID cookie) const { 1.344 + DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT); 1.345 + PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk(); 1.346 + 1.347 + if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR)) 1.348 + return true; 1.349 + 1.350 + for (; import->FirstThunk; import++) { 1.351 + LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name)); 1.352 + PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.353 + RVAToAddr(import->OriginalFirstThunk)); 1.354 + PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.355 + RVAToAddr(import->FirstThunk)); 1.356 + 1.357 + if (!callback(*this, module_name, name_table, iat, cookie)) 1.358 + return false; 1.359 + } 1.360 + 1.361 + return true; 1.362 +} 1.363 + 1.364 +bool PEImage::EnumOneImportChunk(EnumImportsFunction callback, 1.365 + LPCSTR module_name, 1.366 + PIMAGE_THUNK_DATA name_table, 1.367 + PIMAGE_THUNK_DATA iat, PVOID cookie) const { 1.368 + if (NULL == name_table) 1.369 + return false; 1.370 + 1.371 + for (; name_table && name_table->u1.Ordinal; name_table++, iat++) { 1.372 + LPCSTR name = NULL; 1.373 + WORD ordinal = 0; 1.374 + WORD hint = 0; 1.375 + 1.376 + if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { 1.377 + ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); 1.378 + } else { 1.379 + PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( 1.380 + RVAToAddr(name_table->u1.ForwarderString)); 1.381 + 1.382 + hint = import->Hint; 1.383 + name = reinterpret_cast<LPCSTR>(&import->Name); 1.384 + } 1.385 + 1.386 + if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) 1.387 + return false; 1.388 + } 1.389 + 1.390 + return true; 1.391 +} 1.392 + 1.393 +bool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const { 1.394 + EnumAllImportsStorage temp = { callback, cookie }; 1.395 + return EnumImportChunks(ProcessImportChunk, &temp); 1.396 +} 1.397 + 1.398 +bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback, 1.399 + PVOID cookie) const { 1.400 + PVOID directory = GetImageDirectoryEntryAddr( 1.401 + IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); 1.402 + DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); 1.403 + PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory); 1.404 + 1.405 + if (directory == NULL || size == 0) 1.406 + return true; 1.407 + 1.408 + for (; delay_descriptor->rvaHmod; delay_descriptor++) { 1.409 + PIMAGE_THUNK_DATA name_table; 1.410 + PIMAGE_THUNK_DATA iat; 1.411 + PIMAGE_THUNK_DATA bound_iat; // address of the optional bound IAT 1.412 + PIMAGE_THUNK_DATA unload_iat; // address of optional copy of original IAT 1.413 + LPCSTR module_name; 1.414 + 1.415 + // check if VC7-style imports, using RVAs instead of 1.416 + // VC6-style addresses. 1.417 + bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; 1.418 + 1.419 + if (rvas) { 1.420 + module_name = reinterpret_cast<LPCSTR>( 1.421 + RVAToAddr(delay_descriptor->rvaDLLName)); 1.422 + name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.423 + RVAToAddr(delay_descriptor->rvaINT)); 1.424 + iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.425 + RVAToAddr(delay_descriptor->rvaIAT)); 1.426 + bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.427 + RVAToAddr(delay_descriptor->rvaBoundIAT)); 1.428 + unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.429 + RVAToAddr(delay_descriptor->rvaUnloadIAT)); 1.430 + } else { 1.431 +#pragma warning(push) 1.432 +#pragma warning(disable: 4312) 1.433 + // These casts generate warnings because they are 32 bit specific. 1.434 + module_name = reinterpret_cast<LPCSTR>(delay_descriptor->rvaDLLName); 1.435 + name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.436 + delay_descriptor->rvaINT); 1.437 + iat = reinterpret_cast<PIMAGE_THUNK_DATA>(delay_descriptor->rvaIAT); 1.438 + bound_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.439 + delay_descriptor->rvaBoundIAT); 1.440 + unload_iat = reinterpret_cast<PIMAGE_THUNK_DATA>( 1.441 + delay_descriptor->rvaUnloadIAT); 1.442 +#pragma warning(pop) 1.443 + } 1.444 + 1.445 + if (!callback(*this, delay_descriptor, module_name, name_table, iat, 1.446 + bound_iat, unload_iat, cookie)) 1.447 + return false; 1.448 + } 1.449 + 1.450 + return true; 1.451 +} 1.452 + 1.453 +bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback, 1.454 + PImgDelayDescr delay_descriptor, 1.455 + LPCSTR module_name, 1.456 + PIMAGE_THUNK_DATA name_table, 1.457 + PIMAGE_THUNK_DATA iat, 1.458 + PIMAGE_THUNK_DATA bound_iat, 1.459 + PIMAGE_THUNK_DATA unload_iat, 1.460 + PVOID cookie) const { 1.461 + UNREFERENCED_PARAMETER(bound_iat); 1.462 + UNREFERENCED_PARAMETER(unload_iat); 1.463 + 1.464 + for (; name_table->u1.Ordinal; name_table++, iat++) { 1.465 + LPCSTR name = NULL; 1.466 + WORD ordinal = 0; 1.467 + WORD hint = 0; 1.468 + 1.469 + if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { 1.470 + ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); 1.471 + } else { 1.472 + PIMAGE_IMPORT_BY_NAME import; 1.473 + bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; 1.474 + 1.475 + if (rvas) { 1.476 + import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( 1.477 + RVAToAddr(name_table->u1.ForwarderString)); 1.478 + } else { 1.479 +#pragma warning(push) 1.480 +#pragma warning(disable: 4312) 1.481 + // This cast generates a warning because it is 32 bit specific. 1.482 + import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( 1.483 + name_table->u1.ForwarderString); 1.484 +#pragma warning(pop) 1.485 + } 1.486 + 1.487 + hint = import->Hint; 1.488 + name = reinterpret_cast<LPCSTR>(&import->Name); 1.489 + } 1.490 + 1.491 + if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) 1.492 + return false; 1.493 + } 1.494 + 1.495 + return true; 1.496 +} 1.497 + 1.498 +bool PEImage::EnumAllDelayImports(EnumImportsFunction callback, 1.499 + PVOID cookie) const { 1.500 + EnumAllImportsStorage temp = { callback, cookie }; 1.501 + return EnumDelayImportChunks(ProcessDelayImportChunk, &temp); 1.502 +} 1.503 + 1.504 +bool PEImage::VerifyMagic() const { 1.505 + PIMAGE_DOS_HEADER dos_header = GetDosHeader(); 1.506 + 1.507 + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 1.508 + return false; 1.509 + 1.510 + PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); 1.511 + 1.512 + if (nt_headers->Signature != IMAGE_NT_SIGNATURE) 1.513 + return false; 1.514 + 1.515 + if (nt_headers->FileHeader.SizeOfOptionalHeader != 1.516 + sizeof(IMAGE_OPTIONAL_HEADER)) 1.517 + return false; 1.518 + 1.519 + if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) 1.520 + return false; 1.521 + 1.522 + return true; 1.523 +} 1.524 + 1.525 +bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const { 1.526 + LPVOID address = RVAToAddr(rva); 1.527 + return ImageAddrToOnDiskOffset(address, on_disk_offset); 1.528 +} 1.529 + 1.530 +bool PEImage::ImageAddrToOnDiskOffset(LPVOID address, 1.531 + DWORD *on_disk_offset) const { 1.532 + if (NULL == address) 1.533 + return false; 1.534 + 1.535 + // Get the section that this address belongs to. 1.536 + PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address); 1.537 + if (NULL == section_header) 1.538 + return false; 1.539 + 1.540 +#pragma warning(push) 1.541 +#pragma warning(disable: 4311) 1.542 + // These casts generate warnings because they are 32 bit specific. 1.543 + // Don't follow the virtual RVAToAddr, use the one on the base. 1.544 + DWORD offset_within_section = reinterpret_cast<DWORD>(address) - 1.545 + reinterpret_cast<DWORD>(PEImage::RVAToAddr( 1.546 + section_header->VirtualAddress)); 1.547 +#pragma warning(pop) 1.548 + 1.549 + *on_disk_offset = section_header->PointerToRawData + offset_within_section; 1.550 + return true; 1.551 +} 1.552 + 1.553 +PVOID PEImage::RVAToAddr(DWORD rva) const { 1.554 + if (rva == 0) 1.555 + return NULL; 1.556 + 1.557 + return reinterpret_cast<char*>(module_) + rva; 1.558 +} 1.559 + 1.560 +PVOID PEImageAsData::RVAToAddr(DWORD rva) const { 1.561 + if (rva == 0) 1.562 + return NULL; 1.563 + 1.564 + PVOID in_memory = PEImage::RVAToAddr(rva); 1.565 + DWORD disk_offset; 1.566 + 1.567 + if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset)) 1.568 + return NULL; 1.569 + 1.570 + return PEImage::RVAToAddr(disk_offset); 1.571 +} 1.572 + 1.573 +} // namespace win 1.574 +} // namespace base