3-track_hacker Writeup by AI

3-track_hacker Writeup by AI

1. 题目描述

项目 内容
题目名称 track_hacker
题目来源 BugKu
题目类型 Crypto / Traffic Analysis / WebShell 流量分析
附件文件 shell.pcap (15.0KB)

题目背景

本题提供了一个网络抓包文件(shell.pcap),要求分析黑客攻击痕迹,从流量中提取 Flag。攻击者通过 WebShell 进行命令执行,并使用编码隐藏响应数据。


2. 考点分析

考点 分值权重 技能要求
PCAP 文件分析 20% 使用 scapy/Wireshark 分析网络抓包数据
HTTP 协议理解 25% 识别 HTTP 请求/响应结构,提取关键字段
WebShell 特征识别 25% 识别 POST 请求中的命令执行模式
编码解码技术 20% Base64 + zlib 双重压缩的识别与解码
攻击链还原能力 10% 从离散数据包中还原完整攻击流程

核心知识点

  1. WebShell 通信特征 : POST 请求包含 k=密码&c=命令 的参数结构
  2. 数据隐藏技术 : 服务器响应使用 Base64(zlib(数据)) 双重编码
  3. Linux 文件隐藏 : 通过在文件名前加点(.)来隐藏文件
  4. 流量分析工具: Python scapy 库或 Wireshark 的使用

3. 解题思路

3.1 整体思路

复制代码
文件检查 → 协议分析 → HTTP 请求提取 → WebShell 识别 → 编码解码 → Flag 提取

3.2 技术路线

步骤 目标 方法 预期结果
1 了解文件基本信息 file命令、scapy读取 确认 PCAP 格式
2 统计协议分布 遍历数据包计数 发现主要为 HTTP 流量
3 提取 HTTP 请求 解析 TCP 负载 找到 5 个关键 POST 请求
4 识别攻击行为 分析 URL 和参数 发现 WebShell 攻击链
5 解码响应数据 Base64+zlib 解码 获取命令执行结果
6 提取 Flag 匹配 flag{} 模式 得到最终答案

3.3 关键突破口

  • 异常短的响应体: HTTP 响应长度为 10-100 字节,疑似压缩数据
  • 重复的 Base64 字符串 : eJwrLy/XTUksSQQADqgDLQ== 多次出现
  • POST 参数模式 : k=cometohackme&c=命令 符合 WebShell 特征

4. 详细步骤

步骤 1: 文件基本信息检查

bash 复制代码
# 检查文件类型
file shell.pcap
# 输出:pcap capture file, microsecond ts (little-endian) - version 2.4

分析: 确认为标准 PCAP 网络抓包文件,可使用 scapy 或 Wireshark 分析。

步骤 2: 读取并统计协议分布

python 复制代码
from scapy.all import *

packets = rdpcap("shell.pcap")
print(f"总数据包数量:{len(packets)}")  # 输出:109

# 协议分布统计
protocol_count = {}
for pkt in packets:
    proto = pkt.summary().split()[0]
    protocol_count[proto] = protocol_count.get(proto, 0) + 1

# 输出:Loopback: 109 (100%)

分析: 所有 109 个数据包均为 Loopback(本地回环)流量,说明是本地抓包或虚拟机内部流量。

步骤 3: 提取 HTTP 请求详情

python 复制代码
http_requests = []

for i, pkt in enumerate(packets):
    if TCP in pkt and Raw in pkt:
        data = pkt[Raw].load.decode('utf-8', errors='ignore')
        
        if data.startswith('POST ') or data.startswith('GET '):
            lines = data.split('\r\n')
            method_path = lines[0]
            
            # 提取关键信息
            host = ""
            content_type = ""
            post_data = ""
            
            for line in lines[1:]:
                if line.startswith('Host:'):
                    host = line.split(':', 1)[1].strip()
                elif line.startswith('Content-Type:'):
                    content_type = line.split(':', 1)[1].strip()
            
            if '\r\n\r\n' in data:
                body = data.split('\r\n\r\n')[1]
                post_data = body[:100]
            
            http_requests.append({
                'packet_id': i,
                'method_path': method_path,
                'host': host,
                'content_type': content_type,
                'post_data': post_data
            })

发现的关键请求:

包 ID 请求方法 路径 Content-Type POST 数据
4 POST /upload.php text/php multipart/form-data...
14 POST /config.php application/x-www-form-urlencoded k=cometohackme&c=whoami
59 POST /config.php application/x-www-form-urlencoded k=cometohackme&c=mv config.php .config.php
79 POST /.config.php application/x-www-form-urlencoded k=cometohackme&c=whoami
99 POST /.config.php application/x-www-form-urlencoded k=cometohackme&c=cat /flag.txt

步骤 4: 识别 WebShell 攻击特征

WebShell 典型特征:

复制代码
POST /path/to/shell.php
Content-Type: application/x-www-form-urlencoded

password=your_password&exec=command_to_execute

本题中的模式:

复制代码
POST /config.php (或 .config.php)
Content-Type: application/x-www-form-urlencoded

k=cometohackme&c=command
     ↑              ↑
   连接密码      执行的命令

判断: 这是典型的 PHP WebShell 使用方式,攻击者通过 POST 请求传递命令并执行。

步骤 5: 提取并解码 HTTP 响应

python 复制代码
import base64
import zlib

http_responses = []

for i, pkt in enumerate(packets):
    if TCP in pkt and Raw in pkt:
        data = pkt[Raw].load.decode('utf-8', errors='ignore')
        
        if 'HTTP/1.1 200 OK' in data:
            if '\r\n\r\n' in data:
                body = data.split('\r\n\r\n')[1].strip()
                
                # 只处理短文本(可能是压缩的命令输出)
                if len(body) < 100 and len(body) > 10:
                    try:
                        # Base64 解码
                        decoded_b64 = base64.b64decode(body)
                        
                        # zlib 解压
                        decompressed = zlib.decompress(decoded_b64)
                        result = decompressed.decode('utf-8', errors='ignore')
                        
                        print(f"包 {i}: {body} -> {result}")
                    except:
                        pass

解码结果对照表:

包 ID 原始 Base64 Base64 解码 (Hex) zlib 解压结果 对应命令
16 eJwrLy/XTUksSQQADqgDLQ== 789c2b2f2fd74d492c4904000ea8032d www-data whoami
61 eJwDAAAAAAE= 789c030000000001 (空) mv 命令
81 eJwrLy/XTUksSQQADqgDLQ== 789c2b2f2fd74d492c4904000ea8032d www-data whoami
101 eJxLy0lMrw6NTzPMS4n3TVWsBQAz4wXi 789c4bcb494caf0e8d4f33cc4b89f74d55ac050033e305e2 flag{U_f1nd_Me!} cat /flag.txt

步骤 6: 还原完整攻击链

根据时间线整理攻击过程:

复制代码
时间戳: 1531106404 - 1531106442 (约 38 秒的攻击过程)

┌─────────────────────────────────────────────────────────────┐
│ 阶段 1: 上传 WebShell                                        │
├─────────────────────────────────────────────────────────────┤
│ • 包 ID: 4                                                   │
│ • 请求:POST /upload.php                                     │
│ • Content-Type: multipart/form-data                         │
│ • 行为:上传了名为 config.php 的 WebShell 文件               │
│ • 目的:获取服务器控制权                                     │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ 阶段 2: 测试权限                                             │
├─────────────────────────────────────────────────────────────┤
│ • 包 ID: 14                                                  │
│ • 请求:POST /config.php                                     │
│ • 参数:k=cometohackme&c=whoami                             │
│ • 响应:www-data                                            │
│ • 目的:确认 WebShell 可用,当前用户为 www-data             │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ 阶段 3: 隐藏痕迹                                             │
├─────────────────────────────────────────────────────────────┤
│ • 包 ID: 59                                                  │
│ • 请求:POST /config.php                                     │
│ • 参数:k=cometohackme&c=mv config.php .config.php          │
│ • 响应:(空) 成功                                            │
│ • 目的:将 WebShell 重命名为隐藏文件(以.开头)             │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ 阶段 4: 验证隐藏后访问                                       │
├─────────────────────────────────────────────────────────────┤
│ • 包 ID: 79                                                  │
│ • 请求:POST /.config.php                                    │
│ • 参数:k=cometohackme&c=whoami                             │
│ • 响应:www-data                                            │
│ • 目的:确认隐藏后的 WebShell 仍可正常访问                  │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│ 阶段 5: 窃取 Flag                                            │
├─────────────────────────────────────────────────────────────┤
│ • 包 ID: 99                                                  │
│ • 请求:POST /.config.php                                    │
│ • 参数:k=cometohackme&c=cat /flag.txt                      │
│ • 响应:flag{U_f1nd_Me!}                                    │
│ • 目的:读取根目录下的 flag 文件                            │
└─────────────────────────────────────────────────────────────┘

5. 完整代码

5.1 自动化分析脚本

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
BugKu Crypto 6-3-track_hacker - 自动化分析脚本
功能:PCAP 流量分析、WebShell 识别、Base64+zlib 解码、Flag 提取
"""

from scapy.all import *
import base64
import zlib
from collections import defaultdict

def analyze_pcap(filename):
    """主分析函数"""
    packets = rdpcap(filename)
    
    # 基础统计
    print(f"总数据包:{len(packets)}")
    
    # 协议分布
    protocol_count = defaultdict(int)
    for pkt in packets:
        proto = pkt.summary().split()[0]
        protocol_count[proto] += 1
    
    # 提取 HTTP 请求
    http_requests = extract_http_requests(packets)
    print(f"\n发现 {len(http_requests)} 个 HTTP 请求")
    
    # 提取 HTTP 响应并解码
    decoded_results = decode_responses(packets)
    
    # 提取 Flag
    extract_flag(decoded_results)
    
    return decoded_results

def extract_http_requests(packets):
    """提取 HTTP 请求"""
    requests = []
    for i, pkt in enumerate(packets):
        if TCP in pkt and Raw in pkt:
            data = pkt[Raw].load.decode('utf-8', errors='ignore')
            if data.startswith('POST ') or data.startswith('GET '):
                # 解析请求头和数据
                lines = data.split('\r\n')
                requests.append({
                    'id': i,
                    'request': lines[0],
                    'data': data.split('\r\n\r\n')[1][:100] if '\r\n\r\n' in data else ''
                })
    return requests

def decode_responses(packets):
    """解码 HTTP 响应(Base64+zlib)"""
    results = []
    for i, pkt in enumerate(packets):
        if TCP in pkt and Raw in pkt:
            data = pkt[Raw].load.decode('utf-8', errors='ignore')
            if 'HTTP/1.1 200 OK' in data and '\r\n\r\n' in data:
                body = data.split('\r\n\r\n')[1].strip()
                if 10 < len(body) < 100:
                    try:
                        decoded = base64.b64decode(body)
                        decompressed = zlib.decompress(decoded)
                        result = decompressed.decode('utf-8', errors='ignore')
                        results.append({'id': i, 'data': result})
                        print(f"包 {i}: {result}")
                    except:
                        pass
    return results

def extract_flag(results):
    """从解码结果中提取 Flag"""
    for result in results:
        if 'flag{' in result['data'].lower():
            print(f"\n🎉 Flag found: {result['data']}")
            return result['data']
    print("\n❌ Flag not found")
    return None

if __name__ == "__main__":
    analyze_pcap("shell.pcap")

5.2 手动解码验证

python 复制代码
# 手动解码最后一个响应
import base64
import zlib

encoded = "eJxLy0lMrw6NTzPMS4n3TVWsBQAz4wXi"

# 步骤 1: Base64 解码
decoded_b64 = base64.b64decode(encoded)
print(f"Base64 解码后 (Hex): {decoded_b64.hex()}")
# 输出:789c4bcb494caf0e8d4f33cc4b89f74d55ac050033e305e2

# 步骤 2: zlib 解压
decompressed = zlib.decompress(decoded_b64)
print(f"zlib 解压后:{decompressed}")
# 输出:b'flag{U_f1nd_Me!}'

# 步骤 3: 转换为字符串
flag = decompressed.decode('utf-8')
print(f"Flag: {flag}")
# 输出:flag{U_f1nd_Me!}

6. 总结

6.1 技术要点回顾

技术点 说明 应用场景
PCAP 分析 使用 scapy 读取和分析网络抓包 CTF 流量分析题、安全事件调查
WebShell 识别 POST 请求中 password&command 模式 Web 安全、入侵检测
Base64 编码 将二进制数据编码为 ASCII 字符串 数据传输、简单混淆
zlib 压缩 DEFLATE 算法压缩数据 减少数据体积、隐藏内容
Linux 隐藏文件 以点开头的文件名 文件隐藏、持久化后门

原始问题:请阅读目录下的文件,解出这道CTF题目。

相关推荐
AI浩2 小时前
第 6 章:操作与规范 —— 构建安全、自动化的工程标准
运维·安全·自动化
爱学习的小囧2 小时前
ESXi 8.0 升级 9.0 详细攻略:安全升级、避坑与排障全指南
服务器·网络·安全·虚拟化·esxi8.0
wanhengidc3 小时前
云手机 流畅稳定 操作简单
服务器·网络·网络协议·安全·智能手机
Coremail邮件安全3 小时前
2025企业邮箱安全报告发布:AI攻击升级,技术与管理协同成防护趋势
人工智能·安全
薛定猫AI4 小时前
【深度解析】Claude Mythos 泄露与 GLM-5.1:新一代安全与算力博弈下的大模型技术趋势
安全
实在智能RPA4 小时前
深度解析企业级AI Agent安全架构与落地实践
人工智能·安全·ai·安全架构
志栋智能4 小时前
安全自动化不烧钱:低成本实战策略
运维·网络·人工智能·安全·自动化
谪星·阿凯4 小时前
Pikachu靶场完整通关秘籍
安全·网络安全
上海云盾-小余4 小时前
CC 攻击与 DDoS 的本质区别:从原理到防御方案全对比
网络·安全·web安全·ddos