• windows钩子 Hook示例


    1.首先编写一个 win32 dll工程.

    #include "stdafx.h"
    int WINAPI add(int a,int b) { return a+b; }
    BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
    return TRUE; }

    在def文件添加显式导出: (没找到def文件需要添加)

    LIBRARY
    DESCRIPTION "ADD LA"
    EXPORTS
     add  @1;

    2.编写调用此dll的主程序  新建基于对话框的MFC工程

    在dlg头文件里添加声明:

    #include <windef.h>
    public:
     HINSTANCE hAddDll;
     typedef int (WINAPI*AddProc)(int a,int b);
     AddProc add;

    在程序入口 编写加载函数:

    if (hAddDll==NULL)
      hAddDll=::LoadLibrary("add.dll");
    
     add=(AddProc)::GetProcAddress(hAddDll,"add");

    添加一个按钮函数 调用:

     int a=1;
     int b=2;
     int c=add(a,b);
     CString temp;
     temp.Format("%d+%d=%d",a,b,c);
     AfxMessageBox(temp);

    到这里运行主程序 就会看到。弹窗 1+2 = 3的结果。

    3.编写hook dll 新建一个MFC dll 工程。

     在InitInstance函数中添加:

     hinst=::AfxGetInstanceHandle();
     DWORD dwPid=::GetCurrentProcessId();
     hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,dwPid); 
     //调用注入函数
     Inject();
     return CWinApp::InitInstance();

    所有的声明:

    #pragma data_seg("SHARED")
    static HHOOK  hhk=NULL; //鼠标钩子句柄
    static HINSTANCE hinst=NULL; //本dll的实例句柄 (hook.dll)
    #pragma data_seg()
    #pragma comment(linker, "/section:SHARED,rws")
    
    CString temp; //用于显示错误的临时变量
    bool bHook=false; //是否Hook了函数
    bool m_bInjected=false; //是否对API进行了Hook
    BYTE OldCode[5]; //老的系统API入口代码
    BYTE NewCode[5]; //要跳转的API代码 (jmp xxxx)
    typedef int (WINAPI*AddProc)(int a,int b);//add.dll中的add函数定义
    AddProc add; //add.dll中的add函数
    HANDLE hProcess=NULL; //所处进程的句柄
    FARPROC pfadd;  //指向add函数的远指针
    DWORD dwPid;  //所处进程ID://end of 变量定义
    
    //函数定义
    void HookOn();
    void HookOff(); //关闭钩子
    LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam); //鼠标钩子函数
    void Inject(); //具体进行注射,替换入口的函数
    int WINAPI Myadd(int a,int b); //我们定义的新的add()函数
    BOOL InstallHook(); //安装钩子函数
    void UninstallHook(); //卸载钩子函数

    声明函数的实现:

    LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam)
    {
        LRESULT RetVal= CallNextHookEx(hhk,nCode,wParam,lParam);
        return RetVal;
    }
    
    BOOL InstallHook()
    {
    
        hhk=::SetWindowsHookEx(WH_MOUSE,MouseProc,hinst,0);
        return true;
    }
    
    void UninstallHook()
    {
        ::UnhookWindowsHookEx(hhk);
    }
    
    
    
        void Inject()
    {
        if (m_bInjected==false)
        { 
    
        m_bInjected=true;
    
    
        HMODULE hmod=::LoadLibrary("add.dll");
        add=(AddProc)::GetProcAddress(hmod,"add");
        pfadd=(FARPROC)add;
    
        if (pfadd==NULL)
        {
            AfxMessageBox("cannot locate add()");
        }
    
        // 将add()中的入口代码保存入OldCode[]
        _asm 
        { 
            lea edi,OldCode 
                mov esi,pfadd 
                cld 
                movsd 
                movsb 
        }
    
        NewCode[0]=0xe9;//实际上0xe9就相当于jmp指令
        //获取Myadd()的相对地址
        _asm 
        { 
            lea eax,Myadd
                mov ebx,pfadd 
                sub eax,ebx 
                sub eax,5 
                mov dword ptr [NewCode+1],eax 
        } 
        //填充完毕,现在NewCode[]里的指令相当于Jmp Myadd
        HookOn(); //可以开启钩子了
     }
    }
    
    
    void HookOn() 
    { 
        ASSERT(hProcess!=NULL);
    
        DWORD dwTemp=0;
        DWORD dwOldProtect;
    
        //将内存保护模式改为可写,老模式保存入dwOldProtect
        VirtualProtectEx(hProcess,pfadd,5,PAGE_READWRITE,&dwOldProtect); 
        //将所属进程中add()的前5个字节改为Jmp Myadd 
        WriteProcessMemory(hProcess,pfadd,NewCode,5,0);
        //将内存保护模式改回为dwOldProtect
        VirtualProtectEx(hProcess,pfadd,5,dwOldProtect,&dwTemp);
    
        bHook=true; 
    }
    
    void HookOff()//将所属进程中add()的入口代码恢复
    { 
        ASSERT(hProcess!=NULL);
    
        DWORD dwTemp=0;
        DWORD dwOldProtect;
    
        VirtualProtectEx(hProcess,pfadd,5,PAGE_READWRITE,&dwOldProtect); 
        WriteProcessMemory(hProcess,pfadd,OldCode,5,0); 
        VirtualProtectEx(hProcess,pfadd,5,dwOldProtect,&dwTemp); 
        bHook=false; 
    }
    
    
    int WINAPI Myadd(int a,int b)
    {
        //截获了对add()的调用,我们给a,b都加1
        a=a+1;
        b=b+1;
    
        HookOff();//关掉Myadd()钩子防止死循环
    
        int ret;
        ret=add(a,b);
    
        HookOn();//开启Myadd()钩子
    
        return ret;
    }

    在def文件 添加显式导出:

     InstallHook  
     MouseProc
     Myadd
     UninstallHook 

     hook dll 就完成了。

    4.回到主程序 添加2个按钮 一个注入 一个卸载:

    注入:

     hinst=LoadLibrary("hook.dll");
     if(hinst==NULL)
     {
      AfxMessageBox("no hook.dll!");
      return;
     }
     typedef BOOL (CALLBACK *inshook)(); 
     inshook insthook;
    
     insthook=::GetProcAddress(hinst,"InstallHook");
     if(insthook==NULL)
     {
      AfxMessageBox("func not found!");
      return;

    DWORD pid=::GetCurrentProcessId();
    BOOL ret=insthook();

    卸载:

     typedef BOOL (CALLBACK *UnhookProc)(); 
     UnhookProc UninstallHook;
    
     UninstallHook=::GetProcAddress(hinst,"UninstallHook");
     if(UninstallHook==NULL) UninstallHook();
     if (hinst!=NULL)
     {
      ::FreeLibrary(hinst);
     }
     if (hAddDll!=NULL)
     {
      ::FreeLibrary(hAddDll);
     }
     CDialog::OnCancel();

    运行主程序:

    计算:显示1+2 =3

    注入:显示 1+2=5

    完。

    有任何不明白的地方欢迎骚扰:0x7317AF28

  • 相关阅读:
    删除旧版vue-cli
    vue.extend和vue.component的区别
    vue-loader处理vue文件
    CentOS7安装iptables防火墙
    java类的初始化顺序
    java的接口和抽象类的理解
    js中的in操作符
    js中call和apply函数
    js的类型转换
    闭包作用
  • 原文地址:https://www.cnblogs.com/xuandi/p/7071240.html
Copyright © 2020-2023  润新知