强网杯2025-PolyEncryption之VibeReing的胜利

admin 2025-12-22 03:46:49 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 这篇文章介绍了强网杯2025中PolyEncryption题目的解题过程,作者使用AI辅助完成了多层加密算法的分析和解密脚本编写。文章详细描述了C#、Java和Python三层的解密方法,以及如何通过Docker调试确定最终细节,最终提供了完整的Python实现代码用于解密加密的flag文件。 综合评分: 91 文章分类: CTF,逆向分析,漏洞POC,二进制安全,安全工具


cover_image

强网杯2025-PolyEncryption之Vibe Reing的胜利

SleepAlone

看雪学苑

2025年12月20日 18:04 上海

1.由于代码太多太长,导致上传失败同时也影响读感,所以一些非关键的脚本贴了github链接。

#

2.以下所有代码全部由AI完成(少量人工排查),Vibe Reing已经到来!燃烧吧!token!

各个阶段解密脚本

00

C#层解密

1.c#层奇数轮(rr=1)

2.c#层奇数轮(rr!=1)

3.c#层偶数轮(rr=2,rr!=0)

java层解密

https://github.com/Savagel0ve/CTFWP/blob/main/qwb2025/polyenc/exp/decrypt_all_horror_commands.py

python层解密(自动生成patch后dll的反编译结果)

1.rr=0

2.rr=1

3.偶数

4.最后共同的

处理解密脚本产生的文件

01

Vibe Reing使用上一步产生的各层文件,使用cursor让agent根据这些解密文件自动对各个层的代码做出准确注释。

1.saw.cs(main)

2.saw.py

3.saw.java

有了注释之后,让agent自动读取注释,推理出(rr=0, rr=1, rr=2, rr=3)的数据流

1.rr=0

2.rr=1

3.rr=2

4.rr=3

根据AI推理出的数据流,逆向分析写出脚本

02

但是脚本解密失败,有细节不对,解密脚本省略,下面有正确的。

Patch polyencrypt.dll中的saw.python, Hack.java

03

#

Docker Debug看细节

1.Patch dll脚本

2.Patch saw.python 增加日志输出

3.Patch Hack.java 增加Hack中方法被调用的日志记录

4.Debug版本dockerfile

根据Debug docker的日志输出,敲定最终细节

04

#

最终写出解密脚本:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PolyEnc 纯Python实现 - 清晰版本
不使用中间变量,直接实现加密算法
"""

import struct

# ============================================================================
# S-box (来自 saw.py)
# ============================================================================
SBOX = (
0x9b, 0xac, 0x16, 0x92, 0x5d, 0x9c, 0x1f, 0xed, 0xf8, 0x52, 0x18, 0xc4, 0xd9, 0x59, 0xa0, 0x82,
0x3c, 0x88, 0x69, 0x4a, 0x5a, 0xf6, 0x34, 0xc1, 0xba, 0x27, 0xec, 0x23, 0x10, 0x51, 0x1, 0xe5,
0x5e, 0xb1, 0x12, 0xca, 0xe2, 0x9f, 0x65, 0x22, 0x7b, 0x2f, 0x3b, 0xeb, 0x4c, 0xf3, 0xb6, 0xb8,
0x1d, 0x50, 0xc5, 0x8e, 0x36, 0xd4, 0xd1, 0x89, 0x48, 0xad, 0xfe, 0x6e, 0xc0, 0x37, 0xb2, 0xa4,
0x6f, 0x71, 0x98, 0xa6, 0x49, 0x3a, 0x33, 0xff, 0x31, 0xb0, 0x8f, 0x76, 0xe4, 0xc8, 0x47, 0xab,
0xfd, 0x13, 0xd7, 0xc6, 0xdd, 0x73, 0xb5, 0x90, 0x70, 0x6a, 0xb9, 0x60, 0x1b, 0xfa, 0x1c, 0x45,
0xd8, 0x6, 0x68, 0x99, 0xa2, 0x4f, 0x7, 0x54, 0x4d, 0x17, 0x2a, 0x39, 0xa8, 0xa1, 0x84, 0x83,
0x64, 0x9e, 0x80, 0x7f, 0x29, 0xda, 0x61, 0x58, 0x20, 0x9, 0xdb, 0x8, 0x0f, 0xaf, 0x4, 0xd3,
0xf7, 0x5c, 0xee, 0xc9, 0x0c, 0x9d, 0x5, 0x93, 0xf2, 0x57, 0x4b, 0xf1, 0xcf, 0x15, 0xbf, 0xe8,
0xce, 0xea, 0x0e, 0x67, 0x91, 0x38, 0x6d, 0x3, 0x24, 0x25, 0x32, 0x85, 0xf5, 0xa5, 0x95, 0x5b,
0xbe, 0xbc, 0xdf, 0x0b, 0xbd, 0x7e, 0x35, 0x30, 0xae, 0xde, 0xef, 0x87, 0x8c, 0xb3, 0x1e, 0x28,
0x78, 0x6c, 0x75, 0x0a, 0x8a, 0x0d, 0x66, 0x8d, 0xcd, 0x40, 0x3d, 0xfb, 0x4e, 0xe1, 0xf4, 0x53,
0x2c, 0x77, 0x43, 0x26, 0x74, 0x94, 0x9a, 0xb7, 0x11, 0xa3, 0xe7, 0xfc, 0xd5, 0x96, 0x7c, 0xe0,
0xe6, 0x8b, 0xcb, 0x1a, 0x55, 0x62, 0xdc, 0xaa, 0x2, 0x63, 0x86, 0x7d, 0x14, 0x3f, 0x97, 0xa7,
0x72, 0x2e, 0x19, 0x2b, 0x0, 0x6b, 0xe9, 0x5f, 0xc2, 0x21, 0x2d, 0xd0, 0xf0, 0xd6, 0x7a, 0x3e,
0x46, 0x56, 0xd2, 0xe3, 0xbb, 0xb4, 0x44, 0xf9, 0xc7, 0x79, 0x81, 0x41, 0x42, 0xcc, 0xa9, 0xc3
)

# 构建逆S-box
INV_SBOX = [0] * 256
for i in range(256):
    INV_SBOX[SBOX[i]] = i
INV_SBOX = tuple(INV_SBOX)

# ============================================================================
# AES 标准函数
# ============================================================================
def xtime(a):
"""AES xtime: GF(2^8) 乘 2"""
return&nbsp;(((a <<&nbsp;1) ^&nbsp;0x1B) &&nbsp;0xFF)&nbsp;if&nbsp;(a &&nbsp;0x80)&nbsp;else&nbsp;(a <<&nbsp;1)

def&nbsp;mix_column(col):
"""
&nbsp; &nbsp; AES MixColumns 标准实现
&nbsp; &nbsp; 输入: [a0, a1, a2, a3] (4字节)
&nbsp; &nbsp; 输出: [b0, b1, b2, b3]
&nbsp; &nbsp; """
&nbsp; &nbsp; a0, a1, a2, a3 = col
&nbsp; &nbsp; xor_all = a0 ^ a1 ^ a2 ^ a3

&nbsp; &nbsp; b0 = a0 ^ xor_all ^ xtime(a0 ^ a1)
&nbsp; &nbsp; b1 = a1 ^ xor_all ^ xtime(a1 ^ a2)
&nbsp; &nbsp; b2 = a2 ^ xor_all ^ xtime(a2 ^ a3)
&nbsp; &nbsp; b3 = a3 ^ xor_all ^ xtime(a3 ^ a0)

return&nbsp;[b0, b1, b2, b3]

def&nbsp;apply_sbox_to_u32(value):
"""对32位整数应用S-box (小端序)"""
&nbsp; &nbsp; bytes_le = struct.pack("<I", value)
&nbsp; &nbsp; sboxed =&nbsp;bytes([SBOX[b]&nbsp;for&nbsp;b&nbsp;in&nbsp;bytes_le])
return&nbsp;struct.unpack("<I", sboxed)[0]

def&nbsp;rol(value, shift):
"""32位循环左移"""
&nbsp; &nbsp; value &=&nbsp;0xFFFFFFFF
return&nbsp;((value << shift) | (value >> (32&nbsp;- shift))) &&nbsp;0xFFFFFFFF

def&nbsp;gf_mult(a, b):
"""GF(2^8) 乘法"""
&nbsp; &nbsp; p =&nbsp;0
for&nbsp;_&nbsp;in&nbsp;range(8):
if&nbsp;b &&nbsp;1:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p ^= a
&nbsp; &nbsp; &nbsp; &nbsp; hi_bit_set = a &&nbsp;0x80
&nbsp; &nbsp; &nbsp; &nbsp; a = (a <<&nbsp;1) &&nbsp;0xFF
if&nbsp;hi_bit_set:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a ^=&nbsp;0x1B
&nbsp; &nbsp; &nbsp; &nbsp; b >>=&nbsp;1
return&nbsp;p

def&nbsp;inv_mix_column(col):
"""
&nbsp; &nbsp; AES 逆 MixColumns 实现
&nbsp; &nbsp; 输入: [b0, b1, b2, b3] (4字节)
&nbsp; &nbsp; 输出: [a0, a1, a2, a3]
&nbsp; &nbsp; 使用矩阵: [0x0E, 0x0B, 0x0D, 0x09]
&nbsp; &nbsp; """
&nbsp; &nbsp; b0, b1, b2, b3 = col

&nbsp; &nbsp; a0 = gf_mult(0x0E, b0) ^ gf_mult(0x0B, b1) ^ gf_mult(0x0D, b2) ^ gf_mult(0x09, b3)
&nbsp; &nbsp; a1 = gf_mult(0x09, b0) ^ gf_mult(0x0E, b1) ^ gf_mult(0x0B, b2) ^ gf_mult(0x0D, b3)
&nbsp; &nbsp; a2 = gf_mult(0x0D, b0) ^ gf_mult(0x09, b1) ^ gf_mult(0x0E, b2) ^ gf_mult(0x0B, b3)
&nbsp; &nbsp; a3 = gf_mult(0x0B, b0) ^ gf_mult(0x0D, b1) ^ gf_mult(0x09, b2) ^ gf_mult(0x0E, b3)

return&nbsp;[a0, a1, a2, a3]

def&nbsp;apply_inv_sbox_to_u32(value):
"""对32位整数应用逆S-box (小端序)"""
&nbsp; &nbsp; bytes_le = struct.pack("<I", value)
&nbsp; &nbsp; inv_sboxed =&nbsp;bytes([INV_SBOX[b]&nbsp;for&nbsp;b&nbsp;in&nbsp;bytes_le])
return&nbsp;struct.unpack("<I", inv_sboxed)[0]

# ============================================================================
# PolyEnc 加密器
# ============================================================================
class&nbsp;PolyEnc:
def&nbsp;__init__(self):
"""初始化加密器"""
# 轮密钥 (10个,对应 Round 2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
&nbsp; &nbsp; &nbsp; &nbsp; self.round_keys = [
3207972492,&nbsp;1190065579,&nbsp;4165979424,&nbsp;2693353696,&nbsp;3628337899,
1707638109,&nbsp;1003779598,&nbsp;2653425729,&nbsp;795752593,&nbsp;2469382657,
0
&nbsp; &nbsp; &nbsp; &nbsp; ]

# 初始密钥状态
&nbsp; &nbsp; &nbsp; &nbsp; self.initial_key = [
2427014626, &nbsp;# s[1] - 初始魔数
1166827919, &nbsp;# s[2] - 初始魔数
1240047111, &nbsp;# s[3] - 初始魔数
1038097261&nbsp; &nbsp;# s[4] - 初始魔数
&nbsp; &nbsp; &nbsp; &nbsp; ]

def&nbsp;encrypt(self, plaintext_bytes, verbose=False):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 加密16字节明文

&nbsp; &nbsp; &nbsp; &nbsp; 算法流程:
&nbsp; &nbsp; &nbsp; &nbsp; - Round 0: 初始化
&nbsp; &nbsp; &nbsp; &nbsp; - Round 1-21: 奇数轮(SubBytes+MixColumns) + 偶数轮(AddRoundKey)
&nbsp; &nbsp; &nbsp; &nbsp; - Round 22: 输出
&nbsp; &nbsp; &nbsp; &nbsp; """
if&nbsp;len(plaintext_bytes) !=&nbsp;16:
raise&nbsp;ValueError("Input must be 16 bytes")

# 将明文转为4个32位整数 (大端序)
&nbsp; &nbsp; &nbsp; &nbsp; state =&nbsp;list(struct.unpack('>4I', plaintext_bytes))

# 复制初始密钥
&nbsp; &nbsp; &nbsp; &nbsp; key = self.initial_key.copy()

# 轮密钥索引
&nbsp; &nbsp; &nbsp; &nbsp; key_index =&nbsp;0

if&nbsp;verbose:
print(f"【初始状态】")
print(f" &nbsp;state =&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")
print(f" &nbsp;key &nbsp; =&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key]}")

# Round 1-21: 主加密循环
# Round 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 (奇数轮): SubBytes + MixColumns
# Round 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 (偶数轮): ShiftRows + AddRoundKey
for&nbsp;rr&nbsp;in&nbsp;range(1,&nbsp;23):
if&nbsp;rr %&nbsp;2&nbsp;==&nbsp;1: &nbsp;# 奇数轮: SubBytes + MixColumns
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state = self._odd_round(state, key, rr, verbose)
else: &nbsp;# 偶数轮: ShiftRows + AddRoundKey
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state, key, key_index = self._even_round(state, key, key_index, rr, verbose)

&nbsp; &nbsp; &nbsp; &nbsp; final_state = state

# 返回密文 (大端序)
return&nbsp;struct.pack('>4I', *final_state)

def&nbsp;_odd_round(self, state, key, rr, verbose):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 奇数轮: SubBytes + MixColumns

&nbsp; &nbsp; &nbsp; &nbsp; 返回: 16 字节数组 (4x4 矩阵,按行存储)

&nbsp; &nbsp; &nbsp; &nbsp; 同时更新密钥状态 s[2], s[3], s[4]:
&nbsp; &nbsp; &nbsp; &nbsp; - s[2] = B ^ A'
&nbsp; &nbsp; &nbsp; &nbsp; - s[3] = C ^ B ^ A'
&nbsp; &nbsp; &nbsp; &nbsp; - s[4] = D ^ C ^ B ^ A'
&nbsp; &nbsp; &nbsp; &nbsp; """
if&nbsp;verbose:
print(f"\n【Round&nbsp;{rr}】奇数轮 - SubBytes + MixColumns")
print(f" &nbsp;输入 state =&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")
print(f" &nbsp;输入 key &nbsp; =&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key]}")

# 1. 密钥更新 (奇数轮)
if&nbsp;rr ==&nbsp;1:
# Round 1: 密钥保持初始值,不变
pass
else:
# Round 3, 5, 7, ..., 21: 更新 s[2], s[3], s[4]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A_prime = key[0] &nbsp;# 上一个偶数轮更新后的 s[1]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; B = key[1]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; C = key[2]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; D = key[3]

# 密钥级联更新
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[1] = (B ^ A_prime) &&nbsp;0xFFFFFFFF&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# s[2] = B ^ A'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[2] = (C ^ B ^ A_prime) &&nbsp;0xFFFFFFFF&nbsp; &nbsp; &nbsp;&nbsp;# s[3] = C ^ B ^ A'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[3] = (D ^ C ^ B ^ A_prime) &&nbsp;0xFFFFFFFF&nbsp;&nbsp;# s[4] = D ^ C ^ B ^ A'

if&nbsp;verbose:
print(f" &nbsp;密钥更新:")
print(f" &nbsp; &nbsp;A' =&nbsp;{hex(A_prime)}")
print(f" &nbsp; &nbsp;s[2] = B ^ A' =&nbsp;{hex(key[1])}")
print(f" &nbsp; &nbsp;s[3] = C ^ B ^ A' =&nbsp;{hex(key[2])}")
print(f" &nbsp; &nbsp;s[4] = D ^ C ^ B ^ A' =&nbsp;{hex(key[3])}")

# 2. SubBytes: 对 state 的每个32位整数应用S-box
&nbsp; &nbsp; &nbsp; &nbsp; sboxed = [apply_sbox_to_u32(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]

if&nbsp;verbose:
print(f" &nbsp;SubBytes =&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;sboxed]}")

# 3. MixColumns: 对每个 32位整数拆分成 4字节,MixColumns 后得到 16字节
# 结果按倒序排列(从 Docker 日志观察到)
&nbsp; &nbsp; &nbsp; &nbsp; mixed_bytes = []
for&nbsp;val&nbsp;in&nbsp;sboxed: &nbsp;# 倒序处理
# 拆分成4字节 (大端序)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes_be = struct.unpack('4B', struct.pack('>I', val))
# MixColumns
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mixed_col = mix_column(list(bytes_be))
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mixed_bytes.extend(mixed_col)

if&nbsp;verbose:
print(f" &nbsp;MixColumns 16字节:&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;mixed_bytes]}")
# 显示为 4x4 矩阵
print(f" &nbsp;MixColumns 4x4矩阵 (按列):")
for&nbsp;row&nbsp;in&nbsp;range(4):
print(f" &nbsp; &nbsp;row{row}:&nbsp;{[hex(mixed_bytes[col*4&nbsp;+ row])&nbsp;for&nbsp;col&nbsp;in&nbsp;range(4)]}")

return&nbsp;mixed_bytes

def&nbsp;_even_round(self, state_bytes, key, key_index, rr, verbose):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 偶数轮: ShiftRows + 字节打包 + AddRoundKey

&nbsp; &nbsp; &nbsp; &nbsp; 输入: 16 字节数组 (从奇数轮的 MixColumns 输出)
&nbsp; &nbsp; &nbsp; &nbsp; 输出: 4 个 32位整数

&nbsp; &nbsp; &nbsp; &nbsp; 1. ShiftRows: 对 4x4 矩阵按对角线重排
&nbsp; &nbsp; &nbsp; &nbsp; 2. 字节打包: 每 4 字节打包成一个 32位整数
&nbsp; &nbsp; &nbsp; &nbsp; 3. AddRoundKey: state ^= key
&nbsp; &nbsp; &nbsp; &nbsp; 4. 密钥更新: s[1] = A ^ sbox(rol(D, 8)) ^ round_key[i]
&nbsp; &nbsp; &nbsp; &nbsp; """
if&nbsp;verbose:
print(f"\n【Round&nbsp;{rr}】偶数轮 - ShiftRows + AddRoundKey")
print(f" &nbsp;输入 16字节:&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;state_bytes]}")
print(f" &nbsp;输入 key &nbsp; =&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key]}")

# 1. ShiftRows: 标准 AES ShiftRows(按行存储)
# 输入: state_bytes 按列存储 [col0_row0-3, col1_row0-3, col2_row0-3, col3_row0-3]
# 需要先转换为按行存储,然后 ShiftRows,最后按列打包

# 标准 ShiftRows 索引(按行存储):
# col0: 0, 5, 10, 15
# col1: 1, 6, 11, 12
# col2: 2, 7, 8, 13
# col3: 3, 4, 9, 14

# 将按列存储转换为按行存储
# state_bytes[0..3] = col0, state_bytes[4..7] = col1, ...
# 转换为 row0 = [0,4,8,12], row1 = [1,5,9,13], ...
&nbsp; &nbsp; &nbsp; &nbsp; row_based = []
for&nbsp;row&nbsp;in&nbsp;range(4):
for&nbsp;col&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row_based.append(state_bytes[col *&nbsp;4&nbsp;+ row])

# ShiftRows 索引(倒序,因为 state 要倒序)
&nbsp; &nbsp; &nbsp; &nbsp; shiftrows_indices = [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [3,&nbsp;4,&nbsp;9,&nbsp;14], &nbsp;&nbsp;# col3 (倒序第0个)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [2,&nbsp;7,&nbsp;8,&nbsp;13], &nbsp;&nbsp;# col2 (倒序第1个)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [1,&nbsp;6,&nbsp;11,&nbsp;12], &nbsp;# col1 (倒序第2个)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0,&nbsp;5,&nbsp;10,&nbsp;15] &nbsp;&nbsp;# col0 (倒序第3个)
&nbsp; &nbsp; &nbsp; &nbsp; ]

&nbsp; &nbsp; &nbsp; &nbsp; shifted_state = []
for&nbsp;indices&nbsp;in&nbsp;shiftrows_indices:
# 从 row_based 按索引取4个字节,打包成32位整数
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val = (row_based[indices[0]] <<&nbsp;24) | (row_based[indices[1]] <<&nbsp;16) | \
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (row_based[indices[2]] <<&nbsp;8) | row_based[indices[3]]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; shifted_state.append(val)

if&nbsp;verbose:
print(f" &nbsp;ShiftRows + 打包:")
for&nbsp;col&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idx0 =&nbsp;0*4&nbsp;+ col
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idx1 =&nbsp;1*4&nbsp;+ ((col +&nbsp;1) %&nbsp;4)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idx2 =&nbsp;2*4&nbsp;+ ((col +&nbsp;2) %&nbsp;4)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idx3 =&nbsp;3*4&nbsp;+ ((col +&nbsp;3) %&nbsp;4)
print(f" &nbsp; &nbsp;state[{col}] = [{hex(state_bytes[idx0])},&nbsp;{hex(state_bytes[idx1])}, "
f"{hex(state_bytes[idx2])},&nbsp;{hex(state_bytes[idx3])}] =&nbsp;{hex(shifted_state[col])}")

# 2. AddRoundKey: state ^= key
&nbsp; &nbsp; &nbsp; &nbsp; shifted_state = shifted_state[::-1]
&nbsp; &nbsp; &nbsp; &nbsp; new_state = [(shifted_state[i] ^ key[i]) &&nbsp;0xFFFFFFFF&nbsp;for&nbsp;i&nbsp;in&nbsp;range(4)]

if&nbsp;verbose:
print(f" &nbsp;AddRoundKey (state ^= key):")
for&nbsp;i&nbsp;in&nbsp;range(4):
print(f" &nbsp; &nbsp;state[{i}] =&nbsp;{hex(shifted_state[i])}&nbsp;^&nbsp;{hex(key[i])}&nbsp;=&nbsp;{hex(new_state[i])}")

# 3. 密钥更新: s[1] = A ^ sbox(rol(D, 8)) ^ round_key[i]
&nbsp; &nbsp; &nbsp; &nbsp; A = key[0]
&nbsp; &nbsp; &nbsp; &nbsp; D = key[3]

# rol(D, 8) - 循环左移8位
&nbsp; &nbsp; &nbsp; &nbsp; rotated = rol(D,&nbsp;8)

# sbox(rotated)
&nbsp; &nbsp; &nbsp; &nbsp; sboxed = apply_sbox_to_u32(rotated)

# A' = A ^ sboxed ^ round_key[i]
&nbsp; &nbsp; &nbsp; &nbsp; round_key = self.round_keys[key_index]
&nbsp; &nbsp; &nbsp; &nbsp; A_prime = (A ^ sboxed ^ round_key) &&nbsp;0xFFFFFFFF

&nbsp; &nbsp; &nbsp; &nbsp; key[0] = A_prime
&nbsp; &nbsp; &nbsp; &nbsp; key_index +=&nbsp;1

if&nbsp;verbose:
print(f" &nbsp;密钥更新:")
print(f" &nbsp; &nbsp;rol(s[4], 8) =&nbsp;{hex(rotated)}")
print(f" &nbsp; &nbsp;sbox(rotated) =&nbsp;{hex(sboxed)}")
print(f" &nbsp; &nbsp;round_key[{key_index-1}] =&nbsp;{hex(round_key)}")
print(f" &nbsp; &nbsp;s[1] =&nbsp;{hex(A)}&nbsp;^&nbsp;{hex(sboxed)}&nbsp;^&nbsp;{hex(round_key)}&nbsp;=&nbsp;{hex(A_prime)}")

return&nbsp;new_state, key, key_index

def&nbsp;decrypt(self, ciphertext_bytes, verbose=False):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 解密16字节密文

&nbsp; &nbsp; &nbsp; &nbsp; 算法流程:
&nbsp; &nbsp; &nbsp; &nbsp; 1. 先正向生成所有轮的密钥状态
&nbsp; &nbsp; &nbsp; &nbsp; 2. 从 Round 22 逆向到 Round 1
&nbsp; &nbsp; &nbsp; &nbsp; """
if&nbsp;len(ciphertext_bytes) !=&nbsp;16:
raise&nbsp;ValueError("Input must be 16 bytes")

# 1. 正向生成所有轮密钥状态
if&nbsp;verbose:
print(f"\n【生成轮密钥】")
&nbsp; &nbsp; &nbsp; &nbsp; key_states = self._generate_all_round_keys()

if&nbsp;verbose:
print(f"生成了&nbsp;{len(key_states)}&nbsp;组轮密钥")
for&nbsp;rr&nbsp;in&nbsp;sorted(key_states.keys())[:5]: &nbsp;# 只显示前5个
print(f" &nbsp;Round&nbsp;{rr}:&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key_states[rr]]}")
print(f" &nbsp;...")

# 2. 将密文转为4个32位整数 (大端序)
&nbsp; &nbsp; &nbsp; &nbsp; state =&nbsp;list(struct.unpack('>4I', ciphertext_bytes))

if&nbsp;verbose:
print(f"\n【解密开始】")
print(f" &nbsp;密文 (bytes):&nbsp;{ciphertext_bytes.hex().upper()}")
print(f" &nbsp;密文 (u32):&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")

# 3. 逆向执行 Round 22 到 Round 1
for&nbsp;rr&nbsp;in&nbsp;range(22,&nbsp;0, -1):
if&nbsp;rr %&nbsp;2&nbsp;==&nbsp;0: &nbsp;# 偶数轮: 逆AddRoundKey + 逆ShiftRows
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state = self._inv_even_round(state, key_states[rr], rr, verbose)
else: &nbsp;# 奇数轮: 逆MixColumns + 逆SubBytes
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state = self._inv_odd_round(state, key_states[rr], rr, verbose)

if&nbsp;verbose:
print(f"\n【解密结束】")
print(f" &nbsp;明文 (u32):&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")

# 4. 返回明文 (大端序)
&nbsp; &nbsp; &nbsp; &nbsp; plaintext = struct.pack('>4I', *state)

if&nbsp;verbose:
print(f" &nbsp;明文 (bytes):&nbsp;{plaintext.hex().upper()}")

return&nbsp;plaintext

def&nbsp;_generate_all_round_keys(self):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 正向生成所有轮的密钥状态
&nbsp; &nbsp; &nbsp; &nbsp; 返回: 字典 {round_number: key_state}
&nbsp; &nbsp; &nbsp; &nbsp; """
&nbsp; &nbsp; &nbsp; &nbsp; key = self.initial_key.copy()
&nbsp; &nbsp; &nbsp; &nbsp; key_index =&nbsp;0
&nbsp; &nbsp; &nbsp; &nbsp; key_states = {0: key.copy()}

# 模拟加密过程中的密钥更新
for&nbsp;rr&nbsp;in&nbsp;range(1,&nbsp;23):
if&nbsp;rr %&nbsp;2&nbsp;==&nbsp;1: &nbsp;# 奇数轮
if&nbsp;rr >&nbsp;1:
# Round 3, 5, 7, ..., 21: 更新 s[2], s[3], s[4]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A_prime = key[0]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; B = key[1]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; C = key[2]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; D = key[3]

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[1] = (B ^ A_prime) &&nbsp;0xFFFFFFFF
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[2] = (C ^ B ^ A_prime) &&nbsp;0xFFFFFFFF
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[3] = (D ^ C ^ B ^ A_prime) &&nbsp;0xFFFFFFFF

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key_states[rr] = key.copy()
else: &nbsp;# 偶数轮
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key_states[rr] = key.copy()

# 更新 s[1]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A = key[0]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; D = key[3]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rotated = rol(D,&nbsp;8)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sboxed = apply_sbox_to_u32(rotated)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; round_key = self.round_keys[key_index]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A_prime = (A ^ sboxed ^ round_key) &&nbsp;0xFFFFFFFF

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key[0] = A_prime
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key_index +=&nbsp;1

return&nbsp;key_states

def&nbsp;_inv_odd_round(self, state_bytes, key, rr, verbose):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 逆奇数轮: 逆MixColumns + 逆SubBytes

&nbsp; &nbsp; &nbsp; &nbsp; 输入: 16 字节数组
&nbsp; &nbsp; &nbsp; &nbsp; 输出: 4 个 32位整数
&nbsp; &nbsp; &nbsp; &nbsp; """
if&nbsp;verbose:
print(f"\n【Round&nbsp;{rr}&nbsp;逆向】奇数轮 - InvMixColumns + InvSubBytes")
print(f" &nbsp;输入 state (16字节):&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;state_bytes]}")
print(f" &nbsp;输入 key &nbsp; =&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key]}")
# 显示为 4x4 矩阵
print(f" &nbsp;输入 4x4矩阵 (按列):")
for&nbsp;row&nbsp;in&nbsp;range(4):
print(f" &nbsp; &nbsp;row{row}:&nbsp;{[hex(state_bytes[col*4&nbsp;+ row])&nbsp;for&nbsp;col&nbsp;in&nbsp;range(4)]}")

# 1. 逆MixColumns: 对每个32位整数拆分成4字节,逆MixColumns后得到16字节
&nbsp; &nbsp; &nbsp; &nbsp; inv_mixed_bytes = []
for&nbsp;i&nbsp;in&nbsp;range(4):
# 提取4个字节(按列存储)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; col_bytes = state_bytes[i*4:(i+1)*4]
# 逆MixColumns
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inv_mixed_col = inv_mix_column(list(col_bytes))
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inv_mixed_bytes.extend(inv_mixed_col)

if&nbsp;verbose:
print(f" &nbsp;InvMixColumns 16字节:&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;inv_mixed_bytes]}")
# 显示为 4x4 矩阵
print(f" &nbsp;InvMixColumns 4x4矩阵 (按列):")
for&nbsp;row&nbsp;in&nbsp;range(4):
print(f" &nbsp; &nbsp;row{row}:&nbsp;{[hex(inv_mixed_bytes[col*4&nbsp;+ row])&nbsp;for&nbsp;col&nbsp;in&nbsp;range(4)]}")

# 2. 重新打包成4个32位整数(大端序)
&nbsp; &nbsp; &nbsp; &nbsp; sboxed = []
for&nbsp;i&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes_4 = inv_mixed_bytes[i*4:(i+1)*4]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val = struct.unpack('>I',&nbsp;bytes(bytes_4))[0]
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sboxed.append(val)

if&nbsp;verbose:
print(f" &nbsp;打包成u32 (应用InvSubBytes之前):&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;sboxed]}")

# 3. 逆SubBytes: 对每个32位整数应用逆S-box
&nbsp; &nbsp; &nbsp; &nbsp; state = [apply_inv_sbox_to_u32(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;sboxed]

if&nbsp;verbose:
print(f" &nbsp;InvSubBytes (输出state) =&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")

return&nbsp;state

def&nbsp;_inv_even_round(self, state, key, rr, verbose):
"""
&nbsp; &nbsp; &nbsp; &nbsp; 逆偶数轮: 逆AddRoundKey + 逆ShiftRows

&nbsp; &nbsp; &nbsp; &nbsp; 输入: 4 个 32位整数
&nbsp; &nbsp; &nbsp; &nbsp; 输出: 16 字节数组
&nbsp; &nbsp; &nbsp; &nbsp; """
if&nbsp;verbose:
print(f"\n【Round&nbsp;{rr}&nbsp;逆向】偶数轮 - InvAddRoundKey + InvShiftRows")
print(f" &nbsp;输入 state =&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")
print(f" &nbsp;使用 key &nbsp; =&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key]}")

# 1. 逆AddRoundKey: state ^= key (XOR是自逆的)
&nbsp; &nbsp; &nbsp; &nbsp; unkeyed_state = [(state[i] ^ key[i]) &&nbsp;0xFFFFFFFF&nbsp;for&nbsp;i&nbsp;in&nbsp;range(4)]

if&nbsp;verbose:
print(f" &nbsp;InvAddRoundKey (state ^= key):")
for&nbsp;i&nbsp;in&nbsp;range(4):
print(f" &nbsp; &nbsp;state[{i}] =&nbsp;{hex(state[i])}&nbsp;^&nbsp;{hex(key[i])}&nbsp;=&nbsp;{hex(unkeyed_state[i])}")

# 将4个32位整数拆分成16字节
# 按加密时的打包方式逆向
&nbsp; &nbsp; &nbsp; &nbsp; inv_shiftrows_indices = [
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [0,&nbsp;5,&nbsp;10,&nbsp;15], &nbsp;&nbsp;# col0 (对应倒序第3个)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [1,&nbsp;6,&nbsp;11,&nbsp;12], &nbsp;&nbsp;# col1 (对应倒序第2个)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [2,&nbsp;7,&nbsp;8,&nbsp;13], &nbsp; &nbsp;# col2 (对应倒序第1个)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [3,&nbsp;4,&nbsp;9,&nbsp;14] &nbsp; &nbsp;&nbsp;# col3 (对应倒序第0个)
&nbsp; &nbsp; &nbsp; &nbsp; ]

# 先将4个u32解包成按行存储的16字节
&nbsp; &nbsp; &nbsp; &nbsp; row_based = []
for&nbsp;val&nbsp;in&nbsp;unkeyed_state:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row_based.append((val >>&nbsp;24) &&nbsp;0xFF)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row_based.append((val >>&nbsp;16) &&nbsp;0xFF)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row_based.append((val >>&nbsp;8) &&nbsp;0xFF)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row_based.append(val &&nbsp;0xFF)

if&nbsp;verbose:
print(f" &nbsp;解包成16字节(按行):&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;row_based]}")

# 创建逆映射
&nbsp; &nbsp; &nbsp; &nbsp; unshifted_row_based = [0] *&nbsp;16
for&nbsp;col_idx, indices&nbsp;in&nbsp;enumerate(inv_shiftrows_indices):
for&nbsp;byte_idx, src_idx&nbsp;in&nbsp;enumerate(indices):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unshifted_row_based[src_idx] = row_based[col_idx *&nbsp;4&nbsp;+ byte_idx]

if&nbsp;verbose:
print(f" &nbsp;InvShiftRows后(按行):&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;unshifted_row_based]}")

# 转换回按列存储
&nbsp; &nbsp; &nbsp; &nbsp; state_bytes = []
for&nbsp;col&nbsp;in&nbsp;range(4):
for&nbsp;row&nbsp;in&nbsp;range(4):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state_bytes.append(unshifted_row_based[row *&nbsp;4&nbsp;+ col])

if&nbsp;verbose:
print(f" &nbsp;输出 16字节(按列):&nbsp;{[hex(b)&nbsp;for&nbsp;b&nbsp;in&nbsp;state_bytes]}")
# 显示为 4x4 矩阵
print(f" &nbsp;输出 4x4矩阵 (按列):")
for&nbsp;row&nbsp;in&nbsp;range(4):
print(f" &nbsp; &nbsp;row{row}:&nbsp;{[hex(state_bytes[col*4&nbsp;+ row])&nbsp;for&nbsp;col&nbsp;in&nbsp;range(4)]}")

return&nbsp;state_bytes

# ============================================================================
# 测试和验证
# ============================================================================
def&nbsp;test_encrypt():
"""测试加密功能"""
print("="*80)
print("PolyEnc 加密测试")
print("="*80)

# Docker 环境:run.sh 传入 "abe74e3a9c375b3428bf31d1f8fa49c1"
# dotnet 程序将其解析为十六进制并按 32位整数倒序排列

&nbsp; &nbsp; plaintext_hex =&nbsp;"abe74e3a9c375b3428bf31d1f8fa49c1"

# 解析成 4 个 32位整数(每8个字符一组)
&nbsp; &nbsp; chunks = [plaintext_hex[i:i+8]&nbsp;for&nbsp;i&nbsp;in&nbsp;range(0,&nbsp;len(plaintext_hex),&nbsp;8)]
print(f"\n解析输入字符串:&nbsp;{plaintext_hex}")
print(f" &nbsp;分组:&nbsp;{chunks}")

# dotnet 按倒序处理(从 Docker 日志观察到)
&nbsp; &nbsp; chunks_reversed = chunks
print(f" &nbsp;倒序:&nbsp;{chunks_reversed}")

# 转换为字节序列(小端序)
&nbsp; &nbsp; plaintext_bytes =&nbsp;b''.join([bytes.fromhex(c)&nbsp;for&nbsp;c&nbsp;in&nbsp;chunks_reversed])
print(f" &nbsp;字节序列 (hex):&nbsp;{plaintext_bytes.hex().upper()}")

# 重新组装为大端序的 4 个整数(匹配 polyenc 输入格式)
&nbsp; &nbsp; plaintext =&nbsp;bytes.fromhex(''.join(chunks_reversed))

print(f"\n最终明文 (hex):&nbsp;{plaintext.hex().upper()}")
print(f"最终明文 (u32 大端):&nbsp;{[hex(x)&nbsp;for&nbsp;x&nbsp;in&nbsp;struct.unpack('>4I', plaintext)]}")

# 加密
&nbsp; &nbsp; enc = PolyEnc()
&nbsp; &nbsp; ciphertext = enc.encrypt(plaintext, verbose=True)

print(f"\n密文:&nbsp;{ciphertext.hex().upper()}")

return&nbsp;True

def&nbsp;test_verbose():
"""详细输出测试"""
print("\n"&nbsp;+&nbsp;"="*80)
print("详细加密流程(前4轮)")
print("="*80)

&nbsp; &nbsp; plaintext =&nbsp;bytes.fromhex("abe74e3a9c375b3428bf31d1f8fa49c1")

&nbsp; &nbsp; enc = PolyEnc()
# 修改加密函数以支持部分轮次
&nbsp; &nbsp; state =&nbsp;list(struct.unpack('>4I', plaintext))
&nbsp; &nbsp; key = enc.initial_key.copy()
&nbsp; &nbsp; key_index =&nbsp;0

print(f"\n明文:&nbsp;{plaintext.hex().upper()}")
print(f"初始 state =&nbsp;{[hex(s)&nbsp;for&nbsp;s&nbsp;in&nbsp;state]}")
print(f"初始 key &nbsp; =&nbsp;{[hex(k)&nbsp;for&nbsp;k&nbsp;in&nbsp;key]}")

# Round 1-4
for&nbsp;rr&nbsp;in&nbsp;range(1,&nbsp;5):
if&nbsp;rr %&nbsp;2&nbsp;==&nbsp;1:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state = enc._odd_round(state, key, rr, verbose=True)
else:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; state, key, key_index = enc._even_round(state, key, key_index, rr, verbose=True)

def&nbsp;test_decrypt(verbose=True):
"""测试加密和解密功能"""
print("="*80)
print("PolyEnc 加密/解密测试")
print("="*80)

&nbsp; &nbsp; plaintext_hex =&nbsp;"abe74e3a9c375b3428bf31d1f8fa49c1"
&nbsp; &nbsp; plaintext =&nbsp;bytes.fromhex(plaintext_hex)

print(f"\n明文 (hex):&nbsp;{plaintext.hex().upper()}")

# 加密
&nbsp; &nbsp; enc = PolyEnc()
&nbsp; &nbsp; ciphertext = enc.encrypt(plaintext, verbose=False)
print(f"密文 (hex):&nbsp;{ciphertext.hex().upper()}")

print("\n"&nbsp;+&nbsp;"="*80)
print("开始解密...")
print("="*80)

# 解密
&nbsp; &nbsp; decrypted = enc.decrypt(ciphertext, verbose=verbose)

print("\n"&nbsp;+&nbsp;"="*80)
print("解密完成")
print("="*80)
print(f"解密后 (hex):&nbsp;{decrypted.hex().upper()}")

# 验证
if&nbsp;plaintext == decrypted:
print("\n✓ 解密成功!明文与解密结果一致")
return&nbsp;True
else:
print("\n✗ 解密失败!明文与解密结果不一致")
print(f" &nbsp;期望:&nbsp;{plaintext.hex().upper()}")
print(f" &nbsp;实际:&nbsp;{decrypted.hex().upper()}")
return&nbsp;False

def&nbsp;test_with_separate_logs():
"""将加密和解密日志分别输出到不同文件"""
import&nbsp;sys

&nbsp; &nbsp; plaintext_hex =&nbsp;"abe74e3a9c375b3428bf31d1f8fa49c1"
&nbsp; &nbsp; plaintext =&nbsp;bytes.fromhex(plaintext_hex)

print("="*80)
print("PolyEnc 加密/解密测试 (分离日志)")
print("="*80)
print(f"明文:&nbsp;{plaintext.hex().upper()}")

# 1. 加密并输出到文件
print("\n正在生成加密日志...")
with&nbsp;open('encrypt_log.txt',&nbsp;'w', encoding='utf-8')&nbsp;as&nbsp;f:
&nbsp; &nbsp; &nbsp; &nbsp; old_stdout = sys.stdout
&nbsp; &nbsp; &nbsp; &nbsp; sys.stdout = f

&nbsp; &nbsp; &nbsp; &nbsp; enc = PolyEnc()
&nbsp; &nbsp; &nbsp; &nbsp; ciphertext = enc.encrypt(plaintext, verbose=True)

&nbsp; &nbsp; &nbsp; &nbsp; sys.stdout = old_stdout

print(f"✓ 加密日志已保存到: encrypt_log.txt")
print(f" &nbsp;密文:&nbsp;{ciphertext.hex().upper()}")

# 2. 解密并输出到文件
print("\n正在生成解密日志...")
with&nbsp;open('decrypt_log.txt',&nbsp;'w', encoding='utf-8')&nbsp;as&nbsp;f:
&nbsp; &nbsp; &nbsp; &nbsp; old_stdout = sys.stdout
&nbsp; &nbsp; &nbsp; &nbsp; sys.stdout = f

&nbsp; &nbsp; &nbsp; &nbsp; decrypted = enc.decrypt(ciphertext, verbose=True)

&nbsp; &nbsp; &nbsp; &nbsp; sys.stdout = old_stdout

print(f"✓ 解密日志已保存到: decrypt_log.txt")
print(f" &nbsp;解密结果:&nbsp;{decrypted.hex().upper()}")

# 3. 验证
print("\n"&nbsp;+&nbsp;"="*80)
if&nbsp;plaintext == decrypted:
print("✓ 解密成功!明文与解密结果一致")
return&nbsp;True
else:
print("✗ 解密失败!明文与解密结果不一致")
print(f" &nbsp;期望:&nbsp;{plaintext.hex().upper()}")
print(f" &nbsp;实际:&nbsp;{decrypted.hex().upper()}")
return&nbsp;False

def&nbsp;decrypt_flag_file(flag_file='../flag.enc', output_file='flag.txt'):
"""解密 flag.enc 文件"""
print("="*80)
print("解密 FLAG 文件")
print("="*80)

# 1. 读取加密文件
try:
with&nbsp;open(flag_file,&nbsp;'r')&nbsp;as&nbsp;f:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ciphertext_hex = f.read().strip()
except&nbsp;FileNotFoundError:
print(f"✗ 错误: 找不到文件&nbsp;{flag_file}")
return&nbsp;False

print(f"读取文件:&nbsp;{flag_file}")
print(f"密文 (hex):&nbsp;{ciphertext_hex}")
print(f"密文长度:&nbsp;{len(ciphertext_hex)}&nbsp;字符 ({len(ciphertext_hex)//2}&nbsp;字节)")

# 2. 解析十六进制
try:
&nbsp; &nbsp; &nbsp; &nbsp; ciphertext =&nbsp;bytes.fromhex(ciphertext_hex)
except&nbsp;ValueError&nbsp;as&nbsp;e:
print(f"✗ 错误: 无法解析十六进制:&nbsp;{e}")
return&nbsp;False

# 3. 检查长度是否为16的倍数
if&nbsp;len(ciphertext) %&nbsp;16&nbsp;!=&nbsp;0:
print(f"✗ 错误: 密文长度不是16的倍数")
return&nbsp;False

&nbsp; &nbsp; num_blocks =&nbsp;len(ciphertext) //&nbsp;16
print(f"\n密文分块数:&nbsp;{num_blocks}&nbsp;块 (每块 16 字节)")

# 4. 解密每个块
&nbsp; &nbsp; enc = PolyEnc()
&nbsp; &nbsp; plaintext_blocks = []

print("\n开始解密...")
for&nbsp;i&nbsp;in&nbsp;range(num_blocks):
&nbsp; &nbsp; &nbsp; &nbsp; block_start = i *&nbsp;16
&nbsp; &nbsp; &nbsp; &nbsp; block_end = block_start +&nbsp;16
&nbsp; &nbsp; &nbsp; &nbsp; block = ciphertext[block_start:block_end]

print(f"\n块&nbsp;{i+1}/{num_blocks}:")
print(f" &nbsp;密文:&nbsp;{block.hex().upper()}")

try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plaintext_block = enc.decrypt(block, verbose=False)
print(f" &nbsp;明文:&nbsp;{plaintext_block.hex().upper()}")

# 尝试解码为ASCII
try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ascii_text = plaintext_block.decode('ascii', errors='ignore')
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printable =&nbsp;''.join(c&nbsp;if&nbsp;c.isprintable()&nbsp;else&nbsp;'.'&nbsp;for&nbsp;c&nbsp;in&nbsp;ascii_text)
print(f" &nbsp;ASCII:&nbsp;{printable}")
except:
pass

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plaintext_blocks.append(plaintext_block)
except&nbsp;Exception&nbsp;as&nbsp;e:
print(f" &nbsp;✗ 解密失败:&nbsp;{e}")
return&nbsp;False

# 5. 合并所有块
&nbsp; &nbsp; plaintext =&nbsp;b''.join(plaintext_blocks)

print("\n"&nbsp;+&nbsp;"="*80)
print("解密结果")
print("="*80)
print(f"明文 (hex):&nbsp;{plaintext.hex().upper()}")
print(f"明文长度:&nbsp;{len(plaintext)}&nbsp;字节")

# 尝试解码为文本
print("\n尝试解码为文本:")
for&nbsp;encoding&nbsp;in&nbsp;['utf-8',&nbsp;'ascii',&nbsp;'latin-1']:
try:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text = plaintext.decode(encoding)
print(f" &nbsp;[{encoding}]&nbsp;{text}")
except:
print(f" &nbsp;[{encoding}] 解码失败")

# 6. 保存到文件
try:
with&nbsp;open(output_file,&nbsp;'wb')&nbsp;as&nbsp;f:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.write(plaintext)
print(f"\n✓ 明文已保存到:&nbsp;{output_file}")
except&nbsp;Exception&nbsp;as&nbsp;e:
print(f"\n✗ 保存文件失败:&nbsp;{e}")

return&nbsp;True

if&nbsp;__name__ ==&nbsp;"__main__":
import&nbsp;sys

# 检查命令行参数
if&nbsp;len(sys.argv) >&nbsp;1:
if&nbsp;sys.argv[1] ==&nbsp;'--separate-logs':
# 使用分离日志模式
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; test_with_separate_logs()
elif&nbsp;sys.argv[1] ==&nbsp;'--flag':
# 解密 flag.enc
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flag_file = sys.argv[2]&nbsp;if&nbsp;len(sys.argv) >&nbsp;2&nbsp;else&nbsp;'../flag.enc'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; decrypt_flag_file(flag_file)
elif&nbsp;sys.argv[1] ==&nbsp;'--help':
print("用法:")
print(" &nbsp;python polyenc_clean.py &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# 运行加密/解密测试")
print(" &nbsp;python polyenc_clean.py --separate-logs &nbsp;# 生成分离的日志文件")
print(" &nbsp;python polyenc_clean.py --flag [文件] &nbsp; &nbsp;# 解密 flag.enc (默认: ../flag.enc)")
print(" &nbsp;python polyenc_clean.py --help &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # 显示帮助")
else:
print(f"未知选项:&nbsp;{sys.argv[1]}")
print("使用 --help 查看帮助")
else:
# 运行加密测试
&nbsp; &nbsp; &nbsp; &nbsp; success = test_encrypt()

if&nbsp;success:
print("\n"&nbsp;+&nbsp;"="*80)
print("加密算法实现验证成功!")
print("="*80)

# 运行解密测试
print("\n")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; decrypt_success = test_decrypt(verbose=False)

if&nbsp;decrypt_success:
print("\n"&nbsp;+&nbsp;"="*80)
print("加密/解密功能验证完成!")
print("="*80)

# 提示可以解密 flag
print("\n提示:")
print(" &nbsp;- 使用 'python polyenc_clean.py --separate-logs' 生成分离的日志文件")
print(" &nbsp;- 使用 'python polyenc_clean.py --flag' 解密 flag.enc")
else:
print("\n提示: 使用 'python polyenc_clean.py --separate-logs' 生成分离的日志文件")

完整的题目附件以及脚本请见左下角【阅读原文】

#

看雪ID:SleepAlone

https://bbs.kanxue.com/user-home-950548.htm

*本文为看雪论坛优秀文章,由 SleepAlone 原创,转载请注明来自看雪社区

往期推荐

KernelSU检测之“时间侧信道攻击”

记录工作中解决bug用到的逆向知识

写一个简单的ollvm混淆还原

VmProtect.3.0.0beta分析之虚拟机流程

AI辅助逆向APP白盒AES分析

球分享

球点赞

球在看

点击阅读原文查看更多


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:看雪学苑 SleepAlone《强网杯2025-PolyEncryption之Vibe Reing的胜利》

评论:0   参与:  4