zoukankan      html  css  js  c++  java
  • lnline Hook初试

    简单解释下hook:

    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
    钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
     
    hook原理:
    每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程序。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
    Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。

    这是我第一次接触hook,写得很简单,对MessageBox函数hook一下下。

    下面实验的原理:在指定进程中的内存里找到目标函数的地址,然后修改其首地址的前几字节为jmp指令,指向我们自己的自定义函数地址。这样,进程执行这个函数的时候,会先执行我们自己的代码,之后可以选择性执行原函数或不执行。

    流程:

    1.构造跳转指令。

    2.在内存中找到欲hook函数地址,并保存欲hook位置处的前5个字节。

    3.将构造的跳转指令写入需hook的位置处。

    4.当被hook位置被执行时会转到我们的流程执行。

    5.如果要执行原来的流程,那么取消hook,也就是还原被修改的字节。

    6.执行原来的流程。

    7.继续hook住原来的位置。

    下面就要见具体代码实现了。我们来把hook封装一下。

    ILHook.h

    #ifndef __ILHOOK_H_1_
    #define __ILHOOK_H_1_
    
    #include <Windows.h>
    
    class CILHook{
    public:
        CILHook();
        ~CILHook();
        BOOL Hook(LPSTR pszModuleName, LPSTR pszFuncName, PROC pfnHookFunc);
        VOID UnHook();
        BOOL ReHook();
    
    private:
        PROC m_pfnOrig;//函数地址
        BYTE m_bOldBytes[5];//函数入口代码
        BYTE m_bNewBytes[5];//Inline代码
    };
    
    #endif

    ILHook.cpp

    #include "ILHook.h"
    
    CILHook::CILHook(){
        m_pfnOrig=NULL;
        ZeroMemory(m_bOldBytes, 5);
        ZeroMemory(m_bNewBytes, 5);
    }
    CILHook::~CILHook(){
        UnHook();
    }
    
    /*
    函数名称:Hook
    函数功能:对指定模块中的函数进行挂钩
    参数说明:
        pszModuleName:模块名称
        pszFuncName:函数名称
        pfnHookFunc:钩子函数
    */
    BOOL CILHook::Hook(LPSTR pszModuleName,LPSTR pszFuncName,PROC pfnHookFunc){
        BOOL bRet=FALSE;
        //获取指定模块中函数的地址
        m_pfnOrig=(PROC)GetProcAddress(GetModuleHandle(pszModuleName),pszFuncName);
    
        if(m_pfnOrig!=NULL){
            //保存该地址处5个字节的内容
            DWORD dwNum=0;
            ReadProcessMemory(GetCurrentProcess(),m_pfnOrig,m_bOldBytes,5,&dwNum);
            //构造JMP指令
            m_bNewBytes[0]='xe9';//jmp Opcode
            //pfnHookFunc是HOOK后的目标地址
            //m_pfnOrig是原来的地址
            //5是指令长度
            *(DWORD*)(m_bNewBytes+1)=(DWORD)pfnHookFunc-(DWORD)m_pfnOrig-5;
            //将构造好的地址写入该地址处
            WriteProcessMemory(GetCurrentProcess(),m_pfnOrig,m_bNewBytes,5,&dwNum);
    
            bRet=TRUE;
        }
        return bRet;
    }
    
    /*
    函数名称:UnHook
    函数功能:取消函数的挂钩
    */
    VOID CILHook::UnHook(){
        if(m_pfnOrig!=0){
            DWORD dwNum=0;
            WriteProcessMemory(GetCurrentProcess(),m_pfnOrig,m_bOldBytes,5,&dwNum);
        }
    }
    
    /*
    函数名称:ReHook
    函数功能:重新对函数进行挂钩
    */
    BOOL CILHook::ReHook(){
        BOOL bRet=FALSE;
        if(m_pfnOrig!=0){
            DWORD dwNum=0;
            WriteProcessMemory(GetCurrentProcess(),m_pfnOrig,m_bNewBytes,5,&dwNum);
            bRet=TRUE;
        }
        return bRet;
    }

    test.cpp

    #include "ILHook.h"
    
    CILHook MsgHook;
    
    int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType){
        MsgHook.UnHook();
        MessageBox(hWnd,"Hook",lpCaption,uType);
        MessageBox(hWnd,lpText,lpCaption,uType);
        MsgHook.ReHook();
    
        return 0;
    }
    
    int main(){
        MessageBox(NULL,"test","test",MB_OK);
    
        MsgHook.Hook("User32.dll","MessageBoxA",(PROC)MyMessageBoxA);
        MessageBox(NULL,"test","test",MB_OK);
        MsgHook.UnHook();
    
        return 0;
    }

    最后的结果是弹出3个对话框,第一个是正常调用,后两个是跳转到自己的自定义函数里进行两次调用原函数,当然是恢复了hook之后。

    这个例子是lnline hook本进程,后面会学习lnline hook非本进程。

  • 相关阅读:
    初始面向对象
    python之路——迭代器和生成器
    函数进阶
    python之路——初识函数
    实现css两端对齐
    http
    background-size
    call和apply的区别
    js兼容性
    面试题
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4521235.html
Copyright © 2011-2022 走看看