NCTF 2023 Slivery取证题WP

在今年NCTF上做的一道取证题。涉及到的是Sliver的这个红队工具的攻击取证。在这里简单写一下。

为什么又是取证?说好的看web呢?

题目给了一个内存镜像mem和pcap流量包dump.pcapng。很明显是要从内存镜像中取证来解密流量包中的流量。当然是要先从内存镜像下手。

用volatility3分析内存镜像。按照通常的步骤,先看看能看的东西。比如用pslist看一下进程。

python .\vol.py -f D:\Action\mem windows.pslist.PsList
...
4968 5852 SearchProtocol 0xe083685c8080 8 - 0 False 2023-12-21 14:41:10.000000 N/A Disabled
4348 5852 SearchFilterHo 0xe08366ba9080 7 - 0 False 2023-12-21 14:41:10.000000 N/A Disabled
8800 4884 slivery.exe 0xe08368639080 9 - 1 False 2023-12-21 14:41:18.000000 N/A Disabled
8416 656 svchost.exe 0xe0836889d080 11 - 0 False 2023-12-21 14:41:18.000000 N/A Disabled
...

题目名字就叫slivery,那当然要从这个slivery.exe开始分析了。用dumpfiles把这个进程的exe给dump下来先。

python .\vol.py -f D:\Action\mem windows.dumpfiles.DumpFiles --pid 8800

dump的过程中杀毒软件直接给报毒了。用virustotal把.exe.img扫一下,得到的结果就是sliver的木马,那直接按照这个来做就行。

具体有关sliver的攻击取证原理可以参考这篇bloghttps://www.immersivelabs.com/blog/detecting-and-decrypting-sliver-c2-a-threat-hunters-guide/

简单来说就是sliver的服务端和木马使用http或者dns进行通信,流量都经过ChaCha20Poly1305对称加密,并用gzip/换表base/单词表等手段进行编码和混淆。对于这道题来说,我们有了抓取来的攻击的流量。而dump内存时木马还在运行,进行通信的密钥session key还可能留存在进程的内存中。想要解密payload就需要从内存中找到这个32字节的session key。而这个密钥在内存中存在有一个特定的规律:

00 00 [32 bytes key] ?? ?? ?? 00 C0 00 00

为了找到密钥,最简单的方法就是根据这个规律,用正则来把进程中的内存来扫一遍,把所有符合这个规律的32 bytes给找出来。ChaCha20Poly1305算法自带校验,因此挨个试一试能不能解密就行了…

具体操作可以使用那篇blog配套的脚本https://github.com/Immersive-Labs-Sec/SliverC2-Forensics。包含两个简单的py,sliver_pcap_parser.py用pyshark将pcap流量包中的sliver流量并将body导出,sliver_decrypt.py实现了用正则从进程内存中找密钥并尝试解密流量的过程。

实际做的时候可能是由于pyshark版本的原因,流量的处理有点问题,脚本不能直接用,简单改一下就可以了。比赛的时候就主要就是因为调这个脚本浪费了点时间。

先用wireshark简单看一下pcap,可以发现攻击流量使用的是http的形式,服务端的ip大概就是另一个内网地址192.168.207.128

python .\vol.py -f .\mem windows.memmap.Memmap --pid 8800 # dump木马进程的内存 pid.8800.dmp
python .\sliver_pcap_parser.py --pcap .\dump.pcapng --domain_name 192.168.207.128 --filter http # 从pcap中提取sliver的流量
python .\sliver_decrypt.py --file_path .\http-sessions.json --transport http --force .\pid.8800.dmp # 从进程内存中搜索可能的密钥并尝试爆破解密

这样就可以解密出流量了,一堆乱七八糟的东西,可能是因为脚本还是没完全调好。就先翻一翻看看吧。

...
[+] Processing: http://192.168.207.128:80/db/oauth2/namespaces/api.php?b=70z315336
[-] Decoding: gzip-words
[-] Session Key: 28c917760c81fc4747f9c68b23405ad39525291d16ff59170ddc5484a5134077
[-] Message Type: 0
[=] Message Data
b'\n C:\\Users\\August\\Desktop\\flag.zip'
...
[+] Processing: http://192.168.207.128:80/jquery.min.js?i=g25622249
[-] Decoding: gzip-b64
[-] Session Key: 28c917760c81fc4747f9c68b23405ad39525291d16ff59170ddc5484a5134077
[-] Message Type: 22
[=] Message Data
b'\n\x19echo P@33w000000rd_U_GOT\n\x18\x01@\xef\xe3\xc2\x93\x8b\x94\xdb\x8c\xeb\x01J$06a76de5-4afb-44d3-a350-897d85c91960'
...

翻到两条可疑的流量。可以看到桌面上有个flag.zip,又echo了一个东西P@33w000000rd_U_GOT,大概率就是密码了。

直接用foremost从进程内存中找zip。

foremost ./pid.8800.dmp

用密码打开扫出来的zip,就能得到flag了。

NCTF{1d38c372-a636-430e-b47e-95f6136a9bb4}


还是一道很简单的题,直接就能按着blog用现成的脚本做。基本上能找到那篇blog就出了。可能是因为愿意做取证的人本来就不多,比赛上总共就两队交了这道题,咱还拿了个一血,给队伍白捡1000分。

做这道题确实没什么技术含量,但至少攻击取证的思路可以记录下来参考一下。

评论