没有合适的资源?快使用搜索试试~ 我知道了~
鼠标屏幕取词技术windows编程实现教程及详细源代码.doc
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
21 浏览量
2022-07-07
17:18:12
上传
评论
收藏 58KB DOC 举报
鼠标屏幕取词技术windows编程实现教程及详细源代码
资源推荐
资源详情
资源评论





















鼠标屏幕取词技术 windows 编程实现教程及详细源代码
“鼠标屏幕取词”技术是在电子字典中得到广泛地应用的,如
四通利方和金山词霸等软件,这个技术看似简单,其实在
windows 系统中实现却是非常复杂的,总的来说有两种实现方式:
第 一 种 : 采 用 截 获 对 部 分 gdi 的 api 调 用 来 实 现 , 如
textout,textouta 等。
第二种:对每个设备上下文(dc)做一分 copy,并跟踪所有修改上下
文(dc)的操作。
第二种方法更强大,但兼容性不好,而第一种方法使用的截获
windowsapi 的调用,这项技术的强大可能远远超出了您的想象,
毫不夸张的说,利用 windowsapi 拦截技术,你可以改造整个操
作系统,事实上很多外挂式 windows 中文平台就是这么实现的!
而这项技术也正是这篇文章的主题。
截 windowsapi 的调用,具体的说来也可以分为两种方法:
第一种方法通过直接改写 winapi 在内存中的映像,嵌入汇编代
码,使之被调用时跳转到指定的地址运行来截获;第二种方法则
改写 iat(import address table 输入地址表),重定向 winapi 函数
的调用来实现对 winapi 的截获。
第一种方法的实现较为繁琐,而且在 win95、98 下面更有难度,
这是因为虽然微软说 win16 的 api 只是为了兼容性才保留下来,
程序员应该尽可能地调用 32 位的 api,实际上根本就不是这样!
win 9x 内部的大部分 32 位 api 经过变换调用了同名的 16 位 api,

也就是说我们需要在拦截的函数中嵌入 16 位汇编代码!
我们将要介绍的是第二种拦截方法,这种方法在 win95、98 和 nt
下面运行都比较稳定,兼容性较好。由于需要用到关于 windows
虚拟内存的管理、打破进程边界墙、向应用程序的进程空间中注
入代码、pe(portable executable)文件格式和 iat(输入地址表)
等较底层的知识,所以我们先对涉及到的这些知识大概地做一个
介绍,最后会给出拦截部分的关键代码。
先说 windows 虚拟内存的管理。windows9x 给每一个进程分配了
4gb 的地址空间,对于 nt 来说,这个数字是 2gb,系统保留了 2gb
到 4gb 之间的地址空间禁止进程访问,而在 win9x 中,2gb 到 4gb
这部分虚拟地址空间实际上是由所有的 win32 进程所共享的,这
部分地址空间加载了共享 win32 dll、内存映射文件和 vxd、内存
管理器和文件系统码,win9x 中这部分对于每一个进程都是可见
的,这也是 win9x 操作系统不够健壮的原因。win9x 中为 16 位
操作系统保留了 0 到 4mb 的地址空间,而在 4mb 到 2gb 之间也
就是 win32 进程私有的地址空间,由于 每个进程的地址空间都
是相对独立的,也就是说,如果程序想截获其它进程中的 api 调
用,就必须打破进程边界墙,向其它的进程中注入截获 api 调用
的代码,这项工作我们交给钩子函数(setwindowshookex)来完
成,关于如何创建一个包含系统钩子的动态链接库,《电脑高手
杂志》在第?期已经有过专题介绍了,这里就不赘述了。所有系
统钩子的函数必须要在动态库里,这样的话,当进程隐式或显式

调用一个动态库里的函数时,系统会把这个动态库映射到这个进
程的虚拟地址空间里,这使得 dll 成为进程的一部分,以这个进
程的身份执行,使用这个进程的堆栈,也就是说动态链接库中的
代码被钩子函数注入了其它 gui 进程的地址空间(非 gui 进程,
钩子函数就无能为力了),
当包含钩子的 dll 注入其它进程后,就可以取得映射到这个进程
虚拟内存里的各个模块(exe 和 dll)的基地址,如:
hmodule hmodule=getmodulehandle(“mypro.exe”);
在 mfc 程序中,我们可以用 afxgetinstancehandle()函数来得到模块
的基地址。exe 和 dll 被映射到虚拟内存空间的什么地方是由它
们的基地址决定的。它们的基地址是在链接时由链接器决定的。
当你新建一个 win32 工程时,vc++链接器使用缺省的基地址
0x00400000。可以通过链接器的 base 选项改变模块的基地址。exe
通常被映射到虚拟内存的 0x00400000 处,dll 也随之有不同的基
地址,通常被映射到不同进程
的相同的虚拟地址空间处。
系统将 exe 和 dll 原封不动映射到虚拟内存空间中,它们在内存
中的结构与磁盘上的静态文件结构是一样的。即 pe (portable
executable) 文件格式。我们得到了进程模块的基地址以后,就可
以根据 pe 文件的格式穷举这个模块的 image_import_descriptor
数组,看看进程空间中是否引入了我们需要截获的函数所在的动
态链接库,比如需要截获“textouta”,就必须检查“gdi32.dll”是否

被引入了。说到这里,我们有必要介绍一下 pe 文件的格式,如
右图,这是 pe 文件格式的大致框图,最前面是文件头,我们不
必理会,从 pe file optional header 后面开始,就是文件中各个段
的说明,说明后面才是真正的段数据,而实际上我们关心的只有
一个段,那就是“.idata”段,这个段中包含了所有的引入函数信息,
还有 iat(import address table)的 rva(relative virtual address)地
址。
说到这里,截获 windowsapi 的整个原理就要真相大白了。实际
上所有进程对给定的 api 函数的调用总是通过 pe 文件的一个地
方来转移的,这就是一个该模块(可以是 exe 或 dll)的“.idata”段中
的 iat 输入地址表(import address table)。在那里有所有本模块调
用的其它 dll 的函数名及地址。对其它 dll 的函数调用实际上只是
跳转到输入地址表,由输入地址表再跳转到 dll 真正的函数入口。
具体来说,我们将通过 image_import_descriptor 数组来访问“.idata”
段中引入的 dll 的信息,然后通过 image_thunk_data 数组来针对
一个被引入的 dll 访问该 dll 中被引入的每个函数的信息,找到我
们需要截获的函数的跳转地址,然后改成我们自己的函数的地
址……具体的做法在后面的关键代码中会有详细的讲解。
讲了这么多原理,现在让我们回到“鼠标屏幕取词”的专题上来。
除了 api 函数的截获,要实现“鼠标屏幕取词”,还需要做一些其
它的工作,简单的说来,可以把一个完整的取词过程归纳成以下
剩余17页未读,继续阅读
资源评论

oligaga
- 粉丝: 20
- 资源: 2万+

上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助

会员权益专享
安全验证
文档复制为VIP权益,开通VIP直接复制
