网络安全 频道

“QQ尾巴病毒”核心技术的实现

  讲到这里,我所陈述的这些事实一定会让身为读者的你说:钩子!——对,就是钩子,下面我所说的正是用钩子来真实地再现“QQ尾巴病毒”的这一技术。

 
  首先我对钩子做一个简要的介绍,已经熟悉钩子的朋友们可以跳过这一段。所谓Win32钩子(hook)并不是铁钩船长那只人工再现的手臂,而是一段子程序,它可以用来监视、检测系统中的特定消息,并完成一些特定的功能。打个比方来说,你的程序是皇帝,Windows系统充当各省的巡抚;至于钩子,则可以算是皇上的一个钦差。譬如皇帝下旨在全国收税,然后派了一个钦差找到山西巡抚说:“皇上有旨,山西除正常赋税外,加收杏花村酒十坛。”(-_-#……)正如皇帝可以用这种方法来特殊对待特定的巡抚一样,程序员也可以用钩子来捕获处理Windows系统中特定的消息。

  问题具体到了“QQ尾巴病毒”上边,就是我们需要一个钩子,在用户单击了“发送”按钮之后,粘贴我们的文本。我所实现的这段钩子过程为(至于如何挂接这个钩子,我会在稍后说明):

  // 钩子过程,监视“发送”的命令消息
  LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
  {
   CWPSTRUCT *p = (CWPSTRUCT *)lParam;
   // 捕获“发送”按钮
   if (p->message == WM_COMMAND && LOWORD(p->wParam) == 1)
   PasteText(g_hRich);
   return CallNextHookEx(g_hProc, nCode, wParam, lParam);
  }
    在此我对这个回调过程说明几点:
    1、lParam是一个指向CWPSTRUCT结构的指针,这个结构的描述如下:
  typedef struct {
   LPARAM lParam;
   WPARAM wParam;
   UINT message;
   HWND hwnd;
  } CWPSTRUCT, *PCWPSTRUCT;

  这时候像我一样的SDK fans也许会会心一笑:这不是窗口回调的那四个铁杆参数么?如你所说,的确是这样,你甚至可以使用switch (p->message) { /* ... */ }这样的代码写成的钩子函数来全面接管QQ窗口。

  2、g_hRich是一个全局变量,它保存的是QQ消息文本框的句柄。这里之所以采用全局变量,是因为我无法从键盘钩子回调函数的参数中获得这个句柄。至于如何获得这个句柄以及这个全局变量的特殊位置,我会在稍后说明。

  3、CallNextHookEx是调用钩子链中的下一个处理过程,换了钦差就会说:“十坛杏花村酒本钦差已经替皇上收下了,现在请巡抚大人把贵省正常的赋税交上来吧。”(-_-#……)这是书写钩子函数中很重要的一个环节,如果少了这一句,那么可能会导致系统的钩子链出现错误,某些程序也会没有响应——事实上我在编写这个仿真程序的时候QQ就当掉了几回。

  4、你也许会问为什么我捕获的是WM_COMMAND消息,这个原因让我来用下面的SDK代码(虽然QQ是用MFC写的,但是用SDK代码才能说明WM_COMMAND和“发送”按钮的关系)来说明:

  #define IDC_BTN_SENDMSG 1 // “发送”按钮ID的宏定义
  // QQ发送消息对话框回调过程·李马伪造版
  LRESULT CALLBACK ProcSendDlg(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
  {
   switch (Msg)
   {
   case WM_CLOSE:
   EndDialog(hDlg, 0);
   break;
   case WM_COMMAND:
   {
   switch (LOWORD(wParam))
   {
   case IDC_BTN_SENDMSG:
   // 发送消息...
   break;
   // 其它的命令按钮处理部分...
   }
   }
   break;
   // 其它的case部分...
   }
   return 0;
  }

  消息发送的整个过程是:当用户单击了“发送”按钮后,这个按钮的父窗口(也就是“发送消息”的对话框)会收到一条WM_COMMAND的通知消息,其中wParam的低位字(即LOWORD(wParam))为这个按钮的ID,然后再调用代码中发送的部分,这个过程如下图:

0
相关文章