1.打开题目有俩个附件2.challenge.py可以理解为主脚本NE1S是加密的脚本前者信息非常简洁后面要看看加密算法3.注意round_add函数即异或即对每字节做 a[i] XOR b[i]4.32 轮 Feistel 网络可完全折叠可简化为密文左8字节 明文右8字节 ⊕ (K1⊕K3⊕…⊕K31) 明文右 ⊕ K_odd密文右8字节 明文左8字节 ⊕ (K0⊕K2⊕…⊕K30) 明文左 ⊕ K_even5.密钥直接给出密钥扩展gen_subkey用 s_box224 项最大索引 191正好作用在 192 位密钥位串上做置换迭代 8 轮生成 32 个 8 字节子密钥。因为密钥已知直接照抄扩展逻辑算出 K_even / K_odd 即可。6.按照流程1.按 N1ES.py 原逻辑用 key 生成 32 轮子密钥 Kn2. 折叠出 K_even K0⊕K2⊕…⊕K30、K_odd K1⊕K3⊕…⊕K313. base64 解码密文48 字节 3 个 16 字节块4. 每块 明文左 密文右⊕K_even、明文右 密文左⊕K_odd5. 拼接得到 flag7.# -*- coding: utf-8 -*- # N1CTF N1ES 求解脚本 # 原理round_add 恒等于 XOR32 轮 Feistel 可折叠为两次 XOR # 密文左8字节 明文右8字节 ^ K_odd (K_odd K1^K3^...^K31) # 密文右8字节 明文左8字节 ^ K_even (K_even K0^K2^...^K30) import base64 s_box [ 54, 132, 138, 83, 16, 73, 187, 84, 146, 30, 95, 21, 148, 63, 65, 189, 188, 151, 72, 161, 116, 63, 161, 91, 37, 24, 126, 107, 87, 30, 117, 185, 98, 90, 0, 42, 140, 70, 86, 0, 42, 150, 54, 22, 144, 153, 36, 90, 149, 54, 156, 8, 59, 40, 110, 56, 1, 84, 103, 22, 65, 17, 190, 41, 99, 151, 119, 124, 68, 17, 166, 125, 95, 65, 105, 133, 49, 19, 138, 29, 110, 7, 81, 134, 70, 87, 180, 78, 175, 108, 26, 121, 74, 29, 68, 162, 142, 177, 143, 86, 129, 101, 117, 41, 57, 34, 177, 103, 61, 135, 191, 74, 69, 147, 90, 49, 135, 124, 106, 19, 89, 38, 21, 41, 17, 155, 83, 38, 159, 179, 19, 157, 68, 105, 151, 166, 171, 122, 179, 114, 52, 183, 89, 107, 113, 65, 161, 141, 18, 121, 95, 4, 95, 101, 81, 156, 17, 190, 38, 84, 9, 171, 180, 59, 45, 15, 34, 89, 75, 164, 190, 140, 6, 41, 188, 77, 165, 105, 5, 107, 31, 183, 107, 141, 66, 63, 10, 9, 125, 50, 2, 153, 156, 162, 186, 76, 158, 153, 117, 9, 77, 156, 11, 145, 12, 169, 52, 57, 161, 7, 158, 110, 191, 43, 82, 186, 49, 102, 166, 31, 41, 5, 189, 27 ] def round_xor(a, b): round_add 等价于逐字节 XOR return bytes(x ^ y for x, y in zip(a, b)) def permutate(table, block): return [block[x] for x in table] def string_to_bits(data): result [0] * (len(data) * 8) for pos, ch in enumerate(data): for i in range(8): result[(pos 3) i] (ch i) 1 return result def generate(o): k permutate(s_box, o) # 224 位 b [k[i:i7] [1] for i in range(0, len(k), 7)] # 32 组 8 位 c [] for i in range(32): x 0 for pos, j in enumerate(b[i]): x (j pos) c.append((0x10001 ** x) % 0x7f) return c def gen_subkey(key): o string_to_bits(key) k [] for _ in range(8): o generate(o) k.extend(o) o string_to_bits([c for c in o[0:24]]) return [bytes(k[i*8:i*88]) for i in range(32)] def collapse(Kn): Ke Kn[0] Ko Kn[1] for i in range(2, 32, 2): Ke round_xor(Ke, Kn[i]) for i in range(3, 32, 2): Ko round_xor(Ko, Kn[i]) return Ke, Ko def decrypt(ct, Ke, Ko): out b for i in range(0, len(ct), 16): Lc, Rc ct[i:i8], ct[i8:i16] L0 round_xor(Rc, Ke) # 明文左 R0 round_xor(Lc, Ko) # 明文右 out L0 R0 return out if __name__ __main__: key bwxy191iss00000000000cute Kn gen_subkey(key) Ke, Ko collapse(Kn) ct base64.b64decode(HRlgC2ReHW1/WRk2DikfNBo1dl1XZBJrRR9qECMNOjNHDktBJSxcI1hZIz07YjVx) print(decrypt(ct, Ke, Ko).decode())8.运行得到N1CTF{F3istel_n3tw0rk_c4n_b3_ea5i1y_s0lv3d_/--/}9.总结需要读懂简化加密算法可以了解Feistel加密结构