-
-
[原创] 强网杯2025-PolyEncryption之Vibe Reing的胜利
-
发表于: 2025-10-20 22:06 2752
-
c#层奇数轮(rr=1)
c#层奇数轮(rr!=1)
c#层偶数轮(rr=2,rr!=0)
rr=0
rr=1
偶数
最后共同的
saw.cs(main)
saw.py
saw.java
rr=0
rr=1
rr=2
rr=3
解密脚本,省略。下面有正确的。
Patch dll脚本
Patch saw.python 增加日志输出
Patch Hack.java 增加Hack中方法被调用的日志记录
Debug版本dockerfile
完整的题目附件以及脚本请见CTFWP/qwb2025/polyenc at main · Savagel0ve/CTFWP
#!/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-boxINV_SBOX = [0] * 256for i in range(256): INV_SBOX[SBOX[i]] = iINV_SBOX = tuple(INV_SBOX)# ============================================================================# AES 标准函数# ============================================================================def xtime(a): """AES xtime: GF(2^8) 乘 2""" return (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)def mix_column(col): """ AES MixColumns 标准实现 输入: [a0, a1, a2, a3] (4字节) 输出: [b0, b1, b2, b3] """ a0, a1, a2, a3 = col xor_all = a0 ^ a1 ^ a2 ^ a3 b0 = a0 ^ xor_all ^ xtime(a0 ^ a1) b1 = a1 ^ xor_all ^ xtime(a1 ^ a2) b2 = a2 ^ xor_all ^ xtime(a2 ^ a3) b3 = a3 ^ xor_all ^ xtime(a3 ^ a0) return [b0, b1, b2, b3]def apply_sbox_to_u32(value): """对32位整数应用S-box (小端序)""" bytes_le = struct.pack("<I", value) sboxed = bytes([SBOX[b] for b in bytes_le]) return struct.unpack("<I", sboxed)[0]def rol(value, shift): """32位循环左移""" value &= 0xFFFFFFFF return ((value << shift) | (value >> (32 - shift))) & 0xFFFFFFFFdef gf_mult(a, b): """GF(2^8) 乘法""" p = 0 for _ in range(8): if b & 1: p ^= a hi_bit_set = a & 0x80 a = (a << 1) & 0xFF if hi_bit_set: a ^= 0x1B b >>= 1 return pdef inv_mix_column(col): """ AES 逆 MixColumns 实现 输入: [b0, b1, b2, b3] (4字节) 输出: [a0, a1, a2, a3] 使用矩阵: [0x0E, 0x0B, 0x0D, 0x09] """ b0, b1, b2, b3 = col a0 = gf_mult(0x0E, b0) ^ gf_mult(0x0B, b1) ^ gf_mult(0x0D, b2) ^ gf_mult(0x09, b3) a1 = gf_mult(0x09, b0) ^ gf_mult(0x0E, b1) ^ gf_mult(0x0B, b2) ^ gf_mult(0x0D, b3) a2 = gf_mult(0x0D, b0) ^ gf_mult(0x09, b1) ^ gf_mult(0x0E, b2) ^ gf_mult(0x0B, b3) a3 = gf_mult(0x0B, b0) ^ gf_mult(0x0D, b1) ^ gf_mult(0x09, b2) ^ gf_mult(0x0E, b3) return [a0, a1, a2, a3]def apply_inv_sbox_to_u32(value): """对32位整数应用逆S-box (小端序)""" bytes_le = struct.pack("<I", value) inv_sboxed = bytes([INV_SBOX[b] for b in bytes_le]) return struct.unpack("<I", inv_sboxed)[0]# ============================================================================# PolyEnc 加密器# ============================================================================class PolyEnc: def __init__(self): """初始化加密器""" # 轮密钥 (10个,对应 Round 2, 4, 6, 8, 10, 12, 14, 16, 18, 20) self.round_keys = [ 3207972492, 1190065579, 4165979424, 2693353696, 3628337899, 1707638109, 1003779598, 2653425729, 795752593, 2469382657, 0 ] # 初始密钥状态 self.initial_key = [ 2427014626, # s[1] - 初始魔数 1166827919, # s[2] - 初始魔数 1240047111, # s[3] - 初始魔数 1038097261 # s[4] - 初始魔数 ] def encrypt(self, plaintext_bytes, verbose=False): """ 加密16字节明文 算法流程: - Round 0: 初始化 - Round 1-21: 奇数轮(SubBytes+MixColumns) + 偶数轮(AddRoundKey) - Round 22: 输出 """ if len(plaintext_bytes) != 16: raise ValueError("Input must be 16 bytes") # 将明文转为4个32位整数 (大端序) state = list(struct.unpack('>4I', plaintext_bytes)) # 复制初始密钥 key = self.initial_key.copy() # 轮密钥索引 key_index = 0 if verbose: print(f"【初始状态】") print(f" state = {[hex(s) for s in state]}") print(f" key = {[hex(k) for k in 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 rr in range(1, 23): if rr % 2 == 1: # 奇数轮: SubBytes + MixColumns state = self._odd_round(state, key, rr, verbose) else: # 偶数轮: ShiftRows + AddRoundKey state, key, key_index = self._even_round(state, key, key_index, rr, verbose) final_state = state # 返回密文 (大端序) return struct.pack('>4I', *final_state) def _odd_round(self, state, key, rr, verbose): """ 奇数轮: SubBytes + MixColumns 返回: 16 字节数组 (4x4 矩阵,按行存储) 同时更新密钥状态 s[2], s[3], s[4]: - s[2] = B ^ A' - s[3] = C ^ B ^ A' - s[4] = D ^ C ^ B ^ A' """ if verbose: print(f"\n【Round {rr}】奇数轮 - SubBytes + MixColumns") print(f" 输入 state = {[hex(s) for s in state]}") print(f" 输入 key = {[hex(k) for k in key]}") # 1. 密钥更新 (奇数轮) if rr == 1: # Round 1: 密钥保持初始值,不变 pass else: # Round 3, 5, 7, ..., 21: 更新 s[2], s[3], s[4] A_prime = key[0] # 上一个偶数轮更新后的 s[1] B = key[1] C = key[2] D = key[3] # 密钥级联更新 key[1] = (B ^ A_prime) & 0xFFFFFFFF # s[2] = B ^ A' key[2] = (C ^ B ^ A_prime) & 0xFFFFFFFF # s[3] = C ^ B ^ A' key[3] = (D ^ C ^ B ^ A_prime) & 0xFFFFFFFF # s[4] = D ^ C ^ B ^ A' if verbose: print(f" 密钥更新:") print(f" A' = {hex(A_prime)}") print(f" s[2] = B ^ A' = {hex(key[1])}") print(f" s[3] = C ^ B ^ A' = {hex(key[2])}") print(f" s[4] = D ^ C ^ B ^ A' = {hex(key[3])}") # 2. SubBytes: 对 state 的每个32位整数应用S-box sboxed = [apply_sbox_to_u32(s) for s in state] if verbose: print(f" SubBytes = {[hex(s) for s in sboxed]}") # 3. MixColumns: 对每个 32位整数拆分成 4字节,MixColumns 后得到 16字节 # 结果按倒序排列(从 Docker 日志观察到) mixed_bytes = [] for val in sboxed: # 倒序处理 # 拆分成4字节 (大端序) bytes_be = struct.unpack('4B', struct.pack('>I', val)) # MixColumns mixed_col = mix_column(list(bytes_be)) mixed_bytes.extend(mixed_col) if verbose: print(f" MixColumns 16字节: {[hex(b) for b in mixed_bytes]}") # 显示为 4x4 矩阵 print(f" MixColumns 4x4矩阵 (按列):") for row in range(4): print(f" row{row}: {[hex(mixed_bytes[col*4 + row]) for col in range(4)]}") return mixed_bytes def _even_round(self, state_bytes, key, key_index, rr, verbose): """ 偶数轮: ShiftRows + 字节打包 + AddRoundKey 输入: 16 字节数组 (从奇数轮的 MixColumns 输出) 输出: 4 个 32位整数 1. ShiftRows: 对 4x4 矩阵按对角线重排 2. 字节打包: 每 4 字节打包成一个 32位整数 3. AddRoundKey: state ^= key 4. 密钥更新: s[1] = A ^ sbox(rol(D, 8)) ^ round_key[i] """ if verbose: print(f"\n【Round {rr}】偶数轮 - ShiftRows + AddRoundKey") print(f" 输入 16字节: {[hex(b) for b in state_bytes]}") print(f" 输入 key = {[hex(k) for k in 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], ... row_based = [] for row in range(4): for col in range(4): row_based.append(state_bytes[col * 4 + row]) # ShiftRows 索引(倒序,因为 state 要倒序) shiftrows_indices = [ [3, 4, 9, 14], # col3 (倒序第0个) [2, 7, 8, 13], # col2 (倒序第1个) [1, 6, 11, 12], # col1 (倒序第2个) [0, 5, 10, 15] # col0 (倒序第3个) ] shifted_state = [] for indices in shiftrows_indices: # 从 row_based 按索引取4个字节,打包成32位整数 val = (row_based[indices[0]] << 24) | (row_based[indices[1]] << 16) | \ (row_based[indices[2]] << 8) | row_based[indices[3]] shifted_state.append(val) if verbose: print(f" ShiftRows + 打包:") for col in range(4): idx0 = 0*4 + col idx1 = 1*4 + ((col + 1) % 4) idx2 = 2*4 + ((col + 2) % 4) idx3 = 3*4 + ((col + 3) % 4) print(f" state[{col}] = [{hex(state_bytes[idx0])}, {hex(state_bytes[idx1])}, " f"{hex(state_bytes[idx2])}, {hex(state_bytes[idx3])}] = {hex(shifted_state[col])}") # 2. AddRoundKey: state ^= key shifted_state = shifted_state[::-1] new_state = [(shifted_state[i] ^ key[i]) & 0xFFFFFFFF for i in range(4)] if verbose: print(f" AddRoundKey (state ^= key):") for i in range(4): print(f" state[{i}] = {hex(shifted_state[i])} ^ {hex(key[i])} = {hex(new_state[i])}") # 3. 密钥更新: s[1] = A ^ sbox(rol(D, 8)) ^ round_key[i] A = key[0] D = key[3] # rol(D, 8) - 循环左移8位 rotated = rol(D, 8) # sbox(rotated) sboxed = apply_sbox_to_u32(rotated) # A' = A ^ sboxed ^ round_key[i] round_key = self.round_keys[key_index] A_prime = (A ^ sboxed ^ round_key) & 0xFFFFFFFF key[0] = A_prime key_index += 1 if verbose: print(f" 密钥更新:") print(f" rol(s[4], 8) = {hex(rotated)}") print(f" sbox(rotated) = {hex(sboxed)}") print(f" round_key[{key_index-1}] = {hex(round_key)}") print(f" s[1] = {hex(A)} ^ {hex(sboxed)} ^ {hex(round_key)} = {hex(A_prime)}") return new_state, key, key_index def decrypt(self, ciphertext_bytes, verbose=False): """ 解密16字节密文 算法流程: 1. 先正向生成所有轮的密钥状态 2. 从 Round 22 逆向到 Round 1 """ if len(ciphertext_bytes) != 16: raise ValueError("Input must be 16 bytes") # 1. 正向生成所有轮密钥状态 if verbose: print(f"\n【生成轮密钥】") key_states = self._generate_all_round_keys() if verbose: print(f"生成了 {len(key_states)} 组轮密钥") for rr in sorted(key_states.keys())[:5]: # 只显示前5个 print(f" Round {rr}: {[hex(k) for k in key_states[rr]]}") print(f" ...") # 2. 将密文转为4个32位整数 (大端序) state = list(struct.unpack('>4I', ciphertext_bytes)) if verbose: print(f"\n【解密开始】") print(f" 密文 (bytes): {ciphertext_bytes.hex().upper()}") print(f" 密文 (u32): {[hex(s) for s in state]}") # 3. 逆向执行 Round 22 到 Round 1 for rr in range(22, 0, -1): if rr % 2 == 0: # 偶数轮: 逆AddRoundKey + 逆ShiftRows state = self._inv_even_round(state, key_states[rr], rr, verbose) else: # 奇数轮: 逆MixColumns + 逆SubBytes state = self._inv_odd_round(state, key_states[rr], rr, verbose) if verbose: print(f"\n【解密结束】") print(f" 明文 (u32): {[hex(s) for s in state]}") # 4. 返回明文 (大端序) plaintext = struct.pack('>4I', *state) if verbose: print(f" 明文 (bytes): {plaintext.hex().upper()}") return plaintext def _generate_all_round_keys(self): """ 正向生成所有轮的密钥状态 返回: 字典 {round_number: key_state} """ key = self.initial_key.copy() key_index = 0 key_states = {0: key.copy()} # 模拟加密过程中的密钥更新 for rr in range(1, 23): if rr % 2 == 1: # 奇数轮 if rr > 1: # Round 3, 5, 7, ..., 21: 更新 s[2], s[3], s[4] A_prime = key[0] B = key[1] C = key[2] D = key[3] key[1] = (B ^ A_prime) & 0xFFFFFFFF key[2] = (C ^ B ^ A_prime) & 0xFFFFFFFF key[3] = (D ^ C ^ B ^ A_prime) & 0xFFFFFFFF key_states[rr] = key.copy() else: # 偶数轮 key_states[rr] = key.copy() # 更新 s[1] A = key[0] D = key[3] rotated = rol(D, 8) sboxed = apply_sbox_to_u32(rotated) round_key = self.round_keys[key_index] A_prime = (A ^ sboxed ^ round_key) & 0xFFFFFFFF key[0] = A_prime key_index += 1 return key_states def _inv_odd_round(self, state_bytes, key, rr, verbose): """ 逆奇数轮: 逆MixColumns + 逆SubBytes 输入: 16 字节数组 输出: 4 个 32位整数 """ if verbose: print(f"\n【Round {rr} 逆向】奇数轮 - InvMixColumns + InvSubBytes") print(f" 输入 state (16字节): {[hex(b) for b in state_bytes]}") print(f" 输入 key = {[hex(k) for k in key]}") # 显示为 4x4 矩阵 print(f" 输入 4x4矩阵 (按列):") for row in range(4): print(f" row{row}: {[hex(state_bytes[col*4 + row]) for col in range(4)]}") # 1. 逆MixColumns: 对每个32位整数拆分成4字节,逆MixColumns后得到16字节 inv_mixed_bytes = [] for i in range(4): # 提取4个字节(按列存储) col_bytes = state_bytes[i*4:(i+1)*4] # 逆MixColumns inv_mixed_col = inv_mix_column(list(col_bytes)) inv_mixed_bytes.extend(inv_mixed_col) if verbose: print(f" InvMixColumns 16字节: {[hex(b) for b in inv_mixed_bytes]}") # 显示为 4x4 矩阵 print(f" InvMixColumns 4x4矩阵 (按列):") for row in range(4): print(f" row{row}: {[hex(inv_mixed_bytes[col*4 + row]) for col in range(4)]}") # 2. 重新打包成4个32位整数(大端序) sboxed = [] for i in range(4): bytes_4 = inv_mixed_bytes[i*4:(i+1)*4] val = struct.unpack('>I', bytes(bytes_4))[0] sboxed.append(val) if verbose: print(f" 打包成u32 (应用InvSubBytes之前): {[hex(s) for s in sboxed]}") # 3. 逆SubBytes: 对每个32位整数应用逆S-box state = [apply_inv_sbox_to_u32(s) for s in sboxed] if verbose: print(f" InvSubBytes (输出state) = {[hex(s) for s in state]}") return state def _inv_even_round(self, state, key, rr, verbose): """ 逆偶数轮: 逆AddRoundKey + 逆ShiftRows 输入: 4 个 32位整数 输出: 16 字节数组 """ if verbose: print(f"\n【Round {rr} 逆向】偶数轮 - InvAddRoundKey + InvShiftRows") print(f" 输入 state = {[hex(s) for s in state]}") print(f" 使用 key = {[hex(k) for k in key]}") # 1. 逆AddRoundKey: state ^= key (XOR是自逆的) unkeyed_state = [(state[i] ^ key[i]) & 0xFFFFFFFF for i in range(4)] if verbose: print(f" InvAddRoundKey (state ^= key):") for i in range(4): print(f" state[{i}] = {hex(state[i])} ^ {hex(key[i])} = {hex(unkeyed_state[i])}") # 将4个32位整数拆分成16字节 # 按加密时的打包方式逆向 inv_shiftrows_indices = [ [0, 5, 10, 15], # col0 (对应倒序第3个) [1, 6, 11, 12], # col1 (对应倒序第2个) [2, 7, 8, 13], # col2 (对应倒序第1个) [3, 4, 9, 14] # col3 (对应倒序第0个) ] # 先将4个u32解包成按行存储的16字节 row_based = [] for val in unkeyed_state: row_based.append((val >> 24) & 0xFF) row_based.append((val >> 16) & 0xFF) row_based.append((val >> 8) & 0xFF) row_based.append(val & 0xFF) if verbose: print(f" 解包成16字节(按行): {[hex(b) for b in row_based]}") # 创建逆映射 unshifted_row_based = [0] * 16 for col_idx, indices in enumerate(inv_shiftrows_indices): for byte_idx, src_idx in enumerate(indices): unshifted_row_based[src_idx] = row_based[col_idx * 4 + byte_idx] if verbose: print(f" InvShiftRows后(按行): {[hex(b) for b in unshifted_row_based]}") # 转换回按列存储 state_bytes = [] for col in range(4): for row in range(4): state_bytes.append(unshifted_row_based[row * 4 + col]) if verbose: print(f" 输出 16字节(按列): {[hex(b) for b in state_bytes]}") # 显示为 4x4 矩阵 print(f" 输出 4x4矩阵 (按列):") for row in range(4): print(f" row{row}: {[hex(state_bytes[col*4 + row]) for col in range(4)]}") return state_bytes# ============================================================================# 测试和验证# ============================================================================def test_encrypt(): """测试加密功能""" print("="*80) print("PolyEnc 加密测试") print("="*80) # Docker 环境:run.sh 传入 "abe74e3a9c375b3428bf31d1f8fa49c1" # dotnet 程序将其解析为十六进制并按 32位整数倒序排列 plaintext_hex = "abe74e3a9c375b3428bf31d1f8fa49c1" # 解析成 4 个 32位整数(每8个字符一组) chunks = [plaintext_hex[i:i+8] for i in range(0, len(plaintext_hex), 8)] print(f"\n解析输入字符串: {plaintext_hex}") print(f" 分组: {chunks}") # dotnet 按倒序处理(从 Docker 日志观察到) chunks_reversed = chunks print(f" 倒序: {chunks_reversed}") # 转换为字节序列(小端序) plaintext_bytes = b''.join([bytes.fromhex(c) for c in chunks_reversed]) print(f" 字节序列 (hex): {plaintext_bytes.hex().upper()}") # 重新组装为大端序的 4 个整数(匹配 polyenc 输入格式) plaintext = bytes.fromhex(''.join(chunks_reversed)) print(f"\n最终明文 (hex): {plaintext.hex().upper()}") print(f"最终明文 (u32 大端): {[hex(x) for x in struct.unpack('>4I', plaintext)]}") # 加密 enc = PolyEnc() ciphertext = enc.encrypt(plaintext, verbose=True) print(f"\n密文: {ciphertext.hex().upper()}") return Truedef test_verbose(): """详细输出测试""" print("\n" + "="*80) print("详细加密流程(前4轮)") print("="*80) plaintext = bytes.fromhex("abe74e3a9c375b3428bf31d1f8fa49c1") enc = PolyEnc() # 修改加密函数以支持部分轮次 state = list(struct.unpack('>4I', plaintext)) key = enc.initial_key.copy() key_index = 0 print(f"\n明文: {plaintext.hex().upper()}") print(f"初始 state = {[hex(s) for s in state]}") print(f"初始 key = {[hex(k) for k in key]}") # Round 1-4 for rr in range(1, 5): if rr % 2 == 1: state = enc._odd_round(state, key, rr, verbose=True) else: state, key, key_index = enc._even_round(state, key, key_index, rr, verbose=True)def test_decrypt(verbose=True): """测试加密和解密功能""" print("="*80) print("PolyEnc 加密/解密测试") print("="*80) plaintext_hex = "abe74e3a9c375b3428bf31d1f8fa49c1" plaintext = bytes.fromhex(plaintext_hex) print(f"\n明文 (hex): {plaintext.hex().upper()}") # 加密 enc = PolyEnc() ciphertext = enc.encrypt(plaintext, verbose=False) print(f"密文 (hex): {ciphertext.hex().upper()}") print("\n" + "="*80) print("开始解密...") print("="*80) # 解密 decrypted = enc.decrypt(ciphertext, verbose=verbose) print("\n" + "="*80) print("解密完成") print("="*80) print(f"解密后 (hex): {decrypted.hex().upper()}") # 验证 if plaintext == decrypted: print("\n✓ 解密成功!明文与解密结果一致") return True else: print("\n✗ 解密失败!明文与解密结果不一致") print(f" 期望: {plaintext.hex().upper()}") print(f" 实际: {decrypted.hex().upper()}") return Falsedef test_with_separate_logs(): """将加密和解密日志分别输出到不同文件""" import sys plaintext_hex = "abe74e3a9c375b3428bf31d1f8fa49c1" plaintext = bytes.fromhex(plaintext_hex) print("="*80) print("PolyEnc 加密/解密测试 (分离日志)") print("="*80) print(f"明文: {plaintext.hex().upper()}") # 1. 加密并输出到文件 print("\n正在生成加密日志...") with open('encrypt_log.txt', 'w', encoding='utf-8') as f: old_stdout = sys.stdout sys.stdout = f enc = PolyEnc() ciphertext = enc.encrypt(plaintext, verbose=True) sys.stdout = old_stdout print(f"✓ 加密日志已保存到: encrypt_log.txt") print(f" 密文: {ciphertext.hex().upper()}") # 2. 解密并输出到文件 print("\n正在生成解密日志...") with open('decrypt_log.txt', 'w', encoding='utf-8') as f: old_stdout = sys.stdout sys.stdout = f decrypted = enc.decrypt(ciphertext, verbose=True) sys.stdout = old_stdout print(f"✓ 解密日志已保存到: decrypt_log.txt") print(f" 解密结果: {decrypted.hex().upper()}") # 3. 验证 print("\n" + "="*80) if plaintext == decrypted: print("✓ 解密成功!明文与解密结果一致") return True else: print("✗ 解密失败!明文与解密结果不一致") print(f" 期望: {plaintext.hex().upper()}") print(f" 实际: {decrypted.hex().upper()}") return Falsedef decrypt_flag_file(flag_file='../flag.enc', output_file='flag.txt'): """解密 flag.enc 文件""" print("="*80) print("解密 FLAG 文件") print("="*80) # 1. 读取加密文件 try: with open(flag_file, 'r') as f: ciphertext_hex = f.read().strip() except FileNotFoundError: print(f"✗ 错误: 找不到文件 {flag_file}") return False print(f"读取文件: {flag_file}") print(f"密文 (hex): {ciphertext_hex}") print(f"密文长度: {len(ciphertext_hex)} 字符 ({len(ciphertext_hex)//2} 字节)") # 2. 解析十六进制 try: ciphertext = bytes.fromhex(ciphertext_hex) except ValueError as e: print(f"✗ 错误: 无法解析十六进制: {e}") return False # 3. 检查长度是否为16的倍数 if len(ciphertext) % 16 != 0: print(f"✗ 错误: 密文长度不是16的倍数") return False num_blocks = len(ciphertext) // 16 print(f"\n密文分块数: {num_blocks} 块 (每块 16 字节)") # 4. 解密每个块 enc = PolyEnc() plaintext_blocks = [] print("\n开始解密...") for i in range(num_blocks): block_start = i * 16 block_end = block_start + 16 block = ciphertext[block_start:block_end] print(f"\n块 {i+1}/{num_blocks}:") print(f" 密文: {block.hex().upper()}") try: plaintext_block = enc.decrypt(block, verbose=False) print(f" 明文: {plaintext_block.hex().upper()}") # 尝试解码为ASCII try: ascii_text = plaintext_block.decode('ascii', errors='ignore') printable = ''.join(c if c.isprintable() else '.' for c in ascii_text) print(f" ASCII: {printable}") except: pass plaintext_blocks.append(plaintext_block) except Exception as e: print(f" ✗ 解密失败: {e}") return False # 5. 合并所有块 plaintext = b''.join(plaintext_blocks) print("\n" + "="*80) print("解密结果") print("="*80) print(f"明文 (hex): {plaintext.hex().upper()}") print(f"明文长度: {len(plaintext)} 字节") # 尝试解码为文本 print("\n尝试解码为文本:") for encoding in ['utf-8', 'ascii', 'latin-1']: try: text = plaintext.decode(encoding) print(f" [{encoding}] {text}") except: print(f" [{encoding}] 解码失败") # 6. 保存到文件 try: with open(output_file, 'wb') as f: f.write(plaintext) print(f"\n✓ 明文已保存到: {output_file}") except Exception as e: print(f"\n✗ 保存文件失败: {e}") return Trueif __name__ == "__main__": import sys # 检查命令行参数 if len(sys.argv) > 1: if sys.argv[1] == '--separate-logs': # 使用分离日志模式 test_with_separate_logs() elif sys.argv[1] == '--flag': # 解密 flag.enc flag_file = sys.argv[2] if len(sys.argv) > 2 else '../flag.enc' decrypt_flag_file(flag_file) elif sys.argv[1] == '--help': print("用法:") print(" python polyenc_clean.py # 运行加密/解密测试") print(" python polyenc_clean.py --separate-logs # 生成分离的日志文件") print(" python polyenc_clean.py --flag [文件] # 解密 flag.enc (默认: ../flag.enc)") print(" python polyenc_clean.py --help # 显示帮助") else: print(f"未知选项: {sys.argv[1]}") print("使用 --help 查看帮助") else: # 运行加密测试 success = test_encrypt() if success: print("\n" + "="*80) print("加密算法实现验证成功!") print("="*80) # 运行解密测试 print("\n") decrypt_success = test_decrypt(verbose=False) if decrypt_success: print("\n" + "="*80) print("加密/解密功能验证完成!") print("="*80) # 提示可以解密 flag print("\n提示:") print(" - 使用 'python polyenc_clean.py --separate-logs' 生成分离的日志文件") print(" - 使用 'python polyenc_clean.py --flag' 解密 flag.enc") else: print("\n提示: 使用 'python polyenc_clean.py --separate-logs' 生成分离的日志文件")#!/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-boxINV_SBOX = [0] * 256for i in range(256): INV_SBOX[SBOX[i]] = iINV_SBOX = tuple(INV_SBOX)# ============================================================================# AES 标准函数# ============================================================================def xtime(a): """AES xtime: GF(2^8) 乘 2""" return (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)def mix_column(col): """ AES MixColumns 标准实现 输入: [a0, a1, a2, a3] (4字节) 输出: [b0, b1, b2, b3] """ a0, a1, a2, a3 = col xor_all = a0 ^ a1 ^ a2 ^ a3 b0 = a0 ^ xor_all ^ xtime(a0 ^ a1) b1 = a1 ^ xor_all ^ xtime(a1 ^ a2) b2 = a2 ^ xor_all ^ xtime(a2 ^ a3) b3 = a3 ^ xor_all ^ xtime(a3 ^ a0) return [b0, b1, b2, b3]def apply_sbox_to_u32(value): """对32位整数应用S-box (小端序)""" bytes_le = struct.pack("<I", value) sboxed = bytes([SBOX[b] for b in bytes_le]) return struct.unpack("<I", sboxed)[0]def rol(value, shift): """32位循环左移""" value &= 0xFFFFFFFF return ((value << shift) | (value >> (32 - shift))) & 0xFFFFFFFFdef gf_mult(a, b): """GF(2^8) 乘法""" p = 0 for _ in range(8): if b & 1: p ^= a hi_bit_set = a & 0x80 a = (a << 1) & 0xFF if hi_bit_set: a ^= 0x1B b >>= 1 return pdef inv_mix_column(col): """ AES 逆 MixColumns 实现 输入: [b0, b1, b2, b3] (4字节) 输出: [a0, a1, a2, a3] 使用矩阵: [0x0E, 0x0B, 0x0D, 0x09] """ b0, b1, b2, b3 = col a0 = gf_mult(0x0E, b0) ^ gf_mult(0x0B, b1) ^ gf_mult(0x0D, b2) ^ gf_mult(0x09, b3) a1 = gf_mult(0x09, b0) ^ gf_mult(0x0E, b1) ^ gf_mult(0x0B, b2) ^ gf_mult(0x0D, b3) a2 = gf_mult(0x0D, b0) ^ gf_mult(0x09, b1) ^ gf_mult(0x0E, b2) ^ gf_mult(0x0B, b3) a3 = gf_mult(0x0B, b0) ^ gf_mult(0x0D, b1) ^ gf_mult(0x09, b2) ^ gf_mult(0x0E, b3) return [a0, a1, a2, a3]def apply_inv_sbox_to_u32(value): """对32位整数应用逆S-box (小端序)""" bytes_le = struct.pack("<I", value) inv_sboxed = bytes([INV_SBOX[b] for b in bytes_le]) return struct.unpack("<I", inv_sboxed)[0]# ============================================================================# PolyEnc 加密器# ============================================================================class PolyEnc: def __init__(self): """初始化加密器""" # 轮密钥 (10个,对应 Round 2, 4, 6, 8, 10, 12, 14, 16, 18, 20) self.round_keys = [ 3207972492, 1190065579, 4165979424, 2693353696, 3628337899, 1707638109, 1003779598, 2653425729, 795752593, 2469382657, 0 ] # 初始密钥状态 self.initial_key = [ 2427014626, # s[1] - 初始魔数 1166827919, # s[2] - 初始魔数 1240047111, # s[3] - 初始魔数 1038097261 # s[4] - 初始魔数 ] def encrypt(self, plaintext_bytes, verbose=False): """ 加密16字节明文 算法流程: - Round 0: 初始化 - Round 1-21: 奇数轮(SubBytes+MixColumns) + 偶数轮(AddRoundKey) - Round 22: 输出 """ if len(plaintext_bytes) != 16: raise ValueError("Input must be 16 bytes") # 将明文转为4个32位整数 (大端序) state = list(struct.unpack('>4I', plaintext_bytes)) # 复制初始密钥 key = self.initial_key.copy() # 轮密钥索引 key_index = 0 if verbose: print(f"【初始状态】") print(f" state = {[hex(s) for s in state]}") print(f" key = {[hex(k) for k in 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 rr in range(1, 23): if rr % 2 == 1: # 奇数轮: SubBytes + MixColumns state = self._odd_round(state, key, rr, verbose) else: # 偶数轮: ShiftRows + AddRoundKey state, key, key_index = self._even_round(state, key, key_index, rr, verbose) final_state = state # 返回密文 (大端序) return struct.pack('>4I', *final_state) def _odd_round(self, state, key, rr, verbose): """ 奇数轮: SubBytes + MixColumns 返回: 16 字节数组 (4x4 矩阵,按行存储) 同时更新密钥状态 s[2], s[3], s[4]: - s[2] = B ^ A' - s[3] = C ^ B ^ A' - s[4] = D ^ C ^ B ^ A' """ if verbose: print(f"\n【Round {rr}】奇数轮 - SubBytes + MixColumns") print(f" 输入 state = {[hex(s) for s in state]}") print(f" 输入 key = {[hex(k) for k in key]}") # 1. 密钥更新 (奇数轮) if rr == 1: # Round 1: 密钥保持初始值,不变 pass else: # Round 3, 5, 7, ..., 21: 更新 s[2], s[3], s[4] A_prime = key[0] # 上一个偶数轮更新后的 s[1] B = key[1] C = key[2] D = key[3] # 密钥级联更新 key[1] = (B ^ A_prime) & 0xFFFFFFFF # s[2] = B ^ A' key[2] = (C ^ B ^ A_prime) & 0xFFFFFFFF # s[3] = C ^ B ^ A' key[3] = (D ^ C ^ B ^ A_prime) & 0xFFFFFFFF # s[4] = D ^ C ^ B ^ A' if verbose: print(f" 密钥更新:") print(f" A' = {hex(A_prime)}") print(f" s[2] = B ^ A' = {hex(key[1])}") print(f" s[3] = C ^ B ^ A' = {hex(key[2])}") print(f" s[4] = D ^ C ^ B ^ A' = {hex(key[3])}") # 2. SubBytes: 对 state 的每个32位整数应用S-box sboxed = [apply_sbox_to_u32(s) for s in state] if verbose: print(f" SubBytes = {[hex(s) for s in sboxed]}") # 3. MixColumns: 对每个 32位整数拆分成 4字节,MixColumns 后得到 16字节 # 结果按倒序排列(从 Docker 日志观察到) mixed_bytes = [] for val in sboxed: # 倒序处理 # 拆分成4字节 (大端序) bytes_be = struct.unpack('4B', struct.pack('>I', val)) # MixColumns mixed_col = mix_column(list(bytes_be)) mixed_bytes.extend(mixed_col) if verbose: print(f" MixColumns 16字节: {[hex(b) for b in mixed_bytes]}") # 显示为 4x4 矩阵 print(f" MixColumns 4x4矩阵 (按列):") for row in range(4): print(f" row{row}: {[hex(mixed_bytes[col*4 + row]) for col in range(4)]}") return mixed_bytes def _even_round(self, state_bytes, key, key_index, rr, verbose): """ 偶数轮: ShiftRows + 字节打包 + AddRoundKey 输入: 16 字节数组 (从奇数轮的 MixColumns 输出) 输出: 4 个 32位整数 1. ShiftRows: 对 4x4 矩阵按对角线重排 2. 字节打包: 每 4 字节打包成一个 32位整数 3. AddRoundKey: state ^= key 4. 密钥更新: s[1] = A ^ sbox(rol(D, 8)) ^ round_key[i] """ if verbose: print(f"\n【Round {rr}】偶数轮 - ShiftRows + AddRoundKey") print(f" 输入 16字节: {[hex(b) for b in state_bytes]}") print(f" 输入 key = {[hex(k) for k in 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], ... row_based = [] for row in range(4): for col in range(4): row_based.append(state_bytes[col * 4 + row]) # ShiftRows 索引(倒序,因为 state 要倒序) shiftrows_indices = [ [3, 4, 9, 14], # col3 (倒序第0个) [2, 7, 8, 13], # col2 (倒序第1个) [1, 6, 11, 12], # col1 (倒序第2个) [0, 5, 10, 15] # col0 (倒序第3个) ] shifted_state = [] for indices in shiftrows_indices: # 从 row_based 按索引取4个字节,打包成32位整数 val = (row_based[indices[0]] << 24) | (row_based[indices[1]] << 16) | \ (row_based[indices[2]] << 8) | row_based[indices[3]] shifted_state.append(val) if verbose: print(f" ShiftRows + 打包:") for col in range(4): idx0 = 0*4 + col idx1 = 1*4 + ((col + 1) % 4) idx2 = 2*4 + ((col + 2) % 4) idx3 = 3*4 + ((col + 3) % 4) print(f" state[{col}] = [{hex(state_bytes[idx0])}, {hex(state_bytes[idx1])}, " f"{hex(state_bytes[idx2])}, {hex(state_bytes[idx3])}] = {hex(shifted_state[col])}") # 2. AddRoundKey: state ^= key shifted_state = shifted_state[::-1] new_state = [(shifted_state[i] ^ key[i]) & 0xFFFFFFFF for i in range(4)] if verbose: print(f" AddRoundKey (state ^= key):") for i in range(4): print(f" state[{i}] = {hex(shifted_state[i])} ^ {hex(key[i])} = {hex(new_state[i])}") # 3. 密钥更新: s[1] = A ^ sbox(rol(D, 8)) ^ round_key[i] A = key[0] D = key[3] # rol(D, 8) - 循环左移8位 rotated = rol(D, 8) # sbox(rotated) sboxed = apply_sbox_to_u32(rotated) # A' = A ^ sboxed ^ round_key[i] round_key = self.round_keys[key_index] A_prime = (A ^ sboxed ^ round_key) & 0xFFFFFFFF key[0] = A_prime key_index += 1 if verbose: print(f" 密钥更新:") print(f" rol(s[4], 8) = {hex(rotated)}") print(f" sbox(rotated) = {hex(sboxed)}") print(f" round_key[{key_index-1}] = {hex(round_key)}") print(f" s[1] = {hex(A)} ^ {hex(sboxed)} ^ {hex(round_key)} = {hex(A_prime)}") return new_state, key, key_index def decrypt(self, ciphertext_bytes, verbose=False): """ 解密16字节密文 算法流程: 1. 先正向生成所有轮的密钥状态 2. 从 Round 22 逆向到 Round 1 """ if len(ciphertext_bytes) != 16: raise ValueError("Input must be 16 bytes") # 1. 正向生成所有轮密钥状态 if verbose: print(f"\n【生成轮密钥】") key_states = self._generate_all_round_keys() if verbose: print(f"生成了 {len(key_states)} 组轮密钥") for rr in sorted(key_states.keys())[:5]: # 只显示前5个 print(f" Round {rr}: {[hex(k) for k in key_states[rr]]}") print(f" ...") # 2. 将密文转为4个32位整数 (大端序) state = list(struct.unpack('>4I', ciphertext_bytes)) if verbose: print(f"\n【解密开始】") print(f" 密文 (bytes): {ciphertext_bytes.hex().upper()}") print(f" 密文 (u32): {[hex(s) for s in state]}") # 3. 逆向执行 Round 22 到 Round 1 for rr in range(22, 0, -1): if rr % 2 == 0: # 偶数轮: 逆AddRoundKey + 逆ShiftRows state = self._inv_even_round(state, key_states[rr], rr, verbose) else: # 奇数轮: 逆MixColumns + 逆SubBytes state = self._inv_odd_round(state, key_states[rr], rr, verbose) if verbose: print(f"\n【解密结束】") print(f" 明文 (u32): {[hex(s) for s in state]}") # 4. 返回明文 (大端序) plaintext = struct.pack('>4I', *state) if verbose: print(f" 明文 (bytes): {plaintext.hex().upper()}") return plaintext def _generate_all_round_keys(self): """ 正向生成所有轮的密钥状态 返回: 字典 {round_number: key_state} """ key = self.initial_key.copy() key_index = 0 key_states = {0: key.copy()} # 模拟加密过程中的密钥更新 for rr in range(1, 23): if rr % 2 == 1: # 奇数轮 if rr > 1: # Round 3, 5, 7, ..., 21: 更新 s[2], s[3], s[4] A_prime = key[0] B = key[1] C = key[2] D = key[3] key[1] = (B ^ A_prime) & 0xFFFFFFFF key[2] = (C ^ B ^ A_prime) & 0xFFFFFFFF key[3] = (D ^ C ^ B ^ A_prime) & 0xFFFFFFFF key_states[rr] = key.copy() else: # 偶数轮 key_states[rr] = key.copy() # 更新 s[1] A = key[0][培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-10-21 09:48
被SleepAlone编辑
,原因:
赞赏
他的文章
赞赏
雪币:
留言: