您的位置:逆风者 VC++ 正文
 添加时间:2007-09-01 原文发表:2007-08-31 人气:141 来源:vckbase.com

本文章共2572字,分2页,当前第1页,快速翻页:
 

如何获取其它进程中窗口的窗口过程

作者:耿海增

下载源代码
逆风者

开发环境: Windows XP VC6 Platform SDK 或者 VS.NET 2003
测试环境: Windows XP

  曾经以为获取一个窗口的窗口过程很简单,不就是GetWindowLong一下吗,看spyxx获取的多么顺利。后来才发现原来不是这么简单。获取本进程内窗口的窗口过程确实很简单 ,直接调用GetWindowLong(hWnd,GWL_WNDPROC)就可以了(注意,根据窗口是否是Unicode的,你要判断是调用GetWindowLongA,还是GetWindowLongW,可以用IsWindowUnicode来判断), 但是GetWindowLong这个函数内部会检查调用进程和该窗口句柄是否属于同一进程,如果不是,就简单的返回0了。
  既然这样,我们又不能去修改GetWindowLong,那就只有想办法让它认为我们和那个窗口是在一个进程里了。回想起Windows核心编程里讲过,通过创建远程线程的方式 ,可以在其它进程内创建一个新的线程,并且可以指定这个线程的线程函数 。因为Windows的进程之间的地址相互之间是不可见的,所以我们不能指定本地的线程函数,而要在远程分配内存,把我们要做的事情以机器码的形式写进去。

  (spyxx是怎么做的呢?它启动时安装了一个全局的钩子WH_GETMESSAGE,这样,几乎所有有消息循环的程序都会加载它的hook dll,从而可以在其它进程的地址空间里调用GetWindowLong,如果我们仅仅为了获取一下窗口过程装一个全局钩子,未免有点儿太浪费了:))

先来分析一下我们的线程函数都需要做什么。

  首先,需要调用GetWindowLong获取这个窗口的窗口过程,然后要告诉我们。可以用PostMessage或者PostThreadMessage的方式通知我们的程序 。具体如下所示:

//hWndTarget是我们要获取其窗口过程的窗口句柄, 假设 hWndTarget = 0x12345678

//dwThreadId是我们的线程Id                    ,假设 dwThreadId = 0x5678

LONG wndProc = GetWindowLong(hWndTarget,GWL_WNDPROC);

PostThreadMessage(dwThreadId,WM_MYMESSAGE,(WPARAM)hWndTarget,(LPARAM)wndProc);

因为这个时候函数的参数我们都已经知道了,所以可以直接硬编码到程序里。先看一下GetWindowLongA的函数原型:

WINUSERAPI LONG WINAPI GetWindowLongA( HWND hWnd, int nIndex)

一共有两个参数,我们的 GetWindowLongA(hWnd,GWL_WNDPROC)函数调用的汇编代码大概就是这个样子(右边是响应的机器码):

//参数入栈的顺序是从右向左,所以先pushnIndex,然后是pushhWnd

push0xFC                //6AFC             //GWL_WNDPROC的值是-4,写成16进制就是0xFC

pushhWndTarget          //5878563412     //假设hWndTarget=0x12345678

callGetWindowLongA      //E8(GetWindowLongA-下一条指令的地址)

  GetWindowLongA函数的返回值在eax寄存器里,我们的PostThreadMessageA函数里用wParam参数发送该窗口句柄,用lParam参数发送该窗口的窗口过程 ,所以push lParam 就是 push eax

再来看看PostThreadMessageA的函数原型:

WINUSERAPI BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam)

PostThreadMessageA函数调用的汇编代码如下:

//Msg是我们自定义的消息,假设Msg=0x1234

pushlParam                 //pusheax        //50

pushwParam             //pushhWndTarget  //5878563412            //假设hWndTarget=0x12345678

pushMsg                                     //5834120000            //假设Msg=0x1234

pushdwThreadId                              //5878560000            //假设dwThreadId=0x5678

callPostThreadMessageA                   //E8(PostThreadMessageA-下一条指令的地址)

 
 
本文章更多内容1 - 2 - 下一页>>
相关文章

深入 CSocket 编程之阻塞和非阻塞模式
如何获取网页中的密码和文本输入框的内容
OAL点点滴滴(二)
WTL字体类
介绍一个控制并行端口的MFC类
.NET Remoting与分布式应用开发——初识 Re
浅析三线程程序开发思路与实现
带光圈文字输出的实现
WinCE4.2 下轻松调用 Windows Media Player
C 类对象的拷贝构造函数
OAL点点滴滴(一)
精通VC与MATLAB联合编程<十>——综合举例二
如何播放 WAV 文件?
一个原创的仪表控件
WHO AM I?看定自己的耕垦区域
使用MFC的数组类
乱砍设计模式之零
通过异步程序调用(APC)实现的定时功能
视频采集
创建客户区窗口,列表框之间项的拖拽操作

相关评论


本文章所属分类:首页 VC++

  热门关键字: