首页
社区
课程
招聘
[原创] 强网杯2025-PolyEncryption之Vibe Reing的胜利
发表于: 2025-10-20 22:06 2752

[原创] 强网杯2025-PolyEncryption之Vibe Reing的胜利

2025-10-20 22:06
2752

c#层奇数轮(rr=1)

5afK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6X3y4K6K9r3q4J5M7q4)9#2k6X3y4J5j5h3y4C8i4K6g2X3j5$3q4D9L8s2y4Q4x3X3g2H3P5b7`.`.

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

7b7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6X3y4K6K9r3q4J5M7q4)9#2k6X3y4J5j5h3y4C8i4K6g2X3L8$3c8V1i4K6g2X3L8X3!0F1L8$3&6W2i4K6u0W2M7s2V1`.

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

7f3K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6X3y4K6K9r3q4J5M7q4)9#2k6X3y4J5j5h3y4C8i4K6g2X3k6i4k6W2L8W2)9#2k6X3&6G2L8Y4A6W2M7X3!0Q4x3X3g2H3P5b7`.`.

fa0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6X3q4D9L8q4)9#2k6X3S2G2M7Y4u0G2M7W2)9#2k6X3y4G2L8h3#2S2L8X3c8K6i4K6u0W2M7s2V1`.

rr=0

1dbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6Y4u0G2N6h3&6V1x3q4)9#2k6X3q4D9L8q4)9#2k6Y4m8S2N6r3y4Z5k6i4y4Q4x3X3g2H3P5b7`.`.

rr=1

91bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6Y4u0G2N6h3&6V1x3g2)9#2k6X3q4D9L8q4)9#2k6Y4m8S2N6r3y4Z5k6i4y4Q4x3X3g2H3P5b7`.`.

偶数

00aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6Y4m8&6N6r3S2G2L8W2)9#2k6X3g2$3k6h3&6Q4y4h3k6H3j5i4c8U0K9r3g2K6i4K6u0W2M7s2V1`.

最后共同的

7ddK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3k6r3g2U0M7Y4W2H3N6q4)9#2k6X3k6A6L8X3q4D9i4K6g2X3j5$3!0E0L8h3q4F1k6q4)9J5k6i4m8&6

saw.cs(main)

05cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3f1$3q4%4i4K6g2X3c8X3W2^5i4K6u0W2j5%4x3`.

saw.py

00bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3j5i4m8H3i4K6u0r3M7$3q4%4i4K6u0W2M7s2V1`.

saw.java

72eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3f1$3q4%4i4K6u0W2K9X3q4$3j5b7`.`.

rr=0

671K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3N6s2u0S2j5$3g2Q4x3X3g2@1P5s2b7`.

rr=1

bdfK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3N6s2u0S2j5$3f1I4i4K6u0W2N6s2S2@1

rr=2

3fdK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3N6s2u0S2j5$3f1J5i4K6u0W2N6s2S2@1

rr=3

54dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3N6s2u0S2j5$3f1K6i4K6u0W2N6s2S2@1

解密脚本,省略。下面有正确的。

Patch dll脚本

0f8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3M7r3q4@1j5$3S2Q4y4h3k6V1L8r3I4Q4y4h3k6%4K9i4c8Z5i4K6g2X3k6r3g2T1N6h3N6Q4x3X3g2H3P5b7`.`.

Patch saw.python 增加日志输出

5f8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3j5i4m8H3i4K6u0r3M7$3q4%4i4K6g2X3k6r3g2T1N6h3N6Q4x3X3g2H3P5b7`.`.

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

3e7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3k6i4S2H3i4K6u0r3d9r3q4U0K9#2)9J5k6h3A6S2N6X3p5`.

Debug版本dockerfile

b9aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6e0j5i4k6S2k6$3g2D9x3s2k6W2i4K6u0r3b7#2c8r3g2#2m8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4q4%4j5U0t1H3x3U0g2Q4x3V1k6H3L8$3I4&6k6h3&6U0i4K6u0r3c8r3!0U0K9$3g2J5k6X3W2D9k6g2)9J5k6h3c8W2j5Y4g2Y4

完整的题目附件以及脚本请见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-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 (((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))) & 0xFFFFFFFF
 
def 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 p
 
def 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 True
 
def 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 False
 
def 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 False
 
def 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 True
 
if __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-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 (((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))) & 0xFFFFFFFF
 
def 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 p
 
def 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编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回