标签 ctf 下的文章

[开源] AutoRedTeam-Orchestrator - 给 AI 编辑器装上渗透测试工具箱

项目简介

AutoRedTeam-Orchestrator 是一个基于 Model Context Protocol (MCP) 的 AI 驱动自动化渗透测试框架。

它将 101 个安全工具 封装为 MCP 工具,可与支持 MCP 的 AI 编辑器 (Claude Code, Cursor, Windsurf, Kiro, Claude Desktop) 无缝集成,实现自然语言驱动的自动化安全测试

简单说:配置好之后,直接跟 AI 说「帮我扫描 xxx.com 的漏洞」就行了



项目数据概览

指标数量
MCP 工具101
Payload 库2,000+
测试用例1,461
漏洞检测器19


为什么选择 AutoRedTeam-Orchestrator?

特性传统工具AutoRedTeam-Orchestrator
交互方式命令行记忆自然语言对话
学习成本高(需记忆大量参数)低(AI 自动选择工具)
工具整合手动切换工具101 工具统一接口
攻击链规划人工规划MCTS 算法 + 知识图谱
误报过滤人工验证OOB + 统计学验证
报告生成手动编写一键生成专业报告
会话管理支持断点续传
安全性各工具独立MCP 安全中间件统一防护


为什么做这个?

最早是在用 HexStrike,还参与过二次开发,和 #96 分支作者 Ynee 也有过深入交流。

后来在社区找到了 HexStrike 原作者,但他似乎遇到了一些生活上的困难,项目更新明显放缓了。

与其等待,不如自己动手。正好使用中也积累了一些想法:

  1. 为什么非得在 Kali 上跑? → 做成 Windows 原生,Linux 也兼容

  2. 为什么不能和 AI 编辑器联动? → 基于 MCP 协议,Claude Code 直接调用

  3. 为什么工具这么分散? → 101 个工具整合到一起

于是就有了这个项目。


技术栈 & 兼容性

技术栈

语言 Python 3.10+

协议 MCP (Model Context Protocol)

并发 asyncio / httpx / aiohttp

算法 MCTS 蒙特卡洛树搜索

存储 内存图存储 / SQLite

安全 输入验证 / 速率限制 / 操作授权

已测试支持

CLI 工具:

  • Claude Code (终端)

  • Gemini CLI

  • Codex CLI(道德感严重 )

  • iFlow CLI

IDE / 桌面端:

  • Cursor

  • Windsurf

  • Kiro

  • Claude Desktop

  • VS Code (with MCP extension)

基本上只要能跑 MCP 的 IDE/CLI 都可以用这个项目


结果案例:





codex扫描时间过长我停了,具体各位佬可以重新测试一下

GitHub

GitHub - Coff0xc/AutoRedTeam-Orchestrator: AI-Driven Automated Red Team Orchestration Framework | AI驱动的自动化红队编排框架 | 101 MCP Tools | 2000+ Payloads | Full ATT&CK Coverage | MCTS Attack Planner | Knowledge Graph | Cross-platform

欢迎 Star 和 PR!


免责声明

本工具仅限以下场景使用:

  • 授权渗透测试

  • 红队安全评估

  • 安全研究学习

  • CTF 竞赛

严禁用于:

  • 未经授权测试他人系统

  • 任何非法用途

使用本工具造成的任何法律后果由使用者自行承担。

狗头保命,希望大家合法合规使用~


第一次在 L 站发自己的项目,有问题欢迎回帖讨论,也可以去 GitHub 发 Issue 或者按项目里的邮箱联系我,看到就会回复。

希望大家共同进步,也请各位师傅斧正!


📌 转载信息
转载时间: 2026/2/5 05:19:59

最近在刷题(特别是内存取证和流量分析)的时候,深深地体会到了一句话:“原理决定上限,工具决定效率” 。以前死磕命令行敲半天,后来发现大佬们用自动化工具两分钟就梭哈了,留下了没有技术的眼泪 。

本着 “开源精神”,先把这段时间做题挖掘到的几个非常好用但可能新手不知道的工具 分享出来,希望能帮到像我一样的入门选手。同时也想借地向论坛的各位大佬求助一下获取工具的渠道

我的工具分享(取证 / 杂项篇)

随波逐流 (CTF-Tools)

做 MISC 和 Crypto 的应该都知道,但这工具真的值得吹爆。

  • 体验 :基本上集成了市面上 99% 的常见编码、加密、隐写工具。什么 Base 全家桶、AES/DES、图片盲水印、文件分离,统统一键搞定。最强的是它的 **“智能识别”** 功能,把乱码丢进去,它能自动尝试解码,省去了去 Python 库里一个个试的时间。

2. Volatility 的自动化外挂:LovelyMem

  • 推荐理由 :Vol 2.6 虽然经典但命令太长,Vol 3 插件有时候不好配。

  • 体验 :这是一个基于 Vol3 的 Python 脚本,它会自动把 CTF 中最常用的命令(netscan, pslist, filescan, cmdline 等)全跑一遍,然后生成一个整整齐齐的报告文件夹。对于常规题,基本是一键出结果。

3. 流量分析提取:NetworkMiner

  • 推荐理由 :Wireshark 是神,但用来分离文件有点麻烦。

  • 体验 :如果不涉及深层协议分析,只是想把流量包里的图片、文件、证书提取出来,把你 pcap 文件拖进这个工具,它会自动分类展示。很多 “流量藏图” 的题用这个秒解。

4. 全能解码:CyberChef

  • 推荐理由 :应该都知道,但必须再推一次。

  • 体验 :最近遇到 GSM 短信解码的题,直接搜 GSM Decode 就能解,比写 Python 脚本快多了。
    虽然搜集了上面这些,但我发现我的 “信息差” 还是很严重。

  1. 关于工具源 :大家平时都是通过什么渠道第一时间发现这些好用的新工具的?是盯着 GitHub 的某些 Topic,还是有什么聚合站?

  2. 关于圈子 :怎么找到高质量的 CTF 交流群或者安全圈子?(现在加的一些群全是水群,很难学到真东西)。

  3. 其他神器 :在流量分析或者逆向方面,大佬们还有没有什么私藏的 “压箱底” 工具可以安利一下?


📌 转载信息
原作者:
techq
转载时间:
2026/1/16 17:41:10


从 VCTF2025 ez_train学习torch.load反序列化绕过

前言

感觉挺有意思的一道题,赛后看了一下,这个题目主要考察了代码审计和 torch.load 在 weights_only=True 条件下的利用。

题目环境搭建

下载题目附件并解压,

file-20260113204022005.png



题目直接给了 docker 环境,但是是 linux 环境的,为了方便待会调试这里按照题目版本去官网上下载一个 windows 版本的,

file-20260113203804115.png



然后按照题目给的 requirements.txt 中的依赖进行下载,下载好后运行 server.py 启动,启动后如下,

file-20260113204526100.png



这里还注意到题目在 text-generation-webui-3.13\user_data\training\datasets 目录中放了一些文件,一起复制过来。

题目分析

查看题目描述:

file-20260113204951881.png



结合题目名称我们应该主要看 train 模块了,全局搜索发现就只有个 trianing.py 文件

file-20260113205156648.png



然后像这类微调训练大模型的本地 web 应用比较耳熟能详的就是 torch.load 引起的反序列化漏洞了,而这个 training 中就恰好存在这个方法的调用,不难看出这里应该就是出题人的考点了,

file-20260113205625132.png



这段代码大概意思是从 adapter_model.bin 加载 LoRA 的权重参数(只包含 LoRA,不包含基础模型),接着将加载的 LoRA 权重注入到当前的 lora_model 中,如果这个文件内容我们可以控制这里是不是就能进行反序列化了呢?

我们先看这个 {lora_file_path} 能不能控制,简单溯源一下,

file-20260113210229786.png



发现 {lora_file_path} 是由 {Path(shared.args.lora_dir)}{lora_file_path} 拼接而成的,{lora_file_path}lora_name 的值,而这个 lora_name 的值其实就是我们训练时传入的参数,

file-20260113211019396.png


file-20260113211055508.png



至于 {Path(shared.args.lora_dir)} 的值我们调试发现为 user_data/loras 目录,是个固定值,

file-20260113210937792.png



那么现在知道 {lora_file_path} 就一小部分能控制,感觉没什么用啊,而且还需要我们能把文件 adapter_model.bin 文件上传到这个目录下。

后面找了一圈没找到哪里可以上传,但是发现这个应用可以从 huggingface 远程下载 model,而且下载目录就在我们的 user_data/loras 下面吗。简单测试一下,这里填入“paulinsider/llamafactory-hack”,然后点击下载,

file-20260113212126010.png



确实成功把文件下载到了我们要的目录。

file-20260113212353132.png



那么这样思路就清晰了,我们就可以在远程 model 中放入恶意的 adapter_model.bin 文件,然后下载到本地,通过控制训练时的 lora_name 参数使得最后 torch.load 加载的文件是我们的恶意文件,

这里简单尝试一下,假设刚刚下载的 paulinsider_llamafactory-hack 目录下存在恶意 adapter_model.bin 文件,我们填写训练 lora_name 为 paulinsider_llamafactory-hack

file-20260113213321532.png



点击训练后,看到成功使得 torch.load 的文件是我们能控制的文件了,

file-20260113213310006.png



但是这里还是没法进行反序列化,因为这里得 lora_name 设置了weights_only 参数为 True。

torch.load 反序列化绕过

查看题目的requirements.txt 文件发现给的 torch 版本为 2.5.1,网上简单搜了下不难发现其实还是存在绕过方法的,

file-20260113214328275.png



参考 https://i.blackhat.com/BH-USA-25/Presentations/US-25-Jian-Lishuo-Safe-Harbor-or-Hostile-Waters.pdf ,我们先看看这个 weights_only 的工作原理

生成个恶意的 pickle 反序列化文件

torch.load demo

进入 torch.load 中看到当 weights_only 为 true 时会调用到 _legacy_load 方法,

file-20260113215502623.png



然后一直到 pickle_module.load 方法,

file-20260113215923584.png



和正常的 pickle.load() 不一样,这里会调用到 Unpickler.load() 方法,这里面会依次读取字节,然后对每个字节进行判断,对全局变量和函数都有白名单进行限制

file-20260113220408194.png



只能用白名单中提供的,

file-20260113220439125.png



这个白名单是绕不过了,其中也没什么有用的,根据参考文章知道在 torch.load 中其实还调用了 torch.jit.load 方法,而且不受weights_only 参数影响,这个方法可以加载一个已经用 TorchScript 保存好的模型,用于直接推理(不需要原始 Python 代码)

file-20260113220646171.png



所以现在关键是看怎么生成个恶意的 TorchScript 模型,这里面涉及到了 TorchScript 运算符的概念,根据参考文章知道作者是发现了 torch.save 最后可以调用到 aten::save 运算符实现写文件操作,所以最后生成恶意的 TorchScript 模型代码如下

这里注意到在 torch.load 代码下面还有个 newModule.items() 方法调用 ,这里是漏洞触发点,如果只返回了 TorchScript 模型对象是没办法触发到里面的 torch.save 方法,

回到题目,我们可以让adapter_model.bin 为恶意的 TorchScript 模型,然后我们还需要找下触发点,

file-20260113221624043.png



看到返回 state_dict_peft 后调用了 set_peft_model_state_dict 方法进行处理,跟进这个 set_peft_model_state_dict ,把 state_dict_peft 赋值给了state_dict

file-20260113221730914.png



后面又调用到了 _insert_adapter_name_into_state_dict

file-20260113221818019.png



最后发现调用的还是 items 方法

file-20260113221958131.png



所以直接用上面的 poc 就可以了,这里就直接把生成的恶意文件复制到 paulinsider_llamafactory-hack 目录下,然后和上面一下训练

file-20260113223421839.png



成功实现写文件操作

file-20260113223444024.png



查看题目给的 docker 文件不难发现最后应该是通过写定时任务实现 rce。

参考

https://i.blackhat.com/BH-USA-25/Presentations/US-25-Jian-Lishuo-Safe-Harbor-or-Hostile-Waters.pdf

https://github.com/ChaMd5Team/Venom-WP/blob/main/2025VenomCTF/2025_venomctf_web_ez_train.pdf

https://mp.weixin.qq.com/s/2VsxBTIiX5P8b16Rl1ylcA


[CISCN 2022 东北赛区]math

题干

import gmpy2
from Crypto.Util.number import *
from flag import flag
assert flag.startswith(b"flag{")
assert flag.endswith(b"}")
message=bytes_to_long(flag)
def keygen(nbit, dbit):
if 2*dbit < nbit:
while True:
a1 = getRandomNBitInteger(dbit)
b1 = getRandomNBitInteger(nbit//2-dbit)

n1 = a1*b1+1

if isPrime(n1):
break
while True:
a2 = getRandomNBitInteger(dbit)
b2 = getRandomNBitInteger(nbit//2-dbit)

n2=a2*b2+1

n3=a1*b2+1
if isPrime(n2) and isPrime(n3):
break
while True:
a3=getRandomNBitInteger(dbit)
if gmpy2.gcd(a3,a1*b1*a2*b2)==1:
v1=(n1-1)*(n2-1)
k=(a3*inverse(a3,v1)-1)//v1
v2=k*b1+1
if isPrime(v2):
return a3,n1*n2,n3*v2
def encrypt(msg, pubkey):
return pow(msg, pubkey[0], pubkey[1])

分析

分析题干,发现取近似值后有N1约等于 a1*b1*a2*b2 ,N2约等于 a1*b2*k*b1 ,两者结构相似,且有N1/N2约等于a2/k,因此理论上可以尝试采用连分数展开来求解a2和k参数的值。

首先进行可行性分析,计算是否满足收敛的验证条件,经过验证,误差大致在 2^-5112^-512 之间,满足 2^-513 的临界条件,因此满足条件,理论上可以通过连分数展开来求解。

补充:连分数展开前提条件,即确定p/q是否一定是x的某个收敛子的判断依据。要求既约分数p/q满足

QianJianTec1768191074497.png


除了连分数展开以外,此处还可以采用LLL格基规约来求解,原理是近似的,会在后续进行展开说明

对N1/N2进行常规展开之后得到多个候选解,此时可以选用a2与k均为256bit数量级的条件进行约束,经过筛选共有两组候选解

通过上述步骤得到a2与k的值之后,下一步可以采用多种方式求解,其中我认为最易于理解的思路是构造同余关系,进行CRT约束求解。

首先根据已有的式子 phi(N1)=a1*b1*a2*b2 以及 ed-1=k*phi(N1)k*phi(N1)≡-1(mod e) 分别可以构造出 phi(N1)≡0 mod a2k*phi(N1)≡-1(mod e) 两个同余式,随后对其进行CRT求解可以得到 phi(N1)≡_phi(mod a2*e)

需要注意的是构造同余式的过程当中其中的第二个式子需要满足一定的前提条件即 gcd(a2, e) 必须为1,否则得到的将不是模a2*e的解而是模 lcm(a2, e)a2*e/gcd(a2, e) 的解。在本题当中,由于 gcd(a2, e)=1 ,可以继续进行

随后是利用已知的N1与上述CRT求出的同余关系进行N1的分解。由RSA基础公式可知 phi(N1)=N1-(n1+n2)+1 ,由于n1与n2数量级均为512bit,因而 phi(N1)-N1 的量大约为512-513bit,而 a2*e 的数量级也在512bit左右,N1为已知量,因而可以通过小范围爆破来求解n1与n2的实际值

设n1n2分别为pq,则有 p+q=N-phi(N)+1 ,验证条件此处可以设为 x^2-(p+q)*x+N=0 的判别式为完全平方数,爆破完成后即可得到pq的值,随后常规RSA解密即可

exp1

from math import gcd
from gmpy2 import isqrt
from Crypto.Util.number import *
from sympy.ntheory.modular import crt

e = 86905291018330218127760596324522274547253465551209634052618098249596388694529
N1 = 112187114035595515717020336420063560192608507634951355884730277020103272516595827630685773552014888608894587055283796519554267693654102295681730016199369580577243573496236556117934113361938190726830349853086562389955289707685145472794173966128519654167325961312446648312096211985486925702789773780669802574893
N2 = 95727255683184071257205119413595957528984743590073248708202176413951084648626277198841459757379712896901385049813671642628441940941434989886894512089336243796745883128585743868974053010151180059532129088434348142499209024860189145032192068409977856355513219728891104598071910465809354419035148873624856313067
c1 = 71281698683006229705169274763783817580572445422844810406739630520060179171191882439102256990860101502686218994669784245358102850927955191225903171777969259480990566718683951421349181856119965365618782630111357309280954558872160237158905739584091706635219142133906953305905313538806862536551652537126291478865

class ContinuedFraction():
def __init__(self, numerator, denumerator):
self.numberlist = []
self.fractionlist = []
self.GenerateNumberList(numerator, denumerator)
self.GenerateFractionList()

def GenerateNumberList(self, numerator, denumerator):
while numerator != 1:
quotient = numerator // denumerator
remainder = numerator % denumerator
self.numberlist.append(quotient)
numerator = denumerator
denumerator = remainder

def GenerateFractionList(self):
self.fractionlist.append([self.numberlist[0], 1])
for i in range(1, len(self.numberlist)):
numerator = self.numberlist[i]
denumerator = 1
for j in range(i):
temp = numerator
numerator = denumerator + numerator * self.numberlist[i - j - 1]
denumerator = temp
self.fractionlist.append([numerator, denumerator])

a = ContinuedFraction(N1, N2)
for (_, solve) in enumerate(a.fractionlist):
if solve[0].bit_length() == 256 and solve[1].bit_length() == 256:
a2, k = solve
if gcd(a2, k) == 1:
inve = inverse(k, e)
_phi = int(crt([a2, e], [0, -inve%e])[0])
M = a2*e
for i in range(-10,10):
phi = (N1//M)*M+i*M+_phi
s = N1-phi+1
delta = s*s-4*N1
if delta > 0:
t = isqrt(delta)
if t*t == delta:
p = (s+t)//2
q = (s-t)//2
d = inverse(e, (p-1)*(q-1))
m = pow(c1, d, N1)
print(long_to_bytes(m).decode())

接下来是一些其他的思路,得到a2与k的值之后,可以直接尝试直接恢复d,而不是先恢复phi(N1)再分解N1并求解d

已知有 e*d-1=k*phi(N1) ,由于 phi(N1)=a1*a2*b1*b2≡0(mod a2) ,因此 k*phi(N1)≡0(mod k*a2) ,所以有 e*d-1≡0(mod k*a2)gcd(e, a2*k)=1 ,因此可以求解e关于k*a2的逆元inva2k,此时有 d%(a2*k)=inva2k ,注意与后文d的近似值_d做好区分

另外的,与上个思路相似的,有phi(N1)与N1的大小相近,有 d=(k*phi(N1)+1)/e ,根据 phi(N1)=N1-(n1+n2)+1 ,尝试通过N1+1来近似phi(N1),此时估算的_d与实际的d值有误差x为

QianJianTec1768191034522.png


估算误差x大小,ek位数同为256bit,因而d的估计误差x的位数大致在512-513bit左右,关于x有式子 x=_d-d=_d-inva2k-k1*(a2*k)≡_d-inva2k(mod a2*k)

因此满足式子 x=(_d-inva2k)%(a2*k)+t*a2*k ,其中x的位数与a2*k的位数相近,均为512bit左右,因而搜索空间t很小,可以快速爆破t求解x。随后根据预估值_d得到d的值,随后常规RSA求解

exp2

本题中非必要的,但可以作为拓展知识进行补充,在上述的方案中,最后一步枚举t求d的过程当中如果面临搜索空间过大的问题,可以尝试用BSGS算法将时间复杂度由o(B)降到o(sqrt(B))

即在求解inva2k之后,可以通过BSGS算法来求解x,本题中,对任意底数g,有

QianJianTec1768190944164.png



将同余式左侧设为G^t,右侧设为H,成功将问题转化为一个离散对数问题,即求解t,使得 G^t≡H(mod N1)

由于涉及到离散对数求解,此处实现用python可能相对麻烦,因此可能需要切换到sagemath,其中有内置的连分数展开、求解离散对数问题、求解模逆的函数,求解的思路实现起来很方便,具体的参考pcspcs大佬的wp就够了

要注意的是这里选用的不能是常规的bsgs算法实现,而应该是特定的针对指定区间的,类似于bounded bsgs的算法,与常规的算法实现有着些许的差异,具体表现在未知数x的范围,常规的应该在ord(g)-1内,一旦超过一定的量级,就难以求解出结果,而本题中因为知道x的上界,所以不需要群阶信息,也不需要做全范围的离散对数,只用在这个由数量级推算出来的确定的小范围里搜索就可以了。具体细节不难实现,这里就不多赘述了。

对于已知a2和k求解flag的另一种思路是利用爆破高位+coppersmith来求解,此时需要判断未知量是否满足在小根阈值之内,经过验证,当前恰好卡在边界条件上,很可能不稳定甚至求不出解,可以通过爆破少量高位来增强该攻击方案的鲁棒性。

爆破少量高位的具体流程是先枚举一个高位前缀(规模很小, 2^82^12 级别就够用),然后对每个前缀,把 q=a2*b2+1 改写成已知近似值+小偏移的形式,用格方法去抓这个小量。

最后,第一步求解a2和k并非必须借助连分数展开,也有其他原理相似的办法来求解。连分数本质是在进行有理数逼近。既然要找256bit的a2和k使得 N1/N2≈a2/k ,那么理论上就可以把它写成一个整数线性组合尽量小的问题,然后用LLL直接把这组小关系挖出来。将差值视为小量,利用格基规约进行求解。

本题中的小量即为 N1*k-N2*a2 ,相对于主量级这是一个极小的数,不过这里由于不同维度的数量级不一样,需要先进行缩放,把不同维度的量级拉到同一数量级上。

相对于连分数逼近而言,利用LLL算法来求解的容错性与泛用性更高,例如对于不确定是否符合理论阈值的时候,LLL往往还能给出可用的候选,但是运算量这方面而言比连分数展开的方法要重不少。

总结

复盘了一下CISCN 2022 东北赛区 math题目,并把这题里能走通的几条路线放在同一条脉络下统一整理了一遍。主线部分强调的是先把关键参数落地,再用最稳的方式收尾:前半段通过比值逼近筛出 a2k 的候选,后半段用CRT把 phi(N1) 的同余信息拼起来,再借助 phi(N1)N1 的接近性在很小的范围内定位出正确的 p+q,用判别式验平方完成分解并解密。拓展部分则是把收尾拆成可替换的模块:可以不显式恢复 phi(N1),而是直接从 d mod (a2*k) 与近似值 _d 把误差压缩到很小的搜索区间里求出 d;当枚举空间变大时再用bounded BSGS把线性枚举换成开方级复杂度;同时也说明了第一步并不一定非要用连分数,LLL同样可以在结构相似带来的小量关系里挖出候选,而爆破少量高位配合格方法属于可行但不如主线稳的备选。整体来看,这题最有价值的地方在于可以把“结构信息→可求参数→多种收尾工具”的链条串得很清楚,后续遇到类似的结构化RSA题,基本都能沿着同样的节奏把问题拆开、把不确定性压到可控范围内解决。


第三届“数信杯”数据安全大赛数据安全个人赛初赛

数据安全

第四题

题目描述:工程师小王为了保证数据的安全存储,开发了对数据处理的程序,但这样的处理方式安全吗?分析程序功能,解密文件获取原始数据,提交第6行第2列数据。

IDA打开程序



Base64解密即可,第六行数据

MjU3MTA4NzYwNDAgNzE2ODk2MTk4ODI5MDM3NDkzIGFkNzg2MkBiNy5jb20K



答案:716896198829037493

第五题

题目描述:工程师小王认识到前面开发的程序并不能保证对数据的安全存储,现在对处理程序进行了改进,这次能行吗?分析程序功能,解密文件获取原始数据,提交第8行第2列数据。



程序re1e97e14f是64位ELF可执行文件(Linux x86-64,stripped)。通过静态分析确定程序结构:

入口点_start位于0x401190,通过__libc_start_main调用main函数。main函数位于0x401579,负责文件读写和调用核心加密函数。核心加密函数sub_401276位于0x401276,实现三阶段加密处理。

程序执行流程:读取./info_81bedab.ori → 三阶段加密 → 输出./info_81bedab.ori.en

Stage A - 位运算变换(sub_401276内,地址0x4012FE~0x401360):

Stage B - RWX自解密代码执行(sub_401276内,地址0x401360~0x401450):

关键函数调用序列:

0x401368: call malloc(0x1000) 申请4KB内存

0x401380: call mprotect(page, 0x1000, 7) 设置RWX权限

0x4013A0: 从.data段地址0x404060复制0x84(132)字节代码块到RWX页

0x4013B8: 获取密钥 state = (uint16_t)(buf + 0x339)

0x4013D0: 循环调用RWX代码处理每个字节

0x84字节代码块结构(位于.data段0x404060):

解密后的变换代码(key=0x6E72解密后):

等效变换函数:

Stage C - 循环XOR(sub_401276内,地址0x401450~0x4014A0):

解密算法:

Stage C逆操作:cipher XOR "e6911c24" → B[]

从B[0x339]=0xEB, B[0x33A]=0xAB约束搜索Stage B密钥,得到key=0x6E72

Stage B逆操作:通过逆映射表还原 → A[]

Stage A逆操作:A[i] >> 1 → plaintext[]

验证:A[0x339]=0x72, A[0x33A]=0x6E,与key一致

解密成功

答案:878052199921046799

第六题



题目给出一个SQLite数据库文件,提示在Freeblock空闲块中隐藏了自定义链表数据。首先连接数据库查询sys_config表获取三个关键配置:


入口指针格式为"物理页号:偏移",页号0x13B=315,偏移0x4F0=1264,该偏移已跳过Freeblock的4字节头部

链表节点结构为大端序,NextPage占4字节,NextOff占2字节,Len占2字节

加密方式为使用当前物理页号的大端4字节表示循环异或

SQLite文件头偏移16-17处读取页大小为4096字节。链表遍历算法:从入口页315偏移1264开始,读取8字节头部解析出NextPage、

NextOff、Len,然后读取Len字节的加密数据,用struct.pack('>I', current_page)生成4字节密钥循环XOR解密。当NextPage=0且

NextOff=0时链表结束。

解密拼接后得到完整SQL脚本:



执行该SQL查询得到container_id=CN2888991777license_plate=粤B-52816,按题目要求提取container_id和license_plate后五位数字

用下划线连接。

答案:CN2888991777_52816

第七题

题目实现了一个存在漏洞的AES-CBC加密,核心代码如下:

漏洞在于hint泄露了key与message前16字节的异或值。

对于38字节的flag,自定义padding函数会在前面添加10个\x0a字节,得到48字节。PKCS7填充后变成64字节(4块)。

消息结构为:

Block 0: \x0a*10 + flag[0:6]

Block 1: flag[6:22]

Block 2: flag[22:38]

Block 3: \x10*16

由于flag[:5]=b'flag{'已知,只需爆破flag[5]一个字符即可恢复完整key。验证方法是检查解密后最后一块是否为\x10*16。

利用CBC模式特性,后续块使用前一块密文作为IV解密,可恢复完整flag。

答案:flag{IADMIN-TOP-18880101-7634567_2025}

第八题

题目提供损坏的RSA私钥key_pri.pem和加密用户数据encrypted_users.csv。解析私钥DER编码发现大量参数被零填充,属于"变异RSA"私钥恢

复问题。

私钥ASN.1结构解析:

从dp字段提取p的部分高位(496位已知,低48位为0):

p_high =

0x9d025160d56d4971363f3cf2ce7e3e96215c50bf50d0cc606f5645de7ec113d16d931383e649bc2c7328499d219e2982b726ae41c5370

aa8000000000000

使用Coppersmith小根攻击恢复p的完整值。设p = p_high + x + y*2^496,其中x为低位未知部分(约48位),y为高位修正(约16位)。构

造格基,利用LLL算法求解满足p | n的小根。

cuso库求解代码:

恢复完整p =

0xf5e49d025160d56d4971363f3cf2ce7e3e96215c50bf50d0cc606f5645de7ec113d16d931383e649bc2c7328499d219e2982b726ae41c

5370aab851b8a28df37

验证:n mod p = 0,p为512位素数。计算q = n/p,d = e^(-1) mod (p-1)(q-1),构建RSA私钥,使用PKCS1_OAEP解密查找目标记录。

答案:294_010880753296303612_5108757973927325

第九题



答案:S20251001

第十题

题目提供了三个文件:secret_image.png(隐写图片)、multimodal_model.pth(PyTorch模型权重)和stego_hint.txt(提示文件)。

根据提示文件,隐写规则如下:

1图片的R通道中隐藏了模型输入特征

2取图片左上角前20个像素的R值,计算 R值 mod 10 得到20维特征向量

3将20维特征输入MLP模型,输出数值四舍五入取整即为flag的ASCII码

4ASCII码转换为字符得到完整flag

关键点在于"左上角前20个像素"的取法:按扫描顺序取第一列从上到下的20个像素(x=0, y=0..19)。

模型结构为3层全连接神经网络(MLP):20->64->32->27,使用ReLU激活函数。输出27维向量对应flag的27个字符。

答案:flag{A12I_shu1xin2bei_2025}

数据分析

数据应急

题目背景: 一家科技公司服务器被黑客入侵,重要文件被窃取并删除。需要根据系统自动备份的残存内容进行溯源分析。

第一题



三个文件全部导出



答案:HT-2025-001234

第二题

解压压缩包,得到一个内存镜像

非预期

直接搜索flag{



预期解



发现有C:\Program Files\TrueCrypt\TrueCrypt.exe

Elcomsoft Forensic Disk Decryptor挂载

加载内存镜像先搜索一下key

保存1.evk



成功挂载



答案:flag{33c3789a36bb61beb6d4268cd7d13038}

第三题

过滤响应200的包



最后一个包发现是exe程序



导出来看看

解包

找到一个exfiltrator_balanced.pyc

反编译

该程序是一个基于 ICMP 协议的隐蔽数据外带工具,通过将文件切分为 224 字节的数据块并伪装成 Windows Ping 流量发送。其核心安全机

制包含三个部分:
程序运行时会生成一个随机的 16 字节 CryptoSeed 和一个基于时间的 ScrambleSeed(用于乱序)。利用 PBKDF2-HMAC-SHA256 算

法,结合 CryptoSeed 和两组被混淆和硬编码的盐值(b'Bloodharbor!2024'b'Silent_Update!!!'),迭代 10,000 次分别派生出两

层加密所需的 32 字节密钥。
每个数据块首先添加 4 字节大端序长度头,然后使用 ChaCha20-Poly1305 进行内层加密(Layer 1),输出包含 Nonce、密文和 Tag。接着

对 Layer 1 的完整结果使用 AES-256-GCM 进行外层加密(Layer 2),同样输出 Nonce、密文和 Tag,确保了数据的机密性与完整性。
程序首先发送包含种子的元数据块(以 EX1L 开头)。为了对抗流量分析,它利用 ScrambleSeed 初始化随机数生成器,对所有数据块的发

送顺序进行全随机打乱(Shuffle)。发送时,每个 ICMP 包的 Payload 前部填充 16 字节的伪造 Windows Ping 数据,并使用复杂的线性同

余算法生成伪随机的 ICMP ID 和序列号,使得流量在外观和统计特征上极难被识别。



打开流量包,发现流量包含有大量 ICMP 请求,其中部包含 EX1L 标志的 Payload,确认为数据外带。提取 EX1L 元数据块,获取 Crypto

Seed 和 Scramble Seed。加密机制为双层加密:首先是 ChaCha20-Poly1305 (Layer 1,带 4 字节长度头),其次是 AES-GCM (Layer 2)。密

钥由 PBKDF2 基于 Crypto Seed 和硬编码盐值生成。数据块顺序经过混淆,需利用 Scramble Seed 初始化随机数生成器并还原顺序。编写脚

本提取 ICMP Payload,还原顺序并依次解密 Layer 2 和 Layer 1,拼接后得到一个 ZIP 文件。

解压得到100张图片



写一个脚本OCR识别18316978925

[+] 找到目标: person_086.png



答案:江苏省南京市鼓楼区西湖路200号梧桐里15栋4单元101室

数据分析

背景描述

随着维真科技(VerityTech)业务规模的不断扩张,公司积累了大量内部 PDF 文档,包括重要的研发资料、业务报告、内部制度说明等。在长期

的运作过程中,由于文档管理规范不完善、缺乏统一的安全策略,公司文档的安全风险逐渐显现。

近期,公司文档服务器遭遇未知勒索程序攻击。部分 PDF 文件被加密无法打开,系统中还出现可疑链接的文档,疑似为攻击入口。同时,安

全团队在受感染终端中提取到了一份可疑的可执行程序(exe 文件),推测为勒索程序主体。

为了定位安全漏洞、恢复文档数据、查明攻击来源,公司启动了"文档安全事件分析"专项工作。本题给出攻击样本、加密文档及疑似钓鱼

PDF 文档,请你协助安全团队进行取证分析、密钥恢复、数据解密以及钓鱼链接识别。

相关信息

公司合法域名为:

其余域名均视为可疑链接,需重点审查。

第一题

通过file命令识别en.exe为Windows PE可执行文件,使用strings发现Python相关字符串,判断为PyInstaller打包程序。使用pyinstxtractor.py

解包后,在en.exe_extracted/key/目录下发现RSA密钥对文件pr.pem和public_key.pem。读取pr.pem文件内容,定位-----BEGIN PRIVATE

KEY-----标记位置,提取其后的32位字符即为答案。

答案:MIIEvgIBADANBgkqhkiG9w0BAQEFAASC

第二题

反编译

分析解包后的pyc文件,发现加密流程采用混合加密机制:使用RSA-OAEP(SHA256)加密AES密钥并保存到store.key,使用AES-256-ECB模

式对PDF文件进行加密。解密流程为:首先使用提取的RSA私钥pr.pem通过PKCS1_OAEP(SHA256)解密store.key获取AES密钥,然后使用

AES-ECB模式解密PDF文件并去除PKCS7填充,最后计算解密后文件的MD5值。

答案:52fd2cb4fc43eceb3c79233038bb5f42

第三题

使用PyMuPDF遍历999份解密后的PDF,提取PDF Annotation超链接中的URI。合法域名为veritytech.com及其子域名*.veritytech.com,排

除.local和.internal等内部域名后,筛选出所有指向外部非法域名的钓鱼URL。同时检查URL参数中的跳转地址(redirect/next/url等参数)。

过滤掉包含非ASCII字符的无效URL,将所有钓鱼URL按字典序升序排序后用逗号拼接,计算MD5值。

答案:0a16f1ca5e8db1270074d0d39f6edeaf

数据审计

背景描述

某公司运维团队在日常安全巡检过程中发现系统存在异常访问和潜在入侵迹象。经初步技术研判,问题可能与公司用于关键服务器相关。该

服务器被确认存在一定安全风险,但目前尚无法确定攻击者是否已成功获取其中的证书信息。

为进一步排查与分析潜在的数据泄漏情况,运维团队已导出该服务器的所有网络流量文件,请根据流量包文件分析并回答以下问题。

第一题

题目提供了params.csv文件,包含500组RSA参数(id, e, p, q)。需要根据id=285的参数合成RSA私钥,然后遍历所有pcap文件,提取TLS证

书中的公钥模数n,与id=285计算得到的n(n = p * q)进行匹配,找到对应的流量包。具体步骤:首先读取params.csv获取id=285的e、p、

q参数,计算n = p * q;然后遍历pcap文件,解析其中的X.509证书,提取RSA公钥的模数n;最后比对两个n值,相等则说明该pcap使用了

id=285对应的证书。

答案:mAqY0WRHsV.pcap

第二题

需要使用params.csv中的RSA参数生成私钥,然后用私钥解密TLS加密的流量包,获取HTTP明文数据。具体步骤:首先根据e、p、q计算私

钥参数d = e^(-1) mod (p-1)(q-1),生成PEM格式私钥文件;然后遍历每个pcap文件,提取证书中的公钥模数n,匹配对应的私钥;使用

tshark配合私钥解密TLS流量,提取HTTP请求体;解密后的数据为POST请求到/api/v1/user/profile,请求体为hex编码的JSON,包含

username和phone字段;遍历所有解密结果,查找username为"王梅"的记录,获取其phone字段。

答案:13930079365

第三题

系统在请求包中设置了Authorization头部字段,使用JWT进行身份认证。JWT的payload中包含username和phone信息,而请求体中也包含

相同字段。越权访问的判断标准是:JWT中的用户信息与请求体中的用户信息不一致。具体步骤:解密所有流量包获取HTTP明文;提取

Authorization头部中的JWT token;JWT由三部分组成(header.payload.signature),对payload部分进行Base64URL解码获取JSON数

据;同时解析请求体中的hex编码JSON数据;比较JWT payload中的username和phone与请求体中的username和phone;若不一致则判定为

越权访问,统计越权账号总数。

答案:5

作为一个开发,我在学习网络安全知识的时候发现很多平台的漏洞环境都是要靠猜去理解出题人的意图,关键是题目给的信息还非常的少,让我这种脚本小子的挫败感特别强,入个门都很难。

因此我搞了一个公开源码找漏洞拿 FLAG 的平台,目前有十几道题,部分是借鉴网上其他语言的题然后用 golang 重写的,部分是原创的,游客即可查看全部环境源码,不喜欢线上环境直接复制到本地也能跑,欢迎各位师傅测试。

地址: https://cyberpoc.typesafe.cn/

MISC

mahjoong
多开几个环境

自动对局 不知道为啥就出来了

ACTF{y@kumAn_1s_incredl3le}

emoji
Emoji表情符号解码

二进制转字符串

然后倒置

m1Sc_5I6niN

得到ACTF{m1Sc_5I6niN}

Web

babyshiro
题目名字提示shiro

查看文件 密码为vulhub

直接找到利用工具

爆破密钥和利用链

直接执行命令

cat /flag.txt无法读取

附件有个readflag

直接执行./readflag

得到flag


ACTF{We_CANn0T_0ff3r_yOU_41L_xS$_ChAL1ENG3S}

beadmin


注册admin 提示已存在

随意注册


访问flag是假的


继续看代码

Dockfile ENV设置环境变量 password

admin.js中表示环境变量的password


信息泄露 直接登录

访问flag即可

ACTF{3asy_csrf_and_bypass_stup1d_tok3n_g3n3rator}

写在后面

由于在准备考研课程,技术方面有点落下了,平时没有练习相关的CTF题目;

偶尔也打了几次比赛,但是明显没有之前的脑洞和思路;

比如本次比赛MISC的emoji,明明很早就解出字符串了,但是就是想不到倒置,拖了很长时间才想到;

另:shiro工具:https://github.com/j1anFen/shiro_attack