这种霸道的技术,一般不推荐使用,除非无奈之下,不妨可以试试。
原理也很简单,要导入一个Dll,把它在内存中的代码,前几代改为
JUMP 我的函数地址
然后,在我的里,再把他的几行代码改回去,把我自己的事做完之后,再调用它,也可以不调用。最后它返回后,又将它的前几行代码改为JUMP。
原理非常简单:
下面给出一个封装好的类:
/ /
// ULHook.h
#ifndef __ULHOOK_H__
#define __ULHOOK_H__
#include < windows.h >
class CULHook
{
public :
CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook);
~ CULHook();
// 取消挂钩
void Unhook();
// 重新挂钩
void Rehook();
protected :
PROC m_pfnOrig; // 目标API函数的地址
BYTE m_btNewBytes[ 8 ]; // 新构建的个字节
BYTE m_btOldBytes[ 8 ]; // 原来个字节
HMODULE m_hModule;
};
#endif // __ULHOOK_H__
// /
// ULHook.cpp文件
#include " ULHook.h "
CULHook::CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook)
{
// jmp eax == 0xFF, 0xE0
// 生成新的执行代码
BYTE btNewBytes[ 8 ] = { 0xB8 , 0x00 , 0x00 , 0x40 , 0x00 , 0xFF , 0xE0 , 0x00 };
memcpy(m_btNewBytes, btNewBytes, 8 );
* (DWORD * )(m_btNewBytes + 1 ) = (DWORD)pfnHook;
// 加载指定模块,取得API函数地址
m_hModule = ::LoadLibrary(pszModName);
if (m_hModule == NULL)
{
m_pfnOrig = NULL;
return ;
}
m_pfnOrig = ::GetProcAddress(m_hModule, pszFuncName);
// 修改原API函数执行代码的前个字节,使它跳向我们的函数
if (m_pfnOrig != NULL)
{
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery( m_pfnOrig, & mbi, sizeof (mbi) );
::VirtualProtect(m_pfnOrig, 8 , PAGE_READWRITE, & dwOldProtect);
// 保存原来的执行代码
memcpy(m_btOldBytes, m_pfnOrig, 8 );
// 写入新的执行代码
::WriteProcessMemory(::GetCurrentProcess(), ( void * )m_pfnOrig,
m_btNewBytes, sizeof (DWORD) * 2 , NULL);
::VirtualProtect(m_pfnOrig, 8 , mbi.Protect, 0 );
}
}
CULHook:: ~ CULHook()
{
Unhook();
if (m_hModule != NULL)
::FreeLibrary(m_hModule);
}
void CULHook::Unhook()
{
if (m_pfnOrig != NULL)
{
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(m_pfnOrig, & mbi, sizeof (mbi));
::VirtualProtect(m_pfnOrig, 8 , PAGE_READWRITE, & dwOldProtect);
// 写入原来的执行代码
::WriteProcessMemory(::GetCurrentProcess(), ( void * )m_pfnOrig,
m_btOldBytes, sizeof (DWORD) * 2 , NULL);
::VirtualProtect(m_pfnOrig, 8 , mbi.Protect, 0 );
}
}
void CULHook::Rehook()
{
// 修改原API函数执行代码的前个字节,使它跳向我们的函数
if (m_pfnOrig != NULL)
{
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery( m_pfnOrig, & mbi, sizeof (mbi) );
::VirtualProtect(m_pfnOrig, 8 , PAGE_READWRITE, & dwOldProtect);
// 写入新的执行代码
::WriteProcessMemory(::GetCurrentProcess(), ( void * )m_pfnOrig,
m_btNewBytes, sizeof (DWORD) * 2 , NULL);
::VirtualProtect(m_pfnOrig, 8 , mbi.Protect, 0 );
}
}