资源描述:
《作系统中屏幕取词技术的研究.pdf》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库。
1、第26卷湖北师范学院学报(自然科学版)Vol126第2期JournalofHubeiNormalUniversity(NaturalScience)No12,2006Windows操作系统中屏幕取词技术的研究童强(湖北师范学院计算机科学系,湖北黄石435002)摘要:分析Windows操作系统中屏幕取词技术的原理和实现方法,并对其中涉及到的钩子函数的使用,API拦截以及进程间通讯等关键技术和步骤进行了深入研究。关键词:钩子;动态连接库;API拦截;屏幕取词中图分类号:TP316.7;TP311.52文献标
2、识码:A文章编号:100922714(2006)02200752040引言虽然屏幕取词技术被很多翻译软件及字典软件应用,但是由于其核心涉及到Windows操作系统的很多底层技术,包括hook技术,API拦截技术、动态库管理以及进程间的通讯等,实现起来却比较复杂。实现屏幕取词所涉及的这些底层技术也可以运用到其它软件开发中,还有助于剖析和理解Windows操作系统。1实现屏幕取词的原理要实现屏幕取词首先要了解在Windows操作系统的文本是如何输出的,实际上Windows系统下屏幕上不管具体是哪个应用程序的文
3、本输出,最后都是调用Windows系统的动态库GDI32.dll中的TextOutA、TextOutW、ExtTextOutA、ExtTextOutW等几个API函数实现的。即不论哪个程序,只要输出文本都会在程序模块中导入动态库GDI32.dll,并最终利用上述几个函数输出文本。其中TextOutA和ExtTextOutA用于输出ANSI字符,TextOutW和ExtTextOutW用于输出unicode字符。所以实现鼠标屏幕取词的关键就是如何设法在Windows字符输出的时候取得这几个API函数的参数。
4、可以通过采用APIHOOK技术实现对这几个API函数的挂接,在输出字符的时候截获API函数的参数,这些参数包括输出的文本的字符串以及及其输出的位置坐标信息。根据Windows系统的工作原理,当窗体全部或部分需要刷新时,TextOutA等API就会被调用重新[1]输出,比如一个窗体盖住了另一个窗体,当上面窗体移开后下面的窗体会收到系统的WM_PAINT消息而刷新,TextOutA等被调用绘制文字部分,看起来就像真是露出了原来被挡住的部分。因此必须设法在需要的时候让有关窗体的有关区域刷新,具体做法就是在鼠标所
5、在位置画一个小窗体挡住下面的窗体一下(肉眼看不出来),下面的窗体被挡住的字符就会重绘,(另外一种方法是调用Invalidae2rect和Updadawindow函数强制区域刷新)那几个已经被挂接的API就会被调用了,于是在挂接的钩子函数中可以获得其参数,通过计算鼠标位置和输出文本位置就得到了鼠标下的文字了。主要步骤如下:1)挂上API钩子;收稿日期:2005—10—12作者简介:童强(1968—),男,湖北黄石人,讲师,工程师,硕士,主要研究方向为多媒体应用技术、Web应用技术等。·75·2)得到鼠标当前
6、位置,并设法让鼠标下的窗口刷新;3)在API钩子函数中截获字符串,并根据鼠标位置计算出鼠标下的字符;并调用原型函数完成刷新工作。为了随时知道鼠标的位置,还要安装一个鼠标钩子以便随时得到鼠标的屏幕坐标。这里用到了两种钩子,即鼠标钩子和前面提到的API钩子。2挂接API钩子截获API参数如前所述,要获得系统API的输出参数,关键就是对几个有关文本输出的API函数进行挂接。实[2]现API挂接的方法有多种,这里采用的方法是通过操作模块的输入节来挂接API。模块的输入节包含一组该模块运行的时候需要的DLL以及该模
7、块从每个DLL输入的符号的列表。当模块调用一个输入函数时,线程实际上要从模块的输入节中捕获输入函数的地址,然后转移到该地址。要挂接前面讲述的GDI32.dll中的TextOutA、TextOutW、ExtTextOutA、ExtTextOutW等几个API函数,只需要改变模块的输入节中这几个函数的地址,改成预先编写的替代函数地址就可以了。下面是对某个模块输入节进行改写的基本步骤:1)首先对该模块(例如运行的word程序)调用ImageDirectoryEntryToData函数看该模块该模块的输入节,如果
8、返回NULL说明该模块没有输入节,则不做如何动作结束挂接工作。2)如果有输入节,ImageDirectoryEntryToData返回该输入节地址,一个类型为IMAGE_DIRECTO2RY_ENTRY_IMPORT的指针,实际上是一个包含输入节信息的结构体。扫描这个结构体中所有dll的名字,看有没有要找的GDI32.dll(看这个模块是否用到GDI32.dll),如果扫描结束没有找到,说明没有用到GDI32.dll,则结束挂