Exemple #1
0
inline SmartHandle CreateRemoteThreadAndWait(Process const& process,
                                             LPTHREAD_START_ROUTINE func,
                                             DWORD timeout = INFINITE)
{
  SmartHandle remote_thread{::CreateRemoteThread(
    process.GetHandle(), nullptr, 0, func, nullptr, 0, nullptr)};
  if (!remote_thread.GetHandle())
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"CreateRemoteThread failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  DWORD const wait_res =
    ::WaitForSingleObject(remote_thread.GetHandle(), timeout);
  if (wait_res != WAIT_OBJECT_0)
  {
    if (wait_res == WAIT_TIMEOUT)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"WaitForSingleObject timeout."});
    }

    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error{} << ErrorString{"WaitForSingleObject failed."}
              << ErrorCodeWinLast{last_error});
  }

  return remote_thread;
}
Exemple #2
0
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."});
  }
}
Exemple #3
0
inline ModuleRegionInfo GetModuleInfo(Process const& process,
                                      std::wstring const& module)
{
  ModuleRegionInfo mod_info;

  if (module.empty())
  {
    mod_info.module = std::make_shared<Module>(process, nullptr);
  }
  else
  {
    mod_info.module = std::make_shared<Module>(process, module);
  }

  auto const base =
    reinterpret_cast<std::uint8_t*>(mod_info.module->GetHandle());
  PeFile const pe_file{process, base, hadesmem::PeFileType::Image, 0};
  DosHeader const dos_header{process, pe_file};
  NtHeaders const nt_headers{process, pe_file};
  SectionList const sections{process, pe_file};
  for (auto const& s : sections)
  {
    bool const is_code_section =
      !!(s.GetCharacteristics() & IMAGE_SCN_CNT_CODE);
    bool const is_data_section =
      !!(s.GetCharacteristics() & IMAGE_SCN_CNT_INITIALIZED_DATA);
    if (!is_code_section && !is_data_section)
    {
      continue;
    }

    auto const section_beg = static_cast<std::uint8_t*>(
      RvaToVa(process, pe_file, s.GetVirtualAddress()));
    if (section_beg == nullptr)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error() << ErrorString("Could not get section base address."));
    }

    DWORD const section_size = s.GetVirtualSize();
    if (!section_size)
    {
      continue;
    }

    auto const section_end = section_beg + section_size;

    auto& regions =
      is_code_section ? mod_info.code_regions : mod_info.data_regions;
    regions.emplace_back(section_beg, section_end);
  }

  if (mod_info.code_regions.empty() && mod_info.data_regions.empty())
  {
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error() << ErrorString("No valid sections to scan found."));
  }

  return mod_info;
}
Exemple #4
0
    void Unload()
    {
        auto const ntdll = ::GetModuleHandleW(L"ntdll.dll");
        if (!ntdll)
        {
            DWORD const last_error = ::GetLastError();
            HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                            << ErrorString{"GetModuleHandleW failed."}
                                            << ErrorCodeWinLast{last_error});
        }

        typedef NTSTATUS(NTAPI *
                         NtUnloadDriverFn)(PUNICODE_STRING DriverServiceName);

        auto const nt_unload_driver = reinterpret_cast<NtUnloadDriverFn>(
                                          ::GetProcAddress(ntdll, "NtUnloadDriver"));
        if (!nt_unload_driver)
        {
            DWORD const last_error = ::GetLastError();
            HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                            << ErrorString{"GetProcAddress failed."}
                                            << ErrorCodeWinLast{last_error});
        }

        UNICODE_STRING reg_path;
        std::wstring const reg_path_buf =
            L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + name_;
        ::RtlInitUnicodeString(&reg_path, reg_path_buf.c_str());
        auto const unload_status = nt_unload_driver(&reg_path);
        if (!NT_SUCCESS(unload_status))
        {
            HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                            << ErrorString{"NtUnloadDriver failed."}
                                            << ErrorCodeWinStatus{unload_status});
        }

        auto const reg_status = ::RegDeleteTreeW(
                                    HKEY_LOCAL_MACHINE,
                                    (L"SYSTEM\\CurrentControlSet\\Services\\" + name_).c_str());
        if (reg_status != ERROR_SUCCESS)
        {
            DWORD const last_error = ::GetLastError();
            HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                            << ErrorString{"RegDeleteTreeW failed."}
                                            << ErrorCodeWinLast{last_error}
                                            << ErrorCodeWinHr{reg_status});
        }
    }
Exemple #5
0
inline void* GetStartAddress(Thread const& thread)
{
  HMODULE const ntdll = GetModuleHandleW(L"ntdll");
  if (!ntdll)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"GetModuleHandleW failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  FARPROC const nt_query_information_thread_proc =
    GetProcAddress(ntdll, "NtQueryInformationThread");
  if (!nt_query_information_thread_proc)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"GetProcAddress failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  using NtQueryInformationThreadPtr =
    NTSTATUS(NTAPI*)(HANDLE thread_handle,
                     detail::winternl::THREADINFOCLASS thread_information_class,
                     PVOID thread_information,
                     ULONG thread_information_length,
                     PULONG return_length);

  auto const nt_query_information_thread =
    reinterpret_cast<NtQueryInformationThreadPtr>(
      nt_query_information_thread_proc);

  void* start_address = nullptr;
  NTSTATUS const status = nt_query_information_thread(
    thread.GetHandle(),
    detail::winternl::ThreadQuerySetWin32StartAddress,
    &start_address,
    sizeof(start_address),
    nullptr);
  if (!NT_SUCCESS(status))
  {
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error{} << ErrorString{"NtQueryInformationThread failed."}
              << ErrorCodeWinStatus{status});
  }

  return start_address;
}
Exemple #6
0
void* Find(Process const& process,
           ModuleRegionInfo::ScanRegion const& region,
           void* start,
           NeedleIterator n_beg,
           NeedleIterator n_end)
{
  std::uint8_t* s_beg = region.first;
  std::uint8_t* const s_end = region.second;

  // Support custom scan start address.
  if (start)
  {
    // Use specified starting address (plus one, so we don't
    // just find the same thing again) if we're in the target
    // region.
    if (start >= s_beg && start < s_end)
    {
      s_beg = static_cast<std::uint8_t*>(start) + 1;
      if (s_beg == s_end)
      {
        HADESMEM_DETAIL_THROW_EXCEPTION(
          Error() << ErrorString("Invalid start address."));
      }
    }
    // Skip if we're not in the target region.
    else
    {
      return nullptr;
    }
  }

  return FindRaw(process, s_beg, s_end, n_beg, n_end);
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
  void GetCallbacks(OutputIterator callbacks) const
  {
    using OutputIteratorCategory =
      typename std::iterator_traits<OutputIterator>::iterator_category;
    HADESMEM_DETAIL_STATIC_ASSERT(
      std::is_base_of<std::output_iterator_tag, OutputIteratorCategory>::value);

    auto const image_base = GetRuntimeBase(*process_, *pe_file_);
    auto callbacks_raw = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(
      RvaToVa(*process_,
              *pe_file_,
              static_cast<DWORD>(GetAddressOfCallBacks() - image_base)));
    if (!callbacks_raw)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"TLS callbacks are invalid."});
    }

    for (auto callback = Read<PIMAGE_TLS_CALLBACK>(*process_, callbacks_raw);
         callback;
         callback = Read<PIMAGE_TLS_CALLBACK>(*process_, ++callbacks_raw))
    {
      auto const callback_offset =
        reinterpret_cast<ULONGLONG>(callback) - image_base;
      *callbacks = reinterpret_cast<PIMAGE_TLS_CALLBACK>(
        static_cast<ULONG_PTR>(callback_offset));
      ++callbacks;
    }
  }
 void EnsureValid() const
 {
   if (!IsValid())
   {
     HADESMEM_DETAIL_THROW_EXCEPTION(
       Error{} << ErrorString{"DOS header magic invalid."});
   }
 }
Exemple #11
0
 void EnsureValid() const
 {
   if (!IsValid())
   {
     HADESMEM_DETAIL_THROW_EXCEPTION(
       Error{} << ErrorString{"NT headers signature invalid."});
   }
 }
Exemple #12
0
inline std::wstring CombinePath(std::wstring const& base,
                                std::wstring const& append)
{
  // Use newer and better PathCchCombineEx if it's available.
  detail::SmartModuleHandle const path_mod{
    LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll")};
  if (path_mod.IsValid())
  {
    using PathCchCombineExFn = HRESULT(WINAPI*)(PWSTR pszPathOut,
                                                size_t cchPathOut,
                                                PCWSTR pszPathIn,
                                                PCWSTR pszMore,
                                                unsigned long dwFlags);
    auto const path_cch_combine_ex = reinterpret_cast<PathCchCombineExFn>(
      GetProcAddress(path_mod.GetHandle(), "PathCchCombineEx"));
    if (path_cch_combine_ex)
    {
      std::vector<wchar_t> buffer(HADESMEM_DETAIL_MAX_PATH_UNICODE);
      HRESULT const hr = path_cch_combine_ex(buffer.data(),
                                             buffer.size(),
                                             base.c_str(),
                                             append.c_str(),
                                             HADESMEM_PATHCCH_ALLOW_LONG_PATHS);
      if (!SUCCEEDED(hr))
      {
        HADESMEM_DETAIL_THROW_EXCEPTION(
          Error{} << ErrorString{"PathCchCombineEx failed."}
                  << ErrorCodeWinHr{hr});
      }

      return buffer.data();
    }
  }

  // Fall back to older API with MAX_PATH limit.
  std::vector<wchar_t> buffer(MAX_PATH);
  if (!::PathCombineW(buffer.data(), base.c_str(), append.c_str()))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"PathCombineW failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  return buffer.data();
}
Exemple #13
0
 explicit Driver(std::wstring const& name, std::wstring const& path)
     : name_(name), path_(path)
 {
     if (detail::IsPathRelative(path_))
     {
         HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                         << ErrorString{"Path must be absolute."});
     }
 }
Exemple #14
0
  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 (...)
    {
    }
  }
Exemple #15
0
inline void Free(Process const& process, LPVOID address)
{
  if (!::VirtualFreeEx(process.GetHandle(), address, 0, MEM_RELEASE))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"VirtualFreeEx failed."}
                                    << ErrorCodeWinLast{last_error});
  }
}
Exemple #16
0
 void Cleanup()
 {
   if (ResumeThread(handle_) == static_cast<DWORD>(-1))
   {
     DWORD const last_error = ::GetLastError();
     HADESMEM_DETAIL_THROW_EXCEPTION(
       hadesmem::Error{} << hadesmem::ErrorString{"ResumeThread failed."}
                         << hadesmem::ErrorCodeWinLast{last_error});
   }
 }
Exemple #17
0
inline void SetThreadContext(Thread const& thread, CONTEXT const& context)
{
  if (!::SetThreadContext(thread.GetHandle(), &context))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error()
                                    << ErrorString("SetThreadContext failed.")
                                    << ErrorCodeWinLast(last_error));
  }
}
Exemple #18
0
inline void GetPrivilege(std::wstring const& name)
{
    HANDLE process_token_temp = nullptr;
    if (!::OpenProcessToken(::GetCurrentProcess(),
                            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                            &process_token_temp))
    {
        DWORD const last_error = ::GetLastError();
        HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                        << ErrorString{"OpenProcessToken failed."}
                                        << ErrorCodeWinLast{last_error});
    }
    detail::SmartHandle const process_token {
        process_token_temp
    };

    LUID luid = {0, 0};
    if (!::LookupPrivilegeValueW(nullptr, name.c_str(), &luid))
    {
        DWORD const last_error = ::GetLastError();
        HADESMEM_DETAIL_THROW_EXCEPTION(
            Error{} << ErrorString{"LookupPrivilegeValue failed."}
            << ErrorCodeWinLast{last_error});
    }

    TOKEN_PRIVILEGES privileges{};
    privileges.PrivilegeCount = 1;
    privileges.Privileges[0].Luid = luid;
    privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!::AdjustTokenPrivileges(process_token.GetHandle(),
                                 FALSE,
                                 &privileges,
                                 static_cast<DWORD>(sizeof(privileges)),
                                 nullptr,
                                 nullptr) ||
            ::GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        DWORD const last_error = ::GetLastError();
        HADESMEM_DETAIL_THROW_EXCEPTION(
            Error{} << ErrorString{"AdjustTokenPrivileges failed."}
            << ErrorCodeWinLast{last_error});
    }
}
Exemple #19
0
  WORD GetForwarderOrdinal() const
  {
    if (!IsForwardedByOrdinal())
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"Function is not exported by ordinal."});
    }

    try
    {
      std::string const forwarder_function{GetForwarderFunction()};
      return detail::StrToNum<WORD>(forwarder_function.substr(1));
    }
    catch (std::exception const& /*e*/)
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"Invalid forwarder ordinal detected."});
    }
  }
Exemple #20
0
 void SetBaseOfData(DWORD base_of_data)
 {
   if (pe_file_->Is64())
   {
     HADESMEM_DETAIL_THROW_EXCEPTION(
       Error{} << ErrorString{"Invalid field for architecture."});
   }
   else
   {
     data_32_.OptionalHeader.BaseOfData = base_of_data;
   }
 }
Exemple #21
0
 DWORD GetBaseOfData() const
 {
   if (pe_file_->Is64())
   {
     HADESMEM_DETAIL_THROW_EXCEPTION(
       Error{} << ErrorString{"Invalid field for architecture."});
   }
   else
   {
     return data_32_.OptionalHeader.BaseOfData;
   }
 }
Exemple #22
0
 std::string GetName() const
 {
   auto const name_import = static_cast<std::uint8_t*>(
     RvaToVa(*process_, *pe_file_, static_cast<DWORD>(GetAddressOfData())));
   if (!name_import)
   {
     HADESMEM_DETAIL_THROW_EXCEPTION(
       Error{} << ErrorString{"Invalid import name and hint."});
   }
   return detail::CheckedReadString<char>(
     *process_, *pe_file_, name_import + offsetof(IMAGE_IMPORT_BY_NAME, Name));
 }
Exemple #23
0
inline CONTEXT GetThreadContext(Thread const& thread, DWORD context_flags)
{
  if (::GetCurrentThreadId() == thread.GetId() &&
      context_flags != CONTEXT_DEBUG_REGISTERS)
  {
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error() << ErrorString("GetThreadContext called for current thread."));
  }

  CONTEXT context{};
  context.ContextFlags = context_flags;
  if (!::GetThreadContext(thread.GetHandle(), &context))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error()
                                    << ErrorString("GetThreadContext failed.")
                                    << ErrorCodeWinLast(last_error));
  }

  return context;
}
Exemple #24
0
inline BY_HANDLE_FILE_INFORMATION GetFileInformationByHandle(HANDLE file)
{
  BY_HANDLE_FILE_INFORMATION file_info{};
  if (!::GetFileInformationByHandle(file, &file_info))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error{} << ErrorString{"GetFileInformationByHandle failed."}
              << ErrorCodeWinLast{last_error});
  }

  return file_info;
}
Exemple #25
0
inline FARPROC
  FindProcedure(Process const& process, Module const& module, WORD ordinal)
{
  FARPROC const remote_func =
    detail::GetProcAddressInternal(process, module.GetHandle(), ordinal);
  if (!remote_func)
  {
    HADESMEM_DETAIL_THROW_EXCEPTION(
      Error{} << ErrorString{"GetProcAddressInternal failed."});
  }

  return remote_func;
}
Exemple #26
0
inline DWORD GetFileAttributesWrapper(std::wstring const& path)
{
  DWORD const attributes = ::GetFileAttributesW(path.c_str());
  if (attributes == INVALID_FILE_ATTRIBUTES)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"GetFileAttributes failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  return attributes;
}
Exemple #27
0
void HandleWindowChange(HWND wnd)
{
  WindowInfo& window_info = GetWindowInfo();

  if (wnd == nullptr)
  {
    if (window_info.hooked_ && window_info.old_wndproc_ != nullptr)
    {
      ::SetWindowLongPtrW(window_info.old_hwnd_,
                          GWLP_WNDPROC,
                          reinterpret_cast<LONG_PTR>(window_info.old_wndproc_));
      HADESMEM_DETAIL_TRACE_FORMAT_A("Reset window procedure located at %p.",
                                     window_info.old_wndproc_);
    }

    HADESMEM_DETAIL_TRACE_A("Clearing window hook data.");

    window_info.old_hwnd_ = nullptr;
    window_info.old_wndproc_ = nullptr;
    window_info.hooked_ = false;

    return;
  }

  if (!window_info.hooked_)
  {
    window_info.old_hwnd_ = wnd;
    ::SetLastError(0);
    window_info.old_wndproc_ = reinterpret_cast<WNDPROC>(::SetWindowLongPtrW(
      wnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&WindowProc)));
    if (!window_info.old_wndproc_)
    {
      DWORD const last_error = ::GetLastError();
      if (last_error)
      {
        HADESMEM_DETAIL_THROW_EXCEPTION(
          Error{} << ErrorString{"SetWindowLongPtrW failed."}
                  << ErrorCodeWinLast{last_error});
      }
    }
    window_info.hooked_ = true;
    HADESMEM_DETAIL_TRACE_FORMAT_A("Replaced window procedure located at %p.",
                                   window_info.old_wndproc_);
  }
  else
  {
    HADESMEM_DETAIL_TRACE_A("Window is already hooked. Skipping hook request.");
  }
}
Exemple #28
0
  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();
  }
Exemple #29
0
inline std::wstring GetRootPath(std::wstring const& path)
{
  int const drive_num = ::PathGetDriveNumberW(path.c_str());
  if (drive_num == -1)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"PathGetDriveNumber failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  std::vector<wchar_t> drive_path(4);
  ::PathBuildRootW(drive_path.data(), drive_num);
  if (drive_path[0] == L'\0' || drive_path[1] == L'\0' ||
      drive_path[2] == L'\0')
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_DETAIL_THROW_EXCEPTION(Error{}
                                    << ErrorString{"PathBuildRoot failed."}
                                    << ErrorCodeWinLast{last_error});
  }

  return drive_path.data();
}
Exemple #30
0
void Config::LoadFile(std::wstring const& path)
{
  pugi::xml_document doc;
  auto const load_result = doc.load_file(path.c_str());
  if (!load_result)
  {
    HADESMEM_DETAIL_THROW_EXCEPTION(
      hadesmem::Error{}
      << hadesmem::ErrorString{"Loading XML file failed."}
      << hadesmem::ErrorCodeOther{static_cast<DWORD_PTR>(load_result.status)}
      << hadesmem::ErrorStringOther{load_result.description()});
  }

  LoadImpl(doc);
}