explicit RelocationBlockIterator(Process const& process, PeFile const& pe_file) { try { NtHeaders const nt_headers{process, pe_file}; DWORD const data_dir_va = nt_headers.GetDataDirectoryVirtualAddress(PeDataDir::BaseReloc); DWORD const size = nt_headers.GetDataDirectorySize(PeDataDir::BaseReloc); if (!data_dir_va || !size) { return; } auto base = static_cast<std::uint8_t*>(RvaToVa(process, pe_file, data_dir_va)); if (!base) { return; } // Cast to integer and back to avoid pointer overflow UB. auto const reloc_dir_end = reinterpret_cast<void const*>( reinterpret_cast<std::uintptr_t>(base) + size); auto const file_end = static_cast<std::uint8_t*>(pe_file.GetBase()) + pe_file.GetSize(); // Sample: virtrelocXP.exe if (pe_file.GetType() == PeFileType::Data && (reloc_dir_end < base || reloc_dir_end > file_end)) { return; } // TODO: Dump should warn for this. RelocationBlock const relocation_block{ process, pe_file, reinterpret_cast<IMAGE_BASE_RELOCATION*>(base), reloc_dir_end}; if (relocation_block.IsInvalid()) { return; } impl_ = std::make_shared<Impl>( process, pe_file, relocation_block, reloc_dir_end); } catch (std::exception const& /*e*/) { // Nothing to do here. } }
explicit TlsDir(Process const& process, PeFile const& pe_file) : process_{&process}, pe_file_{&pe_file} { NtHeaders const nt_headers{process, pe_file}; DWORD const data_dir_va = nt_headers.GetDataDirectoryVirtualAddress(PeDataDir::TLS); // Windows will load images which don't specify a size for the // TLS directory. if (!data_dir_va) { HADESMEM_DETAIL_THROW_EXCEPTION( Error{} << ErrorString{"PE file has no TLS directory."}); } base_ = static_cast<std::uint8_t*>(RvaToVa(process, pe_file, data_dir_va)); if (!base_) { HADESMEM_DETAIL_THROW_EXCEPTION( Error{} << ErrorString{"TLS directory is invalid."}); } UpdateRead(); }