2024年6月2日发(作者:)

3.2 MIME协议

RFC822文档定义了邮件内容的主体结构和各种邮件头字段的详细细节,但是,它没有定义邮件体的

格式,RFC822文档定义的邮件体部分通常都只能用于表述一段普通的文本,而无法表达出图片、声音等

二进制数据。另外,SMTP服务器在接收邮件内容时,当接收到只有一个“.”字符的单独行时,就会认

为邮件内容已经结束,如果一封邮件正文中正好有内容仅为一个“.”字符的单独行,SMTP服务器就会

丢弃掉该行后面的内容,从而导致信息丢失。

由于Internet的迅猛发展,人们已不满足于电子邮件仅仅是用来交换文本信息,而希望使用电子邮

件来交换更为丰富多彩的多媒体信息,例如,在邮件中嵌入图片、声音、动画和附件。但是,由于图片

和声音等内容是非ASCII码的二进制数据,而RFC822邮件格式只适合用来表达纯文本的邮件内容,所

以,要使用RFC822邮件格式发送这些非ASCII码的二进制数据时,必须先采用某种编码方式将它们“编

码”成可打印的ASCII字符后再作为RFC822邮件格式的内容。邮件阅读程序在读取到这种经过编码处

理的邮件后,再按照相应的解码方式解码出原始的二进制数据,这样就可以借助RFC822邮件格式来传

递多媒体数据了。这种做法需要解决一下两个技术问题:

(1)邮件阅读程序如何知道邮件中嵌入的原始二进制数据所采用的编码方式;

(2)邮件阅读程序如何知道每个嵌入的图像或其他资源在整个邮件内容中的起止位置。

针对这个问题,人们后来专门为此定义了MIME(Multipurpose Internet Mail Extension,多用途

Internet邮件扩展)协议。

MIME协议用于定义复杂邮件体的格式,它可以表达多段平行的文本内容和非文本的邮件内容,例如,

在邮件体中内嵌的图像数据和邮件附件等。另外,MIME协议的数据格式也可以避免邮件内容在传输过程

中发生信息丢失。MIME协议不是对RFC822邮件格式的升级和替代,而是基于RFC822邮件格式的扩展应

用。一言以蔽之,RFC822定义了邮件内容的格式和邮件头字段的详细细节,MIME协议则是定义了如何

在邮件体部分表达出的丰富多样的数据内容。

一个采用了MIME协议的电子邮件就叫做MIME邮件,MIME邮件在RFC822文档中定义的邮件头字段

的基础上,扩充了一些自己专用的邮件头字段,例如,使用MIME-Version头字段指定MIME协议的版本,

使用Content-Type头字段指定邮件体的MIME类型,使用Content-Transfer-Encoding头字段指定编码

方法,如下所示:

MIME-Version: 1.0

Content-Type:multipart/mixed;boundary="----=_NextPart_000_0050_01C"

其中,“multipart/mixed”部分说明邮件体中包含有多段数据,每段数据之间使用boundary属性

中指定的字符文本作为分隔标识符。

另外,MIME邮件也扩展了RFC822文档中已经定义了的邮件头字段的内涵,例如,定义了subject

头字段中的值内容的格式,以便通过编码的方式让邮件主题中也可以使用非ASCII码的字符。subject

头字段中的值嵌套在一对“=?”和“?=”标记符之间,标记符之间的内容由三部分组成:邮件主题的原

始内容的字符集、当前采用的编码方式、编码后的结果,这三部分之间使用“?”进行分隔。下面是一

个对包含有非ASCII码字符的邮件主题进行了编码后的结果:

Subject: =?gb2312?B?TUlNRdCt0unLtcP308q8/g==?=

其中,“gb2312”部分说明邮件主题的原始内容为gb2312编码的字符文本,“B”部分说明对邮件

主题的原始内容按照BASE64方式进行了编码,“TUlNRdCt0unLtcP308q8/g==”为对邮件主题的原始内

容进行了BASE64编码后的结果。

可见,MIME邮件与普通的RFC822邮件的关系犹如Java编程语言中的子类与父类的关系,子类是对

父类的扩展,子类功能更强大,但子类离不父类的支持。如果需要了解MIME的详细细节,可以查阅RFC

2045~2049系列文档。

3.3 MIME邮件的组织结构

一封MIME邮件可以由多个不同类型的MIME消息组合而成,一个MIME消息表示邮件中的一个基本

MIME资源或若干基本MIME消息的组合体。每个MIME消息的数据格式与RFC822数据格式相似,也包括

头和体两部分,分别称为MIME消息头和MIME消息体,它们之间使用空行分隔。MIME消息体中包含了资

源的具体内容,MIME消息头中则包含了对资源的描述信息。多个相同层次的MIME消息必须形成一个MIME

组合消息,它们共同作为所形成的MIME组合消息的MIME消息体,相互之间采用某种分隔标识符进行分

隔,MIME组合消息的消息头中需要描述其中的多个MIME消息的组合类型和分隔标识符。一个MIME组合

消息还可以再与其他MIME消息共同形成一个更大的MIME组合消息,这样就形成了一种多层嵌套的组合

关系,一封MIME邮件就是按这种组合方式所形成的一个最顶层的MIME组合消息。

MIME协议采用这种多层组合方式可以表达出复杂的邮件内容,例如,对于在OutLook Express中显

示出的如图3.4所示效果的一封复杂邮件,可以采用图3.5所示的MIME组合结构来表达。

图3.4中的邮件正文为一段HTML格式的文本和其引用的一个图片资源,该邮件还包含两个附件:一

个是WAV声音文件,一个是EXE可执行文件。该邮件的MIME结构如图3.5所示,其中的HTML文本内容、

图片资源和两个附件用四个独立的MIME消息表示,HTML文本内容和图片资源又组合成一个表示邮件正

文的MIME组合消息,这个MIME组合消息再与两个附件对应的MIME消息组合成了一个更大的MIME组合

消息,这就形成了整封邮件的MIME消息。

图3.4

3.4 MIME消息的头字段

3.4.1 Content-Type

对于表示某个具体资源的MIME消息,它的消息头中需要指定资源的数据类型;对于MIME组合消息,

它的消息头中需要指定组合关系。具体资源的数据类型和组合消息的组合关系,都是通过消息头中的

Content-Type头字段来指定的。Content-Type字段中的内容以“主类型/子类型”的形式出现,主类型

有text、image、audio、video、application、multipart、message等,分别表示文本、图片、音频、

视频、应用程序、组合结构、消息等。每个主类型下面都有多个子类型,例如text主类型包含plain、

html、xml、css等子类型。multipart主类型用于表示MIME组合消息,它是MIME协议中最重要的一种

类型。一封MIME邮件中的MIME消息可以有三种组合关系:混合、关联、选择,它们对应MIME类型如

下:

— multipart/mixed

表示消息体中的内容是混和组合类型,内容可以是文本、声音和附件等不同邮件内容的混

和体,例如图3.5中的整封邮件的MIME类型就必须定义为multipart/mixed。

— multipart/related

表示消息体中的内容是关联(依赖)组合类型,例如图3.5中的邮件正文要使用HTML代码

引用内嵌的图片资源,它们组合成的MIME消息的MIME类型就应该定义为multipart/related,

表示其中某些资源(HTML代码)要引用(依赖)另外的资源(图像数据),引用资源与被引用

的资源必须组合成multipart/related类型的MIME组合消息。

— multipart/alternative

表示消息体中的内容是选择组合类型,例如一封邮件的邮件正文同时采用HTML格式和普通

文本格式进行表达时,就可以将它们嵌套在一个multipart/alternative类型的MIME组合消息

中。这种做法的好处在于如果邮件阅读程序不支持HTML格式时,可以采用其中的文本格式进行

替代。

一封最复杂的电子邮件的基本情况为:含有邮件正文和邮件附件,邮件正文可以同时使用HTML格式

和普通文本格式表示,并且HTML格式的正文中又引用了其他的内嵌资源。对于这种最复杂的电子邮件,

可以采用如图3.6所示的MIME消息结构进行描述。

图3.6

从图3.6中可以看出,如果要在邮件中要添加附件,就必须将整封邮件的MIME类型定义为

multipart/mixed;如果要在HTML格式的正文中引用内嵌资源,那就要定义multipart/related类型的

MIME消息;如果普通文本内容与HTML文本内容共存,那就要定义multipart/alternative类型的MIME

消息。

注意:如果整封邮件中只有普通文本内容与HTML文本内容,那么整封邮件的MIME类型则应定义

为multipart/ alternative;如果整封邮件中包含有HTML文本内容和内嵌资源,但不包含

附件,那么整封邮件的MIME类型则应定义为multipart/related。

在Content-type头字段中除了可以定义消息体的MIME类型外,还可以在MIME类型后面包含相应的

属性,属性以“属性名=属性值”的形式出现,属性与MIME类型之间采用分号(;)分隔,如下所示:

Content-Type:multipart/mixed;boundary="----=_NextPart_000_0050_01C"

常用的属性如表3.1所示。

表3.1

用于说明文本内容的字符集编码

text

image

application

multipart

charset

name

name

boundary

用于说明图片文件的文件名

用于说明应用程序的文件名

用于定义

MIME

消息之间的分隔符

3.4.2 其他头字段

除了Content-Type头字段之外,MIME协议中还定义Content- Transfer-Encoding、

Content-Disposition、Content-ID、Content-Location、Content-Base等几个重要的头字段,这几个

头字段需要与Content-type头字段配合使用,它们的作用如下:

— Content-Transfer-Encoding头字段

Content-Transfer-Encoding头字段用于指定MIME消息体中的内容所采用的邮件编码方式,

详细细节请参看3.4节的讲解。

— Content-Disposition头字段

Content-Disposition头字段用于指定邮件阅读程序处理数据内容的方式,有inline和

attachment两种标准方式,inline表示直接处理,而attachment表示当做附件处理。如果将

Content-Disposition设置为attachment,在其后还可以指定filename属性,如下所示:

Content-Disposition: attachment; filename=""

上面的MIME头字段表示MIME消息体的内容为邮件附件,附件名""。

— Content-ID头字段

Content-ID头字段用于为“multipart/related”组合消息中的内嵌资源指定一个唯一标

识号,在HTML格式的正文中可以使用这个唯一标识号来引用该内嵌资源。例如,假设将一个表

示内嵌图片的MIME消息的Content-ID头字段设置为如下形式:

Content-ID: it315logo_gif

那么,在HTML正文中就需要使用如下HTML语句来引用该图片资源:

注意,在引用Content-ID头字段标识的内嵌资源时,要在资源的唯一标识号前面加上

“cid:”,以说明要采用唯一标识号对资源进行引用。

— Content-Location头字段

Content-Location头字段用于为内嵌资源设置一个URI地址,这个URI地址可以是绝对或

相对的。当使用Content- Location头字段为一个内嵌资源指定一个URI地址后,在HTML格式

的正文中也可以使用这个URI来引用该内嵌资源。例如,假设将一个表示内嵌图片的MIME消息

的Content- Location头字段设置为如下形式:

Content-Location:/images/

那么,在HTML正文中就可以使用如下HTML语句来引用该图片资源:

— Content-Base头字段

Content-Base头字段用于为内嵌资源设置一个基准路径,只有这样,Content-Location头

字段中设置的URI才可以采用相对地址。例如,假设将一个表示内嵌图片的MIME消息的

Content-Base和Content-Location头字段设置为如下形式:

Content-Base: /images/

Content-Location:

那么,内嵌资源的完整路径就是Content-Base头字段设置的基准路径与Content-Location

头字段设置的相对路径相加的结果,在HTML正文中就可以使用如下HTML语句来引用该图片资

源:

3.5 MIME邮件的编码方式

由于每个ASCII码字符只占用一个字节(8个bit位),且最高bit位总为0,即ASCII码字符中的

有真正意义的信息只是后面的7个低bit位,而传统的SMTP协议又是基于ASCII码字符设计的,因此,

一些基于传统SMTP协议设计的SMTP服务器在处理邮件内容时只取出每个字节中的7个低bit位进行处

理,而将最高bit位忽略不计。显然,这样的SMTP服务器在处理包含有非ASCII码字符的邮件内容时,

会出现严重的问题,这就限制了邮件中只能出现英文的ASCII码字符,而不能出现中文字符或二进制数

据。

为了能够在邮件内容中包含中文、图像或声音等非ASCII字符的数据,人们想到了采用某种编码方

式将非ASCII字符的数据转换成可打印的ASCII字符后再发送,邮件阅读程序则按照相应的解码方式从

邮件中还原出原始数据即可,比较常用的两种邮件编码方式为BASE64和Quoted-printable。后来的扩

展SMTP协议允许直接在邮件中传递二进制数据,而不用对它们进行邮件编码,人们将这种没有进行邮

件编码的二进制数据的邮件内容称为8bit编码,为了与此相区别,人们将没有进行邮件编码的纯ASCII

码字符的邮件称为7bit编码。MIME消息体的邮件编码方式通过MIME消息头中的Content- Transfer-

Encoding头字段指定,每种邮件编码方式的介绍如下:

— 7Bit

指消息体内容全部是没有经过编码的ASCII字符。

— 8Bit

指消息体内容是没有经过编码的原始数据,且其中包含有非ASCII字符的数据。现在的邮

件服务器基本上都支持8Bit编码,使用支持8Bit编码的邮件服务器可以简化邮件的处理过程。

— BASE64

Base64是将二进制数据转换成可打印的ASCII字符的一种最常见的编码方式,它的基本原

理是将一组连续的字节数据按6个bit位进行分组,然后对每组数据用一个ASCII字符来表示。

6

6个bit位最多能表示2=64个数值,因此可以使用64个ASCII字符来对应这64个数值,这

64个ASCII字符为:

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"

其中每个字符表示的数值就是该字符在上面的排列中的索引号,索引号从0开始编号。假

设在内存中有如下三个连续的字节数据:

[0110,0001] [0110,0010] [0110,0011]

将它们按6个bit位进行分组后的形式如下:

[0110,00] [01,0110,] [0010,01] [10,0011]

分组后得到了四组数据,每组数据对应的十进制数值分别为24、22、9、35,它们分别对应

Y、W、J、j这四个字符,所以,对[0110,0001] [0110,0010] [0110,0011]这三个字节的数据

进行BASE64编码后的结果是“YWJj”。

BASE64编码要求把3个8位字节(即24个bit)的数据转化为4个6位字节(也是24个

bit)的数据,如果原来的8位字节数据的字节个数不能被3整除,其余数只能是1或2,那么

如何对余下的1个或2个8位字节数据进行处理呢?对于这种情况,仍然按6个bit位对剩余

的字节进行分组,在最后不够6个bit位的内容后面添加几个为0的bit位来凑成6个bit位,

例如,如果最后剩下的一个8位字节的内容如下:

[0110,0001]

对它进行分组后的结果如下:

[0110,00] [01,

0000

]

其中用黑斜体标识的0为填充的bit位,所以,最后剩下的这个字节的BASE64编码结果为

“YQ”。BASE64编码还有规定,如果编码后的整个结果文本的字符个数不是4的整数倍,那么

需要在最后填充“=”字符来凑成4的倍数,所以,在最后这个字节编码的结果后面还要添加两

个“=”字符,即“YQ==”。显然,如果最后剩下两个8位字节的内容,它可以被编码成三个字

符,最后还需要添加一个“=”字符。对一大段数据进行BASE64编码时,可以在编码结果中的

适当位置加入回车换行,MIME规范建议BASE64编码结果中的每行最多76个字符。

— Quoted-printable

Quoted-printable也是一种将二进制数据转换成可打印的ASCII字符的编码方式,它对

ASCII字符不进行转换,只对非ASCII字符的数据进行编码转化。每个非ASCII字符的字节数

据,都被转换成一个"="号后跟这个字节的十六进制数据,例如,“ab中国”的

Quoted-printable编码结果为“ab=d6=d0=b9= fa”。显然,由于"="号在Quoted-printable

编码中具有的特殊意义,所以,原始数据中的"="号字符也需要进行编码转换,用“=3d”表示。

对一大段数据进行Quoted-printable编码时,可以在编码结果中的适当位置加入回车换行,

在回车换行前需要额外再加入一个“=”字符,以表示后面的换行是因编码而造成的软回车,而

非原始数据中原有的回车换行。例如,对于下面一段Quoted-printable编码后的数据:

=D5=E2=CA=C7=CD=A8=D0=C5=B5=C4=B3=CC=D0=

=F2, =C7=EB=D6=B8=BD=CC!

在第一行末尾的“=”字符和换行,都是由于编码后生成的。

3.6 MIME实例分析

了解MIME协议的基本组织结构后,下面用Outlook Express撰写出一封显示效果如图3.4所示的电

子邮件,然后分析该邮件的源文件,以便读者更加深入地了解MIME协议。

Express,单击工具栏中的“创建邮件”按钮,在打开的“新邮件”对话框中输入

启动Outlook

收件人地址、主题和邮件正文,然后选中邮件正文,单击编辑窗口的工具栏上的“》”按钮,在弹出的

菜单栏中单击表示超链接的图标,如图3.7所示。

图3.7

在打开的“超级链接”对话框中输入如图3.8所示的内容,然后单击“OK”按纽。

图3.8

再次单击编辑窗口的工具栏上的“》”按钮,在打开的如图3.7所示的菜单栏中单击表示图片

的图标,在打开的“图片”对话框中单击“浏览”按钮,然后通过打开的对话框选择一个图片文件,结

果如图3.9所示。

单击图3.9中的“OK”按钮,结果如图3.10所示。

图3.9

图3.10

单击图3.10所示窗口中的“插入”à“文件附件”菜单项,在打开的“插入附件”对话框窗口

中选择需要发送的附件,如图3.11所示。

单击“附件”按钮,插入所选中的附件。

单击图3.10所示窗口中的“文件”à“保存”菜单项,在Outlook Express主窗口的“草稿”

目录中就可以看到这封邮件,如图3.12所示。

图3.11

图3.12

将这封邮件从“草稿”目录中移动到“发件箱”目录中,接着按照3.1节中讲解的查看邮件源

文件步骤,打开刚才撰写的这封邮件的源文件。或者在“草稿”目录中选中这封邮件,将它另存为一个

eml文件,再用任意一种文本编辑程序打开这个eml文件,这样也可以查看到刚才撰写的这封邮件的源

文件。为了便于读者看清邮件内容的组织结构关系,笔者专门为此画了一个描述邮件中的各个MIME消

息分隔符的层次关系的示意图,如图3.13所示。

从图3.13中可以看出,在MIME组合消息的消息体中的每个消息单元都要以一个分割符开始,在组

合消息的消息体结束时还需要用一个结束分割符。MIME消息中的分隔符的层次关系与一篇文章中的标题

之间的层次关系非常相似,只是在每个组合消息结束时还要增加一个结束“标题”。为了便于讲解,笔

者对刚才撰写的邮件源文件内容进行了适当修改,并添加了相应的注释,如下所示:

图3.13

1:From:"it315"<*******************>

2:To:<*******************>

3:Subject: =?gb2312?B?TUlNRdCt0unLtcP308q8/g==?=

4:Date: Thu, 1 Dec 2005 20:46:53 +0800

5:MIME-Version: 1.0

6:Content-Type: multipart/mixed;//定义邮件体类型为mixed

7: boundary="----=_NextPart_000_0050_01C"//定义整个邮件内容的分隔符

8:X-Priority: 3

9:X-MSMail-Priority: Normal

10:X-Mailer: Microsoft Outlook Express 6.00.2900.2670

11:X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2670

12:

13:This is a multi-part message in MIME format.//邮件注释

14:

//整个邮件内容的第一部分(即邮件正文)的开始标记

15:------=_NextPart_000_0050_01C

16:Content-Type: multipart/related;

17: type="multipart/alternative";

18: boundary="----=_NextPart_001_0051_01C"//定义邮件正文内部的分隔符

19:

//邮件正文内部的第一部分的开始标记

20:------=_NextPart_001_0051_01C

21:Content-Type: multipart/alternative;

//定义邮件正文内部的第一部分的内部分隔符

22: boundary="----=_NextPart_002_0052_01C"

23:

//邮件正文内部的第一部分的第一部分的开始标记

24:------=_NextPart_002_0052_01C

25:Content-Type: text/plain;

26: charset="gb2312"

27:Content-Transfer-Encoding: base64

28:

29:u7bTrbTzvNK3w87KztLDx7XEzfjVvg0KDQog

//经BASE64编码后的文本格式的邮件正文

30:

//邮件正文内部的第一部分的第二部分的开始标记

31:------=_NextPart_002_0052_01C

32:Content-Type: text/html;

33: charset="gb2312"

34:Content-Transfer-Encoding: base64

35:

36://经BASE64编码后的HTML格式的邮件正文

37:

//邮件正文内部的第一部分的的结束标记

38:------=_NextPart_002_0052_01C--

39:

//邮件正文内部的第二部分(HTML中的内嵌资源)的开始标记

40:------=_NextPart_001_0051_01C

41:Content-Type: image/gif;

42: name=""

43:Content-Transfer-Encoding: base64

44:Content-ID: <004f01c5f675$4e210300$b501a8c0@zxx>

45:

46:R0lGODlh/ABGAOYAADdhmaekZjxsq0N4vHik

47:

// HTML中内嵌的经BASE64编码后的图片数据

48:

//邮件正文的结束标记

49:------=_NextPart_001_0051_01C—

50:

//整个邮件内容的第二部分(第一个附件)的开始标记

51:------=_NextPart_000_0050_01C

52:Content-Type: application/x-msdownload;

53: name=""

54:Content-Transfer-Encoding: base64

55:Content-Disposition: attachment;//声明内容类型为附件

56: filename=""

57:

58:TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA

59:// 第一个邮件附件内容

60:

//整个邮件内容的第三部分(第二个附件)的开始标记

61:------=_NextPart_000_0050_01C

62:Content-Type: audio/wav;

63: name=""

64:Content-Transfer-Encoding: base64

65:Content-Disposition: attachment;//声明内容类型为附件

66: filename=""

67:

68:UklGRjIAAABXQVZFZm10IBIAAAABAAEAIlYAACJWAAABAAgAKABmYWN0

69:AA==//第二个邮件附件内容

70:

//整个邮件内容的结束标记

71:------=_NextPart_000_0050_01C5F6B8.5C492500--

源文件中第1~11行为邮件的邮件头,第15~71行为邮件体。邮件体中的15~49行为邮件正文,

第51-59行为邮件的第一个附件,第61~71行为第二个附件。读者只要对照图3.13来阅读,就很容易

看出这个邮件源文件内容的组织结构。关于上述的邮件源文件内容,还需要做出如下三点补充解释:

(1)每个MIME组合消息的Content-type头字段中的boundary属性用于定义其中嵌套的各个MIME

消息之间的分隔符,如源文件中的第7行、第18行和第22行等。在各个MIME组合消息内部的起始分

隔符是在该MIME组合消息的Content-type头字段中的boundary属性值前面增加了两个减号(-)字符

而形成的,如源文件中的第15行、第20行和第24行等;而每个MIME组合消息的结束分隔符则是在其

起始分隔符的后面又添加两个减号(-)字符而形成的,如源文件中的第38行、第49行和第71行。

(2)在每个MIME组合消息的消息体之前(即第一个开始分隔符之前),可以有一些附加的文本行,

这些文本行相当于MIME消息的注释,在解码时将被忽略,如源文件的13行。

(3)源文件中的第44行使用Content-ID头字段为内嵌的图片资源指定了一个唯一标识号,在HTML

格式的正文中需要使用这个唯一标识号来引用相应的内嵌资源,其引用语句为

004f01c5f675$4e210300$b501a8c0@zxx">,但是由于整个HTML正文部分采用了Base64编码,所以在源

文件的HTML正文部分无法看到原始的引用语句。

多学两招 邮件传播病毒的原理

MIME协议其实就是一种邮件内容的组织协议,支持MIME协议的邮件阅读程序将根据MIME消息头中

定义的MIME类型,调用相应的解析程序来处理消息体中的数据。例如MIME消息头中定义为邮件附件时,

邮件阅读程序会提示用户保存消息体中的数据,如果定义为图像文件时,邮件阅读程序则把消息体中的

数据作为一个图像文件自动打开。

由于邮件数据通常是经过BASE64编码后的ASCII码数据,邮件阅读程序只能通过分析数据的MIME

消息头来获知数据类型,无法通过分析数据本身来获知数据的类型,因此,一些病毒制造者就可以把病

毒程序进行BASE64编码后,再附加在邮件的MIME消息体中,然后在MIME消息头中将其MIME类型定义

为图片或声音等类型,而文件名的扩展名却为.exe。这样,当邮件阅读程序解码带有病毒程序的MIME

消息体后,将执行解码后得到的病毒程序。前些年曾经在全球范围内流行的Nimda病毒,就是通过这种

方式进行传播的,其示意源代码如下:

MIME-Version: 1.0

Content-Type: multipart/related;//声明所包含内容为内嵌资源

type="multipart/alternative";

boundary="====_ABC1234567890DEF_===="

--====_ABC1234567890DEF_====

Content-Type: multipart/alternative;

boundary="====_ABCDEF_===="

--====_ABCDEF_====

Content-Type: text/html;

charset="iso-8859-1"

Content-Transfer-Encoding: 7bit

--====_ABCDEF_====--

--====_ABC1234567890DEF_====

Content-Type: audio/x-wav; name=""

//把exe文件定义成一个wav文件

Content-Transfer-Encoding: base64

Content-ID:

TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAA……//经BASE64编码后的病毒源代码

--====_ABC1234567890DEF_====

这封邮件传播病毒的运行原理非常简单,如上面的源文件中的黑体字部分及相应注释所示,它就是

将一个可执行文件()作为一个audio/x-wav类型的声音文件嵌入到HTML页面中。由于最

初的Outlook Express程序没有检查MIME消息的Content-Type头字段定义的MIME类型与其中的name

属性指定的文件扩展名是否匹配,于是导致用户打开邮件时将执行解码后的程序,从而感

染上了病毒。这个病毒程序又利用Outlook Express中的地址簿向别人发送带毒的邮件,这样一传十,

十传百,Nimda蠕虫就大行其道了。