• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            金山詞霸”屏幕取詞技術揭密(討論稿)

            文章來源:http://blog.joycode.com/yaodong/articles/25506.aspx


            這篇文章最早是發在北極星論壇的一系列帖子,那時候聞怡洋(好像他也是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

            posted on 2006-08-25 00:06 楊粼波 閱讀(587) 評論(0)  編輯 收藏 引用 所屬分類: C++

            久久国产精品国产自线拍免费| 久久精品国产一区二区三区不卡| 亚洲国产精品成人久久蜜臀| 亚洲综合久久夜AV | 亚洲AV无码一区东京热久久| 久久久综合九色合综国产| 久久久久亚洲精品天堂久久久久久| 伊人久久一区二区三区无码| 久久国产精品-国产精品| 亚洲色欲久久久久综合网| 69SEX久久精品国产麻豆| 久久亚洲国产精品五月天婷| www.久久热| 久久久精品人妻一区二区三区蜜桃 | 999久久久免费国产精品播放| 欧美一级久久久久久久大片| 国产精品久久久久aaaa| 久久精品国产亚洲av麻豆图片 | 国产成人久久精品二区三区| 2021国内久久精品| 亚洲国产精品久久久久网站| 综合久久国产九一剧情麻豆| 国产日韩久久免费影院| 新狼窝色AV性久久久久久| 亚洲国产成人久久精品99| 91精品免费久久久久久久久| 欧美亚洲色综久久精品国产| 久久综合偷偷噜噜噜色| 国产亚洲美女精品久久久| 久久91亚洲人成电影网站| 久久精品aⅴ无码中文字字幕重口| 三级片免费观看久久| 久久亚洲欧洲国产综合| 久久99精品免费一区二区| 一本伊大人香蕉久久网手机| 国产精品久久久久久搜索| 久久精品国产亚洲av高清漫画| 久久亚洲精精品中文字幕| 久久亚洲AV成人无码国产| 99999久久久久久亚洲| 97久久香蕉国产线看观看|