這篇文章最早是發在北極星論壇的一系列帖子,那時候聞怡洋(好像他也是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.***
主題 螢幕取詞技術系列講座(二)
作者 亦東
很抱歉讓大家久等了!
我看了一些人的回帖,發現很多人對取詞的原理還是不太清楚。
首先我來解釋一下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 ***x:***x語句,跳轉到自己的**裡。
步驟如下:
1.取得windows api入口,用getprocaddress實現
2.儲存api入口的前五個位元組,因為jmp是0xea,位址是4個位元組
3.寫入跳轉語句
這步最複雜
windows的**段本來是不可以寫的,但是microsoft給自己留了個後門。
有乙個未公開函式是alloccstodsalias,
uint winapi alloccstodsalias(uint);
你可以取到這個函式的入口,把api的**段的選擇符(要是不知道什麼是選擇符,就先去學學保護模式程式設計吧)傳給他,他會返回乙個可寫的資料段選擇符。這個選擇符用完要釋放的。用新選擇符和api入口的偏移量合成乙個指標就可以寫windows的**段了。
這就是取詞技術的最核心的東東,不止取詞,連外掛程式中文平台全屏漢化都是使用的這種技術。現在知道為什麼這麼簡單的幾句話卻很少知道了吧?因為太多的產品使用他,太多的公司靠他賺錢了。
這些公司和產品有:中文之星,四通利方,南極星,金山詞霸,實達銘泰的東方快車,roboword,譯典通,即時漢化專家等等等等。。。。還有至少20多家小公司。他們的具體實現雖然不同,但大致原理是相同的。
?主題 關於螢幕取詞的討論(三)
作者 亦東
讓大家久等,很抱歉,前些時候工作忙硬碟又壞了,太不幸了。
這回來點真格的。
咱們以擷取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()
bool clearhook()
bool hookon()
bhookalready=true; }
}
bool hookoff()
bhookalready=false; }
}
//鉤子函式,一定要和api有相同的引數和宣告
bool winapi mytextout(hdc hdc,int nxstart,int nystart,lpcstr lpszstring,uint cbstring)
上面的**是乙個最簡單的掛api鉤子的例子,我要提醒大家的是,這段**是我憑記憶寫的,我以前的**丟了,我沒有編譯測試過
因為我沒有vc++1.52.所以**可能會有錯。
建議使用borland c++,按16位編譯。
如果用vc++1.52,則要改個選項
在vc++1.52的option裡,有個記憶體模式的設定,選大模式,和"ds!=ss ds load on function entry.",切記,否則會系統崩潰。
用金山詞霸的dll檔案實現螢幕取詞 vb
引用xdictgrb.dll,自己到詞霸目錄找。嚴重注意 要金山詞霸2005的版本中的dll,2003版的我未測試成功。新建專案,在新窗體中新增3個label,名稱預設。窗體中 如下 option explicit implements ixdictgrabsink private gp as gr...
API HOOK 金山詞霸取詞功能原理2
螢幕上的文字大都是由 gdi32.dll 的以下幾個函式顯示的 textouta textoutw exttextouta exttextoutw 實現螢幕抓詞的關鍵就是截獲對這些函式的呼叫,得到程式發給它們的引數。我的方法有以下三個步驟 一 得到滑鼠的當前位置 通過setwindowshookex...
運用金山詞霸元件開發屬於自己的螢幕取詞模組
本軟體是基於金山詞霸元件進行com開發,所以需要你的機子上要裝有金山詞霸軟體 使用金山詞霸的螢幕取詞功能 xdictgrb.dll 1 介面 1.1 grabproxy取詞 物件 function advisegrab xdictgrabsink as ixdictgrabsink as long ...