最近在帮我母校的小盆友们做一个“影评协会”的网站,根据他们的需求,我最后决定再次开始折腾WordPress。要知道和客户讲清楚一些技术性较强的事情是很困难的(比如“网站的内容结构和呈现外观是相互独立的”),不过经过初步的沟通,也最终大概有了一个思路。显然,根据他们的要求,一个简单的、只有日志列表的WordPress主题肯定是不够的。我需要一个内容丰富、灵活性强的主题。于是我在网上找到了一个专门定制收费WordPress主题的网站WooThemes。说实话他们的主题都很不错,但是要收费的,价格还挺高。不过这难不倒我,一番邪恶的搜索之后便下载到了一些“别有用心人士”免费提供的版本。解开一看,模板的footer.php文件居然为了“保护版权”而是用的加密。显然,所谓的“版权”估计就是页面底部的“Theme by WooThemes”之类的话吧。唉,这样加密来加密去,岂不是和PHP的开源精神背道而驰?再说我邪恶一下就邪恶到底吧,破解之!

打开footer.php文件一看,是这样的内容:

<?php /* WARNING: This file is protected by copyright law. To reverse engineer or decode this file is strictly prohibited. */$o="QAAADjtjbnEnZGtmdHQ6JWFufwgAJTk7KAEgOQoNCg0OOyYqKicAAGFoaHNidSdUc2Z1c3QnKirNYAGwA1NuYwMgAdIlAUAnABQFCWRoaXNiOCBpcwH5AmECO2sqa2JhAk4OO280OQAAOzh3b3cnYmRvaCd0c3Vud0AAdApwb2J0L2Bic1hod3NuaGkCgC8gcGhoWAozWASBWHNuc2tiIAZPLi48JzgMsARQCg0AAAAnO3cFrwWvBa0FRnnAdw7oDPEAQQ05b3UUVwAAACcHsCFkaHd+PEQMJw3Dc29iCyBqYi8gXiALMgGEZWsBQWhgbmlhaC8BUikBZG5hJy8nD9+AARoBWGR1YmNuc3QgLicuJ3wTT/AgE08bogN3BpB6J2JrdGID4Dg5RmtrBAAnVW5gbx8gVWJ0YnVxYmMpJwQACg07ZicWAjolRGtuZGxlZmkAAGwnUGh1Y3d1YnR0J1NvYmoAAGIlJ291YmE6JW9zc3c9KCgEKHBwcClwArBiYypwApUqD2BqYnQEUClkaGooAVd3a3IPMHQBKGpoaWIATH4qamZsbmlgKgHzJScocBAgOiUSqFhlawfgJTkIkkUAsCcEticCwzsoZgAMOSc7bmpgJ3R1ZDolFxMVliBzAABiandrZnNiWGNudWJkc2h1QKB+GCMobmpmYGIIgWgKhHdpYCUnAFBwbmNzbzolMDMOEGIRoTolNj4AISUnZmtzOiVQaGgP03QlJygnYFv4ZiYEeihCIw8nFLAjYQBFNzUBBQCBJSlkaGs//yp1B0E0rTJvMm8ybQSSJ1AyfwdxAEgqwBNDOB8YIJ+VOB91WAWyMo8FRA5tAQ5HgCdkOJB0RYBuSKhjzw4CpUkaQmljSPUpkEtUCxNwd0E0M/MB8ESSwAAz/0PAYGhoYGtiWGZpZmt+c25BTWQ0ETs5JyUlNH90R79oWAP/NJI4QkCCvQjDI3NwbnNUETo7qSUk8BRRAdQA4yUDsMAVA5cK4iNAS0hFRktUXAKUWAKjWgnikAACwnRkHzBzJ3N+d2I6JXNif3MFeShtZnFmAWMlL6NvOLMENDdyAkd0KDExA/5gYnUpbXRLgQOjC/EAowWvBwEFrw4wBaJ0BoBzZnNydDQAAFB1JnBqYmtuaWIo5AwQ0ySiESVcIAIxaWZqYiBaWuEIEGhpACg4ZGZra2VmZGw6CvREAQQ1IWYAQGp3PGRocmlzOgTfdVwgaXJqHwJlYnUEswybH9I4wW1ROyhlaGN+DgEoCABvc2prAJAKDQ==";eval(base64_decode("JGxsbD0wO2V2YWwoYmFzZTY0X2RlY29kZSgiSkd4c2JHeHNiR3hzYkd4c1BTZGlZWE5sTmpSZlpHVmpiMlJsSnpzPSIpKTskbGw9MDtldmFsKCRsbGxsbGxsbGxsbCgiSkd4c2JHeHNiR3hzYkd3OUoyOXlaQ2M3IikpOyRsbGxsPTA7JGxsbGxsPTM7ZXZhbCgkbGxsbGxsbGxsbGwoIkpHdzlKR3hzYkd4c2JHeHNiR3hzS0NSdktUcz0iKSk7JGxsbGxsbGw9MDskbGxsbGxsPSgkbGxsbGxsbGxsbCgkbFsxXSk8PDgpKyRsbGxsbGxsbGxsKCRsWzJdKTtldmFsKCRsbGxsbGxsbGxsbCgiSkd4c2JHeHNiR3hzYkd4c2JHdzlKM04wY214bGJpYzciKSk7JGxsbGxsbGxsbD0xNjskbGxsbGxsbGw9IiI7Zm9yKDskbGxsbGw8JGxsbGxsbGxsbGxsbGwoJGwpOyl7aWYoJGxsbGxsbGxsbD09MCl7JGxsbGxsbD0oJGxsbGxsbGxsbGwoJGxbJGxsbGxsKytdKTw8OCk7JGxsbGxsbCs9JGxsbGxsbGxsbGwoJGxbJGxsbGxsKytdKTskbGxsbGxsbGxsPTE2O31pZigkbGxsbGxsJjB4ODAwMCl7JGxsbD0oJGxsbGxsbGxsbGwoJGxbJGxsbGxsKytdKTw8NCk7JGxsbCs9KCRsbGxsbGxsbGxsKCRsWyRsbGxsbF0pPj40KTtpZigkbGxsKXskbGw9KCRsbGxsbGxsbGxsKCRsWyRsbGxsbCsrXSkmMHgwZikrMztmb3IoJGxsbGw9MDskbGxsbDwkbGw7JGxsbGwrKykkbGxsbGxsbGxbJGxsbGxsbGwrJGxsbGxdPSRsbGxsbGxsbFskbGxsbGxsbC0kbGxsKyRsbGxsXTskbGxsbGxsbCs9JGxsO31lbHNleyRsbD0oJGxsbGxsbGxsbGwoJGxbJGxsbGxsKytdKTw8OCk7JGxsKz0kbGxsbGxsbGxsbCgkbFskbGxsbGwrK10pKzE2O2ZvcigkbGxsbD0wOyRsbGxsPCRsbDskbGxsbGxsbGxbJGxsbGxsbGwrJGxsbGwrK109JGxsbGxsbGxsbGwoJGxbJGxsbGxsXSkpOyRsbGxsbCsrOyRsbGxsbGxsKz0kbGw7fX1lbHNlJGxsbGxsbGxsWyRsbGxsbGxsKytdPSRsbGxsbGxsbGxsKCRsWyRsbGxsbCsrXSk7JGxsbGxsbDw8PTE7JGxsbGxsbGxsbC0tO31ldmFsKCRsbGxsbGxsbGxsbCgiSkd4c2JHeHNiR3hzYkd4c2JEMG5ZMmh5SnpzPSIpKTskbGxsbGw9MDtldmFsKCRsbGxsbGxsbGxsbCgiSkd4c2JHeHNiR3hzYkQwaVB5SXVKR3hzYkd4c2JHeHNiR3hzYkNnMk1pazciKSk7JGxsbGxsbGxsbGw9IiI7Zm9yKDskbGxsbGw8JGxsbGxsbGw7KXskbGxsbGxsbGxsbC49JGxsbGxsbGxsbGxsbCgkbGxsbGxsbGxbJGxsbGxsKytdXjB4MDcpO31ldmFsKCRsbGxsbGxsbGxsbCgiSkd4c2JHeHNiR3hzYkM0OUpHeHNiR3hzYkd4c2JHd3VKR3hzYkd4c2JHeHNiR3hzYkNnMk1Da3VJajhpT3c9PSIpKTtldmFsKCRsbGxsbGxsbGwpOw=="));return;?>
明眼人一看就知道代码采用了Base64加密。整个脚本有一个加密字符串$o,一个eval()函数执行某段字符串经base64_decode()解码后的语句。我们首先让eval()执行的具体语句重见天日。将footer.php复制一份到本地调试环境,然后把这个eval修改成echo。浏览器执行后我们可以就可以看到它的内容了。选择浏览器的查看源代码,将其所有内容复制,替换掉eval()那一行,然后稍稍整理一下(许多IDE可以进行这项操作),可得(为保持排版,请点击展开):

<?php /* WARNING: This file is protected by copyright law. To reverse engineer or decode this file is strictly prohibited. */$o "QAAADjtjbnEnZGtmdHQ6JWFufwgAJTk7KAEgOQoNCg0OOyYqKicAAGFoaHNidSdUc2Z1c3QnKirNYAGwA1NuYwMgAdIlAUAnABQFCWRoaXNiOCBpcwH5AmECO2sqa2JhAk4OO280OQAAOzh3b3cnYmRvaCd0c3Vud0AAdApwb2J0L2Bic1hod3NuaGkCgC8gcGhoWAozWASBWHNuc2tiIAZPLi48JzgMsARQCg0AAAAnO3cFrwWvBa0FRnnAdw7oDPEAQQ05b3UUVwAAACcHsCFkaHd+PEQMJw3Dc29iCyBqYi8gXiALMgGEZWsBQWhgbmlhaC8BUikBZG5hJy8nD9+AARoBWGR1YmNuc3QgLicuJ3wTT/AgE08bogN3BpB6J2JrdGID4Dg5RmtrBAAnVW5gbx8gVWJ0YnVxYmMpJwQACg07ZicWAjolRGtuZGxlZmkAAGwnUGh1Y3d1YnR0J1NvYmoAAGIlJ291YmE6JW9zc3c9KCgEKHBwcClwArBiYypwApUqD2BqYnQEUClkaGooAVd3a3IPMHQBKGpoaWIATH4qamZsbmlgKgHzJScocBAgOiUSqFhlawfgJTkIkkUAsCcEticCwzsoZgAMOSc7bmpgJ3R1ZDolFxMVliBzAABiandrZnNiWGNudWJkc2h1QKB+GCMobmpmYGIIgWgKhHdpYCUnAFBwbmNzbzolMDMOEGIRoTolNj4AISUnZmtzOiVQaGgP03QlJygnYFv4ZiYEeihCIw8nFLAjYQBFNzUBBQCBJSlkaGs//yp1B0E0rTJvMm8ybQSSJ1AyfwdxAEgqwBNDOB8YIJ+VOB91WAWyMo8FRA5tAQ5HgCdkOJB0RYBuSKhjzw4CpUkaQmljSPUpkEtUCxNwd0E0M/MB8ESSwAAz/0PAYGhoYGtiWGZpZmt+c25BTWQ0ETs5JyUlNH90R79oWAP/NJI4QkCCvQjDI3NwbnNUETo7qSUk8BRRAdQA4yUDsMAVA5cK4iNAS0hFRktUXAKUWAKjWgnikAACwnRkHzBzJ3N+d2I6JXNif3MFeShtZnFmAWMlL6NvOLMENDdyAkd0KDExA/5gYnUpbXRLgQOjC/EAowWvBwEFrw4wBaJ0BoBzZnNydDQAAFB1JnBqYmtuaWIo5AwQ0ySiESVcIAIxaWZqYiBaWuEIEGhpACg4ZGZra2VmZGw6CvREAQQ1IWYAQGp3PGRocmlzOgTfdVwgaXJqHwJlYnUEswybH9I4wW1ROyhlaGN+DgEoCABvc2prAJAKDQ=="$lll 0; eval ( base64_decode "JGxsbGxsbGxsbGxsPSdiYXNlNjRfZGVjb2RlJzs=" ) ); $ll 0; eval ( $lllllllllll "JGxsbGxsbGxsbGw9J29yZCc7" ) ); $llll 0$lllll 3; eval ( $lllllllllll "JGw9JGxsbGxsbGxsbGxsKCRvKTs=" ) ); $lllllll 0$llllll = ($llllllllll $l [1] ) << 8) + $llllllllll $l [2] ); eval ( $lllllllllll "JGxsbGxsbGxsbGxsbGw9J3N0cmxlbic7" ) ); $lllllllll 16$llllllll ""; for(; $lllll $lllllllllllll $l );) {     if ($lllllllll == 0) {         $llllll = ($llllllllll $l [$lllll ++] ) << 8);         $llllll += $llllllllll $l [$lllll ++] );         $lllllllll 16;     }     if ($llllll 0x8000) {         $lll = ($llllllllll $l [$lllll ++] ) << 4);         $lll += ($llllllllll $l [$lllll] ) >> 4);         if ($lll) {             $ll = ($llllllllll $l [$lllll ++] ) & 0x0f) + 3;             for($llll 0$llll $ll$llll ++)                 $llllllll [$lllllll $llll] = $llllllll [$lllllll $lll $llll];             $lllllll += $ll;         } else {             $ll = ($llllllllll $l [$lllll ++] ) << 8);             $ll += $llllllllll $l [$lllll ++] ) + 16;             for($llll 0$llll $ll$llllllll [$lllllll $llll ++] = $llllllllll $l [$lllll] ))                 ;             $lllll ++;             $lllllll += $ll;         }     } else        $llllllll [$lllllll ++] = $llllllllll $l [$lllll ++] );     $llllll <<= 1;     $lllllllll --; } eval ( $lllllllllll "JGxsbGxsbGxsbGxsbD0nY2hyJzs=" ) ); $lllll 0; eval ( $lllllllllll "JGxsbGxsbGxsbD0iPyIuJGxsbGxsbGxsbGxsbCg2Mik7" ) ); $llllllllll ""; for(; $lllll $lllllll;) {     $llllllllll .= $llllllllllll $llllllll [$lllll ++] ^ 0x07 ); } eval ( $lllllllllll "JGxsbGxsbGxsbC49JGxsbGxsbGxsbGwuJGxsbGxsbGxsbGxsbCg2MCkuIj8iOw==" ) ); eval ( $lllllllll ); return; ?>
现在稍微有点眉目了,不过这其中还有一大堆Base64编码的字符串,和一堆以数个字母l命名的变量和变量函数……看了就头晕。不过我们不需要搞这些解码的过程,只需要解码的结果就可以了。注意到最后一句eval ( $lllllllll );,让我们把它改成echo ( $lllllllll );。再次在浏览器中执行,这下可以通过查看源代码看出一些端倪了吧(见以下代码)!

<div class="fix"></div>       <!-- footer Starts -->    <div id="footer"><div class="content"><div class="col-left"><h3><?php echo stripslashes(get_option('woo_footer_left_title')); ?></h3><p><?php echo stripslashes(get_option('woo_footer_left')); ?></p><div class="hr"></div><p>&copy; <?php the_time('Y'); ?> <?php bloginfo(); ?><?php if ( get_option('woo_footer_credits') ) { echo stripslashes(get_option('woo_footer_credits')); } else { ?>All Rights Reserved. <a title="Clickbank WordPress Theme" href="http://www.wicked-wordpress-themes.com/wordpress-plugins/wordpress-money-making-plugin" target="_blank">ClickBank wordpress plugin</a> <img src="<?php bloginfo('template_directory'); ?>/images/woothemes.png" width="74" height="19" alt="Woo Themes" /></a><?php ?></p></div><div class="col-right"><h3><?php echo stripslashes(get_option('woo_footer_right_title')); ?></h3><p><?php echo stripslashes(get_option('woo_footer_right')); ?></p></div></div><div class="fix"></div></div>     <!-- footer Ends -->  </div> <?php wp_footer(); ?><?php if ( get_option('woo_google_analytics') <> "" ) { echo stripslashes(get_option('woo_google_analytics')); } ?><?php $twitter get_option("widget_twitterwidget"); ?><?php if ( $GLOBALS[twitter_widget] ) { ?><script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"></script> <script type="text/javascript" src="http://twitter.com/statuses/user_timeline/<?php echo $twitter['username']; ?>.json?callback=twitterCallback2&amp;count=<?php echo $twitter['number']; ?>"></script> <?php ?>  </body> </html>   <?

需要指出的是,在Chrome下高亮显示的两行并不能正确显示出,在23行 </div> 结束后直接连接的是25行的 "" ) { echo stripslashes(get_option('woo_google_analytics')); } ?> ,中间缺了一块,不知道为什么。而在IE8中,源代码显示正确。如果实在不放心的话,可以把这段php放到调试器里去调试,直接获取最终那个变量的值,一定不会错的。

至于为什么一上来就把最后一行的eval改成echo呢?事实上在尝试的过程中,我把之前全部的eval()函数都还原成了它的本来面目,方法就是把那个eval换成echo,然后删掉其后的所有内容,在浏览器中得到结果后替换那一行,再把其后的内容还原回去。如此反复几次后就可以把所有的eval()都还原,但是还原的结果其实对最终输出并没有影响,控制最终输出的还是那最后一行的$lllllllll(九个l)变量。总的看来,最终输出的原型存放在$o中,但是是经过了某种畸形的修改的,其后所有的php脚本都是在做还原$o中本来内容的工作,只不过这个还原的过程也显得非常畸形,基本没有可读性。而最后$o的本来内容放在了$lllllllll中,执行它即可。

现在我们终于得到了footer.php的原始面目了,下面要做的就是把上面的那段代码覆盖掉文件原来的全部内容。当然,原来文件中为了保持上下文而在开头和结尾出现的
转自:http://dayanjia.com/2010/02/crack-php-file-encoded-with-base64.html