安全矩阵

 找回密码
 立即注册
搜索
查看: 6572|回复: 0

网络安全编程:Windows消息机制

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2021-1-16 21:42:26 | 显示全部楼层 |阅读模式
原文链接:网络安全编程:Windows消息机制

Windows是一个庞大而复杂的操作系统,它提供了丰富而强大的功能,不但操作灵活方便,而且有众多的应用软件对其进行支持。Windows因有众多软件的支持,从而长期雄霸于PC系统。之所以有众多软件的支持,是因为Windows提供了良好的应用程序开发平台(接口)、完整的开发文档和各种优秀的开发环境。对于一个程序员来说,除了要掌握基本的开发语言以外,还要掌握具体的开发环境和系统平台的相关知识;在掌握编程语言和开发环境等知识后,还要掌握调试技术以及各种调试分析工具。同样,Windows操作系统提供了良好的调试接口,并且有非常多的调试工具。

大部分Windows应用程序都是基于消息机制的(命令行下的程序并不基于消息机制),熟悉Windows操作系统的消息机制是掌握Windows操作系统下编程的基础。

01 对消息的演示测试

在真正学习和认识消息之前,先来完成一个简单的任务,看看消息能完成什么样的工作。首先写一个简单的程序,通过编写的程序发送消息来关闭记事本的进程、获取窗口的标题和设置窗口的标题。

程序的具体代码如下:


  1. void CMsgTestDlg::OnClose()
  2. {
  3.   // 在此处添加处理程序代码
  4.   HWND hWnd = ::FindWindow("Notepad", NULL);
  5.   if ( hWnd == NULL )
  6.   {
  7.     AfxMessageBox("没有找到记事本");
  8.     return ;
  9.   }
  10. ::SendMessage(hWnd, WM_CLOSE, NULL, NULL);
  11. }
  12. void CMsgTestDlg::OnExec()
  13. {
  14.   // 在此处添加处理程序代码
  15.   WinExec("notepad.exe", SW_SHOW);
  16. }
  17. void CMsgTestDlg::OnEditWnd()
  18. {
  19.   // 在此处添加处理程序代码
  20.   HWND hWnd = ::FindWindow(NULL, "无标题 - 记事本");
  21.   if ( hWnd == NULL )
  22.   {
  23.     AfxMessageBox("没有找到记事本");
  24.     return ;
  25.   }
  26.   char *pCaptionText = "消息测试";
  27.   ::SendMessage(hWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)pCaptionText);
  28. }
  29. void CMsgTestDlg::OnGetWnd()
  30. {
  31.   // 在此处添加处理程序代码
  32.   HWND hWnd = ::FindWindow("Notepad", NULL);
  33.   if ( hWnd == NULL )
  34.   {
  35.     AfxMessageBox("没有找到记事本");
  36.     return ;
  37.   }
  38.     char pCaptionText[MAXBYTE] = { 0 };
  39.     ::SendMessage(hWnd, WM_GETTEXT, (WPARAM)MAXBYTE, (LPARAM)pCaptionText);
  40.     AfxMessageBox(pCaptionText);
  41. }   
复制代码

编写的代码中有4个函数:第1个函数OnClose()是用来关闭记事本程序的;第2个函数OnExec()是用来打开记事本程序的,主要是测试其他3个函数时可以方便地打开记事本程序;第3个函数OnEditWnd()是用来修改记事本标题的;第4个函数OnGetWnd()是用来获取当前记事本标题的。程序的界面如图1所示。

​​
图1  消息测试窗口

简单测试一下这个程序。首先单击“打开记事本程序”按钮,出现记事本的窗口(表示记事本程序被打开了);接着单击“修改记事本标题”按钮,可以发现记事本程序的窗口标题改变了;再单击“获取记事本标题”按钮,弹出记事本程序窗口标题的一个对话框;最后单击“关闭记事本程序”按钮,记事本程序被关闭。

02 对“消息测试”程序代码的解释

上面的代码中要学习的API函数有两个,分别是FindWindow()和SendMessage()。下面看一下它们在MSDN中的定义。

FindWindow()函数的定义如下:

  1. HWND FindWindow(
  2. LPCTSTR lpClassName,
  3. LPCTSTR lpWindowName
  4. );
复制代码

FindWindow()函数的功能是,通过指定的窗口类名(lpClassName)或窗口标题(lpWindowName)查找匹配的窗口并返回最上层的窗口句柄。简单理解就是,通过指定的窗口名(窗口名相对于窗口类来说要直观些,因此往往使用的是窗口名)返回窗口句柄。FindWindow()函数有两个参数,分别是 lpClassName 和 lpWindowName。通过前面的描述,该函数通常使用的是第2个参数 lpWindowName,该参数是指定窗口的名称。在例子代码中,为程序指定的窗口名是“无标题—记事本”。“无标题—记事本”是记事本程序打开后的默认窗口标题,当 FindWindow()找到该窗口时,会返回它的窗口句柄。例子代码中也使用了lpClassName(窗口类名),在窗口的名称会改变的情况下,只能通过窗口类名来获取窗口的句柄了。
当使用 FindWindow()函数获取窗口句柄时,指定窗口名是比较直观和容易的。但是,如果窗口名经常发生变化时,那么就不得不使用窗口类名了。

使用FindWindow()函数返回的窗口句柄是为了给SendMessage()函数来使用的。

SendMessage()函数的定义如下:

  1. LRESULT SendMessage(
  2. HWND hWnd,
  3. UINT Msg,
  4. WPARAM wParam,
  5. LPARAM lParam
  6. );
复制代码

该函数的作用是根据指定窗口句柄将消息发送给指定的窗口。该函数有4个参数,第1个参数hWnd是要接收消息的窗口的窗口句柄,第2个参数Msg是要发送消息的消息类型,第3个参数wParam和第4个参数lParam是消息的两个附加参数。第1个参数hWnd在前面已经介绍过了,该参数通过FindWindow()函数获取。


在程序的代码中,SendMessage()函数的第2个参数分别使用的了WM_CLOSE消息、WM_SETTEXT消息和WM_GETTEXT消息。下面来看这3个消息的具体含义。

WM_CLOSE:将 WM_CLOSE 消息发送后,接收到该消息的窗口或应用程序将要关闭。WM_CLOSE 消息没有需要的附加参数,因此 wParam 和 lParam 两个参数都为 NULL。

WM_SETTEXT:应用程序发送 WM_SETTEXT 消息对窗口的文本进行设置。该消息需要附加参数,wParam 参数未被使用,必须指定为 0 值,lParam 参数是一个指向以 NULL 为结尾的字符串的指针。

WM_GETTEXT:应用程序发送 WM_GETTEXT 消息,将对应窗口的文本复制到调用者的缓冲区中。该消息也需要附加参数,wParam 参数指定要复制的字符数数量,lParam 是接收文本的缓冲区。

例子代码在VC6下进行编译连接,生成可执行文件后,可以通过按钮的提示进行测试,以便大家感性认识消息的作用。

03 如何获取窗口的类名称

编写程序调用FindWindow()函数的时候,通常会使用其第2个参数,也就是窗口的标题。但是有些软件的窗口标题会根据不同的情况进行改变,那么程序中就不能在FindWindow()函数中直接通过窗口的标题来获得窗口的句柄了。而窗口的类名通常是不会变的,因此编程时可以指定窗口类名来调用FindWindow()函数以便获取窗口句柄。那么,如何能获取到窗口的类名称呢?这就是下面要介绍的第1个开发辅助工具——Spy++。

Spy++是微软Visual Studio中提供的一个非常实用的小工具,它可以显示系统的进程、窗口等之间的关系,可以提供窗口的各种信息,可以对系统指定的窗口进行消息的监控等。它的功能非常多,这里演示如何用它来获取窗口的类名称。

打开“开始”菜单,在Visual Studio的菜单路径下找到Spy++,打开Spy++窗口,如图2所示。

图2  “Microsoft Spy++”窗口

选择工具栏中的“Find Window”按钮,如图3所示。

图3  “Find Window”按钮

单击“Find Window”按钮,出现如图4所示的窗口。

图4  Find Window窗口

在图4中,用鼠标左键单击“Finder Tool”后面的图标,然后拖曳到指定的窗口上,会显示出“Handle”(窗口句柄)“Caption”(窗口标题)和“Class”(窗口类名),其中“Class”是编程时要使用的“窗口类”名称。

“Hide Spy++”是一个比较实用的功能,它用来隐藏 Spy++主窗口界面。选中该复选框后,拖曳“Finder Tool”后的图标时,图2所示为窗口将被隐藏。这个功能的实用之处在于,有些应用软件有反Spy++的功能,隐藏 Spy++ 主窗口有助于避免被反Spy++的软件检测到。为什么隐藏 Spy++的“Find Window”窗口会有反检测的功能,反检测的原理是什么?原理很简单,目标程序也是通过调用 FindWindow()函数来查找 Spy++窗口的,如果有该窗口,就进行一些相应的处理。

通过Spy++找到的窗口句柄是不能在编程中使用的,每次打开窗口时,窗口的句柄都会改变。

将“Finder Tool”后的图标拖曳到记事本的标题处,Spy++的Find Window窗口显示的内容如图5所示。

图5  获取到信息的Find Window窗口

从图5中可以得到记事本程序的标题和类名称。当编写程序调用FindWindow()函数,不能通过程序的标题文本得到窗口的句柄时,可以通过窗口类名称得到窗口的句柄。

微信公众号:计算机与网络安全









回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-9-20 19:53 , Processed in 0.025070 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表