vc/其他语言 HOOK/API /其他技术 如何捕捉XP系统弹出的MessageBox窗体。
vc/其他语言HOOK/API/其他技术如何捕捉XP系统弹出的MessageBox窗体。想做一个.exe,它能监控并截获其他程序的MessageBox,主要是程序抛异常时...
vc/其他语言 HOOK/API /其他技术 如何捕捉XP系统弹出的MessageBox窗体。
想做一个.exe,它能监控并截获其他程序的MessageBox ,主要是程序抛异常时候的Messagebox。什么方法都可以。希望大家帮忙。 展开
想做一个.exe,它能监控并截获其他程序的MessageBox ,主要是程序抛异常时候的Messagebox。什么方法都可以。希望大家帮忙。 展开
4个回答
展开全部
要实现上述功能,需要API挂接技术。下面有2中方法:
★方法1、
1)、找到你想挂接的函数在内存中的地址(比如User32.dll中的MessageBox)。
2)、将该函数的头几个字节保存在你自己的内存中。
3)、用一个JUMP CPU指令改写该函数的头几个字节,该JUMP会转移到你的替换函数的内存地址。当然,你的替换函数的标记必须与你挂接的函数标记完全相同,即所有的参数和返回值必须一致,调用规则也必须一样。
4)、现在,当一个线程调用已经挂接的函数时,JUMP指令实际上将转移到你的替换函数,你就能干任何你想干的事情。
5)、取消挂接函数,方法是取出第二步保存的字节,将他们放回挂接函数的开头。
6)、调用挂接的函数(它已经不再被挂接),改函数将执行其通常的处理操作。
7)、当原始函数返回时,在此执行第二步和第三步,这样你的替换函数就可以被调用。
注意:这种方法在16位的Windows中使用的非常普遍,并且运行的很好。但是,它存在严重的不足,就是它对CPU依赖型特别大,在x86、Alpha、和其他CPU上的JUMP指令是不同的。另外,这种方法在抢占式多线程环境中根本不起作用。线程需要时间来改写函数开头的代码,但是,其他的线程也许正在试图调用同一个函数,结构将是灾难性的。
因此,建议搂主尽量不要使用这种方法。
★方法2、
众所周知,模块的输入节包涵一组该模块运行时需要的DLL。另外,它还包涵该模块从每个DLL中输入的符号列表。当模块调用一个输入函数时,线程实际上要从模块的输入节中捕获需要的输入函数的地址,然后转移到该地址。
因此,挂接一个特定的函数,只需要改变模块的输入节的中地址。
这种方法是十分健壮的。
★基于方法2的实现思路:
你可以定义一个这样的函数,具体的功能实现我不一一列出了,因为代码很长:
void ReplaceIATEntryInOneMod(PCSTR pszCallModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);
它要做的第一件事情是找出hmodCaller模块的输入节,方法是调用ImageDirectoryEntryToData函数。
注:输入节中所有的字符必须是ANSI,决不能是UNICODE。
然后,扫描DLL模块的名字,找到与pszCallModeName相同名字的DLL模块。重复引用来自pszCallModeName中的所有输入符号,找到目标函数相匹配的地址,楼主需要的是“USER32.DLL”中的“MessageBoxW”或者“MessageBoxA”。
然后调用WriteProcessMemory来替换目标函数的地址。(注:之所以使用WriteProcessMemory而不使用InterlockedExchangePointer是因为无论页面保护属性是什么,即使是PAGE_READONLY也不会引发致命的访问违规)
另外,《Windwos核心编程中》有具体的挂接API例子。
★方法1、
1)、找到你想挂接的函数在内存中的地址(比如User32.dll中的MessageBox)。
2)、将该函数的头几个字节保存在你自己的内存中。
3)、用一个JUMP CPU指令改写该函数的头几个字节,该JUMP会转移到你的替换函数的内存地址。当然,你的替换函数的标记必须与你挂接的函数标记完全相同,即所有的参数和返回值必须一致,调用规则也必须一样。
4)、现在,当一个线程调用已经挂接的函数时,JUMP指令实际上将转移到你的替换函数,你就能干任何你想干的事情。
5)、取消挂接函数,方法是取出第二步保存的字节,将他们放回挂接函数的开头。
6)、调用挂接的函数(它已经不再被挂接),改函数将执行其通常的处理操作。
7)、当原始函数返回时,在此执行第二步和第三步,这样你的替换函数就可以被调用。
注意:这种方法在16位的Windows中使用的非常普遍,并且运行的很好。但是,它存在严重的不足,就是它对CPU依赖型特别大,在x86、Alpha、和其他CPU上的JUMP指令是不同的。另外,这种方法在抢占式多线程环境中根本不起作用。线程需要时间来改写函数开头的代码,但是,其他的线程也许正在试图调用同一个函数,结构将是灾难性的。
因此,建议搂主尽量不要使用这种方法。
★方法2、
众所周知,模块的输入节包涵一组该模块运行时需要的DLL。另外,它还包涵该模块从每个DLL中输入的符号列表。当模块调用一个输入函数时,线程实际上要从模块的输入节中捕获需要的输入函数的地址,然后转移到该地址。
因此,挂接一个特定的函数,只需要改变模块的输入节的中地址。
这种方法是十分健壮的。
★基于方法2的实现思路:
你可以定义一个这样的函数,具体的功能实现我不一一列出了,因为代码很长:
void ReplaceIATEntryInOneMod(PCSTR pszCallModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);
它要做的第一件事情是找出hmodCaller模块的输入节,方法是调用ImageDirectoryEntryToData函数。
注:输入节中所有的字符必须是ANSI,决不能是UNICODE。
然后,扫描DLL模块的名字,找到与pszCallModeName相同名字的DLL模块。重复引用来自pszCallModeName中的所有输入符号,找到目标函数相匹配的地址,楼主需要的是“USER32.DLL”中的“MessageBoxW”或者“MessageBoxA”。
然后调用WriteProcessMemory来替换目标函数的地址。(注:之所以使用WriteProcessMemory而不使用InterlockedExchangePointer是因为无论页面保护属性是什么,即使是PAGE_READONLY也不会引发致命的访问违规)
另外,《Windwos核心编程中》有具体的挂接API例子。
展开全部
可以采用DLL程序注入技术,截取USER32.DLL中的MessageBox函数。用你的程序代替MessageBox函数完成截获。
具体可参考我给的链接
具体可参考我给的链接
参考资料: http://www.77itcn.com/Show.asp?id=432
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
楼上的方法2我一开始也想过,不过不是运行时修改,我想能不能直接在程序的2进制文件中修改呢?
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
吾人子弟
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询