- 注册时间
 - 2021-4-16
 
- 最后登录
 - 2024-7-13
 
- 在线时间
 - 3 小时
 
 
 
 
 
编程入门 
  
	- 龙马币
 - 22 
 
 
 
 
 | 
 
 
C++ 伪任意地址HOOK类源码 
 
前言: 
 
代码HOOK技术不管在安全领域还是在木马病毒方面都运用很广泛,因为他可以改变程序执行流程,悄无声息执行我们自己的代码。 
 
之前我也用过一些hook类,如mhook等,但很多都局限于API HOOK,有的时候无法满足实际应用。也因此,我自己的hook类就诞生了。 
 
先贴核心代码: 
 
- /
 
 - /Hook.h
 
 - #pragma once
 
 -  
 
 - struct t_Context
 
 - {
 
 -         DWORD EDI;
 
 -         DWORD ESI;
 
 -         DWORD EBP;
 
 -         DWORD ESP;
 
 -         DWORD EBX;
 
 -         DWORD EDX;
 
 -         DWORD ECX;
 
 -         DWORD EAX;
 
 - };
 
 -  
 
 - class CHook
 
 - {
 
 - public:
 
 -         CHook(void);
 
 -         ~CHook(void);
 
 -         // 添加Hook
 
 -         bool AddHook(__in DWORD dwHookAddr, __in void *pfnHookProc);
 
 -         // 移除Hook
 
 -         bool RemoveHook();
 
 -         // 寄存器结构体
 
 -         t_Context m_Context;
 
 -         // 返回地址,没有特殊需求不要修改这里
 
 -         DWORD m_dwRetAddr;
 
 - private:
 
 -         // 保存Hook地址,用于RemoveHook
 
 -         DWORD m_dwHookAddr;
 
 -         // 保存原始字节,用于RemoveHook
 
 -         BYTE m_OldCode[5];
 
 - };
 
  复制代码 
 
- //Hook.cpp
 
 - #include "StdAfx.h"
 
 - #include "Hook.h"
 
 - #include "MyOutputDebugString.h"
 
 -  
 
 - //BeaEngine 反汇编引擎
 
 - #define BEA_ENGINE_STATIC
 
 - #define BEA_USE_STDCALL
 
 - #include "bea/headers/BeaEngine.h"
 
 - #pragma comment(lib, "bea/win32/lib/BeaEngine.lib")
 
 - #pragma comment(linker,"/nodefaultlib:crt.lib")
 
 - //BeaEngine end
 
 -  
 
 - //XEDParse 汇编引擎
 
 - #include "XEDParse/XEDParse.h"
 
 - #pragma comment(lib,"XEDParse/XEDParse.lib")
 
 -  
 
 - CHook::CHook(void)
 
 - {
 
 -         memset(&m_Context, 0, sizeof(m_Context));
 
 -         memset(m_OldCode, 0x90, 5);
 
 -         m_dwRetAddr = 0;
 
 -         m_dwHookAddr = 0;
 
 - }
 
 -  
 
 -  
 
 - CHook::~CHook(void)
 
 - {
 
 - }
 
 -  
 
 -  
 
 - // 添加Hook
 
 - bool CHook::AddHook(__in DWORD dwHookAddr, __in void *lpHookProc)
 
 - {
 
 -         //00240000    60              PUSHAD
 
 -         //00240001    9C              PUSHFD
 
 -         //00240002    BF 00012400     MOV EDI,0x240100
 
 -         //00240007    8BF4            MOV ESI,ESP
 
 -         //00240009    83C6 04         ADD ESI,0x4
 
 -         //0024000C    B9 20000000     MOV ECX,0x20
 
 -         //00240011    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]     ; 保存寄存器结构体,备用
 
 -         //00240013    B8 90909090     MOV EAX,0x90909090
 
 -         //00240018    FFD0            CALL EAX                                         ; 调用HookPro
 
 -         //0024001A    9D              POPFD
 
 -         //0024001B    61              POPAD
 
 -         //0024001C    90              NOP                                              ; 个数等于被毁掉的指令总长度
 
 -         //0024001D    68 90909090     PUSH 0x90909090                                  ; jmp back
 
 -         //00240022    C3              RETN
 
 -         //00240023    90              NOP
 
 -         BYTE Shell[0x100] = {0x60, 0x9C, 0xBF, 0x90, 0x90, 0x90, 0x90, 0x8B, 0xF4, 0x83, 0xC6, 0x04, 0xB9, 0x20, 0x00, 0x00, 0x00, 0xF3, 0xA4, 0xB8, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xD0, 0x9D, 0x61, 0x90, 0x90};
 
 -         int pContext = (int)&m_Context;
 
 -         memcpy(&Shell[3], &pContext, 4);
 
 -         int pHookProc = (int)lpHookProc;
 
 -         memcpy(&Shell[0x14], &pHookProc, 4);
 
 -  
 
 -         //保存原始机器码
 
 -         DWORD dwOldProtect = 0;
 
 -         BOOL bRet = VirtualProtect((LPVOID)dwHookAddr, 0x20, PAGE_EXECUTE_READWRITE, &dwOldProtect);
 
 -         if (!bRet)
 
 -         {
 
 -                 MyOutputDebugStringA("VirtualProtect(0x%p) Error!!!", dwHookAddr);
 
 -                 MyOutputDebugStringA("AddHook Failed:0x%p", dwHookAddr);
 
 -                 return false;
 
 -         }
 
 -         memcpy(m_OldCode, (LPVOID)dwHookAddr, 5);//用于hook还原
 
 -  
 
 -         DWORD dwStart = (DWORD)VirtualAlloc(NULL, 0x100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
 -         if (dwStart == 0)
 
 -         {
 
 -                 OutputDebugStringA("VirtualAlloc Error!!!");
 
 -                 MyOutputDebugStringA("AddHook Failed:0x%p", dwHookAddr);
 
 -                 return false;
 
 -         }
 
 -  
 
 -         //开始解析原始指令,通过反汇编引擎,识别要Hook的地址处的指令,以及破坏的指令长度
 
 -         int nSize = 0;//毁掉的指令的总字节数
 
 -         DWORD dwASM = dwStart + 30;//30为前面shell前面部分代码长度
 
 -  
 
 -         DISASM MyDisasm;
 
 -         memset (&MyDisasm, 0, sizeof(DISASM));
 
 -         MyDisasm.EIP = (UIntPtr)dwHookAddr;
 
 -         MyDisasm.Options = PrefixedNumeral + ShowSegmentRegs;
 
 -  
 
 -         while (1)
 
 -         {
 
 -                 //反汇编
 
 -                 int nInstLen = Disasm(&MyDisasm);
 
 -                 if (nInstLen < 1)
 
 -                 {
 
 -                         MyOutputDebugStringA("Disasm(%p) Error!!!", MyDisasm.EIP);
 
 -                         MyOutputDebugStringA("AddHook Failed:0x%p", dwHookAddr);
 
 -                         return false;
 
 -                 }
 
 -                 MyOutputDebugStringA("Addr = 0x%p nInstLen = %d %s", MyDisasm.EIP, nInstLen, MyDisasm.CompleteInstr);
 
 -                 if (MyDisasm.Instruction.BranchType == RetType)
 
 -                 {
 
 -                         MyOutputDebugStringA("要hook的地址开始,后面5个字节对应的指令,不能有ret");
 
 -                         MyOutputDebugStringA("AddHook Failed:0x%p", dwHookAddr);
 
 -                         return false;
 
 -                 }
 
 -                 nSize += nInstLen;
 
 -                 //汇编,先反汇编再汇编的好处在于不用修正相对偏移地址
 
 -                 XEDPARSE parse;
 
 -                 memset(&parse, 0, sizeof(parse));
 
 -                 parse.x64 = false;
 
 -                 parse.cip = dwASM;
 
 -                 memset(parse.instr, 0, 256);
 
 -                 memcpy(parse.instr, MyDisasm.CompleteInstr, 64);
 
 -                 XEDPARSE_STATUS status = XEDParseAssemble(&parse);
 
 -                 if (status == XEDPARSE_ERROR)
 
 -                 {
 
 -                         MyOutputDebugStringA("Parse Error:%s", parse.error);
 
 -                         MyOutputDebugStringA("AddHook Failed:0x%p", dwHookAddr);
 
 -                         return false;
 
 -                 }
 
 -                 memcpy(&Shell[dwASM - dwStart], &parse.dest[0], parse.dest_size);
 
 -  
 
 -                 dwASM += parse.dest_size;
 
 -                 MyDisasm.EIP  += nInstLen;
 
 -                 if (nSize >= 5)
 
 -                 {
 
 -                         m_dwRetAddr = MyDisasm.EIP;
 
 -                         m_dwHookAddr = dwHookAddr;
 
 -                         break;
 
 -                 }
 
 -         }
 
 -         BYTE PushRet[6] = {0x68, 0x90, 0x90, 0x90, 0x90, 0xC3};
 
 -         memcpy(&PushRet[1], &m_dwRetAddr, 4);
 
 -         memcpy(&Shell[dwASM - dwStart], &PushRet[0], 6);
 
 -         //Shell整理好了 写过去
 
 -         memcpy((LPVOID)dwStart, Shell, 0x100);
 
 -  
 
 -         BYTE jmpcode[] = {0xE9, 0xFF, 0xFF, 0xFF, 0xFF}; //jmp Start
 
 -         DWORD VA =  dwStart - dwHookAddr - 5;
 
 -         memcpy(&jmpcode[1], &VA, 4);
 
 -         //hook jmp Start;
 
 -         memcpy((LPVOID)dwHookAddr, jmpcode, sizeof(jmpcode) / sizeof(jmpcode[0]));
 
 -         VirtualProtect((LPVOID)dwHookAddr, 5, dwOldProtect, &dwOldProtect);
 
 -  
 
 -         MyOutputDebugStringA("AddHook Success:0x%p", dwHookAddr);
 
 -         return true;
 
 - }
 
 -  
 
 -  
 
 - // 移除Hook
 
 - bool CHook::RemoveHook(void)
 
 - {
 
 -         //还原原始机器码
 
 -         if (m_dwHookAddr == 0)
 
 -         {
 
 -                 return false;
 
 -         }        
 
 -         DWORD dwOldProtect = 0;
 
 -         VirtualProtect((LPVOID)m_dwHookAddr, 0x20, PAGE_EXECUTE_READWRITE, &dwOldProtect);
 
 -         memcpy((LPVOID)m_dwHookAddr, m_OldCode, 5);
 
 -         VirtualProtect((LPVOID)m_dwHookAddr, 5, dwOldProtect, &dwOldProtect);
 
 -  
 
 -         return true;
 
 - }
 
 
  复制代码 
 
 
核心代码就这些了,由于使用反汇编,汇编库,实现起来代码非常简单,连注释一起也就150行代码哈,下面讲一下如何使用。 
使用方法 
0x00:将MyOutputDebugString.h,MyOutputDebugString.cpp,Hook.h,Hook.cpp,bea文件夹,XEDParse文件夹复制到自己项目的代码目录。 
0x01:将MyOutputDebugString.h,MyOutputDebugString.cpp,Hook.h,Hook.cpp添加到项目中。 
0x02:在需要使用hook的地方,#include "Hook.h",然后就可以使用了。 
0x03:使用示例如下 
- CHook hook1;
 
 -  
 
 - void MyHookPro()
 
 - {
 
 -         //hook回调函数,这里写自己的代码
 
 - }
 
 -  
 
 - hook1.AddHook(dwHookAddr,MyHookPro);
 
 
  复制代码 
 
 
HookDll Demo核心代码: 
 
- #include "stdafx.h"
 
 - #include "Hook.h"
 
 - #include "MyOutputDebugString.h"
 
 -  
 
 - CHook hook1;
 
 - CHook hook2;
 
 - CHook hook3;
 
 - CHook hook4;
 
 -  
 
 - wchar_t szTitle[] = L"Tip:Modify by sunflover";
 
 - void Hook1Proc(void)
 
 - {
 
 -         //在这里添加你的代码
 
 -         MyOutputDebugStringA("Hook1Proc EAX = 0x%.8X ECX = 0x%.8X EDX = 0x%.8X EBX = 0x%.8X ESP = 0x%.8X EBP = 0x%.8X ESI = 0x%.8X EDI = 0x%.8X",
 
 -                 hook1.m_Context.EAX,hook1.m_Context.ECX,hook1.m_Context.EDX,hook1.m_Context.EBX,
 
 -                 hook1.m_Context.ESP,hook1.m_Context.EBP,hook1.m_Context.ESI,hook1.m_Context.EDI);
 
 -  
 
 -         //$ ==>    > 00405AAE  /CALL 到 MessageBoxW 来自 HookTest.00405AA8
 
 -         //$+4      > 00120A06  |hOwner = 00120A06 ('HookDemo',class='#32770')
 
 -         //$+8      > 00550BB8  |Text = "www.jmpoep.com"
 
 -         //$+C      > 02607D40  |Title = "HookTest"
 
 -         //$+10     > 00000000  \Style = MB_OK|MB_APPLMODAL
 
 -         //这里我们改变消息框的标题吧。
 
 -         LPVOID ppTitle= (LPVOID)(hook1.m_Context.ESP +0xC);
 
 -         DWORD pszTitle = (DWORD)&szTitle[0];
 
 -         memcpy(ppTitle,&pszTitle,4);
 
 - }
 
 -  
 
 - void Hook2Proc(void)
 
 - {
 
 -         //在这里添加你的代码
 
 -         MyOutputDebugStringA("Hook2Proc EAX = 0x%.8X ECX = 0x%.8X EDX = 0x%.8X EBX = 0x%.8X ESP = 0x%.8X EBP = 0x%.8X ESI = 0x%.8X EDI = 0x%.8X",
 
 -                 hook2.m_Context.EAX,hook2.m_Context.ECX,hook2.m_Context.EDX,hook2.m_Context.EBX,
 
 -                 hook2.m_Context.ESP,hook2.m_Context.EBP,hook2.m_Context.ESI,hook2.m_Context.EDI);
 
 - }
 
 -  
 
 - void Hook3Proc(void)
 
 - {
 
 -         //在这里添加你的代码
 
 -         MyOutputDebugStringA("Hook3Proc EAX = 0x%.8X ECX = 0x%.8X EDX = 0x%.8X EBX = 0x%.8X ESP = 0x%.8X EBP = 0x%.8X ESI = 0x%.8X EDI = 0x%.8X",
 
 -                 hook3.m_Context.EAX,hook3.m_Context.ECX,hook3.m_Context.EDX,hook3.m_Context.EBX,
 
 -                 hook3.m_Context.ESP,hook3.m_Context.EBP,hook3.m_Context.ESI,hook3.m_Context.EDI);
 
 -         //这里就简单的弹出个消息框
 
 -         MessageBoxA(NULL, "Hook3Proc\tBy sunflover","www.jmpoep.com",MB_ICONINFORMATION);
 
 - }
 
 -  
 
 - void Hook4Proc(void)
 
 - {
 
 -         //在这里添加你的代码
 
 -         MyOutputDebugStringA("Hook3Proc EAX = 0x%.8X ECX = 0x%.8X EDX = 0x%.8X EBX = 0x%.8X ESP = 0x%.8X EBP = 0x%.8X ESI = 0x%.8X EDI = 0x%.8X",
 
 -                 hook4.m_Context.EAX,hook4.m_Context.ECX,hook4.m_Context.EDX,hook4.m_Context.EBX,
 
 -                 hook4.m_Context.ESP,hook4.m_Context.EBP,hook4.m_Context.ESI,hook4.m_Context.EDI);
 
 - }
 
 -  
 
 - //bug1:要hook的地址开始后5个字节,不会retn,如下hook 00405AC5 处会失败,hook 00405AC0成功
 
 - //00405ABD  |.  8B45 E4       mov eax,[local.7]
 
 - //00405AC0  |>  E8 C0CB0F00   call HookDemo.00502685
 
 - //00405AC5  \.  C3            retn
 
 - //00405AC6  /$  33C0          xor eax,eax
 
 - //00405AC8  |.  3945 E4       cmp [local.7],eax
 
 -  
 
 -  
 
 - //请使用Release目录的HookTest.exe测试hook
 
 -  
 
 - BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 
 - {
 
 -         switch (ul_reason_for_call)
 
 -         {
 
 -         case DLL_PROCESS_ATTACH:
 
 -                 {
 
 -                         DWORD dwAddrMSGBOX = (DWORD)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxW");
 
 -                         hook1.AddHook(dwAddrMSGBOX, Hook1Proc);
 
 -                         hook2.AddHook(0x00405AB1, Hook2Proc);
 
 -                         hook3.AddHook(0x00405AC0, Hook3Proc);
 
 -                         hook4.AddHook(0x00405AC5, Hook4Proc);//ret处hook会失败         
 
 -                 }
 
 -         case DLL_THREAD_ATTACH:
 
 -         case DLL_THREAD_DETACH:
 
 -         case DLL_PROCESS_DETACH:
 
 -                 break;
 
 -         }
 
 -         return TRUE;
 
 - }
 
  复制代码 
 
 
理论上存在的问题(也因为这点所以叫伪任意地址Hook): 
0x00:要hook的地址开始后5个字节,不能有retn,如下hook 00405AC5 处会失败,hook 00405AC0成功 
//00405ABD  |.  8B45 E4       mov eax,[local.7] 
//00405AC0  |>  E8 C0CB0F00   call HookDemo.00502685 
//00405AC5  \.  C3            retn 
//00405AC6  /$  33C0          xor eax,eax 
//00405AC8  |.  3945 E4       cmp [local.7],eax 
 
 |   
 
 
 
 |