В данном коде кажется, что вы храните исходные байты в статическом массиве с именем HookJump
, возвращаете указатель на этот массив, а затем переходите к его началу, как если бы он был действительным машинным кодом. За ним не следует остальная часть исходной функции.
Лучшим способом перехвата функций в Windows является использование Microsoft Detours.
Вот мой (рабочий эскиз) Hook
класс, используя Detours:
[Hook.h]
#pragma once
// Copyright (c) 2013 Alf P. Steinbach
#include <rfc/cppx/core/Non_copyable.h> // cppx::Non_copyable
#include <rfc/cppx/core/macros/ASSERT.h> // CPPX_ASSERT
#include <rfc/detours/Transaction.h> // detours::Transaction
namespace detours {
using cppx::Non_copyable;
template< class Func >
class Hook_
: public Non_copyable
{
private:
Func* original_;
Func* replacement_;
public:
auto original_func() const
-> Func*
{ return original_; }
~Hook_()
{
if(original_ != nullptr)
{
Transaction().detach(original_, replacement_).commit();
}
}
Hook_(Func* const original, Func* const replacement)
: original_(original)
, replacement_(replacement)
{
CPPX_ASSERT(original_ != nullptr);
CPPX_ASSERT(replacement_ != nullptr);
Transaction().attach(original_, replacement_).commit();
}
Hook_(Hook_&& other)
: original_(other.original_)
, replacement_(other.replacement_)
{ other.original_ = nullptr; other.replacement_ = nullptr; }
};
template< class Func >
inline auto hook(Func* const original, Func* const replacement)
-> Hook_<Func>
{ return Hook_<Func>(original, replacement); }
} // namespace detours
А вот класс Transaction
что он использует, который, в свою очередь, вызывает API-интерфейсы:
[Transaction.h]
#pragma once
// Copyright (c) 2013 Alf P. Steinbach
#include <rfc/cppx/core/utility/If_.h> // cppx::If
#include <rfc/cppx/core/Non_copyable.h> // cppx::Non_copyable
#include <rfc/cppx/core/Type_.h> // cppx::Type_
#include <thread> // std::thread
#include <type_traits> // std::is_function, std::enable_if
namespace detours {
using cppx::If_;
using cppx::Non_copyable;
using cppx::Type_;
using std::is_function;
using std::thread;
typedef thread::native_handle_type Thread_handle;
class Basic_transaction
: public Non_copyable
{
private:
typedef Type_<void(*)()> Proc;
bool is_committed_;
void raw_attach(Proc& original, Proc const replacement);
void raw_detach(Proc& original, Proc const replacement);
public:
auto is_committed() const
-> bool;
void commit();
auto update_thread(Thread_handle const h)
-> Basic_transaction&;
auto update_this_thread()
-> Basic_transaction&;
template< class Func, class Enabled = If_<is_function<Func>> >
auto attach(Func*& original, Func* const replacement)
-> Basic_transaction&
{
raw_attach(
reinterpret_cast<Proc&>(original),
reinterpret_cast<Proc>(replacement)
);
return *this;
}
template< class Func, class Enabled = If_<is_function<Func>> >
auto detach(Func*& original, Func* const replacement)
-> Basic_transaction&
{
raw_detach(
reinterpret_cast<Proc&>(original),
reinterpret_cast<Proc>(replacement)
);
return *this;
}
~Basic_transaction();
Basic_transaction();
};
class Transaction
: public Basic_transaction
{
public:
Transaction()
{ update_this_thread(); }
};
} // namespace detours
[Transaction.cpp]
#include "Transaction.h"
#include <rfc/cppx/core/throwing.h>
#include <rfc/cppx/core/macros/ASSERT.h> // CPPX_ASSERT
#include <rfc/detours_wrappers/detours_h.h>
using cppx::hopefully;
using cppx::fail;
typedef long Error_code;
namespace detours{
auto Basic_transaction::is_committed() const
-> bool
{ return is_committed_; }
void Basic_transaction::commit()
{
CPPX_ASSERT(!is_committed_);
Error_code const code = ::DetourTransactionCommit();
hopefully(code == 0)
|| fail("Basic_transaction::commit: DetourTransactionCommit failed", code);
is_committed_ = true;
}
auto Basic_transaction::update_thread(Thread_handle const h)
-> Basic_transaction&
{
Error_code const code = ::DetourUpdateThread(reinterpret_cast<HANDLE>(h));
hopefully(code == 0)
|| fail("Transaction::update_thread: DetourUpdateThread failed", code);
return *this;
}
auto Basic_transaction::update_this_thread()
-> Basic_transaction&
{
return update_thread(Thread_handle(::GetCurrentThread()));
}
void Basic_transaction::raw_attach(Proc& original, Proc const replacement)
{
Error_code const code = ::DetourAttach(
reinterpret_cast<void**>(&original),
reinterpret_cast<void*>(replacement)
);
hopefully(code == 0)
|| fail("Transaction::attach: DetourAttach failed", code);
}
void Basic_transaction::raw_detach(Proc& original, Proc const replacement)
{
Error_code const code = ::DetourDetach(
reinterpret_cast<void**>(&original),
reinterpret_cast<void*>(replacement)
);
hopefully(code == 0)
|| fail("Transaction::attach: DetourAttach failed", code);
}
Basic_transaction::~Basic_transaction()
{
if (!is_committed_)
{
Error_code const code = ::DetourTransactionAbort();
hopefully(code == 0)
|| fail("Basic_transaction::<destroy>: DetourTransactionAbort failed", code);
}
}
Basic_transaction::Basic_transaction()
: is_committed_(false)
{
Error_code const code = ::DetourTransactionBegin();
hopefully(code == 0)
|| fail("Basic_transaction::<init>: DetourTransactionBegin failed", code);
}
} // namespace detours
объезды оболочки слух дер:
[detours.h]
#pragma once
#include <rfc/winapi_wrappers/windows_h.h>
#include <microsoft_detours/detours.h>
Затем я использую файл CPP, чтобы принести в конкретной реализации Detours, например, для x86:
[detours_cpp.x86-32.cpp]
// Copyright (c) 2013 Alf P. Steinbach
#define DETOURS_INTERNAL // Necessary for DETOUR_TRACE
#include <rfc/detours_wrappers/detours_h.h>
#define DETOURS_X86
#define DETOURS_32BIT
#include <microsoft_detours/detours.cpp> // Source
#include <microsoft_detours/disasm.cpp> // More source, e.g. DetourCopyInstruction
Почему вы не используете MS Detours, как я предлагал раньше? –
Поскольку MSDetours работает только с Visual Studio. Я использовал его раньше, и он работает отлично, но я хочу научиться писать свои собственные, поэтому я не должен зависеть от него каждый раз. Я до сих пор не могу вернуться :( – Brandon
«MSDetours работает только с Visual Studio» не имеет смысла. –