ELK CLONER: 第一个计算机病毒
它将会得到你磁盘上所有的东东
它甚至将渗透到芯片内部
这就是 Cloner!
它会象胶水一样粘住你
它还会修改内存!
计算机病毒是一种在大量的电子破坏技术手段中最著名的成员.他们实际上就是一些非常危险
的恶意程序,他们是丑陋的,不过在我看来他们很可爱,原于我对internet的驾驭和对计算机
程序的探索.他们会复制自己并且可以传染其它文件,直至现在,这些被传染的文件甚至包括
了那些很清白的文档文件.而且他们很容易获得.他们可以随处传播,任何时间,任何地点.实际
上,没有一个OS可以完全抵御病毒的.一个病毒可以完全依靠系统本身进行复制,比如利用
windows系列操作系统的pe格式的可执行文件和利用类unix操作系统的elf格式.所以,任何
计算机病毒都依附于OS的体系结构,各种OS的病毒的写法都不一样,但任何OS也逃避不了病毒,
包括linux.
正如以上所说,linux也可以被感染.就象windows nt或者macOS这样的操作系统.不论是
PC机上的DOS或Windows,或者是Amiga,都可以创造出病毒代码.那么,我们为什么不来看看
在Windos NT或Linux系统上的一些病毒呢?
你也许会奇怪,事实上第一个计算机病毒是unix病毒(有可能第一个就是Elk Cloner,好象是
编写于1980到1982年之间).Fred Cohen在4BSD的VAX系统上编写了一些非常早的unix病毒,
一年以后Elk Cloner就诞生了.由于unix系统具有内存保护机制,所以人们不太相信unix系统
上的病毒的危害性会超过windows和dos系统,但他们错了.
一些公共的误区
一个最大的误区就是很多高性能的安全系统对病毒蔓延的预防.因为我们是利用DOS系统和它本身
并不存在任何内存保护机制和数据保护机制,我们认为病毒可以完全控制计算机的所有资源.是的,
他们会很轻易的称为DOS和简单的Windows操作系统的完全控制用户.没有内存保护机制和数据保
护机制,计算机病毒可以夺取所有的计算机控制权.相对来说,windows NT和unix系统是非常高级
的保护机制的系统.这可以预防大多数的病毒的传染,但不是所有的.当一个用户以root或
administrator的身份来操作的时候,这些系统的保护机制实际上是停止了的.一个设计的很巧妙
的病毒可以利用自己的方法来找到文件系统上的每个文件;NT ownership或者ACL机制都没有
很好的重视这个问题.
另一个误区就是认为linux系统尤其可以防止病毒的感染,因为linux的程序都来自于源代码,不是
二进制格式.这才应该值得重视,因为毕竟只有极少数的人(甚至管理员)才有足够的能力来从源代码
中发现病毒代码,而且这是一个相当耗费时间和精力的工作.一般的用户习惯于用二进制格式的文件
来交流,因为他们不想在使用这些程序的时候还要很繁琐的执行诸如make config;make之类的命
令,他们喜欢很简单的运行程序.所有的这些原因就给了unix系统上的病毒有足够的空间来访问和
操控系统.
第三个误区就是认为unix系统是绝对安全的,因为它具有很多不同的平台,而且每个版本的unix系
统有很大的不一样.但是现在不能这样看了.现在的病毒都用标准C来编写以适应任何类unix操作
系统,并且他们可以用make程序来跨平台编译.想想那个Morris写的internet的蠕虫病毒利用
的就是这项技术.并且拥有标准的ELF二进制格式和库文件.
Shell脚本
我们面临的第一个问题就是如何传播的问题,这是天生具有的问题,至少在unix系统上是如此,我们
需要想办法使各个平台兼容.所以我们首先想到的是:shell脚本语言.shell在不同的unix系统
上面的差别很小.所以Fred Cohen在他的书:入侵者,蠕虫和病毒(发表于1990年)写到:
"在unix的命令解释语言中,病毒代码可以被写到200个字节之内".也许我们可以根据他的话来写
一个man page的病毒脚本,可以用来操作文件和可执行程序.这和宏病毒非常相像.man page的
病毒不会蔓延到别的系统上,除非你有为别的用户改变man page的格式的习惯.无论如何,这种
病毒都是一个公共的跨系统的病毒.同样,也可以写另个一个脚本病毒来控制mail的阅读者.
书写shell脚本病毒是一个很简单的制造unix病毒的方法.我知道肯定会有很多同行会说,脚本病毒
怎么会是真正的病毒呢?它只是用脚本语言来书写的而不是用汇编.但是实际上,我们评定一个病毒
是病毒本身可以在系统上任意感染传播,而不是这个病毒的大小或者用什么语言来写的.在USENIX
1989 卷2上你可以看到Tom Duff和M. Douglas McIlroy的脚本病毒代码.shell脚本病毒的危
害性不会很大并且它本身极易被破坏,因为它是以明文方式编写并执行的,任何用户和管理员都可以
发觉它的代码.但是,我想大多数的用户都不会理解一下代码的吧:
for %%f in (*.bat) do copy %%f + bfv.bat
通常一个用户会深信不疑的去执行任何脚本,而且不会过问该脚本的由来.这样,这些用户都成为
病毒的目标了;这些都是用户的意识问题,这样是没办法避免病毒的入侵的,所以我们的用户需要
大大加强对这些病毒的防范意识.
蠕虫
另外的一个影响广泛的技术就是蠕虫,想象一下Morris蠕虫:利用攻击程序--一般这些攻击程序
都是已经存在的技术.这个蠕虫利用一个sendmail程序已存在的一个漏洞来获取其它机器的控制
权.病毒一般会利用rexec,fingerd或者口令猜解来尝试连接.在成功入侵之后,它会编译在目标
机器上编译源代码并且执行它.而且会有一个程序来专门负责隐藏自己的脚印.
internet的蠕虫病毒一般都是利用已知的攻击程序去获得目标机的管理员权限.但是蠕虫的生命
也是很短暂的,当该病毒所利用的漏洞被修补的话,那么该蠕虫也就失去它的作用了,因为他们需要
利用exploit这个媒介来进行自身的复制.而exploit又是只针对特定版本的特定程序才会有
效的,所以蠕虫的跨平台能力很差,时效性也很弱.
欺骗库函数
我们可以愚弄那些比较傻的用户.如果你利用LD_PRELOAD环境变量来捉弄他,你可以让他执行你自
己的代码,你已经利用LD_PRELOAD环境变量把标准的库函数替换成了你自己的程序.挺有意思吧?
LD_PRELOAD并不是linux系统特有的并且它一般用在一些应用程序(比如老版本的StarOffice
需要运行在较新版本的red hat系统上)必须用他们自己的(或者比较老的版本,或者修改过的)
库函数,因为在安装的时候没有满足他们的需求.Quantum (Staog病毒的作者)在unix病毒的邮件
列表里面提供了这些代码,我做了修改,也是为了便于大家理解:
------------------------tryld.c------------------------------------
extern int __open(char *, int, int);
extern int execv(char *, char *[], char *envp[]);
int open(char *path, int flags,
int mode){
printf("open: %s\n", path);
return __open(path, flags, mode);
}
/* 注意这里,原来它放弃了envp参数,这样会...:(?!
呵呵,所以我修改了一下,影响不大:)*/
int execve(char *path, char *args[],
char *envp[]){
printf("execve: %s\n", path);
return execv(path, args, envp);
}
-------------------------------------------------------------------
------------------------main.c-------------------------------------
/*test only,by e4gle*/
#include
#include
#include
#include
main()
{
int fd;
execve("/bin/date","",NULL);
if(fd=open("/etc/inittab",O_RDONLY)!=-1)
{
fprintf(stdout,"open file succeed!\n");
}
else
fprintf(stderr,"open error!\n");
close(fd);
return 0;
}
-------------------------------------------------------------------
这段代码获取open和execv并且改变了它们的输出,好,我们测试一下:
[e4gle@redhat62 elf] $ gcc -o main main.c
[e4gle@redhat62 elf] $ ./main
open file succeed! <--证明我们打开文件成功了,open调用正常工作
[e4gle@redhat62 elf] $ ldd -v -r ./main
libc.so.6 => /lib/libc.so.6 (0x4001c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Version information:
./main:
libc.so.6 (GLIBC_2.0) => /lib/libc.so.6
/lib/libc.so.6:
ld-linux.so.2 (GLIBC_2.1.1) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.0) => /lib/ld-linux.so.2
/*跟踪一下库函数的利用,都是glibc的标准库函数,solaris里面是sotruss,我个人认为sotruss
比较好用:)*/
[e4gle@redhat62 elf] $ gcc -shared -o tryld tryld.c
[e4gle@redhat62 elf] $ export LD_PRELOAD=./tryld <--用我们自己的lib
[e4gle@redhat62 elf] $ ./main
execve: /bin/date
open: /etc/inittab
open file succeed!
/*注意!不一样了吧?已经在用我们自己的open和execve了,呵呵:)*/
以上仅仅是个测试代码并且没有任何危害性,但是它足以说明我们利用欺骗函数库来攻击程
序的原理.
内核级的传播
这里我们称作"内核级别的病毒",病毒可以传染内核映像,这样病毒可以控制系统的方方面面.但是
这种病毒技术目前尚处于理论阶段,并没有真正实现,但并不代表以后都不会出现.
与平台兼容的病毒
如果我们用标准C来书写病毒代码的话,各种不同体系的unix系统对于我们来说变化不大.我们只
需要对方计算机有一个c编译器.这样的病毒可以很轻易的扩散,利用普通用户的.rhosts文件这种
小技俩就可以做到.假如没有exploits(是有可能的,因为病毒是跨平台的,因而它可以不借助exploit
来四处扩散),这种可以跨平台的病毒的传染面是非常广的,而且似乎根本没有结束的时候.
当然,很多病毒都还是用汇编来编写的.有很多著名的病毒,但不是第一个linux病毒Bliss,第一次
发表于1997年.Bliss传染ELF格式的二进制文件,但是并没有太多的伤害.它甚至可以利用
被感染文件的--bliss-disinfect-files-please参数来卸载.假如你需要在你的文件里查找
Bliss,注意以下字段:
E8ABD8FFFFC200003634 65643134373130363532
最早的linux病毒是Staog,比Bliss早半年.它用汇编书写并且利用三个/dev/kmem的exploits来获得
的特权,它可以感染任何文件并且可以传播.
它的关键字段:
215B31C966B9FF0131C0 884309884314B00FCD80
当我们利用ELF格式的二进制文件来做病毒:这种病毒被誉为计算机病毒中的标准模式--他们用汇编编写
并且它们通过可执行程序感染,很象典型的DOS下的病毒.可以通过往elf文件的文本段之后的填充
区增加代码来感染ELF文件,搜索目录树中文件的ET_EXEC和ET_DYN标记看看是否被隐藏(这些依靠
管理员自身的经验).
当然,在linux系统下实现这种病毒并不太容易.一个病毒感染的文件属主是普通用户权限的话,那么病毒所
得到的权限当然也就只有普通用户权限(并且病毒不会利用exploit来提升权限),只能对该用户权限级别
的文件和数据造成危害.但是当一个病毒感染了一个root权限的文件的话,那么它就可以控制系统的一切了.
我们安全么?
一个很实际的问题.现在我们的linux系统还可能比较安全.但以后不代表一致这样.linux系统越来越
流行,这将引来一大批的病毒制造者的目光.很多用户都有可能是潜在的病毒制造者,而且如果把unix的
很多用户对unix本身的了解正在减少算在内的话,我们就麻烦了.现在已经有了一些linux系统上的
反病毒程序.现在甚至包括我还有很多unix的系统管理员在内都对制造反病毒程序非常感兴趣.在一个
蠕虫出现之后,我们可以查阅各种文档,甚至书籍.所以我们都一直也在努力着.
最后一个很具讽刺的玩笑:我们具有真正有效的linux反病毒程序,那么微软的outlook/exchange
等也和linux联合了,我们也就真正安全了,可能么?呵呵.