文章总结: 本文包含YunSee团队招新及两道CTF流量分析题解。工厂应急响应题通过分析Modbus、OPCUA、DNS、HTTP、ICMP和SNMP协议提取标志位。BlueBreath题涉及识别webshell流量,利用bkcrack明文攻击破解压缩包,并基于GZIP头推导XOR密钥解密加密通讯,提供Python脚本实现自动化解密。 综合评分: 95 文章分类: CTF,应急响应,WEB安全,恶意软件,安全工具

fig:
fig:
这图片我也不清楚有啥用,没啥可用的信息
先来到wireshark 筛选http POST请求
http.request.method == "POST"
fig:
发现上传了shell.php可疑文件
fig:
像二进制被加密数据
筛选所有包含shell.php 的流
http.request.method == "POST" && http.request.uri contains "shell.php"
fig:
前三个流一大片乱码,怀疑是后门的加密源码
从第四个流开始,这里的传输的加密数据好似哥斯拉那种加密shell后门,请求的命令以及执行结果回显
fig:
数据的开头都是:7b e8 3b 65 66 35 66 66 30 …
fig:
webshell 常见做法是“先压缩再混淆”,于是尝试以 gzip 固定头 1f 8b 08 00 00 00 00 00 00 作为已知明文,利用 C XOR P 反推出前 9 字节密钥
fig:
得到的是可显示的字符串,说明这是密钥的一部分
这里我也不清楚key的长度以及爆破出完整的key,就求助AI了
fig:
拿到完整的key之后,写个解密脚本将加密webshell解密
import re, gzip, socket
import dpkt
PCAP = "BlueBreath.pcapng"
KEY = b"dc3ef5ff0c670152"# 16-byte XOR key
def reassemble(segs):
"""按 TCP seq 重组(处理重传/重叠)"""
ifnot segs:
returnb""
segs = sorted(segs, key=lambda x: x[0])
base = segs[0][0]
out = bytearray()
cur = base
for seq, data in segs:
if seq < cur:
overlap = cur - seq
if overlap >= len(data):
continue
data = data[overlap:]
seq = cur
if seq > cur:
out.extend(b"x00" * (seq - cur))
cur = seq
out.extend(data)
cur += len(data)
return bytes(out)
def parse_http_bodies(stream_bytes, is_request=True):
"""从 TCP 字节流里按 Content-Length 拆 HTTP 消息 body"""
res = []
i = 0
whileTrue:
if is_request:
j = stream_bytes.find(b"POST ", i)
else:
j = stream_bytes.find(b"HTTP/1.", i)
if j == -1:
break
k = stream_bytes.find(b"rnrn", j)
if k == -1:
break
header = stream_bytes[j:k].decode("iso-8859-1", errors="ignore")
m = re.search(r"Content-Length:s*(d+)", header, re.I)
clen = int(m.group(1)) if m else0
body_start = k + 4
body = stream_bytes[body_start:body_start + clen]
res.append((header.split("rn", 1)[0], header, body))
i = body_start + clen
return res
def xor_dec(data, key):
return bytes(b ^ key[i % len(key)] for i, b in enumerate(data))
def main():
# 收集所有 8000 端口 TCP 分段:按 (client_ip, client_port, server_ip, 8000) 归一化成一个连接
streams = {} # key -> {'c2s':[(seq,data)], 's2c':[(seq,data)]}
with open(PCAP, "rb") as f:
pcap = dpkt.pcapng.Reader(f)
for ts, buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
ifnot isinstance(ip, dpkt.ip.IP):
continue
tcp = ip.data
ifnot isinstance(tcp, dpkt.tcp.TCP) ornot tcp.data:
continue
src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
if tcp.dport == 8000:
key = (src, tcp.sport, dst, 8000)
streams.setdefault(key, {"c2s": [], "s2c": []})
streams[key]["c2s"].append((tcp.seq, tcp.data))
elif tcp.sport == 8000:
key = (dst, tcp.dport, src, 8000)
streams.setdefault(key, {"c2s": [], "s2c": []})
streams[key]["s2c"].append((tcp.seq, tcp.data))
except:
pass
# 找出包含 /uploads/shell.php 的连接并解密
for key, d in streams.items():
c2s = reassemble(d["c2s"])
ifb"POST /uploads/shell.php"notin c2s:
continue
s2c = reassemble(d["s2c"])
reqs = parse_http_bodies(c2s, is_request=True)
resps = parse_http_bodies(s2c, is_request=False)
print("n=== shell conn:", key, "===")
for first, header, body in reqs:
if"/uploads/shell.php"notin first:
continue
ifnot body:
continue
p = xor_dec(body, KEY)
try:
out = gzip.decompress(p)
print("[REQ]", out.decode(errors="ignore"))
except Exception as e:
print("[REQ] decrypt fail:", e)
for first, header, body in resps:
ifnot body:
continue
p = xor_dec(body, KEY)
try:
out = gzip.decompress(p)
print("[RESP]", out.decode(errors="ignore"))
except Exception as e:
print("[RESP] decrypt fail:", e)
if __name__ == "__main__":
main()
fig:
加入我们
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:云晞科技Sec 江思澄 江思澄《UniCTF 两道流量分析 WP》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论