金山词霸2003导致我的程序堆栈溢出错误
最近发现金山词霸屏幕取词功能导致连连看在ET内执行的时候堆栈溢出
而连连看单机版则无此问题。郁闷异常,分析金山词霸的取词功能如下:
1 屏幕抓词
屏幕抓词(或者叫动态翻译)是指随着鼠标的移动,软件能够随时获知屏幕上鼠标位置的单词或汉字,并翻译出来提示用户。它对於上网浏览、在线阅读外文文章等很有帮助作用,因此许多词典软件都提供了屏幕抓词功能。
屏幕抓词的关键是如何获得鼠标位置的字符串,Windows的动态链接和消息响应机制为之提供了实现途径。 概括地说,主要通过下面的几个步骤来取得屏幕上鼠标位置的字符串:
. 代码拦截:Windows以DLL方式提供系统服务,可以方便地获取Windows字符输出API的地址,修改其入口代码,拦截应用程序对它们的调用。
. 鼠标HOOK:安装WH—MOUSEPROC类型的全局鼠标HOOK过程,监视鼠标在整个屏幕上的移动。
. 屏幕刷新:使鼠标周围一块区域无效,并强制鼠标位置的窗口刷新屏幕输出。窗口过程响应WM—NCPAINT和WM—PAINT消息,调用ExtTextOut/TextOut等字符输出API更新无效区域里面的字符串。这些调用被我们截获,从堆栈里取得窗口过程传给字符API的参数,如字符串地址、长度、输出坐标、HDC、裁剪区等信息。
2 取词的过程,
0 判断鼠标是否在一个地方停留了一段时间
1 取得鼠标当前位置
2 以鼠标位置为中心生成一个矩形
3 挂上API钩子
4 让这个矩形产生重画消息
5 在钩子里等输出字符
6 计算鼠标在哪个单词上面,把这个单词保存下来
7 如果得到单词则摘掉API钩子,在一段时间后,无论是否得到单词都摘掉API钩子
8 用单词查词库,显示解释框。
3 出错原因(转)
开着金山词霸浏览网页的时候经常就会浏览器自动关闭,实在烦人。刚才又遇到,就稍微分析了一下,觉得因为我们也经常使用钩子,可能会有借鉴,就把分析结果稍微写写,让大家以后编程少犯这样的错误。
翻译软件等关键技术之一就是拦截操作系统的显示函数,从中抓到显示的单词,这点大家都明白不用再多说。比如金山词霸会拦截系统库GDI32.DLL的输出函数ExtTextOutA等,拦截方法是找到这个函数地址,在这入口填写一个JMP 指令,跳转到金山词霸的一个入口,当然其也保存了这个入口开始被JMP指令覆盖的几个字节。金山词霸的这个入口里面又要用这个函数,所以其得到控制权后又恢复了ExtTextOutA这个函数开始的指令,进行调用。这种不好的钩子处理办法就埋下了祸根。可能是其内部信号标记等处理不好,某种情况下钩子想调用恢复后的ExtTextOutA函数的时候,但可能没有恢复成功,就又进入了金山词霸的钩子,这样就导致循环了,堆栈迅速消耗,最终因为堆栈消耗完再进行堆栈操作的时候出现非法操作而导致程序关闭退出。
这就告诉我们如果钩子里面要调用要钩的函数本身,最好要错过钩子。比如在函数入口用写JMP指令做钩子,那么再调用的时候最好调用其下面的哪个入口,或者钩子种在上面调用这个函数的指令那。要不就要保证恢复入口指令一定正确。再就是注意重入问题,就是钩子里面再调用别的函数的时候可能别的函数会用到钩子钩的函数,那你就得保证你的代码是可重入的。其实写过病毒的人恐怕都或多或少接触了重入问题。
程序1: call dword ptr [ExtTextOutA]
要钩的函数:
GDI32.DLL
ExtTextOutA:
push ebp
...
call ExtTextOutW
....
ret
假设环境如上面,钩子方案可以:
1、改写程序1的call dword ptr [ExtTextOutA]中[]内存的值,指向钩子,钩子里面要再用到ExtTextOutA的话正常调用GDI32.DLL中的这个函数就是了。这个方法缺点可能就是要修改地方多。
2、修改GDI32.DLL的函数ExtTextOutA开始指令,指向钩子,但钩子里面再调用这个函数就用里层的ExtTextOutW(这儿是假设的,我也不知道这里面有什么接口)。
3、就是金山词霸用的修改开始指令,要用的时候就恢复开始指令后调用。
(2、3两点有个不好就是要钩的函数开始一定要有几个这个函数体的指令,这几个指令这儿还不能是别的什么函数入口,这点对一般函数没问题,对于一些特殊函数恐怕就不行了)。
4、修改GDI32.DLL的函数引出表的ExtTextOutA的值,指向钩子,这样加载别的DLL的时候用到此函数操作系统就会自动把钩子地址填写,这样就不用程序操心去改写第1个方法要改写的地方了。缺点嘛就是先加载了的DLL无效,再就是恢复麻烦。
5、......
大家可以综合考虑使用自己喜欢的。
金山词霸2003导致我的程序堆栈溢出错误相关推荐
- 系统在此应用程序堆栈溢出_从部署我的第一个完整堆栈Web应用程序中学到的经验教训...
系统在此应用程序堆栈溢出 by Will Abramson 威尔·艾布拉姆森(Will Abramson) 从部署我的第一个完整堆栈Web应用程序中学到的经验教训 (Lessons learned f ...
- 系统在此应用程序堆栈溢出_Web应用程序:在开始之前选择正确的技术堆栈
系统在此应用程序堆栈溢出 You have a great online business idea along with investors and a team ready to get behi ...
- 系统在此应用程序堆栈溢出_部署第一个完整堆栈应用程序之前需要考虑的三件事
系统在此应用程序堆栈溢出 Building a full stack app is no small endeavor, and deploying it comes with its own hos ...
- java上传文件堆溢出_我的正则表达式导致Java中的堆栈溢出;我错过了什么?
我试图使用Scanner的正则表达式来匹配文件中的字符串.正则表达式适用于该行以外的所有内容: DNA="ITTTAITATIATYAAAYIYI[....]ITYTYITTIYAIAIYI ...
- java pattern堆栈溢出_我的正则表达式导致Java中的堆栈溢出;我错过了什么?
我试图使用Scanner的正则表达式来匹配文件中的字符串.正则表达式适用于该行以外的所有内容: DNA="ITTTAITATIATYAAAYIYI[....]ITYTYITTIYAIAIYI ...
- java pattern堆栈溢出_堆栈溢出错误与正则表达式进行解析
我知道有关于正则表达式和长字符串的堆栈溢出错误的一些帖子,但它们没有帮助我,也从不关心我的解析问题类型. 我只是试图从数学函数中找到括号中的字符串,例如 funktionsstring =SIN(3. ...
- 一段堆栈溢出的代码_为什么堆栈溢出的代码片段会破坏您的项目
一段堆栈溢出的代码 Stack Overflow has been the saviour of many programmers, including me. Some of us have nev ...
- 利用 watchpoint 监测堆栈溢出
使用调试器捕获堆栈溢出 开始运行目标程序之前,首先在堆栈的底部设置 watchpoint ,倘若程序堆栈溢出,那么将触发该 watchpoint.假设堆栈起始地址为0x20030000,堆栈深度为0x ...
- java递归堆栈溢出_【java】递归次数过多导致堆栈溢出
在写一个算法中,由于递归调用次数过多,堆栈溢出. 堆栈的大小是系统控制的,无法改变. 如果递归调用出现问题,可以考虑采取循环的方式来解决,将需要的数据在关键的调用点保存下来使用.简单的说,就是用自己的 ...
最新文章
- Struts+Hibernate+MyEclipse+Tomcat+MySQL的乱码之解决
- LeetCode 230. Kth Smallest Element in a BST--C++,Python解法--面试真题--找二叉树中第K小的元素
- ubuntu 12.04.1升级至ubuntu 12.10出现gcc-4.7依赖库错误的解决办法
- Keil 汇编窗口无法设置断点,disassembly显示错误,Keil汇编解析错误
- linux 漏洞数量,Debian Linux被列为过去20年漏洞数量最多的操作系统
- 开源开放 | 一个用于知识驱动的零样本学习研究的开源数据集KZSL(CCKS2021)
- JS弹出DIV并使整个页面背景变暗功能的实现代码
- ansible基本模块-shell
- 基于Go语言构建区块链:part5
- 数学专业学c语言,数学专业C语言教学方法研究.pdf
- python属于汇编语言还是高级语言_python语言属于汇编语言吗?_后端开发
- Aegisub制作字幕从入门到精通:制作srt字幕,制作ass字幕,压制字幕和视频
- 直观理解Law of Total Variance(方差分解公式)
- 日期计算器输入天数计算日期_计算日期范围内的活动
- PD3.1 140W双C快充解决方案
- python imshow调整比例_如何在不拉伸图像的情况下更改matplotlib中imshow的比例?
- PHP采集-数据采集PHP采集器
- Lyndon的量化修炼之路——浅谈趋势指标取参方法
- 如何在线生成动态gif图片?轻松一键教你在线制作gif
- HDOJ_2.1.2_How many prime numbers