DIDCTF 应急响应 流量+日志分析+数据恢复部分
https://www.cnblogs.com/ljnljn/p/19982779
id=980ae054-167e-4a78-b4e4-532c5805b122
source=ljnljn
author=
会员
周边
新闻
博问
闪存
赞助商
Chat2DB
所有博客
当前博客
我的博客
我的园子
账号设置
会员中心
简洁模式
...
退出登录
注册
登录
ljnljn
博客园
首页
新随笔
联系
订阅
管理
DIDCTF 应急响应 流量+日志分析+数据恢复部分
DIDCTF-电子数据取证综合平台
linux-basic-command
网站日志分析
用goaccess工具
ire7-windows-log
筛选一下就出来了
wireshark0
telnet流量
wireshark0.5
http.request.method=="POST"
找login位置
wireshark1
最后一个post流执行了压缩命令，密码是Adm1n!
另外我们可以分离出下载的压缩包
打开文件就可以获得key
wireshark2
让ai写了个icmp解析器
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import re
from datetime import datetime

try:
    from scapy.all import rdpcap, IP, IPv6, ICMP, ICMPv6EchoRequest, ICMPv6EchoReply, Raw
except ImportError:
    messagebox.showerror("缺少依赖", "请先安装 scapy：pip install scapy")
    raise

def printable_ascii(data: bytes) -> str:
    return ''.join(chr(b) if 32 <= b <= 126 else '.' for b in data)

def extract_strings(data: bytes, min_len=4):
    text = printable_ascii(data)
    return re.findall(r"[ -~]{" + str(min_len) + r",}", text)

def hex_dump(data: bytes, width=16):
    lines = []
    for i in range(0, len(data), width):
        chunk = data[i:i + width]
        hex_part = " ".join(f"{b:02x}" for b in chunk)
        ascii_part = printable_ascii(chunk)
        lines.append(f"{i:08x}  {hex_part:<{width * 3}}  {ascii_part}")
    return "\n".join(lines)

class ICMPParserApp:
    def __init__(self, root):
        self.root = root
        self.root.title("ICMP 流量解析器")
        self.root.geometry("1200x720")

        self.packets = []
        self.icmp_records = []

        self.build_ui()

    def build_ui(self):
        top_frame = ttk.Frame(self.root)
        top_frame.pack(fill=tk.X, padx=8, pady=6)

        ttk.Button(top_frame, text="打开 PCAP/PCAPNG", command=self.open_file).pack(side=tk.LEFT, padx=4)
        ttk.Button(top_frame, text="搜索 key/flag", command=self.search_sensitive).pack(side=tk.LEFT, padx=4)
        ttk.Button(top_frame, text="提取所有可见字符串", command=self.show_all_strings).pack(side=tk.LEFT, padx=4)
        ttk.Button(top_frame, text="拼接 Echo Request 首字符", command=self.rebuild_first_chars).pack(side=tk.LEFT, padx=4)
        ttk.Button(top_frame, text="清空", command=self.clear).pack(side=tk.LEFT, padx=4)

        self.status_var = tk.StringVar(value="请打开一个流量包")
        ttk.Label(top_frame, textvariable=self.status_var).pack(side=tk.RIGHT, padx=8)

        main_pane = ttk.PanedWindow(self.root, orient=tk.VERTICAL)
        main_pane.pack(fill=tk.BOTH, expand=True, padx=8, pady=6)

        table_frame = ttk.Frame(main_pane)
        main_pane.add(table_frame, weight=2)

        columns = ("no", "time", "src", "dst", "proto", "type", "code", "len", "ascii")
        self.tree = ttk.Treeview(table_frame, columns=columns, show="headings")

        headers = {
            "no": "序号",
            "time": "时间",
            "src": "源地址",
            "dst": "目的地址",
            "proto": "协议",
            "type": "Type",
            "code": "Code",
            "len": "数据长度",
            "ascii": "Data ASCII 预览"
        }

        widths = {
            "no": 60,
            "time": 160,
            "src": 150,
            "dst": 150,
            "proto": 80,
            "type": 80,
            "code": 80,
            "len": 80,
            "ascii": 420
        }

        for col in columns:
            self.tree.heading(col, text=headers[col])
            self.tree.column(col, width=widths[col], anchor=tk.W)

        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.tree.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.configure(yscrollcommand=scrollbar.set)

        self.tree.bind("<<TreeviewSelect>>", self.on_packet_select)

        detail_frame = ttk.Frame(main_pane)
        main_pane.add(detail_frame, weight=3)

        detail_label = ttk.Label(detail_frame, text="数据区详情：Hex + ASCII")
        detail_label.pack(anchor=tk.W)

        self.text = tk.Text(detail_frame, wrap=tk.NONE, font=("Consolas", 11))
        self.text.pack(fill=tk.BOTH, expand=True)

        x_scroll = ttk.Scrollbar(detail_frame, orient=tk.HORIZONTAL, command=self.text.xview)
        x_scroll.pack(fill=tk.X)
        self.text.configure(xscrollcommand=x_scroll.set)

    def open_file(self):
        file_path = filedialog.askopenfilename(
            title="选择流量包",
            filetypes=[
                ("PCAP files", "*.pcap *.pcapng"),
                ("All files", "*.*")
            ]
        )

        if not file_path:
            return

        try:
            self.clear()
            self.status_var.set("正在解析，请稍等...")

            self.packets = rdpcap(file_path)
            self.parse_icmp_packets()

            self.status_var.set(f"已加载：{file_path}，共发现 {len(self.icmp_records)} 个 ICMP/ICMPv6 包")

            if not self.icmp_records:
                messagebox.showinfo("提示", "没有发现 ICMP/ICMPv6 数据包")

        except Exception as e:
            messagebox.showerror("解析失败", str(e))
            self.status_var.set("解析失败")

    def parse_icmp_packets(self):
        for index, pkt in enumerate(self.packets, start=1):
            record = None

            if IP in pkt and ICMP in pkt:
                ip = pkt[IP]
                icmp = pkt[ICMP]
                payload = bytes(icmp.payload)

                record = {
                    "no": index,
                    "time": self.format_time(float(pkt.time)),
                    "src": ip.src,
                    "dst": ip.dst,
                    "proto": "ICMP",
                    "type": int(icmp.type),
                    "code": int(icmp.code),
                    "payload": payload,
                    "summary": pkt.summary()
                }

            elif IPv6 in pkt and (ICMPv6EchoRequest in pkt or ICMPv6EchoReply in pkt):
                ip = pkt[IPv6]
                if ICMPv6EchoRequest in pkt:
                    icmp6 = pkt[ICMPv6EchoRequest]
                    icmp_type = 128
                else:
                    icmp6 = pkt[ICMPv6EchoReply]
                    icmp_type = 129

                payload = bytes(icmp6.payload)

                record = {
                    "no": index,
                    "time": self.format_time(float(pkt.time)),
                    "src": ip.src,
                    "dst": ip.dst,
                    "proto": "ICMPv6",
                    "type": icmp_type,
                    "code": 0,
                    "payload": payload,
                    "summary": pkt.summary()
                }

            if record:
                self.icmp_records.append(record)
                ascii_preview = printable_ascii(record["payload"])
                if len(ascii_preview) > 80:
                    ascii_preview = ascii_preview[:80] + "..."

                self.tree.insert(
                    "",
                    tk.END,
                    iid=str(len(self.icmp_records) - 1),
                    values=(
                        record["no"],
                        record["time"],
                        record["src"],
                        record["dst"],
                        record["proto"],
                        record["type"],
                        record["code"],
                        len(record["payload"]),
                        ascii_preview
                    )
                )

    def on_packet_select(self, event=None):
        selected = self.tree.selection()
        if not selected:
            return

        idx = int(selected[0])
        record = self.icmp_records[idx]
        payload = record["payload"]

        self.text.delete("1.0", tk.END)

        info = []
        info.append(f"原始包序号：{record['no']}")
        info.append(f"时间：{record['time']}")
        info.append(f"源地址：{record['src']}")
        info.append(f"目的地址：{record['dst']}")
        info.append(f"协议：{record['proto']}")
        info.append(f"Type/Code：{record['type']}/{record['code']}")
        info.append(f"Payload 长度：{len(payload)} 字节")
        info.append(f"摘要：{record['summary']}")
        info.append("")
        info.append("ASCII：")
        info.append(printable_ascii(payload))
        info.append("")
        info.append("Hex Dump：")
        info.append(hex_dump(payload))

        self.text.insert(tk.END, "\n".join(info))

    def search_sensitive(self):
        if not self.icmp_records:
            messagebox.showinfo("提示", "请先打开流量包")
            return

        keywords = ["key", "flag", "password", "pass", "secret", "token"]
        result = []

        for record in self.icmp_records:
            data = printable_ascii(record["payload"])
            lower_data = data.lower()

            if any(k in lower_data for k in keywords):
                result.append(
                    f"[包序号 {record['no']}] {record['src']} -> {record['dst']} "
                    f"Type={record['type']} Code={record['code']}\n{data}\n"
                )

        self.text.delete("1.0", tk.END)

        if result:
            self.text.insert(tk.END, "发现疑似敏感内容：\n\n")
            self.text.insert(tk.END, "\n".join(result))
        else:
            self.text.insert(tk.END, "没有直接发现 key/flag/password/secret/token 等关键字。\n")
            self.text.insert(tk.END, "可以尝试点击“提取所有可见字符串”继续查看。")

    def show_all_strings(self):
        if not self.icmp_records:
            messagebox.showinfo("提示", "请先打开流量包")
            return

        result = []

        for record in self.icmp_records:
            strings = extract_strings(record["payload"], min_len=4)
            if strings:
                result.append(f"[包序号 {record['no']}] {record['src']} -> {record['dst']}")
                for s in strings:
                    result.append(f"  {s}")
                result.append("")

        self.text.delete("1.0", tk.END)

        if result:
            self.text.insert(tk.END, "\n".join(result))
        else:
            self.text.insert(tk.END, "没有提取到长度 >= 4 的可见字符串。")

    def rebuild_first_chars(self):
        if not self.icmp_records:
            messagebox.showinfo("提示", "请先打开流量包")
            return

        chars_all = []
        chars_request = []

        for record in self.icmp_records:
            payload = record["payload"]
            if not payload:
                continue

            first_char = chr(payload[0]) if 32 <= payload[0] <= 126 else "."
            chars_all.append(first_char)

            if record["proto"] == "ICMP" and record["type"] == 8:
                chars_request.append(first_char)

            if record["proto"] == "ICMPv6" and record["type"] == 128:
                chars_request.append(first_char)

        self.text.delete("1.0", tk.END)
        self.text.insert(tk.END, "所有 ICMP/ICMPv6 Payload 首字符拼接：\n")
        self.text.insert(tk.END, "".join(chars_all))
        self.text.insert(tk.END, "\n\nEcho Request Payload 首字符拼接：\n")
        self.text.insert(tk.END, "".join(chars_request))

    def clear(self):
        self.packets = []
        self.icmp_records = []
        for item in self.tree.get_children():
            self.tree.delete(item)
        self.text.delete("1.0", tk.END)
        self.status_var.set("已清空")

    @staticmethod
    def format_time(ts):
        try:
            return datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
        except Exception:
            return str(ts)

if __name__ == "__main__":
    root = tk.Tk()
    app = ICMPParserApp(root)
    root.mainloop()
一共执行三次命令，第三次就显示key1了
wireshark2.1
分离
题目告诉了解压密码直接用就行
wireshark3
这里发现一个key
并且提取的压缩包中有一个带密码，拿这个解
后面大家都知道了
linux-log
找第一次accepted password的位置
welog1
只有最后三条是200
发现有一串hex可疑，进行单独解码
获得了连接密码
data-recovery
用ufs恢复，发现flag
打开就看得到
posted @
2026-05-06 20:58
_ljnljn
阅读(
62
) 
评论(
0
)
收藏
举报
刷新页面
返回顶部
公告
博客园
©  2004-2026
浙公网安备 33010602011771号
浙ICP备2021040463号-3
