WINDOWS下HOOK函数的方法

 

前两天和dvff谈论的一些技术总结。

程序代码:
/
//                     HOOKAPI DEMO PROGRAM
// 文件名:HOOKTEST.C
//
// 描述: 演示WINNT下HOOK系统API过程及方法
//       (扩充为HOOK任意函数的方法)
//
// 作者:东海一鱼
//
// 时间: 2010.7.22       
//
// 使用编译器: VC2003
//
// 使用第三方库: NULL
//
//
// Bug、修复纪录:
//           1、2010.8.4 增加HOOK私有函数代码(被hook函数名TestFn,hook函数名MyHookFn2)
//
//             2、2010.8.6 增加HOOK类虚拟函数代码(被hook函数名TestVirtualFn,
//                hook函数名TestVirtualFn2)
//
//                HOOK类成员函数,主要难度在于成员函数地址的获得。
//              普通成员函数指针在VC6下无法进行强制类型转换,
//              解决手段见GetClassFnAddress辅助函数。
//              类虚拟成员函数HOOK需要获得类实例对象虚表中的虚拟函数指针。                   

#include <stdlib.h>
#include  <stdio.h>
#include  <windows.h>

// #pragma pointers_to_members(best_case)

#ifdef _X86_

#define FLATJMPCODE_LENGTH 5             // x86 平坦内存模式下,绝对跳转指令长度
#define FLATJMPCMD_LENGTH  1             // 机械码0xe9长度
#define FLATJMPCMD         0xe9

#else

#error WINVER ERRORSLECT  ONLY USES ON X86!!!

#endif

///
// 测试类函数HOOK
class TestHookFnClass
{
public:
     virtual  void TestVirtualFn( char* szPlay);
     virtual  void TestVirtualFn2( char* szPlay);
     void TestHookFn( char* szPlay);
     void TestHookFn2( char* szPlay);   
};

void TestHookFnClass::TestHookFn( char* szPlay)
{
    printf( " %s\n ",szPlay);
}

void TestHookFnClass::TestHookFn2( char* szPlay)
{
    printf( " %s - %s\n  ",szPlay, " 类函数已被HOOK! ");
}

void TestHookFnClass::TestVirtualFn( char* szPlay)
{
    printf( " %s\n ",szPlay);
}

void TestHookFnClass::TestVirtualFn2( char* szPlay)
{
    printf( " %s - %s\n ",szPlay, " Virtual2 HOOKS ");
}

/
#ifdef _X86_
// 利用C变参特性,进行类成员函数指针类型转换
LPVOID GetClassFnAddress(...)                     // Add  2010.8.6
{
    LPVOID FnAddress;
   
     __asm
    {
        lea eax,FnAddress
        mov edx,[ebp+ 8]
        mov [eax],edx
    }
     return FnAddress;
}
#endif

// 获得类虚拟成员函数指针
LPVOID GetClassVirtualFnAddress(LPVOID pthis, int Index)  // Add 2010.8.6
{
    LPVOID FnAddress;
   
    *( int*)&FnAddress = *( int*)pthis;                        // lpvtable
    *( int*)&FnAddress = *( int*)(( int*)FnAddress + Index);
     return FnAddress;
}
/
// 我的新API函数
int  __stdcall MyHookFn(HWND hwnd, char* sztext, char* szTitle, int stly)
{          
   
     return printf( " %s - %s\n ",sztext, " 原API函数已被HOOK! ");    //
}

// 我的新私有桩函数
void MyHookFn2( char* szTxt)
{
     char* pBuf = ( char*)malloc(strlen(szTxt) +  sizeof( char*) *  32);
   
    __try
    {
        sprintf(pBuf, " %s - %s ",szTxt, "  原函数已被HOOK! ");
        printf( " %s\n ",pBuf);
    }
    __finally
    {
        free(pBuf);
    }
}

// 私有测试函数
void TestFn( char* szTitle)
{
    printf( " %s ",szTitle);
}

/ /
// HOOK函数
BOOL HookApi(LPVOID ApiFun,LPVOID HookFun)
{
    BOOL    IsSuccess = FALSE;
    DWORD   TempProtectVar;               // 临时保护属性变量
    MEMORY_BASIC_INFORMATION MemInfo;     // 内存分页属性信息
   
    VirtualQuery(ApiFun,&MemInfo, sizeof(MEMORY_BASIC_INFORMATION)); 
   
     if(VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
        PAGE_READWRITE,&MemInfo.Protect))                             // 修改页面为可写
    {
        *(BYTE*)ApiFun = FLATJMPCMD;                                     
        *(DWORD*)((BYTE*)ApiFun + FLATJMPCMD_LENGTH) = (DWORD)HookFun -
            (DWORD)ApiFun - FLATJMPCODE_LENGTH;
       
        VirtualProtect(MemInfo.BaseAddress,MemInfo.RegionSize,
            MemInfo.Protect,&TempProtectVar);                                // 改回原属性
       
        IsSuccess = TRUE;
    }
   
     return IsSuccess;
}

int main( int argc, char** argv)
{
    HMODULE hDll;
    LPVOID  OldFun;    

    TestHookFnClass* TestClass =  new TestHookFnClass();

    __try
    {
        hDll = GetModuleHandle( " User32.dll ");
        OldFun = GetProcAddress(hDll, " MessageBoxA ");   // 要HOOK的API函数
   
         if(OldFun)
        {
             if(HookApi(OldFun,MyHookFn))   // 如果HOOK成功
                MessageBoxA( 0, " call Api MessageBox ", " Is Hookd? ",MB_OK);  // 调用原API,测试HOOK

             if(HookApi(TestFn,MyHookFn2))
                TestFn( " Private Function Hook Test ");   // 调用私有函数,测试HOOK   
           
             if(HookApi(GetClassFnAddress(TestHookFnClass::TestHookFn),
                GetClassFnAddress(TestHookFnClass::TestHookFn2)))
                TestClass->TestHookFn( " Hook Class Member Function Test! "); // 调用类成员函数,测试HOOK

             if(HookApi(GetClassVirtualFnAddress(TestClass, 0),
                GetClassFnAddress(TestHookFnClass::TestHookFn2)))
                TestClass->TestVirtualFn( " Call Class Virtual Function Test! "); // 调用类虚拟函数,测试HOOK
           
             if(HookApi(GetClassVirtualFnAddress(TestClass, 0),
                GetClassVirtualFnAddress(TestClass, 1)))                    
                TestClass->TestVirtualFn( " Call Class Virtual Function Test2! "); // 同上,桩函数为另一虚函数
        }
    }
    __finally
    {
         if(hDll)
            FreeLibrary(hDll);
         if(TestClass)
             delete(TestClass);
    }
   
     return  0;
}

转载于:https://www.cnblogs.com/HeroZearin/articles/2772100.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值