コード例 #1
0
ファイル: patch_dr.hpp プロジェクト: geota/hadesmem
  virtual void RemovePatch() override
  {
    hadesmem::detail::AcquireSRWLock const lock(
      &GetSrwLock(), hadesmem::detail::SRWLockType::Exclusive);

    HADESMEM_DETAIL_TRACE_A("Unsetting DR hook.");

    auto& dr_hooks = GetDrHooks();
    auto const thread_id = ::GetCurrentThreadId();
    auto const iter = dr_hooks.find(thread_id);
    HADESMEM_DETAIL_ASSERT(iter != std::end(dr_hooks));
    auto const dr_index = iter->second;

    Thread const thread(thread_id);
    auto context = GetThreadContext(thread, CONTEXT_DEBUG_REGISTERS);

    // Clear the appropriate DR
    *(&context.Dr0 + dr_index) = 0;
    // Clear appropriate L0-L3 flag
    context.Dr7 &= ~static_cast<std::uintptr_t>(1ULL << (dr_index * 2));

    SetThreadContext(thread, context);

    auto const dr_hooks_removed = dr_hooks.erase(thread_id);
    (void)dr_hooks_removed;
    HADESMEM_DETAIL_ASSERT(dr_hooks_removed);

    auto& veh_hooks = GetVehHooks();
    auto const veh_hooks_removed = veh_hooks.erase(target_);
    (void)veh_hooks_removed;
    HADESMEM_DETAIL_ASSERT(veh_hooks_removed);
  }
コード例 #2
0
ファイル: disassemble.cpp プロジェクト: GliderPro/hadesmem
void DisassembleEp(hadesmem::Process const& process,
                   hadesmem::PeFile const& pe_file,
                   std::uintptr_t ep_rva,
                   void* ep_va,
                   std::size_t tabs)
{
  if (!ep_va)
  {
    return;
  }

  std::wostream& out = GetOutputStreamW();

  // Get the number of bytes from the EP to the end of the file.
  std::size_t max_buffer_size = GetBytesToEndOfFile(pe_file, ep_va);
  // Clamp the amount of data read to the theoretical maximum.
  std::size_t const kMaxInstructions = 10U;
  std::size_t const kMaxInstructionLen = 15U;
  std::size_t const kMaxInstructionsBytes =
    kMaxInstructions * kMaxInstructionLen;
  max_buffer_size = (std::min)(max_buffer_size, kMaxInstructionsBytes);
  auto const disasm_buf =
    hadesmem::ReadVector<std::uint8_t>(process, ep_va, max_buffer_size);
  std::uint64_t const ip = hadesmem::GetRuntimeBase(process, pe_file) + ep_rva;

  ud_t ud_obj;
  ud_init(&ud_obj);
  ud_set_input_buffer(&ud_obj, disasm_buf.data(), max_buffer_size);
  ud_set_syntax(&ud_obj, UD_SYN_INTEL);
  ud_set_pc(&ud_obj, ip);
  ud_set_mode(&ud_obj, pe_file.Is64() ? 64 : 32);

  // Be pessimistic. Use the minimum theoretical amount of instrutions we could
  // fit in our buffer.
  std::size_t const instruction_count = max_buffer_size / kMaxInstructionLen;
  for (std::size_t i = 0U; i < instruction_count; ++i)
  {
    std::uint32_t const len = ud_disassemble(&ud_obj);
    if (len == 0)
    {
      WriteNormal(out, L"WARNING! Disassembly failed.", tabs);
      // If we can't disassemble at least 5 instructions there's probably
      // something strange about the function. Even in the case of a nullsub
      // there is typically some INT3 or NOP padding after it...
      WarnForCurrentFile(i < 5U ? WarningType::kUnsupported
                                : WarningType::kSuspicious);
      break;
    }

    char const* const asm_str = ud_insn_asm(&ud_obj);
    HADESMEM_DETAIL_ASSERT(asm_str);
    char const* const asm_bytes_str = ud_insn_hex(&ud_obj);
    HADESMEM_DETAIL_ASSERT(asm_bytes_str);
    auto const diasm_line =
      hadesmem::detail::MultiByteToWideChar(asm_str) + L" (" +
      hadesmem::detail::MultiByteToWideChar(asm_bytes_str) + L")";
    WriteNormal(out, diasm_line, tabs);
  }
}
コード例 #3
0
ファイル: pe_file.hpp プロジェクト: karliky/hadesmem
  explicit PeFile(Process const& process,
                  void* address,
                  PeFileType type,
                  DWORD size)
    : process_{&process},
      base_{static_cast<std::uint8_t*>(address)},
      type_{type},
      size_{size}
  {
    HADESMEM_DETAIL_ASSERT(base_ != 0);
    if (type == PeFileType::Data && !size)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                      << ErrorString{"Invalid file size."});
    }

    if (type == PeFileType::Image && !size)
    {
      try
      {
        Module const module{process, reinterpret_cast<HMODULE>(address)};
        size_ = module.GetSize();
      }
      catch (...)
      {
        auto const region_alloc_size =
          detail::GetRegionAllocSize(*process_, base_);
        HADESMEM_DETAIL_ASSERT(region_alloc_size <
                               (std::numeric_limits<DWORD>::max)());
        size_ = static_cast<DWORD>(region_alloc_size);
      }
    }

    // Not erroring out anywhere here in order to retain back-compat.
    // TODO: Do this properly as part of the rewrite.
    try
    {
      if (size_ > sizeof(IMAGE_DOS_HEADER))
      {
        auto const nt_hdrs_ofs =
          Read<IMAGE_DOS_HEADER>(process, address).e_lfanew;
        if (size_ >= nt_hdrs_ofs + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))
        {
          auto const nt_hdrs = Read<IMAGE_NT_HEADERS>(
            process, static_cast<std::uint8_t*>(address) + nt_hdrs_ofs);
          if (nt_hdrs.Signature == IMAGE_NT_SIGNATURE &&
              nt_hdrs.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
          {
            is_64_ = true;
          }
        }
      }
    }
    catch (...)
    {
    }
  }
コード例 #4
0
ファイル: write.hpp プロジェクト: GliderPro/hadesmem
inline void
  WriteString(Process const& process, PVOID address, T const* const str)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsCharType<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);
  HADESMEM_DETAIL_ASSERT(str != nullptr);

  WriteString(process, address, std::basic_string<T>(str));
}
コード例 #5
0
ファイル: alloc.hpp プロジェクト: GliderPro/hadesmem
 explicit Allocator(Process const& process,
                    SIZE_T size,
                    PVOID base = nullptr,
                    bool allocated = false)
   : process_{&process},
     base_{allocated ? base : Alloc(process, size, base)},
     size_{size}
 {
   HADESMEM_DETAIL_ASSERT(process_ != 0);
   HADESMEM_DETAIL_ASSERT(base_ != 0);
   HADESMEM_DETAIL_ASSERT(size_ != 0);
 }
コード例 #6
0
ファイル: write.hpp プロジェクト: GliderPro/hadesmem
inline void WriteVector(Process const& process,
                        PVOID address,
                        std::vector<T, Alloc> const& data)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);
  HADESMEM_DETAIL_ASSERT(!data.empty());

  std::size_t const raw_size = data.size() * sizeof(T);
  detail::WriteImpl(process, address, data.data(), raw_size);
}
コード例 #7
0
ファイル: write.hpp プロジェクト: GliderPro/hadesmem
inline void
  Write(Process const& process, PVOID address, T const* beg, T const* end)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);
  HADESMEM_DETAIL_ASSERT(beg != nullptr);
  HADESMEM_DETAIL_ASSERT(end != nullptr);

  std::size_t const count = static_cast<std::size_t>(std::distance(beg, end));
  Write(process, address, beg, count);
}
コード例 #8
0
ファイル: write.hpp プロジェクト: GliderPro/hadesmem
inline void
  Write(Process const& process, PVOID address, T const* ptr, std::size_t count)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);
  HADESMEM_DETAIL_ASSERT(ptr != nullptr);
  HADESMEM_DETAIL_ASSERT(count != 0);

  std::size_t const raw_size =
    static_cast<std::size_t>(std::distance(ptr, ptr + count)) * sizeof(T);
  detail::WriteImpl(process, address, ptr, raw_size);
}
コード例 #9
0
ファイル: pe_file.hpp プロジェクト: karliky/hadesmem
std::basic_string<CharT> CheckedReadString(Process const& process,
                                           PeFile const& pe_file,
                                           void* address)
{
  if (pe_file.GetType() == PeFileType::Image)
  {
    return ReadString<CharT>(process, address);
  }
  else if (pe_file.GetType() == PeFileType::Data)
  {
    void* const file_end =
      static_cast<std::uint8_t*>(pe_file.GetBase()) + pe_file.GetSize();
    if (address >= file_end)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"Invalid VA."});
    }
    // Handle EOF termination.
    // Sample: maxsecXP.exe (Corkami PE Corpus)
    return ReadStringBounded<CharT>(process, address, file_end);
  }
  else
  {
    HADESMEM_DETAIL_ASSERT(false);
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"Unknown PE file type."});
  }
}
コード例 #10
0
ファイル: alloc.hpp プロジェクト: GliderPro/hadesmem
  void Free()
  {
    if (!process_)
    {
      return;
    }

    HADESMEM_DETAIL_ASSERT(base_ != nullptr);
    HADESMEM_DETAIL_ASSERT(size_ != 0);

    ::hadesmem::Free(*process_, base_);

    process_ = nullptr;
    base_ = nullptr;
    size_ = 0;
  }
コード例 #11
0
ファイル: module_list.hpp プロジェクト: GliderPro/hadesmem
  explicit ModuleIterator(Process const& process)
    : impl_{std::make_shared<Impl>()}
  {
    HADESMEM_DETAIL_ASSERT(impl_.get());

    impl_->process_ = &process;

    // CreateToolhelp32Snapshot can fail with ERROR_PARTIAL_COPY for 'zombie'
    // processes.
    try
    {
      impl_->snap_ = detail::CreateToolhelp32Snapshot(
        TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, impl_->process_->GetId());
    }
    catch (std::exception const&)
    {
      impl_.reset();
      return;
    }

    hadesmem::detail::Optional<MODULEENTRY32> const entry =
      detail::Module32First(impl_->snap_.GetHandle());
    if (!entry)
    {
      impl_.reset();
      return;
    }

    impl_->module_ = Module{*impl_->process_, *entry};
  }
コード例 #12
0
  BoundImportDescriptorIterator& operator++()
  {
    try
    {
      HADESMEM_DETAIL_ASSERT(impl_.get());

      auto const cur_base = static_cast<PIMAGE_BOUND_IMPORT_DESCRIPTOR>(
        impl_->bound_import_desc_->GetBase());
      auto const new_base = reinterpret_cast<PIMAGE_BOUND_IMPORT_DESCRIPTOR>(
        reinterpret_cast<IMAGE_BOUND_FORWARDER_REF*>(cur_base + 1) +
        impl_->bound_import_desc_->GetNumberOfModuleForwarderRefs());
      auto const start_base = static_cast<PIMAGE_BOUND_IMPORT_DESCRIPTOR>(
        impl_->bound_import_desc_->GetStart());
      impl_->bound_import_desc_ = BoundImportDescriptor{
        *impl_->process_, *impl_->pe_file_, start_base, new_base};

      if (IsTerminator(*impl_->bound_import_desc_))
      {
        impl_.reset();
        return *this;
      }
    }
    catch (std::exception const& /*e*/)
    {
      impl_.reset();
    }

    return *this;
  }
コード例 #13
0
ULONG WINAPI DirectInput8WProxy::Release()
{
  hadesmem::detail::LastErrorPreserver last_error_preserver;

  refs_--;
  HADESMEM_DETAIL_ASSERT(refs_ >= 0);

  if (refs_ == 0)
  {
    Cleanup();
  }

  last_error_preserver.Revert();
  auto const ret = direct_input_->Release();
  last_error_preserver.Update();

  HADESMEM_DETAIL_TRACE_NOISY_FORMAT_A(
    "Internal refs: [%lu]. External refs: [%lld].", ret, refs_);

  if (ret == 0)
  {
    delete this;
  }

  return ret;
}
コード例 #14
0
  RelocationBlockIterator& operator++()
  {
    try
    {
      HADESMEM_DETAIL_ASSERT(impl_.get());

      auto const next_base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
        reinterpret_cast<std::uintptr_t>(
          impl_->relocation_block_->GetRelocationDataStart()) +
        (impl_->relocation_block_->GetNumberOfRelocations() * sizeof(WORD)));
      // TODO: Dump should warn for integer overflow or mis-aligned off-the-end
      // data.
      if (next_base < impl_->relocation_block_->GetBase() ||
          next_base >= impl_->reloc_dir_end_)
      {
        impl_.reset();
        return *this;
      }

      impl_->relocation_block_ = RelocationBlock{
        *impl_->process_, *impl_->pe_file_, next_base, impl_->reloc_dir_end_};
      // TODO: Dump should warn for this.
      if (impl_->relocation_block_->IsInvalid())
      {
        impl_.reset();
        return *this;
      }
    }
    catch (std::exception const& /*e*/)
    {
      impl_.reset();
    }

    return *this;
  }
コード例 #15
0
ファイル: find_pattern.hpp プロジェクト: JuJuBoSc/hadesmem
void* Find(Process const& process,
           ModuleRegionInfo const& mod_info,
           NeedleIterator n_beg,
           NeedleIterator n_end,
           std::uint32_t flags,
           void* start,
           std::wstring const* name)
{
  HADESMEM_DETAIL_ASSERT(n_beg != n_end);

  bool const scan_data_secs = !!(flags & PatternFlags::kScanData);
  auto const& scan_regions =
    scan_data_secs ? mod_info.data_regions : mod_info.code_regions;
  for (auto const& region : scan_regions)
  {
    if (void* const address = Find(process, region, start, n_beg, n_end))
    {
      return !!(flags & PatternFlags::kRelativeAddress)
               ? static_cast<std::uint8_t*>(address) -
                   reinterpret_cast<std::uintptr_t>(
                     mod_info.module->GetHandle())
               : address;
    }
  }

  if (!!(flags & PatternFlags::kThrowOnUnmatch))
  {
    auto const name_narrow = name ? WideCharToMultiByte(*name) : std::string();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"Could not match pattern."}
                                    << ErrorStringOther{name_narrow});
  }

  return nullptr;
}
コード例 #16
0
HRESULT WINAPI DirectInput8WProxy::QueryInterface(REFIID riid, LPVOID* obj)
{
  hadesmem::detail::LastErrorPreserver last_error_preserver;

  last_error_preserver.Revert();
  auto const ret = direct_input_->QueryInterface(riid, obj);
  last_error_preserver.Update();

  if (SUCCEEDED(ret))
  {
    HADESMEM_DETAIL_TRACE_NOISY_A("Succeeded.");

    if (*obj == direct_input_)
    {
      refs_++;
      *obj = this;
    }
    else
    {
      HADESMEM_DETAIL_TRACE_A("WARNING! Unhandled interface.");
      HADESMEM_DETAIL_ASSERT(false);
      static_cast<IUnknown*>(*obj)->Release();
      return E_NOINTERFACE;
    }
  }
  else
  {
    HADESMEM_DETAIL_TRACE_NOISY_A("Failed.");
  }

  return ret;
}
コード例 #17
0
ファイル: find_pattern.hpp プロジェクト: JuJuBoSc/hadesmem
void* Find(Process const& process,
           std::pair<std::uint8_t*, std::uint8_t*> const& region,
           NeedleIterator n_beg,
           NeedleIterator n_end,
           std::uint32_t flags,
           void* start,
           std::wstring const* name)
{
  HADESMEM_DETAIL_ASSERT(n_beg != n_end);

  if (void* const address = Find(process, region, start, n_beg, n_end))
  {
    return !!(flags & PatternFlags::kRelativeAddress)
             ? static_cast<std::uint8_t*>(address) -
                 reinterpret_cast<std::uintptr_t>(region.first)
             : address;
  }

  if (!!(flags & PatternFlags::kThrowOnUnmatch))
  {
    auto const name_narrow = name ? WideCharToMultiByte(*name) : std::string();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"Could not match pattern."}
                                    << ErrorStringOther{name_narrow});
  }

  return nullptr;
}
コード例 #18
0
ファイル: find_pattern.hpp プロジェクト: JuJuBoSc/hadesmem
void* FindRaw(Process const& process,
              std::uint8_t* s_beg,
              std::uint8_t* s_end,
              NeedleIterator n_beg,
              NeedleIterator n_end)
{
  HADESMEM_DETAIL_ASSERT(s_beg < s_end);

  std::ptrdiff_t const mem_size = s_end - s_beg;
  std::vector<std::uint8_t> const haystack{ReadVector<std::uint8_t>(
    process, s_beg, static_cast<std::size_t>(mem_size))};

  auto const h_beg = std::begin(haystack);
  auto const h_end = std::end(haystack);
  auto const iter =
    std::search(h_beg,
                h_end,
                n_beg,
                n_end,
                [](std::uint8_t h_cur, detail::PatternDataByte const& n_cur)
                {
                  return n_cur.wildcard || h_cur == n_cur.data;
                });

  if (iter != h_end)
  {
    return s_beg + std::distance(h_beg, iter);
  }

  return nullptr;
}
コード例 #19
0
ファイル: read.hpp プロジェクト: lvous/hadesmem
void ReadStringEx(Process const& process,
                  PVOID address,
                  OutputIterator data,
                  std::size_t chunk_len,
                  void* upper_bound)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsCharType<T>::value);
  HADESMEM_DETAIL_STATIC_ASSERT(std::is_base_of<
    std::output_iterator_tag,
    typename std::iterator_traits<OutputIterator>::iterator_category>::value);

  HADESMEM_DETAIL_ASSERT(chunk_len != 0);

  for (;;)
  {
    detail::ProtectGuard protect_guard{
      process, address, detail::ProtectGuardType::kRead};

    MEMORY_BASIC_INFORMATION const mbi = detail::Query(process, address);
    PVOID const region_next_real =
      static_cast<PBYTE>(mbi.BaseAddress) + mbi.RegionSize;
    void* const region_next = upper_bound
                                ? (std::min)(upper_bound, region_next_real)
                                : region_next_real;

    T* cur = static_cast<T*>(address);
    while (cur + 1 <= region_next)
    {
      std::size_t const len_to_end = reinterpret_cast<DWORD_PTR>(region_next) -
                                     reinterpret_cast<DWORD_PTR>(cur);
      std::size_t const buf_len_bytes =
        (std::min)(chunk_len * sizeof(T), len_to_end);
      std::size_t const buf_len = buf_len_bytes / sizeof(T);

      std::vector<T> buf(buf_len);
      detail::ReadUnchecked(process, cur, buf.data(), buf.size() * sizeof(T));

      auto const iter = std::find(std::begin(buf), std::end(buf), T());
      std::copy(std::begin(buf), iter, data);

      if (iter != std::end(buf) || region_next == upper_bound)
      {
        protect_guard.Restore();
        return;
      }

      cur += buf_len;
    }

    address = region_next;

    protect_guard.Restore();

    if (upper_bound && cur >= upper_bound)
    {
      return;
    }
  }
}
コード例 #20
0
ファイル: read.hpp プロジェクト: lvous/hadesmem
inline void
  Read(Process const& process, PVOID address, std::size_t n, OutputIterator out)
{
  HADESMEM_DETAIL_ASSERT(n ? address != nullptr : true);

  auto const data = ReadVector<T>(process, address, n);
  std::copy(std::begin(data), std::end(data), out);
}
コード例 #21
0
ファイル: write.hpp プロジェクト: GliderPro/hadesmem
inline void Write(Process const& process, PVOID address, T const& data)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);

  detail::WriteImpl(process, address, data);
}
コード例 #22
0
ファイル: thread_list.hpp プロジェクト: GliderPro/hadesmem
  ThreadIterator& operator++()
  {
    HADESMEM_DETAIL_ASSERT(impl_.get());

    Advance();

    return *this;
  }
コード例 #23
0
ファイル: write_impl.hpp プロジェクト: GliderPro/hadesmem
void WriteImpl(Process const& process, PVOID address, T const& data)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);

  WriteImpl(process, address, std::addressof(data), sizeof(data));
}
コード例 #24
0
ファイル: callbacks.hpp プロジェクト: lvous/hadesmem
 void Unregister(std::size_t id)
 {
   hadesmem::detail::AcquireSRWLock lock(
     &srw_lock_, hadesmem::detail::SRWLockType::Exclusive);
   auto const num_removed = callbacks_.erase(id);
   HADESMEM_DETAIL_ASSERT(num_removed == 1);
   (void)num_removed;
 }
コード例 #25
0
ファイル: callbacks.hpp プロジェクト: lvous/hadesmem
 std::size_t Register(Callback const& callback)
 {
   hadesmem::detail::AcquireSRWLock lock(
     &srw_lock_, hadesmem::detail::SRWLockType::Exclusive);
   auto const cur_id = next_id_++;
   HADESMEM_DETAIL_ASSERT(next_id_ > cur_id);
   callbacks_[cur_id] = callback;
   return cur_id;
 }
コード例 #26
0
ファイル: read.hpp プロジェクト: lvous/hadesmem
inline std::vector<T, Alloc>
  ReadVector(Process const& process, PVOID address, std::size_t count)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);
  HADESMEM_DETAIL_STATIC_ASSERT(std::is_default_constructible<T>::value);

  HADESMEM_DETAIL_ASSERT(count ? address != nullptr : true);

  return ReadVectorEx<T, Alloc>(process, address, count, ReadFlags::kNone);
}
コード例 #27
0
ファイル: write.hpp プロジェクト: GliderPro/hadesmem
inline void WriteString(Process const& process,
                        PVOID address,
                        std::basic_string<T, Traits, Alloc> const& data)
{
  HADESMEM_DETAIL_STATIC_ASSERT(detail::IsCharType<T>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);

  return Write(process, address, data.c_str(), data.size() + 1);
}
コード例 #28
0
ファイル: write_impl.hpp プロジェクト: GliderPro/hadesmem
inline void WriteImpl(Process const& process,
                      PVOID address,
                      LPCVOID data,
                      std::size_t len)
{
  HADESMEM_DETAIL_ASSERT(address != nullptr);
  HADESMEM_DETAIL_ASSERT(data != nullptr);
  HADESMEM_DETAIL_ASSERT(len != 0);

  for (;;)
  {
    ProtectGuard protect_guard{process, address, ProtectGuardType::kWrite};

    MEMORY_BASIC_INFORMATION const mbi = detail::Query(process, address);
    void* const region_next =
      static_cast<std::uint8_t*>(mbi.BaseAddress) + mbi.RegionSize;

    void* const address_end = static_cast<std::uint8_t*>(address) + len;
    if (address_end <= region_next)
    {
      WriteUnchecked(process, address, data, len);

      protect_guard.Restore();

      return;
    }
    else
    {
      std::size_t const len_new =
        reinterpret_cast<std::uintptr_t>(region_next) -
        reinterpret_cast<std::uintptr_t>(address);

      WriteUnchecked(process, address, data, len_new);

      protect_guard.Restore();

      address = static_cast<std::uint8_t*>(address) + len_new;
      data = static_cast<std::uint8_t const*>(data) + len_new;
      len -= len_new;
    }
  }
}
コード例 #29
0
ファイル: write_impl.hpp プロジェクト: GliderPro/hadesmem
inline void WriteUnchecked(Process const& process,
                           PVOID address,
                           LPCVOID data,
                           std::size_t len)
{
  HADESMEM_DETAIL_ASSERT(address != nullptr);
  HADESMEM_DETAIL_ASSERT(data != nullptr);
  HADESMEM_DETAIL_ASSERT(len != 0);

  SIZE_T bytes_written = 0;
  if (!::WriteProcessMemory(
        process.GetHandle(), address, data, len, &bytes_written) ||
      bytes_written != len)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"WriteProcessMemory failed."}
                                    << ErrorCodeWinLast{last_error});
  }
}
コード例 #30
0
ファイル: read.hpp プロジェクト: lvous/hadesmem
inline void Read(Process const& process, PVOID address, OutputIterator out)
{
  HADESMEM_DETAIL_STATIC_ASSERT(std::is_base_of<
    std::output_iterator_tag,
    typename std::iterator_traits<OutputIterator>::iterator_category>::value);

  HADESMEM_DETAIL_ASSERT(address != nullptr);

  auto const data = detail::ReadImpl<std::array<T, N>>(process, address);
  std::copy(&data[0], &data[0] + N, out);
}