有下面的需求:
在自己的应用程序中要监视屏幕文字的输出.由于自己的应用程序中采用一个控件,这个控件是第三方的,因此无法知道屏幕在具体位置的输出结果,因此想安装一个钩子,监视系统API(GDI32.DLL)的输出,这个钩子安装在自己的应用程序中,用应用程序中的函数替换系统API的屏幕输出函数.
这个改如何实现呢?
在自己的应用程序中要监视屏幕文字的输出.由于自己的应用程序中采用一个控件,这个控件是第三方的,因此无法知道屏幕在具体位置的输出结果,因此想安装一个钩子,监视系统API(GDI32.DLL)的输出,这个钩子安装在自己的应用程序中,用应用程序中的函数替换系统API的屏幕输出函数.
这个改如何实现呢?
下面的代码是 形成 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
};这是为什么呢?
//第一个参数 lpJMPCode 钩子函数的前5个字节
//第二个参数 lpCodePoint 钩子函数地址