Web
SecretPhotoGallery
首先尝试使用用户名 admin 和密码 -1' union select 1,2,3 --+ 进行SQL注入,绕过登录进入后台。
在页面源码中发现注释,提示JWT密钥为 GALLERY2024SECRET。利用该密钥,我们伪造了一个管理员token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4iLCJpYXQiOjE3NjQ5OTIyNTR9.bCHvNXksavEel3wGMknzge7Erwp0PySoVx_UpLQnSKs。
获得管理员权限后,存在文件读取功能。尝试使用 php://filter 进行文件读取时,发现 base64 等常见过滤器被禁用。最终使用 php://filter/read=convert.iconv.utf8.utf16/resource=flag.php 成功读取 flag.php 文件内容,获取flag。
devweb
题目是一个基于 Vite 构建的前端应用。通过分析前端JS代码(assets/index-BgDOi0T5.js),发现关键信息。
- 硬编码的RSA公钥与登录逻辑:前端使用以下RSA公钥加密密码后发送给后端。
-----BEGIN PUBLIC KEY-----
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgGyAKgwgFtRvud51H9otkcAxKh/8
/iIlj3WlPJ0RL1pDtRvyMu5/edP84Mp9FqnZNCXKi1042pd4Y2Bf9QT0/z1i6KPi
Z8zT3XNTtPOqIHO5aVaOfAl8lr52AurMZVpXwEUS2hh+Q/AN4/SV9AZPCgrUXk61
9aaw0Md9MNvn3w0JAgMBAAE=
-----END PUBLIC KEY-----
- 泄露的下载接口:在JS代码中发现了一个文件下载组件的定义,其中泄露了一个合法的文件名和签名组合。
- File:
app.jmx
- Sign:
6f742c2e79030435b7edc1d79b8678f6
漏洞利用步骤:
- 弱口令登录:编写脚本,使用RSA公钥加密常用弱口令进行爆破,发现
admin/123456 可以成功登录(此步骤非必需,但有助于理解流程)。
- 下载并分析
app.jmx:直接访问 /download?file=app.jmx&sign=6f742c2e79030435b7edc1d79b8678f6 下载该JMeter测试计划文件。在其中的Groovy脚本里发现了签名生成算法。
- 重构签名算法:根据
app.jmx中的逻辑,签名算法如下(Python实现):
import hashlib
def calculate_sign(filename):
salt = "f9bc855c9df15ba7602945fb939deefc"
first_mi = hashlib.md5(filename.encode('utf-8')).hexdigest()
jie_str = first_mi[5:16]
new_str = first_mi + jie_str + salt
sign = hashlib.md5(new_str.encode('utf-8')).hexdigest()
return sign
- 任意文件读取:利用上述脚本,可以为任意文件名生成合法签名。尝试使用目录穿越读取flag,Payload为
../../flag。计算签名后,请求 /download?file=../../flag&sign=<计算出的签名>,成功获取Flag: DASCTF{21a8d433-4689-4e8e-9818-9ae50d48243a}。
自动化利用脚本(EXP)核心逻辑:
# 伪代码摘要
import requests, hashlib
# 1. 使用RSA加密弱口令尝试登录(可选)
# 2. 使用上述 calculate_sign 函数计算目标文件签名
# 3. 构造请求下载文件,如 download?file=../../flag&sign=...
Reverse
androidfile
本题为简单的代码混淆,使用JEB等工具可直接反编译。关键逻辑为RC4解密得到一段被RSA加密的key和IV,随后进行RSA解密得到AES的key和IV,最后用AES解密获取flag。
ezmac
给出了一段异或加密的数组,解密脚本如下:
a = [0x7D,0x7B,0x68,0x7F,0x69,0x78,0x44,0x78,0x72,0x21,0x74,0x76,0x75,0x22,0x26,0x7B,0x7C,0x7E,0x78,0x7A,0x2E,0x2D,0x7F,0x2D]
for i in range(len(a)):
a[i] = a[i] ^ (57 + i)
print(''.join([chr(x) for x in a]))
login
一个简单的C/S架构程序,采用RSA + RC4进行数据传输加密。通过逆向分析通信协议,可以编写解密脚本来获取flag。核心是利用服务器提供的RSA私钥(real_n_hex, real_d_hex)解密客户端发送的、经过RC4加密的RSA密文。
androidfff
本题使用了Flutter框架。使用blutter等工具进行逆向,分析出核心逻辑是一个简单的异或操作。解密脚本如下:
tagged = [236,230,194,226,204,232,146,168,188,142,140,140,174,128,218,182,130,218,130,186,218,174,166,130,150,158]
plain = [(x >> 1) ^ 50 for x in tagged]
print(''.join(map(chr, plain)))
Misc
DigitalSignature
题目要求从给定的以太坊签名消息中恢复签名者地址。使用eth_account库可以轻松完成:
from eth_account import Account
from eth_account.messages import encode_defunct
message_text = "Find out the signer. Flag is account address that wrapped by DASCTF{}."
signature = "0x019c4c2968032373cb8e19f13450e93a1abf8658097405cda5489ea22d3779b57815a7e27498057a8c29bcd38f9678b917a887665c1f0d970761cacdd8c41fb61b"
message = encode_defunct(text=message_text)
address = Account.recover_message(message, signature=signature)
print(f"Flag: DASCTF{{{address}}}")
stegh小鬼
本题是一道综合隐写题,涉及多种编码和加密方式。
- 图片分析:在图片中发现“快乐小鬼”字样,提示十六进制逆序操作。对图片进行十六进制分析并逆序,提取出一段文字。
- 压缩包解密:上述文字作为密钥,可解密一个压缩包。
- Emoji-AES:解密出的
flag.txt内容是Emoji-AES加密文本,需要密码。
- 深层隐写:在原始图片中利用
steghide,以密码2333333提取出pass.txt文件。
- 多重编码:
pass.txt内容包含颜文字和Emoji。删除颜文字部分,得到一串Emoji,使用Base100解码得到字符串 This_1s_P4ssw0rd。
- 最终解密:使用密码
This_1s_P4ssw0rd 对flag.txt进行Emoji-AES解密,获得最终flag。
Steganography_challenges0.2
- 尾部信息:图片文件尾部包含提示,指出使用RC4加密,密钥为
monkey。
from PIL import Image
from Crypto.Cipher import ARC4
import os
def decrypt_image(input_path, output_path, key='monkey'):
# ... 使用密钥key对图片每个像素的RGB值进行RC4流密钥异或解密
解密后得到一张新图片。
- LSB隐写:观察解密后图片的RGB通道,发现LSB隐写痕迹。在特定坐标区域(
(1243,1243)到(1258,1255))提取RGB三个通道最低位交替排列的二进制流,转换为字符串后得到密码:Oversized_chips。
- 带密码LSB:使用密码
Oversized_chips 对整张图片再次进行LSB隐写提取,得到另一张包含盲水印特征的图片。
- 盲水印提取:对最后得到的图片进行盲水印提取,获得flag。
Crypto
lost LFSR key
题目提供了一个自定义的LFSR(线性反馈移位寄存器)伪随机数生成器myRNG,并给出了其掩码mask以及用其生成的密钥流与flag异或后的密文c。目标是恢复LFSR的初始状态(seed)。由于LFSR的输出是线性的,可以根据已知的mask和足够长的密钥流输出,通过建立线性方程组来求解初始的64位种子,进而恢复密钥和flag。这通常需要用到密码学中常见的相关攻击或代数攻击思想。
two_examples
题目给出了一个基于格(Lattice)的密码系统参数:在有限域GF(p)上的矩阵A, B和向量b1, b2,以及一个用恢复出的密钥进行RSA加密的密文(c, N)。
解题思路:
- 构造格问题:根据题目描述,存在小向量e,使得
[A|B] * s ≈ b1 和 [B|A] * s ≈ b2(存在小误差e)。这可以构造为一个带误差的线性方程组问题(LWE问题的一种变体),适合用格基规约(LLL算法)求解。
- 求解小向量e:将方程组和模数p一起构造为一个格,使用LLL算法进行规约,寻找包含误差向量e的短向量。
- 恢复密钥S:得到e后,可以精确求解方程组,得到密钥向量S(由s1和s2拼接而成)。
- 生成RSA私钥:将s1和s2分别进行SHA512哈希并转换为整数,相加后作为RSA私钥d的候选值。由于可能存在偏移,在候选值附近进行爆破,尝试解密RSA密文c,成功即可得到flag。
Serration
本题考察针对RSA的侧信道攻击。服务端提供一个可查询的RSA解密预言机,但每次查询会返回程序执行时的缓存命中(Cache Hit)统计信息,这是一种基于缓存的侧信道。
攻击流程:
- 获取公钥:连接服务器,获取RSA公钥(N, e)。
- 侧信道校准:发送精心构造的明文(如0和(N-1)经过盲化后的值),观察并比较返回的缓存命中统计,确定哪一行代码的命中数差异最大,这条代码行即对数据敏感,其命中数可用来推断解密中间值的比特。
- 提取私钥高位:利用比特翻转思想。假设我们知道私钥d(或一个因子p)的部分高位,可以构造使得在模幂运算中某次乘法操作数极大的密文。如果猜测的比特正确,该极大值不会出现,缓存命中模式与基线相似;如果错误,则会出现极大值,导致缓存访问模式发生变化(命中数下降)。通过这种差异,可以逐位恢复出p的高位。
- Coppersmith攻击:获得p的高590位后,剩余低位未知数较少,可以利用Coppersmith定理在多项式时间内恢复完整的p。将问题转化为在模N下求解
f(x) = p_high * 2^k + x 的小根问题。
- 分解N获取flag:恢复出p后,计算q = N // p,进而得到私钥解密获取flag。
Pwn
rcms
程序存在Use-After-Free(UAF)漏洞。利用思路如下:
- 泄露堆地址:通过UAF读取被释放块的内容,泄露堆基址。
- 泄露代码段地址:利用堆上的指针错位,构造读取,泄露程序基址。
- 构造任意写:通过UAF修改释放块
fd指针,使其指向got表或相关函数指针区域,在后续申请时实现任意地址写。
- 劫持
__free_hook:将__free_hook覆盖为后门函数地址或system地址。
- 触发:再次释放一个块,触发
free,进而执行system(“/bin/sh”)或后门获取shell。
mvmp
本题实现了一个自定义的虚拟机(VM)。逆向分析VM的指令集(opcode)后发现,其指令集中直接提供了syscall操作码,且VM进程本身未开启沙箱(seccomp)。
攻击思路:
直接编写VM汇编代码,调用execve(“/bin/sh”, 0, 0)系统调用即可获得shell。
- 构造VM程序,设置
R0指向/bin/sh字符串地址,R1和R2为0。
- 使用
syscall_p0指令(表示第一个参数是指针)执行系统调用号0x3B(即59,execve)。
- 将编译好的VM字节码作为输入提交给程序,VM执行后即弹出shell。
CV_Manager
程序存在UAF漏洞,并且开启了沙箱(seccomp),限制了许多系统调用。常规的__free_hook劫持system或one_gadget可能受阻。
利用思路:利用UAF伪造_IO_2_1_stdout_结构体,进行FSOP(File Stream Oriented Programming)攻击。
- 泄露地址:通过UAF泄露堆和libc地址。
- 伪造
_IO_FILE结构:在堆上精心布局,伪造一个_IO_FILE(_IO_2_1_stderr_)结构,特别是其_wide_data和vtable,使其在调用某些输出函数(如exit时的刷新操作)时,能跳转到system函数,并且其参数指向我们控制的字符串(如/bin/sh)。
- 触发:通过漏洞(如再次释放或编辑)将全局
stdout或stderr指针指向我们伪造的结构体,然后触发程序流程调用exit或执行到_IO_flush_all_lockp,从而执行system(“/bin/sh”),绕过沙箱限制。
总结:本次DASCTF比赛题目覆盖了常见的网络安全攻防技术点,包括Web漏洞利用、逆向分析、综合隐写、密码学攻击和二进制漏洞利用,考察了选手全面的安全技术能力。