金山词霸”屏幕取词技术揭密(讨论稿)

这篇文章最早是发在北极星论坛的一系列帖子,那时候闻怡洋(好像他也是MVP)也在那里混
原始的帖子我已经没有了,但不知道是谁帮我收集整理了下来(非常感谢),我用google找到了
?
这是我进金山之前写的,应该不算泄露公司技术秘密吧
而且这些现在看来似乎已经有些过时了
?
那时讨论的只是Win31和Win9x下的取词实现
?
我到了金山之后不是负责取词模块,而是做UI,因为有个家伙比我更擅长做这种东西
他用SoftIce调试汇编代码非常熟练,做逆向工程方面有过人的天分。
?
?
“亦东” 是我那时的笔名
?
?
“金山词霸”屏幕取词技术揭密(讨论稿)
?
主题  屏幕取词技术系列讲座(一)
作者   亦东
很多人对这个问题感兴趣。
原因是这项技术让人感觉很神奇,也很有商业价值。
现在词典市场金山词霸占了绝对优势,所以再做字典也没什么前途了。我就是这么认为的,所以我虽然掌握了这项技术,却没去做字典软件。只做了一个和词霸相似的软件自己用,本来想拿出来做共享软件,但我的词库是“偷”来的,而且词汇不多,所以也就算了,词库太小,只能取词有什么用呢?而且词霸有共享版的。
但既然很多人想了解这项技术,我也不会保留。我准备分多次讲述这项技术的所有细节。
大约每周一两次。想知道的人就常常来看看吧!
一.基础知识
首先想编这种程序需要一些基础知识。
会用Vc++,包括16/32位。
精通Windows API特别是GDI,KERNEL部分。
懂汇编语言,会用softice调试程序,因为这种程序最好用softice调试。
二.基本原理
在Window 3.x时代,windows系统提供的字符输出函数只有很少的几个。
TextOut
ExtTextOut
DrawText
......
其中DrawText最终是用ExtTextOut实现的。
所以Windows的所有字符输出都是由调用TextOut和ExtTextOut实现的。因此,如果你可以修改这两个函数的入口,让程序先调用你自己的一个函数再调用系统的字符输出,你就可以得到Windows所有输出的字符了。
到了Windows95时代,原理基本没变,但是95比3.x要复杂。开始的时候,一些在windows3.x下编写的取词软件仍然可以是使用。但是后来出了个IE4,结果很多词典软件就因为不支持IE4而被淘汰了,但同时也给一些软件创造了机会,如金山词霸。其实IE4的问题并不复杂,只不过它的输出的是unicode字符,是用TextOutW和ExtTextOutW输出的。知道了这一点,只要也截取就可以了。不过实现方法复杂一点,以后会有详细讲解。现在又出了个IE5,结果词霸也不好用了,微软真是 #^@#$%$ *&^&#@#@..........
我研究后找到了一种解决办法,但还有些问题,有时会取错,正在继续研究,希望大家共同探讨。
另外还有WindowsNT,原理也是一样,只是实现方法和95下完全不同。
三.技术要点
要实现取词,主要要解决以下技术问题。
1.截取API入口,获得API的参数。
2.安全地潜入Windows内部,良好地兼容Windows的各个版本
3.计算鼠标所在的单词和字母。
4.如果你在Window95下,做32位程序,还涉及Windows32/16混合编程的技术。
今天先到这里吧!最好准备一份softice for 95/98和金山词霸,让我们先来分析一下别人是怎么做的。
欢迎与我联系
E-Mail:yeedong@163.net
主题  屏幕取词技术系列讲座(二)
作者   亦东
很抱歉让大家久等了!
我看了一些人的回帖,发现很多人对取词的原理还是不太清楚。
首先我来解释一下hook问题。词霸中的确用到了hook,而且他用了两种hook其中一种是Windows标准hook,通过SetWindowHook安装一个回调函数,它安装了一个鼠标hook,是为了可以及时响应鼠标的消息用的和取词没太大关系。
另一种钩子是API钩子,这才是取词的核心技术所在。他在TextOut等函数的开头写了一个jmp语句,跳转到自己的代码里。
你用softice看不到这个跳转语句是因为它只在取词的一瞬间才存在,平时是没有的。
你可以在TextOut开头设一个读写断点
bpm textout
再取词,就会找到词霸用来写钩子的代码了。
/**********************************
所以我在次强调,想学这种技术一定要懂汇编语言和熟练使用softice.
**********************************/
至于从cjktl95中dump出来的未公开函数是和Windows32/16混合编程有关的,以后我会提到他们。
我先来讲述取词的过程,
0 判断鼠标是否在一个地方停留了一段时间
1 取得鼠标当前位置
2 以鼠标位置为中心生成一个矩形
3 挂上API钩子
4 让这个矩形产生重画消息
5 在钩子里等输出字符
6 计算鼠标在哪个单词上面,把这个单词保存下来
7 如果得到单词则摘掉API钩子,在一段时间后,无论是否得到单词都摘掉API钩子
8 用单词查词库,显示解释框。
很多步骤实现起来都有一些难度,所以在中国可以做一个完善的取词词典的人屈指可数。
其中0,1,2,7,8比较简单就不提了。
先说如何挂钩子:
所谓钩子其实就是在WindowsAPI入口写一个JMP XXXX:XXXX语句,跳转到自己的代码里。
步骤如下:
1.取得Windows API入口,用GetProcAddress实现
2.保存API入口的前五个字节,因为JMP是0xEA,地址是4个字节
3.写入跳转语句
这步最复杂
Windows的代码段本来是不可以写的,但是Microsoft给自己留了个后门。
有一个未公开函数是AllocCsToDsAlias,
UINT WINAPI ALLOCCSTODSALIAS(UINT);
你可以取到这个函数的入口,把API的代码段的选择符(要是不知道什么是选择符,就先去学学保护模式编程吧)传给他,他会返回一个可写的数据段选择符。这个选择符用完要释放的。用新选择符和API入口的偏移量合成一个指针就可以写windows的代码段了。
这就是取词技术的最核心的东东,不止取词,连外挂中文平台全屏汉化都是使用的这种技术。现在知道为什么这么简单的几句话却很少知道了吧?因为太多的产品使用他,太多的公司靠他赚钱了。
这些公司和产品有:中文之星,四通利方,南极星,金山词霸,实达铭泰的东方快车,roboword,译典通,即时汉化专家等等等等。。。。还有至少20多家小公司。他们的具体实现虽然不同,但大致原理是相同的。
我这些都是随手写的,也没有提纲之类的东西,以后如果有机会我会整理一下,大家先凑合着看吧!xixi...
?
主题  关于屏幕取词的讨论(三)
作者   亦东

让大家久等,很抱歉,前些时候工作忙硬盘又坏了,太不幸了。
这回来点真格的。
咱们以截取TextOut为例。
下面是代码:
//截取TextOut
typedef UINT (WINAPI* ALLOCCSTODSALIAS)(UINT);
ALLOCCSTODSALIAS AllocCsToDsAlias;
BYTE NewValue[5];//保存新的入口代码
BYTE OldValue[5];//API原来的入口代码
unsigned char * Address=NULL;//可写的API入口地址
UINT DsSelector=NULL;//指向API入口的可写的选择符
WORD OffSetEntry=NULL;//API的偏移量
BOOL bHookAlready = FALSE; //是否挂钩子的标志
BOOL InitHook()
{
HMODULE hKernel,hGdi;
hKernel = GetModuleHandle("Kernel");
if(hKernel==NULL)
return FALSE;
AllocCsToDsAlias = (ALLOCCSTODSALIAS)GetProcAddress(hKernel,"AllocCsToDsAlias");//这是未公开的API所以要这样取地址
if(AllocCsToDsAlias==NULL)
return FALSE;
hGdi = GetModuleHandle("Gdi");
if(hmGdi==NULL)
return FALSE;
FARPROC Entry = GetProcAddress(hGdi,"TextOut");
if(Entry==NULL)
return FALSE;
OffSetEntry = (WORD)(FP_OFF(Entry));//取得API代码段的选择符
DsSelector = AllocCsToDsAlias(FP_SEG(Entry));//分配一个等同的可写的选择符
Address = (unsigned char*)MK_FP(DsSelector,OffSetEntry);//合成地址
NewValue[0]=0xEA;
*((DWORD*)(NewValue+1)) = (DWORD)MyTextOut;
OldValue[0]=Address[0];
*((DWORD*)(OldValue+1)) = *((DWORD*)(Address+1));
}
BOOL ClearHook()
{
if(bHookAlready)
HookOff();
FreeSelector(DsSelector);
}
BOOL HookOn()
{
if(!bHookAlready){
for(int i=0;i<5;i++){
Address[i]=NewValue[i];
}
bHookAlready=TRUE;
}
}
BOOL HookOff()
{
if(bHookAlready){
for(int i=0;i<5;i++){
Address[i]=OldValue[i];
}
bHookAlready=FALSE;
}
}
//钩子函数,一定要和API有相同的参数和声明
BOOL WINAPI MyTextOut(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,UINT cbString)
{
BOOL ret;
HookOff();
ret = TextOut(hdc,nXStart,nYStart,lpszString,cbString);//调原来的TextOut
HookOn();
return ret;
}
上面的代码是一个最简单的挂API钩子的例子,我要提醒大家的是,这段代码是我凭记忆写的,我以前的代码丢了,我没有编译测试过
因为我没有VC++1.52.所以代码可能会有错。
建议使用Borland c++,按16位编译。
如果用VC++1.52,则要改个选项
在VC++1.52的Option里,有个内存模式的设置,选大模式,和"DS!=SS DS Load on Function entry.",切记,否则会系统崩溃。
有什么不明白的可以给我写信
yeedong@163.net

关于屏幕取词的问题(转)相关推荐

  1. 【Linux】ubuntu下词典软件Goldendict介绍(可屏幕取词)和StarDict(星际译王)的安装...

    转载自:http://emuch.net/html/201012/2730970.html GoldenDict 是一款不错的.与 StarDict(星际译王)类似的词典软件.它使用 WebKit 作 ...

  2. [IE9] 开发IE9上的屏幕取词功能

    "屏幕取词"是词典软件(如:金山词霸)里面一个必要功能. 在IE9中,由于使用Direct2D接口取代GDI做页面渲染,原来基于GDI接口的屏幕取词技术将无法继续正常工作. 因此, ...

  3. 金山词霸”屏幕取词技术揭密(讨论稿)

    金山词霸"屏幕取词技术揭密(讨论稿) 主题 屏幕取词技术系列讲座(一) 作者 亦东 很多人对这个问题感兴趣. 原因是这项技术让人感觉很神奇,也很有商业价值. 现在词典市场金山词霸占了绝对优势 ...

  4. 火狐用有道词典不能屏幕取词的解决办法

    2019独角兽企业重金招聘Python工程师标准>>> 1 取消火狐浏览器自动使用硬件加速功能 2 有道词典安装OCR插件强力屏幕取词功能 转载于:https://my.oschin ...

  5. c# 实现金山词霸一样的屏幕取词

    c# 屏幕取词想做金山词霸一样的屏幕取词 告诉你两个方法: 第一: 在金山词霸中2005中带了一个XdictGrb.dll,添加引用 然后下面是代码 using System; using Syste ...

  6. 关于金山词霸的屏幕取词1

    "金山词霸"屏幕取词技术揭密(讨论稿) (17千字) 发信人:5,555 时 间:2001-11-1 9:30:12 详细信息: "金山词霸"屏幕取词技术揭密( ...

  7. 解决金山词霸和有道词典不能对pdf文档屏幕取词的方法

    解决金山词霸和有道词典不能对pdf文档屏幕取词的方法 http://www.docin.com/p-14101033.html

  8. python屏幕取词_GetWord 3.3 屏幕取词

    1. 缘起 要搞一个作弊软件,需要把屏幕上的试题取下来. 据说针对IE的取词很难,所以也就打消了自己开发的念头,找一找好用的控件. 发现了两个可以用的,一个是金山词霸的XdictGrb.dll文件,一 ...

  9. PDF转Word+转Html+英文论文轻松翻译+屏幕取词

    分享一个编辑PDF,PDF转格式,一键翻译PDF论文的好办法.今天的分享,对于需要阅读大量英文文献,或者需要对PDF文件进行更高阶操作的朋友都是非常有用的.我觉得是属于超级干货了.如果你觉得我的分享不 ...

  10. Word 2010也可以屏幕取词翻译

            Word 2010的屏幕取词翻译就像是一个迷你版词霸,不仅能做到即点即译,而且支持单词和短语发音 在早期的Word版本中就有不错的翻译功能,能够实现简单的中英文互译,而Word 201 ...

最新文章

  1. 快速区域积分直方图实现
  2. 九零后程序员心塞大哭:“我累的心脏疼,父母却说我工作很轻松”
  3. [2020.11.4NOIP模拟赛]简单的打击【NTT】
  4. HTML列表内容自动排序,JS实现HTML表格排序功能
  5. 普通用户的sudo权限,禁止root用户登录
  6. 计算机网络英文题库,强烈推荐计算机网络英文试题库(附答案)chapter.doc
  7. 【声学基础】概述——振动学
  8. ffmpeg 2.6.3在Linux下的编译
  9. wxpython textctrl_如何从wxpython中的textctrl接受值
  10. android 底部去除list渐变,layer-list渐变色的处理
  11. sql 列转行_转行数据分析师如何开始学习SQL | 工科生三个月转行数据分析学习心得...
  12. 一句话道破X64和X86的区别
  13. 安卓手机玩游戏卡顿怎么解决_安卓手机卡顿如何解决?教你四招,流畅度立刻飙升!...
  14. Win10家庭版中文用户名改英文用户名方法(亲测管用)
  15. PTA团体程序设计天梯赛-练习集(3)
  16. 信号处理--常用术语
  17. spark-shuffle
  18. xamarin android 微信,转换微信SDK为Xamarin绑定库 Android5.5.8 iOS1.8.6.2
  19. syscall常量解释(持续完善中)
  20. 如何使用《背景音乐提取器》提取歌曲中的背景音乐

热门文章

  1. 终端电阻对CAN总线的影响
  2. 在微信浏览器中做分享到朋友圈和分享到好友
  3. 【UCIe】UCIe 软件配置
  4. 如何更新或回刷BIOS
  5. Spark RDD案例(五)经纬度转换为地理位置
  6. 介绍5款热门的Chat GPT应用,总有适合你的一款
  7. 建筑图纸设计加密软件在规划设计行业的应用价值
  8. 独立开发变现周刊(第39期):在线表情包生成器,月流览量1千2百万
  9. vue admin后台管理系统快速开发源码/模板文档
  10. ip和端口号的正则表达式