这种霸道的技术,一般不推荐使用,除非无奈之下,不妨可以试试。
原理也很简单,要导入一个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);
}
}
// 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);
}
}
小人本潜水在思源的贴边 ID又多 又有钱 快活乐无边 谁知道站总监 他蛮横不留情面 他勾结站长目无天 占我ID夺我钱 我马甲跟他来翻脸 反被他来把经验减 我同学骂他欺新人 反被他捉进了小黑屋里面 874了一百遍啊一百遍 啊 最后他咬舌自尽 遗恨人间 他还将我和马甲赶出了思源 流落在人间 我为求回思源 无奈行乞在贴前 谁知道站总监他实在太阴险 知道此情形竟派人来暗算将我发文狂删到0篇 小人ID强 残命独留全 可怜马甲他 竟遭删 为求养ID 惟有傍人卖身自作践 一面苦赚钱 一面写诗篇 发誓把名气显 手刃总监意志坚啊 从此总监ID念心间 我永铭记此仇不供戴天 |