有下面的需求: 
在自己的应用程序中要监视屏幕文字的输出.由于自己的应用程序中采用一个控件,这个控件是第三方的,因此无法知道屏幕在具体位置的输出结果,因此想安装一个钩子,监视系统API(GDI32.DLL)的输出,这个钩子安装在自己的应用程序中,用应用程序中的函数替换系统API的屏幕输出函数.
这个改如何实现呢?

解决方案 »

  1.   


    下面的代码是 形成 JMP 指令﹒
    //第一个参数 lpJMPCode   钩子函数的
    //第二个参数 lpCodePoint 钩子函数
    void MakeJMPCode(LPBYTE lpJMPCode, LPVOID lpCodePoint)
    {

    BYTE temp;
    WORD wHiWord = HIWORD(lpCodePoint);
    WORD wLoWord = LOWORD(lpCodePoint);
    WORD wCS; _asm   //取当前选择符
    {
    push ax;  //压入ax
    push cs;  //压入cs        
    pop  ax;  //弹出cs到ax
    mov  wCS, ax; //将ax给wCS,实际是把cs给wCS
    pop  ax;  //恢复ax
    };

    //lpJMPCode[0] = 0xea; //填入JMP指令的机器码
    lpJMPCode[0] = 0xe9; //填入JMP指令的机器码
     
    temp = LOBYTE(wLoWord); // -------------------------
    lpJMPCode[1] = temp;
    temp = HIBYTE(wLoWord);
    lpJMPCode[2] = temp; // 填入地址﹒在內存中的顺序为
    temp = LOBYTE(wHiWord); // Point: 0x1234
    lpJMPCode[3] = temp; // 內存: 4321
    temp = HIBYTE(wHiWord);
    lpJMPCode[4] = temp; // -------------------------

    temp = LOBYTE(wCS); // 填入选择符
    lpJMPCode[5] = temp;
    temp = HIBYTE(wCS);
    lpJMPCode[6] = temp; //return;
    }当程序执行到MakeJMPCode 函数时,
    当整个HOOK代码 位于动态连接库中时, 他的执行结果是正确的.
    如果整个HOOK代码位于应用程序中,MakeJMPCode 函数返回的时候,就会给出堆栈溢出的错误.经过调试跟踪,发现是下面红字代码的原因:
    _asm   //取当前选择符
    {
    push ax;  //压入ax
    push cs;  //压入cs        
    pop  ax;  //弹出cs到ax
    mov  wCS, ax; //将ax给wCS,实际是把cs给wCS

    pop  ax;  //恢复ax
    };这是为什么呢?
      

  2.   

    所谓的第三方,举个例子来说,在MFC基于对话狂的应用程序中,放置了一个webbrowers控件,这个控件就是第三方的.对于webbrowers的输出,我们是不知道的,如果想获得webbrowers的屏幕输出,用钩子就可以知道
      

  3.   

    void MakeJMPCode(LPBYTE lpJMPCode, LPVOID lpCodePoint) 
    //第一个参数 lpJMPCode   钩子函数的前5个字节
    //第二个参数 lpCodePoint 钩子函数地址