﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-TODD-随笔分类-攻防</title><link>http://www.blogjava.net/Todd/category/44805.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 10 Jun 2010 06:25:44 GMT</lastBuildDate><pubDate>Thu, 10 Jun 2010 06:25:44 GMT</pubDate><ttl>60</ttl><item><title>如何检测SQL注入和CSS攻击漏洞</title><link>http://www.blogjava.net/Todd/archive/2010/06/09/323154.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Wed, 09 Jun 2010 06:50:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/06/09/323154.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/323154.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/06/09/323154.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/323154.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/323154.html</trackback:ping><description><![CDATA[<div id="blog_text" class="cnt">
<p>http://www.symantec.com/connect/articles/detection-sql-injection-and-cross-site-scripting-attacks<br />
</p>
<p>在这两年中，安全专家应该对网络应用层的攻击更加重视。因为无论你有多强壮的防
火墙规则设置或者非常勤于补漏的修补机制，如果你的网络应用程序开发者没有遵循安全代码进行开发，攻击者将通过80端口进入你的系统。广泛被使用的两个主
要攻击技术是SQL注入[ref1]和CSS[ref2]攻击。SQL注入是指：通过互联网的输入区域，插入SQL
meta-characters（特殊字符
代表一些数据）和指令，操纵执行后端的SQL查询的技术。这些攻击主要针对其他组织的WEB服务器。CSS攻击通过在URL里插入script标签，然后
诱导信任它们的用户点击它们，确保恶意Javascript代码在受害人的机器上运行。这些攻击利用了用户和服务器之间的信任关系，事实上服务器没有对输
入、输出进行检测，从而未拒绝javascript代码。</p>
<p>这篇文章讨论SQL注入和CSS攻击漏洞的检测技术。网上已经有很多关于这两种基于WEB攻击的讨论，比如如何实施攻击，他们的影响，怎样更好的编
制和设计程序防止这些攻击。 然而, 对如何检测这些攻击并没有足够的讨论。我们采用流行的开源的IDS Snort[ref
3],组建根据检测这些攻击的规则的正则表达式。附带，Snort默认规则设定包含检测CSS的方法，但是这些容易被避开检测。比如大多通过hex进制编
码,如%3C%73%63%72%69%70% 74%3E代替&lt;script&gt;避开检测。</p>
<p>依赖level of
paranoia组织的能力，我们已经编写了多种检测相同攻击的规则。如果你希望检测各种可能的SQL注入攻击，那么你需要简单的留意任何现行的SQL
meta-characters，如单引号，分号和双重破折号。同样的一个极端检测CSS攻击的方法，只要简单地提防HTML标记的角括号。但这样会检测
出很多错误。为了避免这些，这些规则需要修改使它检测更精确些, 当仍然不能避免错误。</p>
<p>在Snort规则中使用pcre(Perl Compatible Regular
Expressions)[ref4]关键字，每个规则可以带或不带其他规则动作。这些规则也可以被公用软件如grep(文档搜索工具)使用，来审阅网络
服务器日志。 但是,需要警惕的是，用户的输入只有当以GET提交请求时，WEB服务器才会记录日记,如果是以POST提交的请求在日记中是不会记录的。</p>
<p><strong>2. SQL注入的正则表示式</strong></p>
<p>当
你为SQL注入攻击选择正则表示式的时候，重点要记住攻击者可以通过提交表单进行SQL注入，也可以通过Cookie区域。你的输入检测逻辑应该考虑用户
组织的各类型输入(比如表单或Cookie信息)。并且如果你发现许多警告来自一个规则，请留意单引号或者是分号，也许些字符是你的Web应用程序创造的
合法的在CookieS中的输入。因此, 您需要根据你的特殊的WEB应用程序评估每个规则。</p>
<p>依照前面提到，一个琐细的检测SQL射入攻击的正则表达式要留意SQL特殊的meta-characters
譬如单引号(&#8217;)双重扩则号(--),为了查出这些字符和他们hex等值数, 以下正则表达式适用:</p>
<p><strong>2.1 检测SQL meta-characters的正则表达式 </strong></p>
<p>/(\%27)|(&#8217;)|(--)|(\%23)|(#)/ix</p>
<p><strong>解释:</strong></p>
<p>我 们首先检查单引号等值的hex，单引号本身或者双重扩折号。这些是MS SQL Server或Oracle的字符, 表示后边的为评论,
随后的都将被忽略。 另外，如果你使用MySQL,你需要留意 &#8217;#&#8217;和它等值的hex的出现。注意我们不需要检查双重破折号等值的hex,
因为这不是HTML meta-character, 浏览器不会进行编码。 并且,
如果攻击者设法手工修改双重破折号为它的hex值%2D(使用代理像Achilles[ref 5]), SQL注入将失败。 <br />
加入上述正则表达式的新的Snort规则如下:</p>
<p>alert tcp $EXTERNAL_NET any -&gt; $HTTP_SERVERS $HTTP_PORTS (msg:"SQL
Injection - Paranoid";
flow:to_server,established;uricontent:".pl";pcre:"/(\%27)|(&#8217;)|(--)|(%23)|(#)/i";
classtype:Web-application-attack; sid:9099; rev:5;)</p>
<p>在本篇讨论中, uricontent关键字的值为".pl ", 因为在我们的测试环境里, CGI
程序是用Perl写的。uricontent关键字的值取决于您的特殊应用, 这个值也许是".php ", 或" .asp ", 或" .jsp
", 等。 从这点考虑, 我们不显示对应的Snort 规则, 但是我们会给出创造这些规则的正则表达式。
通过这些正则表达式你可以很简单的创造很多的Snort规则.在前面的正则表达式里,
我们检测双重破折号是因为：即便没有单引号的存在那里也可能是SQL射入点[ref 6]。 例如, SQL查询条目只包含数值，如下:</p>
<p>select value1, value2, num_value3 from database <br />
where num_value3=some_user_supplied_number</p>
<p>这种情况，攻击者可以执行额外的SQL查询, 示范提交如下输入:</p>
<p>3; insert values into some_other_table</p>
<p>最后, pcre的修饰符&#8217; i&#8217; 和&#8217; x &#8217; 是用于分别匹配大小写和忽略空白处的。
上面的规则也可以另外扩展来检查分号的存在。然而，分号很可以是正常HTTP应答的一部分。为了减少这种错误，也是为了任何正常的单引号和双重扩折号的出
现，上面的规则应该被修改成先检测＝号的存。用户输入会响应一个GET或POST请求，一般输入提交如下：</p>
<p>username=some_user_supplied_value&amp;password=some_user_supplied_value</p>
<p>因此, SQL 注入尝试将导致用户的输入出现在a = 号或它等效的hex值之后。</p>
<p><strong>2.2 修正检测SQL meta-characters的正则表达式</strong></p>
<p>/((\%3D)|(=))[^ ]*((\%27)|(&#8217;)|(--)|(\%3B)|(:))/i</p>
<p><strong>解释:</strong></p>
<p>这个规则首先留意 = 号或它的hex值(%3D)，然后考虑零个或多个除换行符以外的任意字符，最后检测单引号，双重破折号或分号。</p>
<p>典型的SQL注入会尝试围绕单引号的用途操作原来的查询，以便得到有用的价值。讨论这个攻击一般使用1&#8217;or&#8217;1&#8217;=&#8217;1字符串. 但是,
这个串的侦查很容易被逃避，譬如用1&#8217;or2&gt;1 --.
然而唯一恒定的部分是最初的字符的值，跟随一单引号，再加&#8217;or&#8217;。随后的布尔逻辑可能在一定范围上变化，可以是普通样式也可能是非常复杂的。这些攻击可
以相当精确被侦测，通过以下的正则表达式。2.3章节讲解。</p>
<p><strong>2.3 典型的 SQL 注入攻击的正则表达式</strong></p>
<strong>
<p>/w*((\%27)|(&#8217;))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix</p>
<p><strong>解释:</strong> <br />
w* - 零个或多个字符或者下划线。 <br />
(\%27)|&#8217; - 单引号或它的hex等值。 <br />
(\%6 F)|o|(\%4 F))((\%72)|r|-(\%52) －&#8216;or&#8217;的大小写以及它的hex等值。</p>
<p>union&#8217;SQL 查询在SQL注入各种数据库中攻击中同样是很常见的。如果前面的正则表达式仅仅检测单引号或则其他的SQL meta
characters
，会造成很多的错误存在。你应该进一步修改查询，检测单引号和关键字&#8216;union&#8217;。这同样可以进一步扩展其他的SQL关键字，像&#8217;select&#8217;,
&#8217;insert&#8217;, &#8217;update&#8217;, &#8217;delete&#8217;, 等等。</p>
<p><strong>2.4 检测SQL注入，UNION查询关键字的正则表达式</strong></p>
<p>/((\%27)|(&#8217;))union/ix</p>
<p>(\%27)|(&#8217;) - 单引号和它的hex等值 <br />
union - union关键字</p>
<p>可以同样为其他SQL查询定制表达式，如 &gt;select, insert, update, delete, drop, 等等.</p>
<p>如果，到这个阶段，攻击者已经发现web应用程序存在SQL注入漏洞，他将尝试利用它。如果他认识到后端服务器式MS SQL
server，他一般会尝试运行一些危险的储存和扩展储存过程。这些过程一般以&#8216;sp&#8217;或&#8216;xp&#8217;字母开头。典型的，他可能尝试运行
&#8216;xp_cmdshell&#8217;扩展储存过程（通过SQL Server执行Windows
命令）。SQL服务器的SA权限有执行这些命令的权限。同样他们可以通过xp_regread, xp_regwrite等储存过程修改注册表。</p>
<p><strong>2.5 检测MS SQL Server SQL注入攻击的正则表达式</strong></p>
<p>/exec(s|+)+(s|x)pw+/ix</p>
<p><strong>解释:</strong> <br />
exec - 请求执行储存或扩展储存过程的关键字 <br />
(s|+)+ - 一个或多个的空白或它们的http等值编码 <br />
(s|x) p- &#8216;sp&#8217;或&#8216;xp&#8217;字母用来辨认储存或扩展储存过程 <br />
w+ - 一个或多个字符或下划线来匹配过程的名称</p>
<p><strong>3. 跨站脚本(CSS)的正则表达式</strong></p>
<p>当发动CSS攻击或检测一个网站漏洞的时候,
攻击者可能首先使简单的HTML标签如&lt;b&gt;(粗体),&lt;i&gt;(斜体)或&lt;u&gt;(下划线)，或者他可能尝试简单的
script标签如&lt;script&gt;alert("OK")&lt;/script&gt;.
因为大多数出版物和网络传播的检测网站是否有css漏洞都拿这个作为例子。这些尝试都可以很简单的被检测出来。
然而，高明点的攻击者可能用它的hex值替换整个字符串。这样&lt;script&gt;标签会以%3C%73%63%72%69%70%74%3E出
现。
另一方面，攻击者可能使用web代理服务器像Achilles会自动转换一些特殊字符如&lt;换成%3C、&gt;换成%3E.这样攻击发生时，URL
中通常以hex等值代替角括号。</p>
<p>下列正则表达式将检测任何文本中包含的html的&lt;、&gt;。它将捉住试图使用&lt;
b&gt;、&lt;u&gt;、或&lt;script&gt;。这正则表达式应该忽略大小写。我们需要同时检测角括号和它的hex等值(%
3C|&lt;)。检测hex进制转化的整个字符串，我们必须检测用户输入的数字和%号，即使用[a-z0-9%]
。这可能会导致一些错误出现，不是大部分会检测到真实攻击的。</p>
<p><strong>3.1 一般 CSS 攻击的正则表达式</strong></p>
<p>/((\%3C)|&lt;)((\%2F)|/)*[a-z0-9\%]+((\%3E)|&gt;)/ix</p>
<p><strong>解释:</strong> <br />
((\%3C)|&lt;) －检查&lt;和它hex等值 <br />
((\%2F)|/)*－结束标签/或它的 hex等值 <br />
[a-z0-9\%]+ －检查标签里的字母或它hex等值 <br />
((\%3E)|&gt;) －检查&gt;或它的hex等值</p>
<p><strong>Snort 规则:</strong> <br />
alert tcp $EXTERNAL_NET any -&gt; $HTTP_SERVERS $HTTP_PORTS (msg:"NII
Cross-site scripting attempt"; flow:to_server,established;
pcre:"/((\%3C)|&lt;)((\%2F)|/)*[a-z0-9\%]+((\%3E)|&gt;)/i";
classtype:Web-application-attack; sid:9000; rev:5;)</p>
<p>跨站脚本同样可以使用&lt;img src=&gt;技术。现行默认的snort规则可以被轻易避开。</p>
<p><strong>3.2章节提供了防止这种技术的方法。</strong></p>
<p>3.2 "&lt;img src" CSS 攻击正则表达式</p>
<p>/((\%3C)|&lt;)((\%69)|i|(\%49))((\%6D)|m|(\%4D))((\%67)|g|(\%47))[^
]+((\%3E)|&gt;)/I</p>
<p><strong>解释:</strong> <br />
(\%3 C)|&lt;) -&lt;或它的hex等值 <br />
(\%69)|i|(\%49))((\%6D)|m|(\%4D))((\%67)|g|(\%47)
-&#8217;img&#8217;字母或它的大小写hex等值的变化组合 <br />
[^ ]+ -除了换行符以外的任何跟随&lt;img的字符 <br />
(\%3E)|&gt;) -&gt;或它的hex等值</p>
<p>3.3 CSS 攻击的极端的正则表达式</p>
<p>/((\%3C)|&lt;)[^ ]+((\%3E)|&gt;)/I</p>
<p><strong>解释:</strong></p>
<p>这个规则简单寻找&lt;+除换行符外的任何字符+&gt;。由于你的web服务器和web应用程序的构架，这个规则可能产生一些错误。但它能保证
捉住任何CCS或者类似CSS的攻击。</p>
<p><strong>总结:</strong></p>
<p>在
这篇文章中，我们提出了不同种类的正则表达式规则来检测SQL注入和跨站脚本攻击。有些规则简单而极端，一个潜在的攻击都将提高警惕。但这些极端的规则可
能导致一些主动的错误。考虑到这点，我们修改了这些简单的规则，利用了另外的样式，他们可以检查的更准确些。在这些网络应用成的攻击检测中，我们推荐将这
些作为调试你IDS或日志分析方法的起点。再经过几次修改后，在你对正常网交易部分的非恶意应答进行评估以后，你应该可以准备的检测那些攻击了。<strong>
<p>这篇是翻译老外的文章，css 跨站攻击只需过滤掉html尖括号即可，擦，又被专家们忽悠了，网上盛传的</p>
<p>完整的XSS wrom安全检测实例示范，第一次就把标记对都过滤了，下面竟然还用标记测试，啥逻辑，我只想知道是怎么成功的，搞笑，误人</p>
</strong></p>
</strong></div>
<img src ="http://www.blogjava.net/Todd/aggbug/323154.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-06-09 14:50 <a href="http://www.blogjava.net/Todd/archive/2010/06/09/323154.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矛与盾的较量（4）——奇妙的Base64编码</title><link>http://www.blogjava.net/Todd/archive/2010/05/20/321432.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Wed, 19 May 2010 17:48:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/05/20/321432.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/321432.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/05/20/321432.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/321432.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/321432.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 下载本节例子程序 (6.93 KB)各位看官应该都是资深的网虫了，小弟斗胆在此问问大家，平时上网时，除了泡MM、到论坛灌水、扔版砖&#8230;&#8230;之外，进行的最多的是什么活动？对了，你一定会说：是收发电子邮件！（谁敢说自己没收/发过电子邮件的？拉出去枪毙了！！）收/发E-mail的时候有一个安全性的问题——假想一下，你花了一整天时间给系花写的情书，在发送的过程中被隔壁宿...&nbsp;&nbsp;<a href='http://www.blogjava.net/Todd/archive/2010/05/20/321432.html'>阅读全文</a><img src ="http://www.blogjava.net/Todd/aggbug/321432.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-05-20 01:48 <a href="http://www.blogjava.net/Todd/archive/2010/05/20/321432.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矛与盾的较量（3）——CRC实践篇</title><link>http://www.blogjava.net/Todd/archive/2010/05/20/321431.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Wed, 19 May 2010 17:47:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/05/20/321431.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/321431.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/05/20/321431.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/321431.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/321431.html</trackback:ping><description><![CDATA[<a href="http://www.luocong.com/articles/zipped/CRC32_Test.zip">下载本节例子程序</a> (13.4 KB)<br />
<strong>（特别感谢汇编高手 <font color="red">dREAMtHEATER</font> 对我的代码作出了相当好的优化！请参观他的<a href="http://notexpad.yeah.net/" target="_blank">主页</a>）</strong><br />
<br />
上一节里我们介绍了CRC-32的实现原理，可是原理不能当饭吃吧？下面让我们来看看CRC是怎么应用到文件保护上的&#8230;&#8230;<br />
<br />
（由于本文涉及到的源代码比较多，so请各位读者自行下载代码进行分析）<br />
<br />
在
《原理篇》里面，我们已经知道，通过对一个字符串进行CRC-32转换，最后可以得到一个4个字节长的CRC-32值，而且无论该字符串有多长，最终生成
的CRC-32值都肯定是4个字节长。这就给了我们一个启示：是否能够在一个文件的某个地方储存这个CRC-32值，然后在文件运行的时候，再读取这个
CRC-32值，进行比较？<br />
<br />
答案是肯定的。让我们先来看看PE文件的结构：（什么？你不懂PE文件结构？！那&#8230;&#8230;先去找点资料看看吧，到处都有的哦）<br />
<br />
在
PE的可选映像头（IMAGE_OPTIONAL_HEADER）里面，有一个保留字段：Win32Version，根据MSDN的资料，它的值一般是
0，而且它的长度是4个DWORD。呵呵，你是不是已经想到什么了呢？对了，它的长度和我们要储存的CRC-32正好是相等的，而且它的值是不变的，一般
是0（别问我为什么啊，我也不知道）。这就给我们提供了一个储存CRC-32空间的可能，而实际上，有很多Win32病毒也是利用这个
Win32Verion保留字段来储存它们的感染标志的。<br />
<br />
好了，明确了目标，我们来看看具体应该怎么实现：<br />
<br />
1、先写一个
第三方的程序，我假设它叫&#8220;AddCRC32ToFile.exe&#8221;。我们可以利用这个程序，打开一个文件，假设这个文件叫做
&#8220;CRC32_Test.exe&#8221;，然后&#8220;AddCRC32ToFile.exe&#8221;就会计算出&#8220;CRC32_Test.exe&#8221;的CRC-32值，并把这
个CRC-32值写入&#8220;CRC32_Test.exe&#8221;的Win32Version处。（其实这步要到最后才做的）<br />
<br />
2、写好需要进行保护
的程序，在这里我假设它叫做&#8220;CRC32_Test.exe&#8221;，记住一定要在这个程序里面加入CRC-32的校验模块。这个校验模块的工作过程是这样
的：a、先读取自身文件的所有内容，储存在一个字符串中，然后把这个字符串的Win32Version处的4个字节改成4个0，再把字符串进行CRC-
32转换，这时我们就得到了一个&#8220;原始&#8221;文件的CRC-32值；b、读取自身文件的Win32Version处的值，这个值是我们通过
&#8220;AddCRC32ToFile.exe&#8221;写进去的。最后我们把步骤a和b中得到的两个CRC-32值进行比较，如果相等的话，说明文件没有被修改过；反
之就说明文件已经被修改了。<br />
<br />
很复杂是吧？其实好好想一想，没啥困难的。关键是要按照以下步骤进行：<br />
<br />
1、一定要先在
&#8220;CRC32_Test.exe&#8221;里面写好所有的模块，然后才用&#8220;AddCRC32ToFile.exe&#8221;把&#8220;CRC32_Test.exe&#8221;的CRC-
32值写入&#8220;CRC32_Test.exe&#8221;的Win32Version处，否则最后得到的结果肯定是不正确的。顺序一定不能搞错！！！<br />
<br />
2、今后一旦修改了&#8220;CRC32_Test.exe&#8221;的内容（比如重新编译了一次），就一定要再用&#8220;AddCRC32ToFile.exe&#8221;重新把CRC-32值写入&#8220;CRC32_Test.exe&#8221;中去，否则结果也是会不正确的。<br />
<br />
其实方案不止这一种，还有以下的几种是可行的：<br />
1、把CRC-32的值写入一个单独的DLL文件中（或者别的什么乱七八糟的地方，随你的便），然后在运行的时候读取DLL文件中储存好的CRC-32值，进行比较。<br />
2、把CRC-32的值追加到.exe文件的最后，在运行的时候读取这最后的4个字节的内容，进行比较。不过我觉得这样做不太好，呵呵，因为增加了文件的长度。<br />
&#8230;&#8230;<br />
<br />
我的方案的缺点分析：<br />
CRC-32的值其实可以由Cracker自行计算得出后，重新写入到Win32Version处。这样的话，我们做的工作岂不是没有意义了？<br />
其
实解决的方法还是有的，我们可以在计算CRC-32值之前，对需要进行转换的字符串加点手脚，例如对这个字符串进行移位、xor等操作，或者把自己的生日
等信息加入到字符串中，随你的便什么都行，总之不是单纯的文件的内容就行了，然后在最后比较的时候，也用同样的方法反计算出CRC-32值。这样得到的
CRC-32就不是由文件的内容计算出来的，相信对Cracker的阻力也会加大不少。<br />
<br />
总结：<br />
应用CRC原理到文件的自校验保护中，是一种很灵活的手段，可用的方法有很多种。本文只是抛砖引玉，希望高手能给出更好的解决方法，并请发信到<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#99;&#111;&#116;&#104;&#101;&#114;&#64;&#49;&#54;&#51;&#46;&#110;&#101;&#116;&#63;&#115;&#117;&#98;&#106;&#101;&#99;&#116;&#61;&#37;&#69;&#56;&#37;&#56;&#48;&#37;&#56;&#49;&#37;&#69;&#55;&#37;&#66;&#68;&#37;&#57;&#55;&#37;&#69;&#70;&#37;&#66;&#67;&#37;&#56;&#67;&#37;&#69;&#54;&#37;&#57;&#67;&#37;&#56;&#57;&#37;&#69;&#53;&#37;&#56;&#53;&#37;&#66;&#51;&#67;&#82;&#67;&#45;&#51;&#50;&#37;&#69;&#55;&#37;&#57;&#65;&#37;&#56;&#52;&#37;&#69;&#57;&#37;&#57;&#55;&#37;&#65;&#69;&#37;&#69;&#57;&#37;&#65;&#50;&#37;&#57;&#56;&#37;&#69;&#54;&#37;&#56;&#51;&#37;&#66;&#51;&#37;&#69;&#56;&#37;&#66;&#55;&#37;&#57;&#70;&#37;&#69;&#52;&#37;&#66;&#68;&#37;&#65;&#48;&#37;&#69;&#55;&#37;&#65;&#48;&#37;&#57;&#52;&#37;&#69;&#55;&#37;&#65;&#57;&#37;&#66;&#54;&#37;&#69;&#70;&#37;&#66;&#67;&#37;&#56;&#49;" title="共同研究！">lcother@163.net</a>，我们共同研究，多谢！！！
<img src ="http://www.blogjava.net/Todd/aggbug/321431.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-05-20 01:47 <a href="http://www.blogjava.net/Todd/archive/2010/05/20/321431.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矛与盾的较量（2）——CRC原理篇</title><link>http://www.blogjava.net/Todd/archive/2010/05/20/321430.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Wed, 19 May 2010 17:45:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/05/20/321430.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/321430.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/05/20/321430.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/321430.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/321430.html</trackback:ping><description><![CDATA[<a href="http://www.luocong.com/articles/zipped/CRC32_base.zip">下载本节例子程序</a> (4.29 KB)<br />
<strong>（特别感谢汇编高手 <font color="red">dREAMtHEATER</font> 对我的代码作出了相当好的优化！请参观他的<a href="http://notexpad.yeah.net/" target="_blank">主页</a>）</strong><br />
<br />
上一节我们介绍了花指令，不过花指令毕竟是一种很简单的东西，基本上入了门的Cracker都可以对付得了。所以，我们很有必要给自己的软件加上更好的保护。CRC校验就是其中的一种不错的方法。<br />
<br />
CRC
是什么东西呢？其实我们大家都不应该会对它陌生，回忆一下？你用过RAR和ZIP等压缩软件吗？它们是不是常常会给你一个恼人的&#8220;CRC校验错误&#8221;信息
呢？我想你应该明白了吧，CRC就是块数据的计算值，它的全称是&#8220;Cyclic Redundancy
Check&#8221;，中文名是&#8220;循环冗余码&#8221;，&#8220;CRC校验&#8221;就是&#8220;循环冗余校验&#8221;。（哇，真拗口，希望大家不要当我是唐僧，呵呵。^_^）<br />
<br />
CRC
有什么用呢？它的应用范围很广泛，最常见的就是在网络传输中进行信息的校对。其实我们大可以把它应用到软件保护中去，因为它的计算是非常非常非常严格的。
严格到什么程度呢？你的程序只要被改动了一个字节（甚至只是大小写的改动），它的值就会跟原来的不同。Hoho，是不是很厉害呢？所以只要给你的&#8220;原&#8221;程
序计算好CRC值，储存在某个地方，然后在程序中随机地再对文件进行CRC校验，接着跟第一次生成并保存好的CRC值进行比较，如果相等的话就说明你的程
序没有被修改/破解过，如果不等的话，那么很可能你的程序遭到了病毒的感染，或者被Cracker用16进制工具暴力破解过了。<br />
<br />
废话说完了，我们先来看看CRC的原理。<br />
（由于CRC实现起来有一定的难度，所以具体怎样用它来保护文件，留待下一节再讲。）<br />
<br />
首先看两个式子：<br />
式一：9 / 3 = 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（余数 = 0）<br />
式二：(9 + 2 ) / 3 = 3&nbsp;&nbsp; （余数 = 2）<br />
<br />
在小学里我们就知道，除法运算就是将被减数重复地减去除数X次，然后留下余数。<br />
所以上面的两个式子可以用二进制计算为：（什么？你不会二进制计算？我倒～～～）<br />
<br />
式一：<br />
1001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 9<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp; --&gt; 3<br />
---------<br />
0110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 6<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp; --&gt; 3<br />
---------<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 3<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp; --&gt; 3<br />
---------<br />
0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 0，余数<br />
一共减了3次，所以商是3，而最后一次减出来的结果是0，所以余数为0<br />
<br />
式二：<br />
1011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 11<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp; --&gt; 3<br />
---------<br />
1000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 8<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp; --&gt; 3<br />
---------<br />
0101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 5<br />
0011&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp; --&gt; 3<br />
---------<br />
0010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 2,余数<br />
一共减了3次，所以商是3，而最后一次减出来的结果是2，所以余数为2<br />
<br />
看明白了吧？很好，let&#8217;s go on!<br />
<br />
二进制减法运算的规则是，如果遇到0-1的情况，那么要从高位借1，就变成了(10+0)-1=1<br />
CRC运算有什么不同呢？让我们看下面的例子：<br />
<br />
这次用式子30 / 9，不过请读者注意最后的余数：<br />
<br />
11110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 30<br />
1001&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 9<br />
---------<br />
&nbsp;1100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 12&nbsp;&nbsp;&nbsp;&nbsp;（很奇怪吧？为什么不是21呢？）<br />
&nbsp;1001&nbsp;&nbsp; -&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 9<br />
&nbsp;--------<br />
&nbsp;&nbsp;101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 5，余数 --&gt; the CRC!<br />
<br />
这个式子的计算过程是不是很奇怪呢？它不是直接减的，而是用XOR的方式来运算（程序员应该都很熟悉XOR吧），最后得到一个余数。<br />
<br />
对啦，这个就是CRC的运算方法，明白了吗？CRC的本质是进行XOR运算，运算的过程我们不用管它，因为运算过程对最后的结果没有意义；我们真正感兴趣的只是最终得到的余数，这个余数就是CRC值。<br />
<br />
进行一个CRC运算我们需要选择一个除数，这个除数我们叫它为&#8220;poly&#8221;，宽度W就是最高位的位置，所以我刚才举的例子中的除数9，这个poly 1001的W是3，而不是4，注意最高位总是1。（别问为什么，这个是规定）<br />
<br />
如果我们想计算一个位串的CRC码，我们想确定每一个位都被处理过，因此，我们要在目标位串后面加上W个0位。现在让我们根据CRC的规范来改写一下上面的例子：<br />
<br />
Poly&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;1001，宽度W = 3<br />
位串Bitstring&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;11110<br />
Bitstring + W zeroes&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;11110 + 000 = 11110000<br />
<br />
11110000<br />
1001||||&nbsp;&nbsp;&nbsp;&nbsp;-<br />
-------------<br />
&nbsp;1100|||<br />
&nbsp;1001|||&nbsp;&nbsp;&nbsp;&nbsp;-<br />
&nbsp;------------<br />
&nbsp;&nbsp;1010||<br />
&nbsp;&nbsp;1001||&nbsp;&nbsp;&nbsp;&nbsp;-<br />
&nbsp;&nbsp;-----------<br />
&nbsp;&nbsp; 0110|<br />
&nbsp;&nbsp; 0000|&nbsp;&nbsp;&nbsp;&nbsp;-<br />
&nbsp;&nbsp; ----------<br />
&nbsp;&nbsp;&nbsp;&nbsp;1100<br />
&nbsp;&nbsp;&nbsp;&nbsp;1001&nbsp;&nbsp;&nbsp;&nbsp;-<br />
&nbsp;&nbsp;&nbsp;&nbsp;---------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt; 5，余数 --&gt; the CRC!<br />
<br />
还有两点重要声明如下：<br />
1、只有当Bitstring的最高位为1，我们才将它与poly进行XOR运算，否则我们只是将Bitstring左移一位。<br />
2、XOR运算的结果就是被操作位串Bitstring与poly的低W位进行XOR运算，因为最高位总为0。<br />
<br />
呵呵，是不是有点头晕脑胀的感觉了？看不懂的话，再从头看一遍，其实是很好理解的。（就是一个XOR运算嘛！）<br />
<br />
<br />
好啦，原理介绍到这里，下面我讲讲具体怎么编程。<br />
<br />
由于速度的关系，CRC的实现主要是通过查表法，对于CRC-16和CRC-32，各自有一个现成的表，大家可以直接引入到程序中使用。（由于这两个表太长，在这里不列出来了，请读者自行在网络上查找，很容易找到的。）<br />
<br />
如果我们没有这个表怎么办呢？或者你跟我一样，懒得自己输入？不用急，我们可以&#8220;自己动手，丰衣足食&#8221;。<br />
你可能会说，自己编程来生成这个表，会不会太慢了？其实大可不必担心，因为我们是在汇编代码的级别进行运算的，而这个表只有区区256个双字，根本影响不了速度。<br />
<br />
这个表的C语言描述如下：<br />
<br />
<table bgcolor="#fbedbb" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td><a name="L1"><font color="#ff0000">for</font> <font color="#ff00ff">(</font>i <font color="#3080ca">=</font> <font color="#802000">0</font><font color="#9932cd"><strong>;</strong></font> i <font color="#3080ca">&lt;</font> <font color="#802000">256</font><font color="#9932cd"><strong>;</strong></font> i<font color="#3080ca">++</font><font color="#ff00ff">)</font><br />
            </a><a name="L2"><font color="#db3098">{</font><br />
            </a><a name="L3">&nbsp;&nbsp;&nbsp;&nbsp;crc <font color="#3080ca">=</font> i<font color="#9932cd"><strong>;</strong></font><br />
            </a><a name="L4">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">for</font> <font color="#ff00ff">(</font>j <font color="#3080ca">=</font> <font color="#802000">0</font><font color="#9932cd"><strong>;</strong></font> j <font color="#3080ca">&lt;</font> <font color="#802000">8</font><font color="#9932cd"><strong>;</strong></font> j<font color="#3080ca">++</font><font color="#ff00ff">)</font><br />
            </a><a name="L5">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#db3098">{</font><br />
            </a><a name="L6">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">if</font> <font color="#ff00ff">(</font>crc <font color="#3080ca">&amp;</font> <font color="#802000">1</font><font color="#ff00ff">)</font><br />
            </a><a name="L7">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crc <font color="#3080ca">=</font> <font color="#ff00ff">(</font>crc <font color="#3080ca">&gt;&gt;</font> <font color="#802000">1</font><font color="#ff00ff">)</font> <font color="#3080ca">^</font> <font color="#802000">0xEDB88320</font><font color="#9932cd"><strong>;</strong></font><br />
            </a><a name="L8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">else</font><br />
            </a><a name="L9">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crc <font color="#3080ca">&gt;&gt;=</font> <font color="#802000">1</font><font color="#9932cd"><strong>;</strong></font><br />
            </a><a name="L10">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#db3098">}</font><br />
            </a><a name="L11">&nbsp;&nbsp;&nbsp;&nbsp;crc32tbl<font color="#871f78">[</font>i<font color="#871f78">]</font> <font color="#3080ca">=</font> crc<font color="#9932cd"><strong>;</strong></font><br />
            </a><a name="L12"><font color="#db3098">}</font></a></td>
        </tr>
    </tbody>
</table>
<br />
生成表之后，就可以进行运算了。<br />
我们的算法如下：<br />
1、将寄存器向右边移动一个字节。<br />
2、将刚移出的那个字节与我们的字符串中的新字节进行XOR运算，得出一个指向值表table[0..255]的索引。<br />
3、将索引所指的表值与寄存器做XOR运算。<br />
4、如果数据没有全部处理完，则跳到步骤1。<br />
<br />
这个算法的C语言描述如下：<br />
<br />
<table bgcolor="#fbedbb" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td><a name="L1">&nbsp;&nbsp;&nbsp;&nbsp;temp <font color="#3080ca">=</font> <font color="#ff00ff">(</font>oldcrc <font color="#3080ca">^</font> abyte<font color="#ff00ff">)</font> <font color="#3080ca">&amp;</font> <font color="#802000">0x000000FF</font><font color="#9932cd"><strong>;</strong></font><br />
            </a><a name="L2">&nbsp;&nbsp;&nbsp;&nbsp;crc&nbsp;&nbsp;<font color="#3080ca">=</font> <font color="#ff00ff">(</font><font color="#ff00ff">(</font> oldcrc <font color="#3080ca">&gt;&gt;</font> <font color="#802000">8</font><font color="#ff00ff">)</font> <font color="#3080ca">&amp;</font> <font color="#802000">0x00FFFFFF</font><font color="#ff00ff">)</font> <font color="#3080ca">^</font> crc32tbl<font color="#871f78">[</font>temp<font color="#871f78">]</font><font color="#9932cd"><strong>;</strong></font><br />
            </a><a name="L3">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">return</font> crc<font color="#9932cd"><strong>;</strong></font></a></td>
        </tr>
    </tbody>
</table>
<br />
好啦，所有的东东都说完啦，最后献上一个完整的Win32Asm例子，请读者仔细研究吧！<br />
（汇编方面的CRC-32资料极少啊，我个人认为下面给出的是很宝贵的资料。）<br />
<br />
<br />
<table bgcolor="#fbedbb" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td><a name="L1"><font color="#238e23">;****************************************************</font><br />
            </a><a name="L2"><font color="#238e23">;程序名称：演示CRC32原理</font><br />
            </a><a name="L3"><font color="#238e23">;作者：罗聪</font><br />
            </a><a name="L4"><font color="#238e23">;日期：2002-8-24</font><br />
            </a><a name="L5"><font color="#238e23">;出处：http://laoluoc.yeah.net（老罗的缤纷天地）</font><br />
            </a><a name="L6"><font color="#238e23">;注意事项：如欲转载，请保持本程序的完整，并注明：转载自&#8220;老罗的缤纷天地&#8221;（http://laoluoc.yeah.net）</font><br />
            </a><a name="L7"><font color="#238e23">;</font><br />
            </a><a name="L8"><font color="#238e23">;特别感谢Win32ASM高手—— dREAMtHEATER 为我的代码作了相当好的优化！</font><br />
            </a><a name="L9"><font color="#238e23">;请各位前去 http://NoteXPad.yeah.net 下载他的小巧的&#8220;cool 记事本&#8221;—— NoteXPad 来试用！（100% Win32ASM 编写）</font><br />
            </a><a name="L10"><font color="#238e23">;</font><br />
            </a><a name="L11"><font color="#238e23">;****************************************************</font><br />
            </a><a name="L12"><br />
            </a><a name="L13"><font color="#9932cd"><strong>.</strong></font><font color="#802000">386</font><br />
            </a><a name="L14"><font color="#9932cd"><strong>.</strong></font><font color="#ff0000">model</font> <font color="#ff0000">flat</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">stdcall</font><br />
            </a><a name="L15"><font color="#ff0000">option</font> <font color="#ff0000">casemap</font><font color="#3080ca">:</font>none<br />
            </a><a name="L16"><br />
            </a><a name="L17"><font color="#ff8000">include</font> windows.inc<br />
            </a><a name="L18"><font color="#ff8000">include</font> kernel32.inc<br />
            </a><a name="L19"><font color="#ff8000">include</font> user32.inc<br />
            </a><a name="L20"><font color="#ff8000">includelib</font> kernel32.lib<br />
            </a><a name="L21"><font color="#ff8000">includelib</font> user32.lib<br />
            </a><a name="L22"><br />
            </a><a name="L23">WndProc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">proto</font> <font color="#3080ca">:</font><font color="#ff0000">DWORD</font><font color="#9932cd"><strong>,</strong></font> <font color="#3080ca">:</font><font color="#ff0000">DWORD</font><font color="#9932cd"><strong>,</strong></font> <font color="#3080ca">:</font><font color="#ff0000">DWORD</font><font color="#9932cd"><strong>,</strong></font> <font color="#3080ca">:</font><font color="#ff0000">DWORD</font><br />
            </a><a name="L24">init_crc32table&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">proto</font><br />
            </a><a name="L25">arraycrc32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">proto</font><br />
            </a><a name="L26"><br />
            </a><a name="L27"><font color="#9932cd"><strong>.</strong></font><font color="#ff0000">const</font><br />
            </a><a name="L28">IDC_BUTTON_OPEN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">equ</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">3000</font><br />
            </a><a name="L29">IDC_EDIT_INPUT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">equ</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">3001</font><br />
            </a><a name="L30"><br />
            </a><a name="L31"><font color="#9932cd"><strong>.</strong></font><font color="#ff0000">data</font><br />
            </a><a name="L32">szDlgName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">db</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">"lc_dialog"</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">0</font><br />
            </a><a name="L33">szTitle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">db</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">"CRC demo by LC"</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">0</font><br />
            </a><a name="L34">szTemplate&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">db</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">"字符串 ""%s"" 的 CRC32 值是：%X"</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">0</font><br />
            </a><a name="L35">crc32tbl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">dd</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">256</font> <font color="#ff0000">dup</font><font color="#ff00ff">(</font><font color="#802000">0</font><font color="#ff00ff">)</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;CRC-32 table</font><br />
            </a><a name="L36">szBuffer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">db</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">255</font> <font color="#ff0000">dup</font><font color="#ff00ff">(</font><font color="#802000">0</font><font color="#ff00ff">)</font><br />
            </a><a name="L37"><br />
            </a><a name="L38"><font color="#9932cd"><strong>.</strong></font><font color="#ff0000">data</font><font color="#3080ca">?</font><br />
            </a><a name="L39">szText&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">db</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">300</font> <font color="#ff0000">dup</font><font color="#ff00ff">(</font><font color="#3080ca">?</font><font color="#ff00ff">)</font><br />
            </a><a name="L40"><br />
            </a><a name="L41"><font color="#9932cd"><strong>.</strong></font><font color="#ff0000">code</font><br />
            </a><a name="L42">main<font color="#3080ca">:</font><br />
            </a><a name="L43">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> GetModuleHandle<font color="#9932cd"><strong>,</strong></font> NULL<br />
            </a><a name="L44">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> DialogBoxParam<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">offset</font> szDlgName<font color="#9932cd"><strong>,</strong></font> <font color="#802000">0</font><font color="#9932cd"><strong>,</strong></font> WndProc<font color="#9932cd"><strong>,</strong></font> <font color="#802000">0</font><br />
            </a><a name="L45">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> ExitProcess<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">eax</font><br />
            </a><a name="L46"><br />
            </a><a name="L47">WndProc <font color="#ff0000">proc</font> <font color="#ff0000">uses</font> <font color="#ff0000">ebx</font> hWnd<font color="#3080ca">:</font>HWND<font color="#9932cd"><strong>,</strong></font> uMsg<font color="#3080ca">:</font>UINT<font color="#9932cd"><strong>,</strong></font> wParam<font color="#3080ca">:</font>WPARAM<font color="#9932cd"><strong>,</strong></font> lParam<font color="#3080ca">:</font>LPARAM<br />
            </a><a name="L48"><br />
            </a><a name="L49">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">if</font> uMsg <font color="#3080ca">=</font><font color="#3080ca">=</font> WM_CLOSE<br />
            </a><a name="L50">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> EndDialog<font color="#9932cd"><strong>,</strong></font> hWnd<font color="#9932cd"><strong>,</strong></font> <font color="#802000">0</font><br />
            </a><a name="L51">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            </a><a name="L52">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">elseif</font> uMsg <font color="#3080ca">=</font><font color="#3080ca">=</font> WM_COMMAND<br />
            </a><a name="L53">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font> <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font>wParam<br />
            </a><a name="L54">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font> <font color="#ff0000">edx</font><font color="#9932cd"><strong>,</strong></font><font color="#ff0000">eax</font><br />
            </a><a name="L55">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">shr</font> <font color="#ff0000">edx</font><font color="#9932cd"><strong>,</strong></font><font color="#802000">16</font><br />
            </a><a name="L56">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">movzx</font> <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">ax</font><br />
            </a><a name="L57">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">if</font> <font color="#ff0000">edx</font> <font color="#3080ca">=</font><font color="#3080ca">=</font> BN_CLICKED<br />
            </a><a name="L58">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">IF</font> <font color="#ff0000">eax</font> <font color="#3080ca">=</font><font color="#3080ca">=</font> IDCANCEL<br />
            </a><a name="L59">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> EndDialog<font color="#9932cd"><strong>,</strong></font> hWnd<font color="#9932cd"><strong>,</strong></font> NULL<br />
            </a><a name="L60">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">ELSEIF</font> <font color="#ff0000">eax</font> <font color="#3080ca">=</font><font color="#3080ca">=</font> IDC_BUTTON_OPEN <font color="#3080ca">|</font><font color="#3080ca">|</font> <font color="#ff0000">eax</font> <font color="#3080ca">=</font><font color="#3080ca">=</font> IDOK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            </a><a name="L61">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;******************************************</font><br />
            </a><a name="L62">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;关键代码开始：（当当当当&#8230;&#8230;）</font><br />
            </a><a name="L63">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;******************************************</font><br />
            </a><a name="L64">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;取得用户输入的字符串：</font><br />
            </a><a name="L65">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> GetDlgItemText<font color="#9932cd"><strong>,</strong></font> hWnd<font color="#9932cd"><strong>,</strong></font> IDC_EDIT_INPUT<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">addr</font> szBuffer<font color="#9932cd"><strong>,</strong></font> <font color="#802000">255</font><br />
            </a><a name="L66"><br />
            </a><a name="L67">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;初始化crc32table：</font><br />
            </a><a name="L68">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> init_crc32table<br />
            </a><a name="L69"><br />
            </a><a name="L70">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;下面赋值给寄存器ebx，以便进行crc32转换：</font><br />
            </a><a name="L71">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;EBX是待转换的字符串的首地址：</font><br />
            </a><a name="L72">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">lea</font> <font color="#ff0000">ebx</font><font color="#9932cd"><strong>,</strong></font> szBuffer<br />
            </a><a name="L73"><br />
            </a><a name="L74">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;进行crc32转换：</font><br />
            </a><a name="L75">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> arraycrc32<br />
            </a><a name="L76"><br />
            </a><a name="L77">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;格式化输出：</font><br />
            </a><a name="L78">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> wsprintf<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">addr</font> szText<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">addr</font> szTemplate<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">addr</font> szBuffer<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">eax</font><br />
            </a><a name="L79"><br />
            </a><a name="L80">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;好啦，让我们显示结果：</font><br />
            </a><a name="L81">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">invoke</font> MessageBox<font color="#9932cd"><strong>,</strong></font> hWnd<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">addr</font> szText<font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">addr</font> szTitle<font color="#9932cd"><strong>,</strong></font> MB_OK<br />
            </a><a name="L82">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">ENDIF</font><br />
            </a><a name="L83">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">endif</font><br />
            </a><a name="L84">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">ELSE</font><br />
            </a><a name="L85">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font> <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font>FALSE<br />
            </a><a name="L86">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">ret</font><br />
            </a><a name="L87">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#9932cd"><strong>.</strong></font><font color="#ff0000">ENDIF</font><br />
            </a><a name="L88">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font> <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font>TRUE<br />
            </a><a name="L89">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">ret</font><br />
            </a><a name="L90">WndProc <font color="#ff0000">endp</font><br />
            </a><a name="L91"><br />
            </a><a name="L92"><font color="#238e23">;**********************************************************</font><br />
            </a><a name="L93"><font color="#238e23">;函数功能：生成CRC-32表</font><br />
            </a><a name="L94"><font color="#238e23">;**********************************************************</font><br />
            </a><a name="L95">init_crc32table&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">proc</font><br />
            </a><a name="L96"><br />
            </a><a name="L97">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;如果用C语言来表示，应该如下：</font><br />
            </a><a name="L98">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;</font><br />
            </a><a name="L99">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; 256; i++)</font><br />
            </a><a name="L100">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;{</font><br />
            </a><a name="L101">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crc = i;</font><br />
            </a><a name="L102">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (j = 0; j &lt; 8; j++)</font><br />
            </a><a name="L103">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</font><br />
            </a><a name="L104">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (crc &amp; 1)</font><br />
            </a><a name="L105">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crc = (crc &gt;&gt; 1) ^ 0xEDB88320;</font><br />
            </a><a name="L106">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else</font><br />
            </a><a name="L107">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crc &gt;&gt;= 1;</font><br />
            </a><a name="L108">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</font><br />
            </a><a name="L109">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crc32tbl[i] = crc;</font><br />
            </a><a name="L110">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;}</font><br />
            </a><a name="L111">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;</font><br />
            </a><a name="L112">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;呵呵，让我们把上面的语句改成assembly的：</font><br />
            </a><a name="L113"><br />
            </a><a name="L114">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">ecx</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">256</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">; repeat for every DWORD in table</font><br />
            </a><a name="L115">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">edx</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">0EDB88320h</font><br />
            </a><a name="L116"><font color="#802000">$BigLoop</font><font color="#3080ca">:</font><br />
            </a><a name="L117">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">lea</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#871f78">[</font><font color="#ff0000">ecx</font><font color="#3080ca">-</font><font color="#802000">1</font><font color="#871f78">]</font><br />
            </a><a name="L118">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">push</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">ecx</font><br />
            </a><a name="L119">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">ecx</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">8</font><br />
            </a><a name="L120"><font color="#802000">$SmallLoop</font><font color="#3080ca">:</font><br />
            </a><a name="L121">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">shr</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">1</font><br />
            </a><a name="L122">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">jnc</font>&nbsp;&nbsp;&nbsp;&nbsp; @F<br />
            </a><a name="L123">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">xor</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">edx</font><br />
            </a><a name="L124">@@<font color="#3080ca">:</font><br />
            </a><a name="L125">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">dec</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">ecx</font><br />
            </a><a name="L126">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">jne</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#802000">$SmallLoop</font><br />
            </a><a name="L127">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">pop</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">ecx</font><br />
            </a><a name="L128">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#871f78">[</font>crc32tbl<font color="#3080ca">+</font><font color="#ff0000">ecx</font><font color="#3080ca">*</font><font color="#802000">4</font><font color="#3080ca">-</font><font color="#802000">4</font><font color="#871f78">]</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">eax</font><br />
            </a><a name="L129">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">dec</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">ecx</font><br />
            </a><a name="L130">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">jne</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#802000">$BigLoop</font><br />
            </a><a name="L131"><br />
            </a><a name="L132">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">ret</font><br />
            </a><a name="L133">init_crc32table&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">endp</font><br />
            </a><a name="L134"><br />
            </a><a name="L135"><br />
            </a><a name="L136"><font color="#238e23">;**************************************************************</font><br />
            </a><a name="L137"><font color="#238e23">;函数功能：计算CRC-32</font><br />
            </a><a name="L138"><font color="#238e23">;**************************************************************</font><br />
            </a><a name="L139">arraycrc32&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">proc</font><br />
            </a><a name="L140"><br />
            </a><a name="L141">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;计算 CRC-32 ，我采用的是把整个字符串当作一个数组，然后把这个数组的首地址赋值给 EBX，把数组的长度赋值给 ECX，然后循环计算，返回值（计算出来的 CRC-32 值）储存在 EAX 中：</font><br />
            </a><a name="L142">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;</font><br />
            </a><a name="L143">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">; 参数：</font><br />
            </a><a name="L144">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EBX = address of first byte</font><br />
            </a><a name="L145">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">; 返回值：</font><br />
            </a><a name="L146">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EAX = CRC-32 of the entire array</font><br />
            </a><a name="L147">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EBX = ?</font><br />
            </a><a name="L148">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ECX = 0</font><br />
            </a><a name="L149">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EDX = ?</font><br />
            </a><a name="L150"><br />
            </a><a name="L151">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#3080ca">-</font><font color="#802000">1</font> <font color="#238e23">; 先初始化eax</font><br />
            </a><a name="L152">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">or</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">ebx</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">ebx</font><br />
            </a><a name="L153">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">jz</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">$Done</font>&nbsp;&nbsp; <font color="#238e23">; 避免出现空指针</font><br />
            </a><a name="L154">@@<font color="#3080ca">:</font><br />
            </a><a name="L155">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">mov</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">dl</font><font color="#9932cd"><strong>,</strong></font> <font color="#871f78">[</font><font color="#ff0000">ebx</font><font color="#871f78">]</font><br />
            </a><a name="L156">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">or</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">dl</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">dl</font><br />
            </a><a name="L157">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">je</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#802000">$Done</font>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;判断是否对字符串扫描完毕</font><br />
            </a><a name="L158">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            </a><a name="L159"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;这里我用查表法来计算 CRC-32 ，因此非常快速：</font><br />
            </a><a name="L160">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;因为这是assembly代码，所以不需要给这个过程传递参数，只需要把oldcrc赋值给EAX，以及把byte赋值给DL：</font><br />
            </a><a name="L161">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;</font><br />
            </a><a name="L162">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">; 在C语言中的形式：</font><br />
            </a><a name="L163">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;</font><br />
            </a><a name="L164">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp; temp = (oldcrc ^ abyte) &amp; 0x000000FF;</font><br />
            </a><a name="L165">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp; crc&nbsp;&nbsp;= (( oldcrc &gt;&gt; 8) &amp; 0x00FFFFFF) ^ crc32tbl[temp];</font><br />
            </a><a name="L166">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;</font><br />
            </a><a name="L167">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">; 参数：</font><br />
            </a><a name="L168">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EAX = old CRC-32</font><br />
            </a><a name="L169">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DL = a byte</font><br />
            </a><a name="L170">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">; 返回值：</font><br />
            </a><a name="L171">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EAX = new CRC-32</font><br />
            </a><a name="L172">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#238e23">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EDX = ?</font><br />
            </a><a name="L173">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            </a><a name="L174">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">xor</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">dl</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">al</font><br />
            </a><a name="L175">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">movzx</font>&nbsp;&nbsp; <font color="#ff0000">edx</font><font color="#9932cd"><strong>,</strong></font> <font color="#ff0000">dl</font><br />
            </a><a name="L176">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">shr</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#802000">8</font><br />
            </a><a name="L177">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">xor</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><font color="#9932cd"><strong>,</strong></font> <font color="#871f78">[</font>crc32tbl<font color="#3080ca">+</font><font color="#ff0000">edx</font><font color="#3080ca">*</font><font color="#802000">4</font><font color="#871f78">]</font><br />
            </a><a name="L178">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            </a><a name="L179">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">inc</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">ebx</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            </a><a name="L180">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">jmp</font>&nbsp;&nbsp;&nbsp;&nbsp; @B<br />
            </a><a name="L181"><br />
            </a><a name="L182"><font color="#802000">$Done</font><font color="#3080ca">:</font><br />
            </a><a name="L183">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">not</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">eax</font><br />
            </a><a name="L184">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">ret</font><br />
            </a><a name="L185">arraycrc32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">endp</font><br />
            </a><a name="L186"><br />
            </a><a name="L187"><font color="#ff0000">end</font> main<br />
            </a><a name="L188"><font color="#238e23">;********************&nbsp;&nbsp;&nbsp;&nbsp;over&nbsp;&nbsp;&nbsp;&nbsp;********************</font><br />
            </a><a name="L189"><font color="#238e23">;by LC</font></a></td>
        </tr>
    </tbody>
</table>
<br />
<br />
下面是它的资源文件：<br />
<br />
<table bgcolor="#fbedbb" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td><strong><br />
            #include "resource.h"<br />
            <br />
            #define IDC_BUTTON_OPEN&nbsp;&nbsp;&nbsp;&nbsp;3000<br />
            #define IDC_EDIT_INPUT 3001<br />
            #define IDC_STATIC -1<br />
            <br />
            LC_DIALOG DIALOGEX 10, 10, 195, 60<br />
            STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | <br />
            &nbsp;&nbsp;&nbsp;&nbsp;WS_SYSMENU<br />
            CAPTION "lc&#8217;s assembly framework"<br />
            FONT 9, "宋体", 0, 0, 0x0<br />
            BEGIN<br />
            &nbsp;&nbsp;&nbsp;&nbsp;LTEXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "请输入一个字符串（区分大小写）：",IDC_STATIC,11,7,130,10<br />
            &nbsp;&nbsp;&nbsp;&nbsp;EDITTEXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IDC_EDIT_INPUT,11,20,173,12,ES_AUTOHSCROLL<br />
            &nbsp;&nbsp;&nbsp;&nbsp;DEFPUSHBUTTON&nbsp;&nbsp; "Ca&amp;lc",IDC_BUTTON_OPEN,71,39,52,15<br />
            END</strong></td>
        </tr>
    </tbody>
</table>
<br />
<br />
如果你能够完全理解本节的内容，那么请留意我的下一讲，我将具体介绍如何运用CRC-32对你的文件进行保护。（呵呵，好戏在后头&#8230;&#8230;）
<img src ="http://www.blogjava.net/Todd/aggbug/321430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-05-20 01:45 <a href="http://www.blogjava.net/Todd/archive/2010/05/20/321430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矛与盾的较量（1）——花指令【转自老罗】</title><link>http://www.blogjava.net/Todd/archive/2010/05/20/321429.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Wed, 19 May 2010 17:44:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/05/20/321429.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/321429.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/05/20/321429.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/321429.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/321429.html</trackback:ping><description><![CDATA[<p>
有矛就有盾。<br />
所以我们要讨论加密技术。<br />
<br />
我们知道，所有的编译型语
言，例如VC、BCB、Delphi和Win32ASM&#8230;&#8230;最终都会把源代码编译成机器能识别的0和1——因此也能够反过来把这些0和1反编译成汇编代
码。反编译有什么用呢？试想想，你辛辛苦苦写了一个perfect的软件出来，正准备把它卖上100万份，忽然！在市面上出现了很多仿制你的东
西&#8230;&#8230;hoho，不知道你会怎么想呢？反正我是会欲哭无泪的。还有另外一种情况，你的软件是用注册码的形式来授权的，每份license要卖30个美刀。
呵呵，正当你在考虑着一年后是去加利福尼亚还是夏威夷度假的时候，你的软件被Crack了——也就是说，你一分钱都不会得到&#8230;&#8230;（啊！我想跳楼啦！！）<br />
<br />
所以我们要讨论如何给自己的程序加密。这次就先说说最简单的花指令。<br />
<br />
在解释这个&#8220;花指令&#8221;之前，不妨先做几个小小的实验。<br />
<br />
我们先来写一个程序，命名为hua.asm，内容如下：<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>;***************************************************************<br />
            ;花指令实验1<br />
            ;作者：罗聪<br />
            ;日期：2002-8-21<br />
            ;***************************************************************<br />
            .386<br />
            .model flat, stdcall<br />
            option casemap:none<br />
            <br />
            include "masm32"include"windows.inc<br />
            include "masm32"include"kernel32.inc<br />
            include "masm32"include"user32.inc<br />
            includelib "masm32"lib"kernel32.lib<br />
            includelib "masm32"lib"user32.lib<br />
            <br />
            .data<br />
            szText&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"嘿嘿，这是一个花指令程序&#8230;&#8230;", 0<br />
            szCaption&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"花指令演示 by LC 2002-8-21", 0<br />
            <br />
            .code<br />
            main:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jmp Do_It<br />
            Do_It:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke ExitProcess, 0<br />
            end main</td>
        </tr>
    </tbody>
</table>
<br />
<br />
然后用W32Dasm v10来反编译它，得到的结果如下：（由于篇幅所限，这里只列出关键部分）<br />
<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++<br />
            //********************** Start of Code in Object .text **************<br />
            Program Entry Point = 00401000 (hua.exe File Offset:00001600)<br />
            <br />
            <br />
            <br />
            //******************** Program Entry Point ********<br />
            :00401000 EB00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jmp 00401002<br />
            <br />
            * Referenced by a (U)nconditional or ?onditional Jump at Address:<br />
            |:00401000(U)<br />
            |<br />
            :00401002 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Possible StringData Ref from Data Obj -&gt;"花指令演示 by LC 2002-8-21"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401004 681F304000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 0040301F<br />
            <br />
            * Possible StringData Ref from Data Obj -&gt;"嘿嘿，这是一个花指令程序&#8230;&#8230;"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401009 6800304000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00403000<br />
            :0040100E 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: USER32.MessageBoxA, Ord:01BBh<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401010 E80D000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 00401022<br />
            :00401015 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: KERNEL32.ExitProcess, Ord:0075h<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401017 E800000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 0040101C<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
哇，好夸张啊！你可能会说。反编译出来的代码几乎是跟源代码一一对应的，这样一来？我们的程序还有什么秘密可言呢？完全可以从反编译的结果中理解程序的功能。<br />
<br />
而且我们还可以在W32Dasm的&#8220;String Data References&#8221;中得到：<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>"嘿嘿，这个是一个花指令程序&#8230;&#8230;"<br />
            "花指令演示 by LC 2002-8-21"<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
把刚才的源程序稍做修改，来做第二个实验：<br />
<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>;***************************************************************<br />
            ;花指令实验2<br />
            ;作者：罗聪<br />
            ;日期：2002-8-21<br />
            ;***************************************************************<br />
            .386<br />
            .model flat, stdcall<br />
            option casemap:none<br />
            <br />
            include "masm32"include"windows.inc<br />
            include "masm32"include"kernel32.inc<br />
            include "masm32"include"user32.inc<br />
            includelib "masm32"lib"kernel32.lib<br />
            includelib "masm32"lib"user32.lib<br />
            <br />
            .data<br />
            szText&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"嘿嘿，这是一个花指令程序&#8230;&#8230;", 0<br />
            szCaption&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"花指令演示 by LC 2002-8-21", 0<br />
            <br />
            .code<br />
            main:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jz Do_It&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第一个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jnz Do_It&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第一个实验中的源程序的区别<br />
            Do_It:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK<br />
            end main<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
用W32Dasm反编译一下：<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++<br />
            //********************** Start of Code in Object .text **************<br />
            Program Entry Point = 00401000 (hua.exe File Offset:00001600)<br />
            <br />
            <br />
            <br />
            //******************** Program Entry Point ********<br />
            :00401000 7402&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;je 00401004<br />
            :00401002 7500&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jne 00401004<br />
            <br />
            * Referenced by a (U)nconditional or ?onditional Jump at Addresses:<br />
            |:00401000?, :00401002?<br />
            |<br />
            :00401004 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Possible StringData Ref from Data Obj -&gt;"花指令演示 by LC 2002-8-21"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401006 681F304000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 0040301F<br />
            <br />
            * Possible StringData Ref from Data Obj -&gt;"嘿嘿，这是一个花指令程序&#8230;&#8230;"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :0040100B 6800304000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00403000<br />
            :00401010 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: USER32.MessageBoxA, Ord:01BBh<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401012 E801000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 00401018<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
可以看出，这时的W32Dasm反编译出来的汇编指令还是正确的。但是W32Dasm其实已经逐渐落入我们设下的&#8220;陷阱&#8221;了。<br />
<br />
下面我们来做第三个实验，把源程序改成：<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>;***************************************************************<br />
            ;花指令实验3<br />
            ;作者：罗聪<br />
            ;日期：2002-8-21<br />
            ;***************************************************************<br />
            .386<br />
            .model flat, stdcall<br />
            option casemap:none<br />
            <br />
            include "masm32"include"windows.inc<br />
            include "masm32"include"kernel32.inc<br />
            include "masm32"include"user32.inc<br />
            includelib "masm32"lib"kernel32.lib<br />
            includelib "masm32"lib"user32.lib<br />
            <br />
            .data<br />
            szText&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"嘿嘿，这是一个花指令程序&#8230;&#8230;", 0<br />
            szCaption&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"花指令演示 by LC 2002-8-21", 0<br />
            <br />
            .code<br />
            main:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jz Do_It&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第一个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jnz Do_It&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第一个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;db 0E8h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第二个实验中的源程序的区别<br />
            Do_It:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke ExitProcess, 0<br />
            end main<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
我们来看看W32Dasm中反编译出来的东西：<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++<br />
            //********************** Start of Code in Object .text **************<br />
            Program Entry Point = 00401000 (hua.exe File Offset:00001600)<br />
            <br />
            <br />
            <br />
            //******************** Program Entry Point ********<br />
            :00401000 7403&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;je 00401005<br />
            :00401002 7501&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jne 00401005<br />
            :00401004 E86A00681D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call 1DA81073<br />
            :00401009 304000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xor byte ptr [eax+00], al<br />
            <br />
            * Possible StringData Ref from Data Obj -&gt;"嘿嘿，这是一个花指令程序&#8230;&#8230;"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :0040100C 6800304000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00403000<br />
            :00401011 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: USER32.MessageBoxA, Ord:01BBh<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401013 E80E000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 00401026<br />
            :00401018 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: KERNEL32.ExitProcess, Ord:0075h<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :0040101A E801000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 00401020<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
呵呵，很明显了，这时的 00401004 到 00401009 行出错了，而且这时查看&#8220;String Data References&#8221;，也只剩下了：<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>"嘿嘿，这是一个花指令程序&#8230;&#8230;"</td>
        </tr>
    </tbody>
</table>
<br />
<br />
让我们进一步隐藏信息，做第四个实验：<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>;***************************************************************<br />
            ;花指令实验4<br />
            ;作者：罗聪<br />
            ;日期：2002-8-21<br />
            ;***************************************************************<br />
            .386<br />
            .model flat, stdcall<br />
            option casemap:none<br />
            <br />
            include "masm32"include"windows.inc<br />
            include "masm32"include"kernel32.inc<br />
            include "masm32"include"user32.inc<br />
            includelib "masm32"lib"kernel32.lib<br />
            includelib "masm32"lib"user32.lib<br />
            <br />
            .data<br />
            szText&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"嘿嘿，这是一个花指令程序&#8230;&#8230;", 0<br />
            szCaption&nbsp;&nbsp;&nbsp;&nbsp;db&nbsp;&nbsp;&nbsp;&nbsp;"花指令演示 by LC 2002-8-21", 0<br />
            <br />
            .code<br />
            main:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jz Do_It&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第一个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;jnz Do_It&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第一个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;db 0E8h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第二个实验中的源程序的区别<br />
            Do_It:<br />
            &nbsp;&nbsp;&nbsp;&nbsp;lea eax, szText&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第三个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;lea ebx, szCaption&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第三个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke MessageBox, NULL, eax, ebx, MB_OK&nbsp;&nbsp;&nbsp;&nbsp;;注意这里和第三个实验中的源程序的区别<br />
            &nbsp;&nbsp;&nbsp;&nbsp;invoke ExitProcess, 0<br />
            end main<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
编译，再用W32Dasm反编译，得到的是：<br />
<br />
<table bgcolor="#cccccc" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++<br />
            //********************** Start of Code in Object .text **************<br />
            Program Entry Point = 00401000 (hua.exe File Offset:00001600)<br />
            <br />
            <br />
            <br />
            //******************** Program Entry Point ********<br />
            :00401000 7403&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;je 00401005<br />
            :00401002 7501&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jne 00401005<br />
            :00401004 E88D050030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call 30401596<br />
            :00401009 40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inc eax<br />
            :0040100A 008D1D1D3040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add byte ptr [ebp+40301D1D], cl<br />
            :00401010 006A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add byte ptr [edx+00], ch<br />
            :00401013 53&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push ebx<br />
            :00401014 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push eax<br />
            :00401015 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: USER32.MessageBoxA, Ord:01BBh<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :00401017 E80E000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 0040102A<br />
            :0040101C 6A00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push 00000000<br />
            <br />
            * Reference To: KERNEL32.ExitProcess, Ord:0075h<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
            :0040101E E801000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Call 00401024<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
呵呵，这次不但面目全非了，而且&#8220;String Data References&#8221;按钮已经变成了灰色。什么蛛丝马迹都没有了。<br />
<br />
各位看官看到这里明白了吗？其实花指令就是人为地构造一些&#8220;陷阱&#8221;和一些无用的字节。例如第二个实验中的：<br />
<br />
jz Do_It<br />
jnz Do_It<br />
<br />
其实这个跟 jmp Do_It 还不是一样吗？（呵呵，如果在大学的期末考试里这样写，一定会被判不及格&#8230;&#8230;）<br />
<br />
是的，其实程序原有的功能和逻辑还是一样的，我们只不过是换了一种表现形式而已。然而，反编译工具是没有人脑那么智能的，它们往往就会把这些指令理解错，从而错误地确定了指令的起始位置。<br />
<br />
要实现这种绝对跳转的功能，还可以用很多的方法，例如：<br />
<br />
Push Do_It<br />
ret<br />
<br />
<br />
<strong>花指令是很容易理解的，不过大家要注意适时而用，不要滥用啊，能起到迷惑破解者和隐藏信息的作用就行了，不然将来要维护代码时，我怕被迷惑的反而是你自己哦，呵呵&#8230;&#8230;</strong>
</p>
<img src ="http://www.blogjava.net/Todd/aggbug/321429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-05-20 01:44 <a href="http://www.blogjava.net/Todd/archive/2010/05/20/321429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四个有用的过虑器</title><link>http://www.blogjava.net/Todd/archive/2010/04/24/319270.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Sat, 24 Apr 2010 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/04/24/319270.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/319270.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/04/24/319270.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/319270.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/319270.html</trackback:ping><description><![CDATA[一、使浏览器不缓存页面的过滤器
<p>import javax.servlet.*;<br />
import javax.servlet.http.HttpServletResponse;<br />
import java.io.IOException;</p>
<p>/**<br />
&nbsp;* 用于的使 Browser 不缓存页面的过滤器<br />
&nbsp;*/<br />
public class ForceNoCacheFilter&nbsp;implements Filter {</p>
<p>&nbsp;public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException<br />
&nbsp;{<br />
&nbsp;&nbsp;((HttpServletResponse) response).setHeader("Cache-Control","no-cache");<br />
&nbsp;&nbsp;((HttpServletResponse) response).setHeader("Pragma","no-cache");<br />
&nbsp;&nbsp;((HttpServletResponse) response).setDateHeader ("Expires", -1);<br />
&nbsp;&nbsp;filterChain.doFilter(request, response);<br />
&nbsp;}</p>
<p>&nbsp;public void destroy()<br />
&nbsp;{<br />
&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp; public void init(FilterConfig filterConfig) throws ServletException<br />
&nbsp;{<br />
&nbsp;}<br />
}</p>
<p>二、检测用户是否登陆的过滤器</p>
<p>import javax.servlet.*;<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpServletResponse;<br />
import javax.servlet.http.HttpSession;<br />
import java.util.List;<br />
import java.util.ArrayList;<br />
import java.util.StringTokenizer;<br />
import java.io.IOException;</p>
<p>/**<br />
&nbsp;* 用于检测用户是否登陆的过滤器，如果未登录，则重定向到指的登录页面&lt;p&gt;<br />
&nbsp;* 配置参数&lt;p&gt;<br />
&nbsp;* checkSessionKey 需检查的在 Session 中保存的关键字&lt;br/&gt;<br />
&nbsp;* redirectURL 如果用户未登录，则重定向到指定的页面，URL不包括 ContextPath&lt;br/&gt;<br />
&nbsp;* notCheckURLList 不做检查的URL列表，以分号分开，并且 URL 中不包括 ContextPath&lt;br/&gt;<br />
&nbsp;*/<br />
public class CheckLoginFilter<br />
&nbsp;implements Filter<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;protected FilterConfig filterConfig = null;<br />
&nbsp;&nbsp;&nbsp; private String redirectURL = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private List notCheckURLList = new ArrayList();<br />
&nbsp;&nbsp;&nbsp;&nbsp;private String sessionKey = null;</p>
<p>&nbsp;public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException<br />
&nbsp;{<br />
&nbsp;&nbsp;HttpServletRequest request = (HttpServletRequest) servletRequest;<br />
&nbsp;&nbsp;HttpServletResponse response = (HttpServletResponse) servletResponse;</p>
<p>&nbsp;&nbsp; HttpSession session = request.getSession();<br />
&nbsp;&nbsp;if(sessionKey == null)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;filterChain.doFilter(request, response);<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if((!checkRequestURIIntNotFilterList(request)) &amp;&amp; session.getAttribute(sessionKey) == null)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;response.sendRedirect(request.getContextPath() + redirectURL);<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;filterChain.doFilter(servletRequest, servletResponse);<br />
&nbsp;}</p>
<p>&nbsp;public void destroy()<br />
&nbsp;{<br />
&nbsp;&nbsp;notCheckURLList.clear();<br />
&nbsp;}</p>
<p>&nbsp;private boolean checkRequestURIIntNotFilterList(HttpServletRequest request)<br />
&nbsp;{<br />
&nbsp;&nbsp;String uri = request.getServletPath() + (request.getPathInfo() == null ? "" : request.getPathInfo());<br />
&nbsp;&nbsp;return notCheckURLList.contains(uri);<br />
&nbsp;}</p>
<p>&nbsp;public void init(FilterConfig filterConfig) throws ServletException<br />
&nbsp;{<br />
&nbsp;&nbsp;this.filterConfig = filterConfig;<br />
&nbsp;&nbsp;redirectURL = filterConfig.getInitParameter("redirectURL");<br />
&nbsp; sessionKey = filterConfig.getInitParameter("checkSessionKey");</p>
<p>&nbsp;&nbsp;String notCheckURLListStr = filterConfig.getInitParameter("notCheckURLList");</p>
<p>&nbsp;&nbsp;if(notCheckURLListStr != null)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;StringTokenizer st = new StringTokenizer(notCheckURLListStr, ";");<br />
&nbsp;&nbsp;&nbsp;notCheckURLList.clear();<br />
&nbsp;&nbsp;&nbsp;while(st.hasMoreTokens())<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;notCheckURLList.add(st.nextToken());<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}</p>
<p>三、字符编码的过滤器</p>
<p>import javax.servlet.*;<br />
import java.io.IOException;</p>
<p>/**<br />
&nbsp;* 用于设置 HTTP 请求字符编码的过滤器，通过过滤器参数encoding指明使用何种字符编码,用于处理Html Form请求参数的中文问题<br />
&nbsp;*/<br />
public class CharacterEncodingFilter<br />
&nbsp;implements Filter<br />
{<br />
&nbsp;protected FilterConfig filterConfig = null;<br />
&nbsp;protected String encoding = "";</p>
<p>&nbsp;public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(encoding != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servletRequest.setCharacterEncoding(encoding);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filterChain.doFilter(servletRequest, servletResponse);<br />
&nbsp;}</p>
<p>&nbsp;public void destroy()<br />
&nbsp;{<br />
&nbsp;&nbsp;filterConfig = null;<br />
&nbsp;&nbsp;encoding = null;<br />
&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp; public void init(FilterConfig filterConfig) throws ServletException<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.filterConfig = filterConfig;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.encoding = filterConfig.getInitParameter("encoding");</p>
<p>&nbsp;}<br />
}</p>
<p>四、资源保护过滤器</p>
<p>
<pre>package catalog.view.util;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
//
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This Filter class handle the security of the application.
*
<p>
* It should be configured inside the web.xml.
*
* @author <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#100;&#101;&#114;&#101;&#107;&#95;&#115;&#104;&#101;&#110;&#64;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">Derek Y. Shen</a>
*/
public class SecurityFilter implements Filter {
//the login page uri
private static final String LOGIN_PAGE_URI = "login.jsf";
//the logger object
private Log logger = LogFactory.getLog(this.getClass());
//a set of restricted resources
private Set restrictedResources;
/**
* Initializes the Filter.
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.restrictedResources = new HashSet();
this.restrictedResources.add("/createProduct.jsf");
this.restrictedResources.add("/editProduct.jsf");
this.restrictedResources.add("/productList.jsf");
}
/**
* Standard doFilter object.
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
this.logger.debug("doFilter");
String contextPath = ((HttpServletRequest)req).getContextPath();
String requestUri = ((HttpServletRequest)req).getRequestURI();
this.logger.debug("contextPath = " + contextPath);
this.logger.debug("requestUri = " + requestUri);
if (this.contains(requestUri, contextPath) &amp;&amp; !this.authorize((HttpServletRequest)req)) {
this.logger.debug("authorization failed");
((HttpServletRequest)req).getRequestDispatcher(LOGIN_PAGE_URI).forward(req, res);
}
else {
this.logger.debug("authorization succeeded");
chain.doFilter(req, res);
}
}
public void destroy() {}
private boolean contains(String value, String contextPath) {
Iterator ite = this.restrictedResources.iterator();
while (ite.hasNext()) {
String restrictedResource = (String)ite.next();
if ((contextPath + restrictedResource).equalsIgnoreCase(value)) {
return true;
}
}
return false;
}
private boolean authorize(HttpServletRequest req) {
//处理用户登录
/*	UserBean user = (UserBean)req.getSession().getAttribute(BeanNames.USER_BEAN);
if (user != null &amp;&amp; user.getLoggedIn()) {
//user logged in
return true;
}
else {
return false;
}*/
}
}</p>
</pre>
<img src ="http://www.blogjava.net/Todd/aggbug/319270.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-04-24 16:36 <a href="http://www.blogjava.net/Todd/archive/2010/04/24/319270.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java防止非法和重复表单提交</title><link>http://www.blogjava.net/Todd/archive/2010/04/23/319184.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Fri, 23 Apr 2010 03:22:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/04/23/319184.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/319184.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/04/23/319184.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/319184.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/319184.html</trackback:ping><description><![CDATA[<p>真是一切都逃不过session,看了DZ的formhash;struts token什么啊，就是个session,安全级别比验证码还低。<br />
<strong>看看别人的分析有益身心啊，看之，目前来讲一切都逃不过session<br />
<br />
<br />
预期达到目标</strong><span style="font-size: 9pt; color: #333333">:</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="background: #d9d9d9">1</span></span>、当用户进行的是<span style="font-size: 9pt; background: #d9d9d9; color: #333333">Refresh/Reload/Back/Forward</span>操作、以及先<span style="font-size: 9pt; background: #d9d9d9; color: #333333">Back</span>再<span style="font-size: 9pt; background: #d9d9d9; color: #333333">Submit</span>操作时，仅仅是<span style="font-size: 9pt; background: #d9d9d9; color: #333333">reloading</span>先前的结果页。</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2</span>、当用户重复提交同一个任务操作时<span style="font-size: 9pt; background: #d9d9d9; color: #333333">,</span>后台服务接收并处理第一次提交的任务，后面提交不起作用（不转向也不提示）。</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3</span>、该功能具有公用性。</p>
<p style="text-align: left" align="left"><strong>基本形成思路：</strong></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1</span>、在<span style="font-size: 9pt; color: #333333">basic filter</span>中实现公用性</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="background: #d9d9d9">if(true){//</span></span>问题<span style="font-size: 9pt; background: #d9d9d9; color: #333333">1</span>：如何确定是否为重复提交</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chain.doFilter(request,response);</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span>问题<span style="font-size: 9pt; background: #d9d9d9; color: #333333">2</span>：如何实现不转向、不提示也不显示空白页</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2</span>、网上资料概括</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="background: #d9d9d9">a</span></span>、提交表单后按钮变灰<span style="font-size: 9pt; background: #d9d9d9; color: #333333">/</span>隐藏提交按钮</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b</span>、在<span style="font-size: 9pt; background: #d9d9d9; color: #333333">js</span>里设置全局变量，提交后修改该变量的值，依据变量的值判断是否重复提交</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var flag=true;</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function checkForm(){</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flag==false){</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag=false;</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.form1.submit();</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c</span>、<span style="font-size: 9pt; background: #d9d9d9; color: #333333">struts </span>（<span style="font-size: 9pt; background: #d9d9d9; color: #333333">webwork</span>没有找到这个资料）</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span>验证事务控制令牌<span style="font-size: 9pt; background: #d9d9d9; color: #333333">,&lt;html:form &gt;</span>会自动根据<span style="font-size: 9pt; background: #d9d9d9; color: #333333">session</span>中标识生成一个隐含<span style="font-size: 9pt; background: #d9d9d9; color: #333333">input</span>代表令牌，防止两次提交</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>在<span style="font-size: 9pt; background: #d9d9d9; color: #333333">action</span>中：</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&lt;input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"&gt;</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!isTokenValid(request))</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors.add(ActionErrors.GLOBAL_ERROR,</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ActionError("error.transaction.token"));</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resetToken(request); //</span>删除<span style="font-size: 9pt; background: #d9d9d9; color: #333333">session</span>中的令牌</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action</span>有这样的一个方法生成令牌华</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; protected String generateToken(HttpServletRequest request) {</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpSession session = request.getSession();</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte id[] = session.getId().getBytes();</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte now[] =</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Long(System.currentTimeMillis()).toString().getBytes();</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageDigest md = MessageDigest.getInstance("MD5");</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; md.update(id);</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; md.update(now);</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (toHex(md.digest()));</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IllegalStateException e) {</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (null);</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (NoSuchAlgorithmException e) {</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (null);</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d</span>、用户使用浏览器时，可以经常使用向后的按钮，因此就有可能重复提交一个他们已经提交过的<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>，这样就会带来一个重复事务处理的问题。同样，一个用户也可能在接收到一个确认的页面之前按下停止的按钮，接着再次提交同一个<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>。对于这些情况，我们都想跟踪并且禁止这些重复的提交，我们可以使用一个控制<span style="font-size: 9pt; background: #d9d9d9; color: #333333">servlet</span>来提供一个控制点，以解决这个问题。</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>　　同步记号（<span style="font-size: 9pt; background: #d9d9d9; color: #333333">Synchronizer (or Dvu) Token</span>）</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="font-size: 9pt; background: #d9d9d9; color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left">这个策略是为了解决重复的<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>提交问题。一个同步的记号被设置在一个用户的<span style="font-size: 9pt; background: #d9d9d9; color: #333333">Session</span>中，并且包含在返回到客户的每一个<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>中。当<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>被提交时，<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>中的同步标记就和<span style="font-size: 9pt; background: #d9d9d9; color: #333333">Session</span>中的同步标记作对比。在<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>首次提交的时候，这两个标记应该是一样的。如果标记不一样，那么该<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>就会禁止提交，一个错误就会返回给用户。在用户提交一个<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>时，如果按下浏览器中的后退按钮并尝试重新提交同一个<span style="font-size: 9pt; background: #d9d9d9; color: #333333">form</span>时，标记就会出现不匹配的现象。</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left"><span style="color: #000000">另一方面，如果两个标记值匹配，那么我们就可以确信整个流程是正确的。在这种情况下，Session中的标记值就会被修改为一个新的值，同时允许提交该form。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　你也可以使用这个策略来控制对某些页面的直接访问，就好象上面资源保护中描述的一样。例如，假设一个用户将某个应用的页面A收藏到收藏夹中，而页面A只允许通过页面B和C访问。当用户直接通过收藏夹来访问页面A，这时页面的访问顺序就是不正确的，这样同步标记将处在一个不同步的状态，或者它根本就不存在。不论怎样，访问都被禁止了。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e、做一个hidden框，名字自己定，提交后得到这个值放入session，提交前判断session是否为空 &nbsp; 解决方案： &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、后台公共类中实现前台的Form中自动生成两个hidden文本功能，一个是作page是否重复提交判断，并由系统自动附上关键值（如struts采用的方案）；另一个作为button是否重复提交判断（struts中好像没有）。由后台公共类实现界面两个hidden text自动生成的好处在于公用性。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、在basic filter中根据两个hidden text值判断是否为重复提交。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、javascript中作一个公共方法，实现功能：如果需要判断是否重复提交，就给第二个hidden text附上关键值，并使该功能不可用。 . 个人感想：我相信未来该功能一定会被服务器集成，而不再由开发人员进行编码.</span></p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left">----------------------------------------示例代码----------------------------------------------------</p>
<p style="text-indent: 27pt; line-height: 12pt; text-align: left" align="left">第一，对于不支持POST的，可以简单的使用如下代码<br />
if ("POST".equals(request.getMethod())) ...{<br />
&nbsp; // 正常进行<br />
}else...{<br />
&nbsp; // 异常请求<br />
&nbsp; out.print("异常访问");<br />
&nbsp; return;<br />
}<br />
如果是servlet, 可以将doGet方法直接返回，不进行处理就行了<br />
public void doGet(HttpServletRequest request, HttpServletResponse response) ...{<br />
&nbsp; return;<br />
}<br />
public void doPost(HttpServletRequest request, HttpServletResponse response) ...{<br />
&nbsp; // 正常进行操作<br />
}<br />
还可以采用特定的标志来区分，比如 <br />
&lt;form&gt;&lt;input type="hidden" name="action" value="insert"/&gt;&lt;/form&gt; <br />
程序里这样判断<br />
if ("POST".equals(request.getMethod()) &amp;&amp; ("insert".equals(request.getParameter("action")))) ...{<br />
&nbsp; // 正常进行<br />
}else...{<br />
&nbsp; // 异常请求<br />
&nbsp; out.print("异常访问");<br />
&nbsp; return;<br />
}<br />
第二，判断提交的来源referer,代码如下<br />
if ("POST".equals(request.getMethod())) ...{<br />
&nbsp; String referer = request.getHeader("referer");<br />
&nbsp; if (referer == null || !referer.startsWith("<a href="http://%22+request.getservername/">http://"+request.getServerName</a>())) ...{<br />
&nbsp;&nbsp;&nbsp; // 非法来源<br />
&nbsp;&nbsp;&nbsp; return;<br />
&nbsp; }<br />
&nbsp; // 正常进行<br />
}else...{<br />
&nbsp; // 异常请求<br />
&nbsp; out.print("异常访问");<br />
&nbsp; return;<br />
}<br />
第三 防止重复提交的hashCode <br />
在表单显示页面<br />
&nbsp; //生成一个formhash,算法可以自己定，不随便重复就可以了<br />
&nbsp; String formhash = MD5.encode(Long.toString(new Date().getTime()));<br />
&nbsp; //读取当前session里面的hashCode集合，此处使用了Set，方便判断。<br />
&nbsp; Set&lt;String&gt; formhashSession = (Set&lt;String&gt;) session.getAttribute("formhashSession");<br />
&nbsp; if (formhashSession == null) ...{<br />
&nbsp;&nbsp;&nbsp; formhashSession = new HashSet&lt;String&gt;();<br />
&nbsp; }<br />
&nbsp; // 检测重复问题<br />
&nbsp; while (formhashSession.contains(formhash)) ...{<br />
&nbsp;&nbsp;&nbsp; formhash = MD5.encode(Long.toString(new Date().getTime()));<br />
&nbsp; }<br />
&nbsp; // 保存到session里面<br />
&nbsp; formhashSession.add(formhash);<br />
&nbsp; // 保存<br />
&nbsp; session.setAttribute("formhashSession", formhashSession);<br />
表单里面增加如下字段<br />
&lt;input type="hidden" name="formhash" id="formhash" value="&lt;%=formhash%&gt;" /&gt; <br />
在表单提交页面进行如下处理<br />
&nbsp;&nbsp;&nbsp; // 拿到表单的formhash<br />
&nbsp;&nbsp;&nbsp; String formhash = upload.getParameter("formhash");<br />
&nbsp;&nbsp;&nbsp; // 拿到session里面的集合<br />
&nbsp;&nbsp;&nbsp; Set&lt;String&gt; formhashSession = (Set&lt;String&gt;) session.getAttribute("formhashSession");<br />
&nbsp;&nbsp;&nbsp; // 如果没有，则是重复提交，或者非法提交<br />
&nbsp;&nbsp;&nbsp; if (formhashSession == null || !formhashSession.contains(formhash)) ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("请不要重复提交！");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; // 下面进行其它的操作<br />
&nbsp;&nbsp;&nbsp; // <br />
&nbsp;&nbsp;&nbsp; // 最后,如果操作成功,从session里面把这个formhash 删掉！<br />
&nbsp;&nbsp;&nbsp; // 以免用户少填写了某个字段，造成表单无法再次提交<br />
&nbsp;&nbsp;&nbsp; formhashSession.remove(formhash);<br />
&nbsp;&nbsp;&nbsp; session.setAttribute("formhashSession", formhashSession);</p>
<img src ="http://www.blogjava.net/Todd/aggbug/319184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-04-23 11:22 <a href="http://www.blogjava.net/Todd/archive/2010/04/23/319184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】黑客攻破apache.org官网</title><link>http://www.blogjava.net/Todd/archive/2010/04/22/319162.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Thu, 22 Apr 2010 15:51:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/04/22/319162.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/319162.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/04/22/319162.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/319162.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/319162.html</trackback:ping><description><![CDATA[Apache是全球使用最多的Web Server之一，近期Apache的官网被黑客入侵了，素包子根据apache网站的描述，分析了下黑客的思路。大概包含5个过程，虽然道路曲折，但黑客快速通关，一步一步的接近目标，有很多可圈可点的地方，还是相当精彩的。可惜最后people.apache.org没搞下来，否则可以写小说拍电影了，不过男女主角不能是aXi和aJiao。<br />
<br />
1、通过跨站漏洞社工了几个管理员，获得JIRA（一个项目管理程序）后台管理权限，并修改相关设置，上传jsp木马。<br />
<br />
2、在后台看到其他用户的帐号，通过登陆入口暴力跑密码，破解了几百个帐号。<br />
<br />
官方说是&#8220;At the same time as the XSS attack&#8221;，我不这么认为，我认为是获取后台之后，能看到帐号了，才可以高效率的破解密码。如果不通过后台就可以破解几百个帐号，那这个事情早就发生了。<br />
<br />
3、部署了一个JAR，可以记录登陆帐号及密码，然后用JIRA的系统发邮件给apache的管理人员说：&#8220;JIRA出现故障了，请你使用邮件里的临时密码登陆，并修改密码&#8221;，相关人员登陆了，并把密码修改成自己常用的密码，当然，这些密码都被记录下来了 ：）<br />
<br />
4、正如黑客所算计的，上述被记录的密码中，有密码可以登陆brutus.apache.org，更让黑客开心和省心的是，这个可以登陆的帐号竟然具备完全的sodu权限，提权都不用提了，直接就是root，真是爽的一塌糊涂啊。而这个被root的brutus.apache.org上面跑着JIRA、Confluence和Bugzilla。<br />
<br />
5、brutus.apache.org上的部分用户保存了subversion的密码，黑客用这些密码登陆了people.apache.org，但是并没获得其他权限。这个people.apache.org可是apache的主服务器之一，如果root了这个机器，那基本可以获得所有apache主要人员的密码了。可惜，黑客们功亏一篑。<br />
<br />
整个故事到此结束，下面说说Apache是如何发现自己被入侵的。<br />
<br />
根据apache官方的描述&#8220;About 6 hours after they started resetting passwords, we noticed the attackers and began shutting down services&#8221;，我猜测apache是因为黑客重设了用户密码这个行为才发现被入侵的。<br />
<br />
如果说的是黑客重设的是JIRA的密码，那么就是因为黑客做戏没做足全套导致的，可能apache管理人员上去看之后，发现没啥问题，被忽悠了。<br />
<br />
如果说的是黑客重设其他密码，我想不到整个过程中还需要重设什么其他的密码。<br />
<br />
我还是对apache的安全措施非常好奇，到底是如何发现的？到底是相关人员安全敏感度高呢，还是黑客留下了一些痕迹被安全检查措施发现了。如果是后者的话，检查周期又是多长呢？24小时？<br />
<br />
经验教训：<br />
<br />
回头再看看黑客的整个攻击过程，素包子相信在细节上会有很多可以吸取教训的地方。从长远来看，可以加强安全意识培训、实施SDL安全开发生命周期、日志集中分析、主机入侵检测系统等等，这些都是需要企业的安全部门长期投入去做的事情；相对短平快的方法是要求重要的人员、重要的应用、重要的系统使用双因素动态密码认证。<br />
<br />
<img src ="http://www.blogjava.net/Todd/aggbug/319162.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-04-22 23:51 <a href="http://www.blogjava.net/Todd/archive/2010/04/22/319162.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google攻击最新调查结果曝光：密码系统受害</title><link>http://www.blogjava.net/Todd/archive/2010/04/22/319161.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Thu, 22 Apr 2010 15:49:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/04/22/319161.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/319161.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/04/22/319161.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/319161.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/319161.html</trackback:ping><description><![CDATA[<p><a href="http://www.nytimes.com/2010/04/20/technology/20google.html">《纽约时报》网站4月19日发表文章</a>透露，据一位了解Google去年12月遭受攻击调查细节的专家在几天前的一次安全技术会议上描述，受到攻击的系统中，包括<strong>代号为Gaia的Google内部密码系统</strong>。Google的员工和成百万全世界的用户都通过这个系统登录到 Gmail和其他各种网上服务。</p>
<p>目前没有证据表明有Gmail用户的密码被盗。Google公司方面表示，在受到攻击数小时后，公司就激活了Gmail新的加密层，而且加强了数据 中心的安全性，并进一步加强了其网上服务与用户计算机之间通信连接的安全。但是，有安全分析人员指出，攻击者在攻入了内部密码系统之后，有可能在Gaia 系统和Google全球数据中心中安装木马，只不过在Google的安全专家获知受攻击之后，这变得非常困难。另外，攻击者在获取了系统的源代码并了解了 系统运作机理之后，也有可能（虽然可能性不大）发现Google还不知道的安全漏洞，这种隐患很令安全专家头痛。</p>
<p>文中还解释了此次Google所受攻击的详细过程：</p>
<p>1. 攻击者首先通过微软MSN给一个Google中国的员工A发去一条即时消息。</p>
<p>2. 这个员工在不知情的情况下点击了其中的网址，并访问了&#8220;已污染的&#8221;网站，使攻击者获得了访问A使用的计算机的权限。</p>
<p>3. 攻击者由此访问了Google公司的内部目录系统（名为Moma），其中保存着所有Google员工的工作情况，包括具体员工的信息。</p>
<p>4. 在查找到了位于Google美国总部的Gaia软件开发者的名字之后，他们继而首先尝试访问开发者的工作电脑。</p>
<p>5. 然后使用了一连串复杂的技术获取了Gaia系统源代码库的访问权限。</p>
<p>6. 接下来，他们把偷到的软件传输到云计算服务提供商Rackspace的计算机上，此后再传到哪里，就不再为人所知。</p>
<p>文中说，Gaia系统目前仍然在使用，现在的正式名称被称为Single Sign-On。</p>
<p>本周一Google的高管拒绝对此进行评论，说其中暴露的安全问题早已经解决。</p>
<p>有安全专家表示，新的攻击细节很可能增加人们对云计算安全的担心。由于海量的信息现在被相对集中存放在一些计算机系统中，单点被攻破就可能带来灾难 性的损失。</p>
<img src ="http://www.blogjava.net/Todd/aggbug/319161.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-04-22 23:49 <a href="http://www.blogjava.net/Todd/archive/2010/04/22/319161.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>apache ab 使用</title><link>http://www.blogjava.net/Todd/archive/2010/04/22/319160.html</link><dc:creator>Todd</dc:creator><author>Todd</author><pubDate>Thu, 22 Apr 2010 15:29:00 GMT</pubDate><guid>http://www.blogjava.net/Todd/archive/2010/04/22/319160.html</guid><wfw:comment>http://www.blogjava.net/Todd/comments/319160.html</wfw:comment><comments>http://www.blogjava.net/Todd/archive/2010/04/22/319160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Todd/comments/commentRss/319160.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Todd/services/trackbacks/319160.html</trackback:ping><description><![CDATA[格式： ./ab [options] [http://]hostname[:port]/path<br />
参数：<br />
&nbsp;&nbsp;&nbsp; -n requests&nbsp;&nbsp;&nbsp;&nbsp; Number of requests to perform<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">//在测试会话中所执行的请求个数。默认时，仅执行一个请求</font><br />
&nbsp;&nbsp;&nbsp; -c concurrency Number of multiple requests to make<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">//一次产生的请求个数。默认是一次一个。 </font><br />
&nbsp;&nbsp;&nbsp; -t timelimit&nbsp;&nbsp;&nbsp; Seconds to max. wait for responses<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">//测试所进行的最大秒数。其内部隐含值是-n 50000。它可以使对服务器的测试限制在一个固定的总时间以内。默认时，没有时间限制。<br />
</font>&nbsp;&nbsp;&nbsp; -p postfile&nbsp;&nbsp;&nbsp;&nbsp; File containing data to POST<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">//包含了需要POST的数据的文件. </font><br />
&nbsp;&nbsp;&nbsp; -T content-type Content-type header for POSTing<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">//POST数据所使用的Content-type头信息。</font><br />
&nbsp;&nbsp;&nbsp; -v verbosity&nbsp;&nbsp;&nbsp; How much troubleshooting info to print<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">//设置显示信息的详细程度 - 4或更大值会显示头信息， 3或更大值可以显示响应代码(404, 200等), 2或更大值可以显示警告和其他信息。 -V 显示版本号并退出。<br />
</font>&nbsp;&nbsp;&nbsp; -w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print out results in HTML tables<br />
&nbsp;&nbsp;&nbsp;<font color="#ff0000"> //以HTML表的格式输出结果。默认时，它是白色背景的两列宽度的一张表。<br />
</font>&nbsp;&nbsp;&nbsp; -i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Use HEAD instead of GET<br />
&nbsp;&nbsp;<font color="#ff0000"> // 执行HEAD请求，而不是GET。</font><br />
&nbsp;&nbsp;&nbsp; -x attributes&nbsp;&nbsp; String to insert as table attributes<br />
&nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp; -y attributes&nbsp;&nbsp; String to insert as tr attributes<br />
&nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp; -z attributes&nbsp;&nbsp; String to insert as td or th attributes<br />
&nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp; -C attribute&nbsp;&nbsp;&nbsp; Add cookie, eg. 'Apache=1234. (repeatable)<br />
&nbsp;&nbsp;&nbsp; //<font color="#ff0000">-C cookie-name=value 对请求附加一个Cookie:行。 其典型形式是name=value的一个参数对。此参数可以重复。</font><br />
&nbsp;&nbsp;&nbsp; -H attribute&nbsp;&nbsp;&nbsp; Add Arbitrary header line, eg. 'Accept-Encoding: gzip'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inserted after all normal header lines. (repeatable)<br />
&nbsp;&nbsp;&nbsp; -A attribute&nbsp;&nbsp;&nbsp; Add Basic WWW Authentication, the attributes<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; are a colon separated username and password.<br />
&nbsp;&nbsp;&nbsp; -P attribute&nbsp;&nbsp;&nbsp; Add Basic Proxy Authentication, the attributes<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; are a colon separated username and password.<br />
&nbsp;&nbsp;&nbsp; //<font color="#ff0000">-P proxy-auth-username:password 对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开，并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码)，此字符串都会被发送。</font><br />
&nbsp;&nbsp;&nbsp; -X proxy:port&nbsp;&nbsp; Proxyserver and port number to use<br />
&nbsp;&nbsp;&nbsp; -V&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print version number and exit<br />
&nbsp;&nbsp;&nbsp; -k&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Use HTTP KeepAlive feature<br />
&nbsp;&nbsp;&nbsp; -d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Do not show percentiles served table.<br />
&nbsp;&nbsp;&nbsp; -S&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Do not show confidence estimators and warnings.<br />
&nbsp;&nbsp;&nbsp; -g filename&nbsp;&nbsp;&nbsp;&nbsp; Output collected data to gnuplot format file.<br />
&nbsp;&nbsp;&nbsp; -e filename&nbsp;&nbsp;&nbsp;&nbsp; Output CSV file with percentages served<br />
&nbsp;&nbsp;&nbsp; -h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Display usage information (this message)<br />
&nbsp;&nbsp;&nbsp; //-attributes 设置 属性的字符串. 缺陷程序中有各种静态声明的固定长度的缓冲区。另外，对命令行参数、服务器的响应头和其他外部输入的解析也很简单，这可能会有不良后果。它没有完整地实现HTTP/1.x; 仅接受某些'预想'的响应格式。 strstr(3)的频繁使用可能会带来性能问题，即, 你可能是在测试ab而不是服务器的性能。
<p>参数很多,一般我们用 -c 和 -n 参数就可以了. 例如:</p>
<p>./ab -c 1000 -n 1000 <a href="http://127.0.0.1/index.php"><font color="#0000ff">http://127.0.0.1/index.php</font></a></p>
<p>这个表示同时处理1000个请求并运行1000次index.php文件.<br />
#/usr/local/xiaobai/apache2054/bin/ab -c 1000 -n 1000 <a href="http://127.0.0.1/index.html.zh-cn.gb2312"><font color="#0000ff">http://127.0.0.1/index.html.zh-cn.gb2312</font></a> <br />
This is ApacheBench, Version 2.0.41-dev &lt;$Revision: 1.121.2.12 $&gt; apache-2.0<br />
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, <a href="http://www.zeustech.net/"><font color="#0000ff">http://www.zeustech.net/</font></a><br />
Copyright (c) 1998-2002 The Apache Software Foundation, <a href="http://www.apache.org/"><font color="#0000ff">http://www.apache.org/</font></a></p>
<p>Benchmarking 127.0.0.1 (be patient)<br />
Completed 100 requests<br />
Completed 200 requests<br />
Completed 300 requests<br />
Completed 400 requests<br />
Completed 500 requests<br />
Completed 600 requests<br />
Completed 700 requests<br />
Completed 800 requests<br />
Completed 900 requests<br />
Finished 1000 requests</p>
<p><br />
Server Software:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Apache/2.0.54<br />
<font color="#ff0000">//平台apache 版本2.0.54<br />
</font>Server Hostname:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 127.0.0.1<br />
<font color="#ff0000">//服务器主机名<br />
</font>Server Port:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 80<br />
<font color="#ff0000">//服务器端口</font></p>
<p>Document Path:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /index.html.zh-cn.gb2312<br />
<font color="#ff0000">//测试的页面文档</font><br />
Document Length:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1018 bytes<br />
<font color="#ff0000">//文档大小</font></p>
<p>Concurrency Level:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1000<br />
<font color="#ff0000">//并发数<br />
</font>Time taken for tests:&nbsp;&nbsp; 8.188731 seconds<br />
<font color="#ff0000">//整个测试持续的时间</font><br />
Complete requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1000<br />
<font color="#ff0000">//完成的请求数量</font><br />
Failed requests:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br />
<font color="#ff0000">//失败的请求数量</font><br />
Write errors:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0<br />
<br />
Total transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1361581 bytes<br />
<font color="#ff0000">//整个场景中的网络传输量</font><br />
HTML transferred:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1055666 bytes<br />
<font color="#ff0000">//整个场景中的HTML内容传输量<br />
</font>Requests per second:&nbsp;&nbsp;&nbsp; 122.12 [#/sec] (mean)<br />
<font color="#ff0000">//<span style="color: red">大家最关心的指标之一，相当于</span><span style="color: red"> LR </span><span style="color: red">中的</span><span style="color: red"> </span><strong><span style="color: red">每秒事务数</span></strong><span style="color: red"> </span><span style="color: red">，后面括号中的</span><span style="color: red"> mean </span><span style="color: red">表示这是一个平均值</span></font><br />
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8188.731 [ms] (mean)<br />
<font color="#ff0000">//<span style="color: red">大家最关心的指标之二，相当于</span><span style="color: red"> LR </span><span style="color: red">中的</span><span style="color: red"> </span><strong><span style="color: red">平均事务响应时间</span></strong><span style="color: red"> </span><span style="color: red">，后面括号中的</span><span style="color: red"> mean </span><span style="color: red">表示这是一个平均值</span></font><br />
Time per request:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8.189 [ms] (mean, across all concurrent requests)<br />
<font color="#ff0000">//每个请求实际运行时间的平均值</font><br />
Transfer rate:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 162.30 [Kbytes/sec] received<br />
<font color="#ff0000">//<span style="color: red">平均每秒网络上的流量，可以帮助排除是否存在网络流量过大导致响应时间延长的问题</span></font></p>
<p>Connection Times (ms)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; min mean[+/-sd] median&nbsp;&nbsp; max<br />
Connect:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 646 1078.7&nbsp;&nbsp;&nbsp;&nbsp; 89&nbsp;&nbsp;&nbsp; 3291<br />
Processing:&nbsp;&nbsp; 165 992 493.1&nbsp;&nbsp;&nbsp; 938&nbsp;&nbsp;&nbsp; 4712<br />
Waiting:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 118 934 480.6&nbsp;&nbsp;&nbsp; 882&nbsp;&nbsp;&nbsp; 4554<br />
Total:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 813 1638 1338.9&nbsp;&nbsp; 1093&nbsp;&nbsp;&nbsp; 7785<br />
<font color="#ff0000">//<span style="color: red">网络上消耗的时间的分解，各项数据的具体算法还不是很清楚</span></font></p>
<p>Percentage of the requests served within a certain time (ms)<br />
50%&nbsp;&nbsp; 1093<br />
66%&nbsp;&nbsp; 1247<br />
75%&nbsp;&nbsp; 1373<br />
80%&nbsp;&nbsp; 1493<br />
90%&nbsp;&nbsp; 4061<br />
95%&nbsp;&nbsp; 4398<br />
98%&nbsp;&nbsp; 5608<br />
99%&nbsp;&nbsp; 7368<br />
100%&nbsp;&nbsp; 7785 (longest request)<br />
<font color="#ff0000">//整个场景中所有请求的响应情况。在场景中每个请求都有一个响应时间，其中50％的用户响应时间小于1093 毫秒，60％ 的用户响应时间小于1247 毫秒，最大的响应时间小于7785 毫秒</font></p>
<p><font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于对于并发请求，cpu实际上并不是同时处理的，而是按照每个请求获得的时间片逐个轮转处理的，所以基本上第一个Time per request时间约等于第二个Time per request时间乘以并发请求数</font></p>
 <img src ="http://www.blogjava.net/Todd/aggbug/319160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Todd/" target="_blank">Todd</a> 2010-04-22 23:29 <a href="http://www.blogjava.net/Todd/archive/2010/04/22/319160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>