谁有类似金山词霸一样的屏幕抓词的示例?(100分)

  • 主题发起人 主题发起人 舟舶通
  • 开始时间 开始时间

舟舶通

Unregistered / Unconfirmed
GUEST, unregistred user!
分少了点吧
 
我以前有,现在很难找了
 
to 小天:还可以加100分。<br>
 
哈哈,好东东,先放上来先。<br>可能大家要不到我的分了!<br><br><br>屏幕抓词的技术实现 (2001年6月13日) <br><br>本站更新 &nbsp;分类:系统 &nbsp; 作者: &nbsp;推荐: &nbsp; 阅读次数:201 &nbsp;<br>(http://www.tommstudio.com) &nbsp;<br><br>--------------------------------------------------------------------------------<br><br>  屏幕上的文字大都是由gdi32.dll的以下几个函数显示的:TextOutA、TextO <br><br>utW、ExtTextOutA、 <br>ExtTextOutW。实现屏幕抓词的关键就是截获对这些函数的调用,得到程序发给他 <br><br>们的参数。 <br><br>  我的方法有以下三个步骤: <br><br>  一、得到鼠标的当前位置 <br><br>  通过SetWindowsHookEx实现。 <br><br>  二、向鼠标下的窗口发重画消息,让它调用系统函数重画 <br><br>  通过WindowFromPoint,ScreenToClient,InvalidateRect 实现。 <br><br>  三、截获对系统函数的调用,取得参数(以TextOutA为例) <br><br>  1.仿照TextOutA作成自己的函数MyTextOutA,与TextOutA有相同参数和返回 <br><br>值,放在系统钩子所在 <br>的DLL里。 <br><br>  SysFunc1=(DWORD)GetProcAddress(GetModuleHandle("gdi32.dll"),"TextO <br><br>utA"); <br><br>  BOOL WINAPI MyTextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR l <br><br>pszString,int cbString) <br><br>  { //输出lpszString的处理 <br><br>return ((FARPROC)SysFunc1)(hdc,nXStart,nYStart,lpszString,cbString);} <br><br><br><br>  2.由于系统鼠标钩子已经完成注入其它GUI进程的工作,我们不需要为注入再 <br><br>做工作。 <br><br>  如果你知道所有系统钩子的函数必须要在动态库里,就不会对“注入”感到 <br><br>奇怪。当进程隐式或显式 <br>调用一个动态库里的函数时,系统都要把这个动态库映射到这个进程的虚拟地址 <br><br>空间里(以下简称“地址空 <br>间”)。这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的 <br><br>堆栈(见图1)。 <br><br><br>  图1 DLL映射到虚拟地址空间中 <br><br>  对系统钩子来说,系统自动将包含“钩子回调函数”的DLL映射到受钩子函数 <br><br>影响的所有进程的地址 <br>空间中,即将这个DLL注入了那些进程。 <br><br>  3.当包含钩子的DLL注入其它进程后,寻找映射到这个进程虚拟内存里的各个 <br><br>模块(EXE和DLL)的 <br>基地址。EXE和DLL被映射到虚拟内存空间的什么地方是由它们的基地址决定的。 <br><br>它们的基地址是在链接 <br>时由链接器决定的。当你新建一个Win32工程时,VC++链接器使用缺省的基地址 <br><br>0x00400000。可以通 <br>过链接器的BASE选项改变模块的基地址。EXE通常被映射到虚拟内存的0x0040000 <br><br>0处,DLL也随之有 <br>不同的基地址,通常被映射到不同进程的相同的虚拟地址空间处。 <br><br>  如何知道EXE和DLL被映射到哪里了呢? <br><br>  在Win32中,HMODULE和HINSTANCE是相同的。它们就是相应模块被装入进程的 <br><br>虚拟内存空间的 <br>基地址。比如: <br><br>  HMODULE hmodule=GetModuleHandle(″gdi32.dll″); <br><br>  返回的模块句柄强制转换为指针后,就是gdi32.dll被装入的基地址。 <br><br>  关于如何找到虚拟内存空间映射了哪些DLL?我用如下方式实现: <br><br>while(VirtualQuery (base, &mbi, sizeof (mbi))〉0) <br><br>{ if(mbi.Type==MEM-IMAGE) <br><br>ChangeFuncEntry((DWORD)mbi.BaseAddress,1); <br><br>base=(DWORD)mbi.BaseAddress+mbi.RegionSize; } <br><br>  4.得到模块的基地址后,根据PE文件的格式穷举这个模块的IMAGE-IMPORT- <br><br>DESCRIPTOR数组, <br>看是否引入了gdi32.dll。如是,则穷举IMAGE-THUNK-DATA数组,看是否引入了 <br><br>TextOutA函数。 <br><br>  5.如果找到,将其替换为相应的自己的函数。 <br><br>  系统将EXE和DLL原封不动映射到虚拟内存空间中,它们在内存中的结构与磁 <br><br>盘上的静态文件结构 <br>是一样的。即PE (Portable Executable) 文件格式。 <br><br>  所有对给定API函数的调用总是通过可执行文件的同一个地方转移。那就是一 <br><br>个模块(可以是EXE或 <br>DLL)的输入地址表(import address table)。那里有所有本模块调用的其它DLL的 <br><br>函数名及地址。对其它DLL <br>的函数调用实际上只是跳转到输入地址表,由输入地址表再跳转到DLL真正的函数 <br><br>入口。例如: <br><br><br>  图2 对MessageBox()的调用跳转到输入地址表,从输入地址表再跳转到Mess <br><br>ageBox函数 <br><br><br><br>  IMAGE-IMPORT-DESCRIPTOR和IMAGE-THUNK-DATA分别对应于DLL和函数。 <br><br>它们是PE <br>文件的输入地址表的格式(数据结构参见winnt.h)。 <br><br>  BOOL ChangeFuncEntry(HMODULE hmodule) <br><br>  { PIMAGE-DOS-HEADER pDOSHeader; <br><br>  PIMAGE-NT-HEADERS pNTHeader; <br><br>  PIMAGE-IMPORT-DESCRIPTOR pImportDesc; <br><br>/?get system functions and my functions′entry?/ <br><br>  pSysFunc1=(DWORD)GetProcAddress(GetModuleHandle(″gdi32.dll″),″T <br><br>extOutA″); <br><br>  pMyFunc1= (DWORD)GetProcAddress(GetModuleHandle(″hookdll.dll″),″ <br><br>MyTextOutA″); <br><br>pDOSHeader=(PIMAGE-DOS-HEADER)hmodule; <br><br>  if (IsBadReadPtr(hmodule, sizeof(PIMAGE-NT-HEADERS))) <br><br>   return FALSE; <br><br>  if (pDOSHeader-〉e-magic != IMAGE-DOS-SIGNATURE) <br><br>   return FALSE; <br><br>  pNTHeader=(PIMAGE-NT-HEADERS)((DWORD)pDOSHeader+(DWORD)pDOSHead <br><br>er-〉e- <br>lfanew); <br><br>  if (pNTHeader-)Signature != IMAGE-NT-SIGNATURE) <br><br>   return FALSE; <br><br>  pImportDesc = (PIMAGE-IMPORT-DESCRIPTOR)((DWORD)hmodule+(DWORD) <br><br>pNTHeader <br>-)OptionalHeader.DataDirectory <br><br>   [IMAGE-DIRECTORY-ENTRY-IMPORT].VirtualAddress); <br><br>  if (pImportDesc == (PIMAGE-IMPORT-DESCRIPTOR)pNTHeader) <br><br>return FALSE; <br><br>  while (pImportDesc-)Name) <br><br>  { PIMAGE-THUNK-DATA pThunk; <br><br>  strcpy(buffer,(char?)((DWORD)hmodule+(DWORD)pImportDesc-)Name)) <br><br>; <br><br>CharLower(buffer); <br><br>if(strcmp(buffer,"gdi32.dll")) <br><br>{ pImportDesc++; <br><br>continue; <br><br>}else <br><br>{ pThunk=(PIMAGE-THUNK-DATA)((DWORD)hmodule+(DWORD)pImportDesc-)Fi <br><br>rstThunk); <br><br>while (pThunk-)u1.Function) <br><br>{ if ((pThunk-)u1.Function) == pSysFunc1) <br><br>{ VirtualProtect((LPVOID)(&pThunk-)u1.Function), <br><br>   sizeof(DWORD),PAGE-EXECUTE-READWRITE, &dwProtect); <br><br>   (pThunk-)u1.Function)=pMyFunc1; <br><br>   VirtualProtect((LPVOID)(&pThunk-)u1.Function), sizeof(DWORD),dw <br><br>Protect,&temp); } <br><br>pThunk++; } return 1;}}} <br><br>  替换了输入地址表中TextOutA的入口为MyTextOutA后,截获系统函数调用的 <br><br>主要部分已经完成,当 <br>一个被注入进程调用TextOutA时,其实调用的是MyTextOutA,只需在MyTextOutA <br><br>中显示传进来的字符 <br>串,再交给TextOutA处理即可。 <br>&nbsp;<br>&nbsp;<br><br><br>--------------------------------------------------------------------------------<br>
 
没那么简单,还有很多事情要处理,文字位置的识别,对各类程序的特殊处理比如ie<br>还有和已知的用类似apihook技术的程序之间的兼容,比如不和糍粑冲突。
 
mybase上有一篇文章《鼠标屏幕取词技术的原理和实现》可参考
 
在许多系统中,出于安全或其它原因,常常要求随时对键盘进行监控,一个专业的监控程序必须具备两点,一是实时;二是作为指示图标运行。实际应用中把利用Hook(即钩子)技术编写的应用程序添加到Windows的任务栏的指示区中就能够很好的达到这个目的。我在参考了API帮助文档基础上,根据在Delphi开发环境中的具体实现分别对这两部分进行详细论述。 <br><br>一、Hook(钩子)的实现: <br><br>---- Hook是应用程序在Microsoft Windows 消息处理过程中设置的用来监控消息流并且处理系统中尚未到达目的窗口的某一类型消息过程的机制。如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就不起作用;如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对系统进行监控。根据需要,我们采用的是在DLL中实现Hook的方式。 <br><br>---- 1.新建一个导出两个函数的DLL文件,在hookproc.pas中定义了钩子具体实现过程。代码如下: <br><br>library keyspy;<br>uses<br>windows, messages, hookproc in 'hookproc.pas';<br>exports<br>setkeyhook,<br>endkeyhook;<br>begin<br>nexthookproc:=0;<br>procsaveexit:=exitproc;<br>exitproc:=@keyhookexit;<br>end.<br><br>2.在Hookproc.pas中实现了钩子具体过程:<br>unit hookproc;<br>interface<br>uses<br>Windows, Messages, SysUtils, Controls, StdCtrls;<br>var<br>nexthookproc:hhook;<br>procsaveexit:pointer;<br>function keyboardhook(icode:integer;wparam:wparam;<br>lparam:lparam):lresult;stdcall;export;<br>function setkeyhook:bool;export;//加载钩子<br>function endkeyhook:bool;export;//卸载钩子<br>procedure keyhookexit;far;<br>const<br>afilename='c:/debug.txt';//将键盘输入动作写入文件中<br>var<br>debugfile:textfile;<br>implementation<br>function keyboardhookhandler(icode:integer;wparam:wparam;<br>lparam:lparam):lresult;stdcall;export;<br>begin<br>if icode&lt;0 then<br>begin<br>result:=callnexthookex(hnexthookproc,icode,wparam,lparam);<br>exit;<br>end;<br>assignfile(debugfile,afilename);<br>append(debugfile);<br>if getkeystate(vk_return)&lt;0 then<br>begin<br>writeln(debugfile,'');<br>write(debugfile,char(wparam));<br>end<br>else<br>write(debugfile,char(wparam));<br>closefile(debugfile);<br>result:=0;<br>end;<br>function endkeyhook:bool;export;<br>begin<br>if nexthookproc&lt;&gt;0 then begin<br>unhookwindowshookex(nexthookproc);<br>nexthookproc:=0;<br>messagebeep(0); end;<br>result:=hnexthookproc=0;<br>end;<br>procedure keyhookexit;far;<br>begin<br>if nexthookproc&lt;&gt;0 then endkeyhook;<br>exitproc:=procsaveexit; end;<br>end.<br>---- 二、Win95/98使用任务栏右方指示区来显示应用程序或工具图标对指示区图标的操作涉及了一个API函数Shell_NotifyIcon,它有两个参数,一个是指向TnotifyIconData结构的指针,另一个是要添加、删除、改动图标的标志。通过该函函数将应用程序的图标添加到指示区中,使其作为图标运行,增加专业特色。当程序起动后,用鼠标右键点击图标,则弹出一个菜单,可选择sethook或endhook。 <br><br>unit kb;<br>interface<br>uses<br>Windows, Messages, SysUtils, Classes,<br>Graphics, Controls, Forms,<br>Dialogs,<br>StdCtrls, Menus,shellapi;<br>const<br>icon_id=1;<br>MI_iconevent=wm_user+1;//定义一个用户消息<br>type<br>TForm1 = class(TForm)<br>PopupMenu1: TPopupMenu;<br>sethook1: TMenuItem;<br>endhook1: TMenuItem;<br>N1: TMenuItem;<br>About1: TMenuItem;<br>Close1: TMenuItem;<br>Gettext1: TMenuItem;<br>procedure FormCreate(Sender: TObject);<br>procedure sethook1Click(Sender: TObject);<br>procedure endhook1Click(Sender: TObject);<br>procedure FormDestroy(Sender: TObject);<br>procedure Close1Click(Sender: TObject);<br>private<br>{ Private declarations }<br>nid:tnotifyicondata;<br>normalicon:ticon;<br>public<br>{ Public declarations }<br>procedure icontray(var msg:tmessage); <br>message mi_iconevent;<br>end;<br>var<br>Form1: TForm1;<br>implementation<br>{$R *.DFM}<br>function setkeyhook:bool;external 'keyspy.dll';<br>function endkeyhook:bool;external 'keyspy.dll';<br><br>procedure tform1.icontray(var msg:tmessage);<br>var<br>pt:tpoint;<br>begin<br>if msg.lparam=wm_lbuttondown then<br>sethook1click(self);<br>if msg.LParam=wm_rbuttondown then<br>begin<br>getcursorpos(pt);<br>setforegroundwindow(handle);<br>popupmenu1.popup(pt.x,pt.y);<br>end;<br>end;<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>normalicon:=ticon.create;<br>application.title:=caption;<br>nid.cbsize:=sizeof(nid);<br>nid.wnd:=handle;<br>nid.uid:=icon_id;<br>nid.uflags:=nif_icon or nif_message or nif_tip;<br>nid.ucallbackmessage:=mi_iconevent;<br>nid.hIcon :=normalicon.handle;<br>strcopy(nid.sztip,pchar(caption));<br>nid.uFlags:=nif_message or nif_icon or nif_tip;<br>shell_notifyicon(nim_add,@nid);<br>SetWindowLong(Application.Handle,<br>GWL_EXSTYLE,WS_EX_TOOLWINDOW);<br>end;<br><br>procedure TForm1.sethook1Click(Sender: TObject);<br>begin<br>setkeyhook;<br>end;<br><br>procedure TForm1.endhook1Click(Sender: TObject);<br>begin<br>endkeyhook;<br>end;<br><br>procedure TForm1.FormDestroy(Sender: TObject);<br>begin<br>nid.uFlags :=0;<br>shell_notifyicon(nim_delete,@nid);<br>end;<br><br>procedure TForm1.Close1Click(Sender: TObject);<br>begin<br>application.terminate;<br>end;<br>---- 该程序虽然只用了几个shellai函数,但是它涉及到了在Delphi中对DLL的引用、钩子实现、对指示区的操作、用户定义消息的处理、文件的读写等比较重要的内容,我相信这篇文章能对许多Delphi的初学者有所帮助。 <br>---- 该程序在Win98、Delphi4.0中正常运行。 <br>
 
谢谢各位!
 
如果事情如此简单《金山词霸》就不用买钱了!<br><br>我试了2个多月都没有找出来啦。<br><br>如果有兴趣可以看看我没有完成的心得!在我的主页上<br><br>suncw.home.chinaren.com
 
有一个示例程序在《Delphi俱乐部3.0》上,我没有用过啊。你可以试一试。<br>地址:http://www.tommstudio.com/newclub30/d_excellents.asp
 
《电脑爱好者》13期上有delphi API Hook的例子。<br>
 
前不久买了《着迷词王》上面送了真正的商用的,而且可用于9x和2000的<br>原程序!可惜是VC写的,我没有看懂。很可惜啊!<br>这次这个可是货真价实的!!!!!!!!!!!!!<br>绝对没有错!<br><br>本来我想放到我的网页上可是好像又不太好,<br>如果大家有要,留言给我吧。<br><br>suncw.y365.com
 
晨晨,能否给一份,EMAIL:mypost@263.net.<br>我很想将它改用到DELPHI下。
 
有vc的,而且要做也只能用vc
 
to 小天:<br>&nbsp; 您写的MyTextOut呢?关键的地方不公开.唉唉....<br>&nbsp; 还有TextOut取代过程?
 
晨晨,请给我一份,请MAIL TO :reisher@sohu.com
 
后退
顶部