因为注释比较齐全,所以同样不多说别的了。
#include "StdAfx.h"
#include "Hook.h"
//导入bea反汇编引擎
#define BEA_ENGINE_STATIC
#define BEA_USE_STDCALL
#include "../beaEngine/headers/BeaEngine.h"
#ifdef _WIN64
#pragma comment(lib, "../beaEngine/win64/lib/BeaEngineCheetah64.lib")
#pragma comment(linker,"/nodefaultlib:crt64.lib")
#else
#pragma comment(lib, "../beaEngine/win32/lib/BeaEngineCheetah.lib")
#pragma comment(linker,"/nodefaultlib:crt.lib")
#endif//BeaEngine end
//静态成员初始化
BYTE* CHook::m_szRet = 0;
//中转函数的shellcode
#ifdef _WIN64
BYTE CHook::m_szTransferFunction[TRANSFER_FUNC_SIZE] = {
0x50 , 0x51 , 0x52 , 0xB9 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x48 , 0x89 , 0xE2 , 0x48 , 0x83 , 0xea ,
0x68 , 0x48 , 0x83 , 0xec , 0x20 , 0xE8 , 0x00 , 0x00 , 0x00 , 0x00 , 0x83 ,
0x04 , 0x24 , 0x12 , 0x68 , 0x00 , 0x00 , 0x00 ,
0x00 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x00 , 0x00 ,
0x00 , 0x00 , 0xC3 , 0x48 , 0x83 , 0xc4 , 0x20 ,0x53 , 0x55 , 0x54 , 0x56 ,
0x57 , 0x41 , 0x50 , 0x41 , 0x51 , 0x41 , 0x52 ,
0x41 , 0x53 , 0x41 , 0x54 , 0x41 , 0x55 , 0x41 ,
0x56 , 0x41 , 0x57 , 0xE8 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x00 ,
0x00 , 0x00 , 0x00 , 0xC7 , 0x44 , 0x24 , 0x04 ,
0x00 , 0x00 , 0x00 , 0x00 , 0xC3 , 0x41 , 0x5F ,
0x41 , 0x5E , 0x41 , 0x5D , 0x41 , 0x5C , 0x41 ,
0x5B , 0x41 , 0x5A , 0x41 , 0x59 , 0x41 , 0x58 ,
0x5F , 0x5E , 0x5C , 0x5D , 0x5B , 0x5A , 0x59 ,
0x58 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x9c , 0x50 , 0x51 , 0x52 , 0x48 , 0x83 , 0xec , 0x20 , 0xB9 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0x31 , 0xD2 ,
0xE8 , 0x00 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 ,
0x24 , 0x12 , 0x68 , 0x00 , 0x00 , 0x00 , 0x00 ,
0xC7 , 0x44 , 0x24 , 0x04 , 0x00 , 0x00 , 0x00 ,
0x00 , 0xC3 , 0x48 , 0x83 , 0xc4 , 0x20 , 0x5A , 0x59 , 0x58 , 0x9d , 0x68 , 0x00 ,
0x00 , 0x00 , 0x00 , 0xC7 , 0x44 , 0x24 , 0x04 ,
0x00 , 0x00 , 0x00 , 0x00 , 0xC3
};
BYTE CHook::m_szTransferFunction_ForCall[TRANSFER_FUNC_FOR_CALL_SIZE] = {
0x50 , 0x51 , 0x52 , 0x\
B9 , 0x78 , 0x56 , 0x34 , 0x12 , 0x\
48 , 0x87 , 0x54 , 0x24 , 0x18 , 0x48 , 0x83 , 0xEC , 0x20 , 0x\
E8 , 0x00 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
48 , 0x83 , 0xC4 , 0x20 , 0x\
B9 , 0x78 , 0x56 , 0x34 , 0x12 , 0x\
48 , 0x89 , 0xE2 , 0x48 , 0x83 , 0xEA , 0x68 , 0x48 , 0x83 , 0xEC , 0x20 , 0x\
E8 , 0x00 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
48 , 0x83 , 0xC4 , 0x20 , 0x53 , 0x55 , 0x54 , 0x56 , 0x57 , 0x41 , 0x50 , 0x41 , 0x51 , 0x41 , 0x52 , 0x41 , 0x53 , 0x41 , 0x54 , 0x41 , 0x55 , 0x41 , 0x56 , 0x41 , 0x57 , 0x\
E8 , 0x00 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
41 , 0x5F , 0x41 , 0x5E , 0x41 , 0x5D , 0x41 , 0x5C , 0x41 , 0x5B , 0x41 , 0x5A , 0x41 , 0x59 , 0x41 , 0x58 , 0x5F , 0x5E , 0x5C , 0x5D , 0x5B , 0x5A , 0x59 , 0x58 , 0x48 , 0x83 , 0xC4 , 0x08 , 0x\
68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0x\
90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x\
50 , 0x51 , 0x52 , 0x\
B9 , 0x78 , 0x56 , 0x34 , 0x12 , 0x\
48 , 0x89 , 0xE2 , 0x48 , 0x83 , 0xEA , 0x68 , 0x48 , 0x83 , 0xEC , 0x20 , 0x\
E8 , 0x20 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
48 , 0x83 , 0xC4 , 0x20 , 0x53 , 0x55 , 0x54 , 0x56 , 0x57 , 0x41 , 0x50 , 0x41 , 0x51 , 0x41 , 0x52 , 0x41 , 0x53 , 0x41 , 0x54 , 0x41 , 0x55 , 0x41 , 0x56 , 0x41 , 0x57 , 0x\
E8 , 0x20 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
41 , 0x5F , 0x41 , 0x5E , 0x41 , 0x5D , 0x41 , 0x5C , 0x41 , 0x5B , 0x41 , 0x5A , 0x41 , 0x59 , 0x41 , 0x58 , 0x5F , 0x5E , 0x5C , 0x5D , 0x5B , 0x5A , 0x59 , 0x\
B9 , 0x78 , 0x56 , 0x34 , 0x12 , 0x\
48 , 0x83 , 0xEC , 0x20 , 0x\
E8 , 0x20 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
48 , 0x83 , 0xC4 , 0x20 , 0x48 , 0x87 , 0x04 , 0x24 , 0x50 , 0x51 , 0x52 , 0x48 , 0x83 , 0xEC , 0x20 , 0x\
B9 , 0x78 , 0x56 , 0x34 , 0x12 , 0x\
48 , 0x31 , 0xD2 , 0x\
E8 , 0x20 , 0x00 , 0x00 , 0x00 , 0x83 , 0x04 , 0x24 , 0x12 , 0x68 , 0x78 , 0x56 , 0x34 , 0x12 , 0xC7 , 0x44 , 0x24 , 0x04 , 0x21 , 0x43 , 0x65 , 0x87 , 0xC3 , 0x\
48 , 0x83 , 0xC4 , 0x20 , 0x5A , 0x59 , 0x58 , 0xC3
};
#else
BYTE CHook::m_szTransferFunction[TRANSFER_FUNC_SIZE] = {
0x50 , 0x54 , 0x83 , 0x2C , 0x24 , 0x1C ,
0x68 , /*[pos:0x7]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0xc]*/0x00 , 0x00 , 0x00 , 0x00 ,
0x58 , 0x60 ,
0xE8 , /*[pos:0x13]*/0x00 , 0x00 , 0x00 , 0x00 ,
0x61 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x50 , 0x6A , 0x00 ,
0x68 , /*[pos:0x3a]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0x3f]*/0x00 , 0x00 , 0x00 , 0x00 ,
0x58 ,
0xE9 , /*[pos:0x45]*/0x00 , 0x00 , 0x00 , 0x00
};
BYTE CHook::m_szTransferFunction_ForCall[TRANSFER_FUNC_FOR_CALL_SIZE] = {
0x87 , 0x04 , 0x24 , 0x50 ,
0x68 , /*[pos:0x5]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0xa]*/0xC9 , 0xFB , 0xD1 , 0x76 ,
0x54 , 0x83 , 0x2C , 0x24 , 0x1C ,
0x68 , /*[pos:0x14]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0x19]*/0xBA , 0xFB , 0xD1 , 0x76 ,
0x58 , 0x60 ,
0xE8 , /*[pos:0x20]*/0x2F , 0xE7 , 0xFF , 0xFF ,
0x61 ,
0x68 , /*[pos:0x26]*/0x00 , 0x00 , 0x00 , 0x00 ,
/*[pos:0x2a]*/0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 , 0x90 ,
/*[pos:0x48]*/0x50 , 0x54 , 0x83 , 0x2C , 0x24 , 0x1C ,
0x68 , /*[pos:0x4f]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0x54]*/0x7F , 0xFB , 0xD1 , 0x76 ,
0x58 , 0x60 ,
0xE8 , /*[pos:0x5b]*/0xF4 , 0xE6 , 0xFF , 0xFF ,
0x61 , 0x50 ,
0x68 , /*[pos:0x62]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0x67]*/0xC8 , 0xF8 , 0xD1 , 0x76 ,
0x87 , 0x04 , 0x24 , 0x50 , 0x6A , 0x00 ,
0x68 , /*[pos:0x72]*/0x00 , 0x00 , 0x00 , 0x00 ,
0xE8 , /*[pos:0x77]*/0x5C , 0xFB , 0xD1 , 0x76 ,
0x58 , 0xC3
};
#endif
//dllmain中创建线程dwWaitThread,调用MyEntry.cpp的StartHook函数
//在暴露给用户的MyEntry.cpp中隐藏起来这些东西。
extern void WINAPI StartHook();
DWORD WINAPI dwWaitThread( LPVOID lpArgs )
{
StartHook();
return 0;
}
//写jmp的x86版本函数
void CHook::WriteJMP_x86(DWORD_PTR dwFrom , DWORD_PTR dwTo)
{
DWORD_PTR dwAdr = dwFrom;
DWORD dwOldP;
VirtualProtect((LPVOID)dwAdr , 0x100 , PAGE_EXECUTE_READWRITE , &dwOldP);
*(BYTE*)dwAdr = 0xE9;
dwAdr+=1;
*(DWORD*)dwAdr = dwTo - (dwFrom + 5);
}
//写call的x86版本函数
void CHook::WriteCall_x86(DWORD_PTR dwFrom , DWORD_PTR dwTo)
{
DWORD_PTR dwAdr = dwFrom;
DWORD dwOldP;
VirtualProtect((LPVOID)dwAdr , 0x100 , PAGE_EXECUTE_READWRITE , &dwOldP);
*(BYTE*)dwAdr = 0xE8;
dwAdr+=1;
*(DWORD*)dwAdr = dwTo - (dwFrom + 5);
}
//类构造函数
CHook::CHook(void* pOriginAdr , void* pNewHook)
{
Init();
SetHook(pOriginAdr , pNewHook);
}
CHook::CHook(void* pOriginAdr , void* pNewHook , void* pHookAfterCall)
{
Init();
SetHook(pOriginAdr , pNewHook , pHookAfterCall);
}
//析构函数
CHook::~CHook(void)
{
//等待hook函数走完再析构和释放
if (m_szMyTransfer)
{
while (TlsGetValue(m_dwTlsIndexForRegister))
{
Sleep(500);
}
RemoveHook();
delete[] m_szMyTransfer;
}
TlsFree(m_dwTlsIndexForRegister);
TlsFree(m_dwTlsIndexForRetAdr);
}
//获取hook点现场
ST_REGISTER* CHook::GetRegOnHookPoint()
{
return (ST_REGISTER*)TlsGetValue(m_dwTlsIndexForRegister);
}
void CHook::Init()
{
//初始化两个Tls变量
m_dwTlsIndexForRetAdr = TlsAlloc();
TlsSetValue(m_dwTlsIndexForRetAdr , 0);
m_dwTlsIndexForRegister = TlsAlloc();
TlsSetValue(m_dwTlsIndexForRegister , 0);
//初始化“直接返回”的函数体,一字节0xc3
DWORD dwOld;
if (!m_szRet)
{
m_szRet = new BYTE[1];
*m_szRet = 0xc3;
VirtualProtect(m_szRet , 100 , PAGE_EXECUTE_READWRITE , &dwOld);
}
}
//设置普通hook
BOOL CHook::SetHook( void* pOriginAdr , void* pNewHook )
{
//创建一块内存区域用于存放shellcode
DWORD dwOld;
m_szMyTransfer = new BYTE[TRANSFER_FUNC_SIZE];
memcpy(m_szMyTransfer , m_szTransferFunction , TRANSFER_FUNC_SIZE);
VirtualProtect(m_szMyTransfer , 100 , PAGE_EXECUTE_READWRITE , &dwOld);
//shellcode中需要修正的位置保存成数组,方便编译
#ifdef _WIN64
unsigned int szOffset[] = {0x4 , 0x13 , 0x43 , 0x72 , 0x99 , 0xa0 , 0xbf};
#else
unsigned int szOffset[] = {0x7 , 0xc-1 , 0x13-1 , 0x18 , 0x3a , 0x3f-1 , 0x45-1};
#endif
BOOL bRet = FALSE;
HMODULE hMod = GetModuleHandle(_T("Kernel32.dll"));
FARPROC pFunc_TlsSetValue = GetProcAddress(hMod , "TlsSetValue");
//把hook位置被破坏的指令保存到m_szMyTransfer + szOffset[3]这个地址,中转函数会执行这部分指令
int dwCodeLen = TransplantCode(pOriginAdr , m_szMyTransfer + szOffset[3]);
//如果允许破坏的空间足够大
if (dwCodeLen >= JMP_CODE_LEN)
{
//保存hook地址
m_pOrigin_Adr = pOriginAdr;
//保存破坏的空间大小
m_nOrigin_CodeLen = dwCodeLen;
//申请空间,保存被破坏的指令字节
m_pOldCode = new BYTE[dwCodeLen];
memcpy(m_pOldCode , pOriginAdr , dwCodeLen);
//修正shellcode中的各种偏移
*(DWORD32*)(m_szMyTransfer + szOffset[0]) = m_dwTlsIndexForRegister;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[1]) , (DWORD_PTR)pFunc_TlsSetValue);
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[2]) , (DWORD_PTR)pNewHook);
// memcpy((LPVOID)(m_szMyTransfer + szOffset[3]) , (LPVOID)pOriginAdr , dwCodeLen);
*(DWORD32*)(m_szMyTransfer + szOffset[4]) = m_dwTlsIndexForRegister;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[5]) , (DWORD_PTR)pFunc_TlsSetValue);
WriteJMP((DWORD_PTR)(m_szMyTransfer + szOffset[6]) , (DWORD_PTR)pOriginAdr + dwCodeLen);
WriteJMP((DWORD_PTR)pOriginAdr , (DWORD_PTR)m_szMyTransfer);
bRet = TRUE;
}
else
{
m_szMyTransfer = 0;
m_pOrigin_Adr = 0;
MessageBox(0 , _T("hook点异常,指令无法识别或含有跳转指令") , _T("hook失败") , MB_OK);
}
return bRet;
}
BOOL CHook::SetHook( void* pOriginAdr , void* pNewHook , void* pHookAfterCall )
{
//创建一块内存区域用于存放shellcode
DWORD dwOld;
m_szMyTransfer = new BYTE[TRANSFER_FUNC_FOR_CALL_SIZE];
memcpy(m_szMyTransfer , m_szTransferFunction_ForCall , TRANSFER_FUNC_FOR_CALL_SIZE);
VirtualProtect(m_szMyTransfer , 100 , PAGE_EXECUTE_READWRITE , &dwOld);
//shellcode中需要修正的位置保存成数组,方便编译
#ifdef _WIN64
unsigned int szOffset[] = {0x4 , 0x11 , 0x2d , 0x3c , 0x6c , 0x9b+4 , 0xc8+4 ,
0xa8+4 , 0xcc+4 , 0xdb+4 , 0x10b+4 , 0x13a+4 , 0x142+4 , 0x169+4 , 0x170+4};
#else
unsigned int szOffset[] = {0x5 , 0xa-1 , 0x14 , 0x19-1 , 0x20-1 , 0x26 , 0x48 ,
0x2a , 0x4f , 0x54-1 , 0x5b-1 , 0x62 , 0x67-1 , 0x72 , 0x77-1};
#endif
BOOL bRet = FALSE;
if (!pNewHook && !pHookAfterCall)
{
return bRet;
}
HMODULE hMod = GetModuleHandle(_T("Kernel32.dll"));
FARPROC pFunc_TlsSetValue = GetProcAddress(hMod , "TlsSetValue");
FARPROC pFunc_TlsGetValue = GetProcAddress(hMod , "TlsGetValue");
//用户回调函数分为函数执行前和函数执行后,如果某个回调函数设置为null,则替换为m_szRet这个直接c3返回的函数
void* pBefore = pNewHook;
void* pAfter = pHookAfterCall;
if (!pBefore)
{
pBefore = m_szRet;
}
if (!pAfter)
{
pAfter = m_szRet;
}
//把hook位置被破坏的指令保存到m_szMyTransfer + szOffset[3]这个地址,中转函数会执行这部分指令
int dwCodeLen = TransplantCode(pOriginAdr , m_szMyTransfer + szOffset[7]);
//如果允许破坏的空间足够大
if (dwCodeLen >= JMP_CODE_LEN)
{
//保存hook地址
m_pOrigin_Adr = pOriginAdr;
//保存破坏的空间大小
m_nOrigin_CodeLen = dwCodeLen;
//申请空间,保存被破坏的指令字节
m_pOldCode = new BYTE[dwCodeLen];
memcpy(m_pOldCode , pOriginAdr , dwCodeLen);
//修正shellcode中的各种偏移
*(DWORD32*)(m_szMyTransfer + szOffset[0]) = m_dwTlsIndexForRetAdr;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[1]) , (DWORD_PTR)pFunc_TlsSetValue);
*(DWORD32*)(m_szMyTransfer + szOffset[2]) = m_dwTlsIndexForRegister;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[3]) , (DWORD_PTR)pFunc_TlsSetValue);
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[4]) , (DWORD_PTR)pBefore);
#ifdef _WIN64
BYTE szTmp = *(m_szMyTransfer + szOffset[7]);
WriteJMP((DWORD_PTR)m_szMyTransfer+szOffset[5] , (DWORD_PTR)m_szMyTransfer+szOffset[6]);
*(m_szMyTransfer + szOffset[7]) = szTmp;
#else
*(DWORD32*)(m_szMyTransfer + szOffset[5]) = (DWORD)m_szMyTransfer+szOffset[6];
#endif
// memcpy((LPVOID)(m_szMyTransfer + szOffset[7]) , (LPVOID)pOriginAdr , dwCodeLen);
WriteJMP((DWORD_PTR)m_szMyTransfer+szOffset[7]+dwCodeLen , (DWORD_PTR)(DWORD_PTR)pOriginAdr + dwCodeLen);
*(DWORD32*)(m_szMyTransfer + szOffset[8]) = m_dwTlsIndexForRegister;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[9]) , (DWORD_PTR)pFunc_TlsSetValue);
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[10]) , (DWORD_PTR)pAfter);
*(DWORD32*)(m_szMyTransfer + szOffset[11]) = m_dwTlsIndexForRetAdr;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[12]) , (DWORD_PTR)pFunc_TlsGetValue);
*(DWORD32*)(m_szMyTransfer + szOffset[13]) = m_dwTlsIndexForRegister;
WriteCall((DWORD_PTR)(m_szMyTransfer + szOffset[14]) , (DWORD_PTR)pFunc_TlsSetValue);
WriteJMP((DWORD_PTR)pOriginAdr , (DWORD_PTR)m_szMyTransfer);
bRet = TRUE;
}
else
{
m_szMyTransfer = 0;
m_pOrigin_Adr = 0;
MessageBox(0 , _T("hook点异常,指令无法识别或含有跳转指令") , _T("hook失败") , MB_OK);
}
return bRet;
}
int CHook::TransplantCode( void* pOriginAdr , BYTE* pDestAdr )
{
//初始化bea引擎
DISASM MyDisasm;
memset (&MyDisasm, 0, sizeof(DISASM));
#if defined(_WIN64)
MyDisasm.Archi = 64;
#else
MyDisasm.Archi = 0;
#endif
//以hook点pOriginAdr开始识别指令
MyDisasm.EIP = (UIntPtr)pOriginAdr;
DWORD dwCodeLen = 0;
while (1)
{
//调用Disasm解析指令
int nLen = Disasm(&MyDisasm);
//无法识别就滚蛋
if (nLen == UNKNOWN_OPCODE)
break;
//含有跳转也滚蛋
if (MyDisasm.Instruction.BranchType == RetType)
break;
//记录识别的长度
dwCodeLen += nLen;
//迁移当前指令到中转函数的空间中
memcpy(pDestAdr , (void*)MyDisasm.EIP, nLen);
//这个判断目前似乎只有x64才会产生作用
//用于识别类似于mov [eip+xxx],register这样的指令
//即以eip为原点偏移的指令,jmp其实也是,不过跳转指令在上面已经被pass了
if (nLen > 4 && MyDisasm.Instruction.AddrValue)
{
//计算指令中的偏移数据
DWORD32* pArg = (DWORD32*)(MyDisasm.EIP + nLen - 4);
//如果确实是以eip为偏移的指令
if (*pArg + nLen + MyDisasm.EIP == MyDisasm.Instruction.AddrValue)
{
//计算迁移后的实际eip为原点的偏移数据
DWORD32* pNewArg = (DWORD32*)(pDestAdr + nLen - 4);
//修正偏移数据
*pNewArg = MyDisasm.Instruction.AddrValue - nLen - (DWORD_PTR)pDestAdr;
}
}
pDestAdr += nLen;
MyDisasm.EIP += nLen;
//如果空间已经足够就中断
if (dwCodeLen >= JMP_CODE_LEN)
{
break;
}
};
return dwCodeLen;
}
//写jmp的x64版本函数
void CHook::WriteJMP_x64( DWORD_PTR dwFrom , DWORD_PTR dwTo )
{
DWORD_PTR dwAdr = dwFrom;
DWORD dwOldP;
VirtualProtect((LPVOID)dwAdr , 0x100 , PAGE_EXECUTE_READWRITE , &dwOldP);
*(BYTE*)dwAdr = 0x68;
dwAdr+=1;
*(DWORD32*)dwAdr = DWORD32(dwTo & 0xffffffff);
dwAdr+=4;
*(DWORD32*)dwAdr = DWORD32(0x042444c7);
dwAdr+=4;
*(DWORD32*)dwAdr = DWORD32(dwTo >> 32);
dwAdr+=4;
*(BYTE*)dwAdr = 0xc3;
/*
push 地址的低32位
mov dword ptr ss:[rsp+4],地址的高32位
ret
*/
//14 bytes
}
//写call的x64版本函数
void CHook::WriteCall_x64( DWORD_PTR dwFrom , DWORD_PTR dwTo )
{
DWORD_PTR dwAdr = dwFrom;
DWORD dwOldP;
VirtualProtect((LPVOID)dwAdr , 0x100 , PAGE_EXECUTE_READWRITE , &dwOldP);
*(BYTE*)dwAdr = 0xE8;
dwAdr+=1;
*(DWORD*)dwAdr = DWORD32(0);
dwAdr+=4;
*(DWORD32*)dwAdr = DWORD32(0x12240483);
dwAdr+=4;
*(BYTE*)dwAdr = 0x68;
dwAdr+=1;
*(DWORD32*)dwAdr = DWORD32(dwTo & 0xffffffff);
dwAdr+=4;
*(DWORD32*)dwAdr = DWORD32(0x042444c7);
dwAdr+=4;
*(DWORD32*)dwAdr = DWORD32(dwTo >> 32);
dwAdr+=4;
*(BYTE*)dwAdr = 0xc3;
/*
call @next //e8 00 00 00 00
@next:
add dword ptr ss:[rsp],12
push 地址的低32位
mov dword ptr ss:[rsp+4],地址的高32位
ret
*/
//23 bytes
}
//移除hook的线程
//严格来说,也许应该遍历所有线程,保证没有线程运行到hook位置和中转函数
//然后冻结线程,再移除hook,这样才正规和安全
//然而我不会
DWORD WINAPI RemoveHook_Thread(LPVOID lpParam )
{
CHook *pHook = (CHook*)lpParam;
//当GetRegOnHookPoint获取hook现场返回0时候,说明基本执行完毕了
while (pHook->GetRegOnHookPoint())
{
Sleep(500);
}
//正式移除hook
pHook->RemoveHook_unsafe();
return 0;
}
BOOL CHook::RemoveHook()
{
if (TlsGetValue(m_dwTlsIndexForRegister))
{
CreateThread(0 , 0 , RemoveHook_Thread , this , 0 , 0);
}
else
{
RemoveHook_unsafe();
}
return TRUE;
}
BOOL CHook::RemoveHook_unsafe()
{
//恢复hook点
memcpy((LPVOID)m_pOrigin_Adr , (LPVOID)m_pOldCode , m_nOrigin_CodeLen);
//释放保存的指令
delete[] m_pOldCode;
//释放中转函数
delete[] m_szMyTransfer;
return TRUE;
}