Есть ли способ использовать MS Detours в этом примере?
Прежде всего, я студент и хочу извлечь уроки из этой проблемы, поэтому мне нужен не полный код решения в качестве ответа, а помощь.
Эти ссылки могут вам помочь:)
https://github.com/microsoft/Detours
https://github.com/microsoft/Detours/wiki
https://www.codeproject.com/Articles/30140/API-Hooking-with-MS-Detours
https://devblogs.microsoft.com/oldnewthing/20110921-00/?p=9583
У меня есть код, который будет связывать функцию с другой функцией, изменяя точку горячего исправления исходной функции. Проблема в том, что этот пример не работает с архитектурой x64, поэтому мне нужно использовать некоторые инструменты для реализации этой перехвата. Я использую MS Detours для этого, но в моей реализации есть проблема, и мне нужна помощь экспертов, потому что я новичок в этой области, и я хочу понять это и изучить как можно лучше.
Вот код, который у меня есть сейчас (::Trace(...)
не имеет значения, поэтому можете просто пропустить с ним строки):
//
// Constructor
//
CFunctionControll::CFunctionControll(const TCHAR* sczName, BYTE* pOrigFunc, BYTE* pDetourFunc)
{
::Trace(2, _T("CFunctionControll::CFuncDetour_Beging"));
m_sczName = sczName;
m_dwOrgProtect = 0;
m_pOrigFunc = pOrigFunc;
m_pDetourFunc = pDetourFunc;
::Trace(2, _T("CFunctionControll::CFuncDetour_End"));
}
//
// Destructor
//
CFunctionControll::~CFunctionControll()
{
::Trace(2, _T("CFunctionControll::~CFuncDetour_Beging"));
Disable();
::Trace(2, _T("CFunctionControll::~CFuncDetour_End"));
}
//
// Enable - the hooking will be active
//
void CFunctionControll::Enable()
{
::Trace(2, _T("CFunctionControll::Enable_Begin"));
try
{
Init();
if (m_dwOrgProtect)
{
// saving the original hot-patch point
memcpy(m_arrHotPatchPoint, m_pOrigFunc - 5, 7);
// hot-patch point: "mov edi, edi" -> jmp short $-5
m_pOrigFunc[0] = 0xEB;
m_pOrigFunc[1] = 0xF9;
// jmp relative to pOrigFuncNop
// Before "hot-patch point" there is allways 5 times "nop" (until Windows 7) or "int 3" (Windows 10)
BYTE* pOrigFuncNop = m_pOrigFunc - 5;
pOrigFuncNop[0] = 0xE9;
int addressdifference = m_pDetourFunc - (pOrigFuncNop + 5);
memcpy(pOrigFuncNop + 1, &addressdifference, 4);
}
}
catch (...)
{
// TODO
}
::Trace(2, _T("CFunctionControll::Enable_End"));
}
//
// Disable - deactivating the hook function
//
void CFunctionControll::Disable()
{
::Trace(2, _T("CFunctionControll::Disable_Begin"));
try
{
if (m_dwOrgProtect)
{
// Overwrite the hot-patch to original one
memcpy(m_pOrigFunc - 5, m_arrHotPatchPoint, 7);
}
}
catch (...)
{
// TODO
}
::Trace(2, _T("CFunctionControll::Disable_End"));
}
//
// Init - marks hot-patch-point-memory as "EXECUTE/READ/WRITE"
//
void CFunctionControll::Init()
{
if (!m_dwOrgProtect)
{
::Trace(2, _T("CFunctionControll::Init_Begin"));
if (m_pOrigFunc[0] == 0xFF && m_pOrigFunc[1] == 0x25) // "jmp dword ptr ds:[offset]": ds:[offset] - the true function address
{
CString strMsg;
strMsg.Format(_T("CFunctionControll::Enable: 'jmp dword ptr ds:[offset] hot-patch-point' in function: %s."), m_sczName);
::Trace(2, strMsg);
DWORD dwAddress = *(DWORD*)(m_pOrigFunc + 2); // ds:[offset] - function address
__asm
{
mov eax, dwAddress
mov eax, dword ptr ds : [eax]
mov dwAddress, eax
}
m_pOrigFunc = (BYTE*)dwAddress;
}
if (m_pOrigFunc[0] == 0x8B && m_pOrigFunc[1] == 0xFF || // "mov edi, edi" oder
m_pOrigFunc[0] == 0xEB && m_pOrigFunc[1] == 0x9F) // "jmp short $-5": the function is already hooked
{
if (!VirtualProtect(m_pOrigFunc - 5, 7, PAGE_EXECUTE_READWRITE, &m_dwOrgProtect))
{
DWORD nErr = GetLastError();
CString strMsg;
strMsg.Format(_T("CFunctionControll::Enable: function VirtualProtect failed. Errorcode: %X"), nErr);
::Trace(1, strMsg);
m_dwOrgProtect = 0;
}
else if (m_pOrigFunc[0] == 0xEB && m_pOrigFunc[1] == 0x9F)
{
CString strMsg;
strMsg.Format(_T("CFunctionControll::Enable: function %s is already hooked!"), m_sczName);
::Trace(1, strMsg);
}
}
else
{
CString strMsg;
strMsg.Format(_T("CFunctionControll::Enable: unknown 'hot-patch-point' format in function: %s!"), m_sczName);
::Trace(1, strMsg);
m_dwOrgProtect = 0;
}
::Trace(2, _T("CFunctionControll::Init_End"));
}
}
Вот мой код после использования MS Detours:
// Constructor
CFunctionControll::CFunctionControll(BYTE* pOrigFunc, BYTE* pDetourFunc)
{
m_pOrigFunc = pOrigFunc;
m_pDetourFunc = pDetourFunc;
}
// Destructor
CFunctionControll::~CFunctionControll()
{
Disable();
}
void CFunctionControll::Enable()
{
try
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(LPVOID&)m_pOrigFunc+2, m_pDetourFunc);
if (!DetourTransactionCommit())
throw transactionerror;
}
catch (TransactionError)
{
// Add proper exception handling later
}
}
void CFunctionControll::Disable()
{
try
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(LPVOID&)m_pOrigFunc+2, m_pDetourFunc);
if (!DetourTransactionCommit())
throw transactionerror;
}
catch (TransactionError)
{
// Add proper exception handling later
}
}
class TransactionError : public std::exception
{
virtual const char* what() const throw()
{
return "DetourTransactionCommit() failed.";
}
} transactionerror;
Вы можете найти объяснение функций MS Detours здесь: https://github.com/microsoft/Detours/wiki/Using-Detours
Кто-нибудь может мне помочь с проблемой?