1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  | 
# ctf_crc_collision_solver.py
# Author: 无问社区AI mini模型 | 网络安全专家
# 功能:求解基于 CRC16 + CRC8 双重校验绕过的 CTF 题目
import requests
# ==================== CRC8 查表数组(来自PHP源码)====================
crc8_table = [
    0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
    0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
    0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
    0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
    0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
    0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
    0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
    0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
    0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
    0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
    0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
    0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
    0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
    0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
    0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
    0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
    0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
    0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
    0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
    0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
    0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
    0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
    0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
    0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
    0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
    0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
    0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
    0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
    0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
    0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
    0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
    0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
]
# ==================== 构建 CRC8 反查表 ====================
# 用于反向计算最后一个字节以匹配目标 CRC8
table_inv = [0] * 256
for idx, val in enumerate(crc8_table):
    table_inv[val] = idx
# ==================== CRC16 计算函数(Modbus风格)====================
def compute_crc16(data: bytes) -> int:
    """
    模拟 PHP 中的 CRC16(Modbus) 算法
    初始值: 0xFFFF, 多项式: 0xA001 (反向)
    """
    chk = 0xFFFF
    for b in data:
        chk ^= b
        for _ in range(8):
            if chk & 1:
                chk = (chk >> 1) ^ 0xA001
            else:
                chk >>= 1
        chk &= 0xFFFF  # 保持在 16 位内
    return chk
# ==================== CRC8 计算函数 ====================
def calculate_crc8(data: bytes) -> int:
    """
    模拟 PHP 中的 CRC8 查表算法
    """
    crc = 0
    for b in data:
        crc = crc8_table[(crc ^ b) & 0xFF]
    return crc & 0xFF
# ==================== 主逻辑开始 ====================
ORIGINAL_PASS = b"Enj0yNSSCTF4th!"
PREFIX_LEN = 12
TARGET_PASS_LEN = len(ORIGINAL_PASS)  # 必须为15
prefix = ORIGINAL_PASS[:PREFIX_LEN]   # 固定前12位: "Enj0yNSSCTF4"
# --- 步骤1:计算原始密码的 CRC 值 ---
target_crc16 = compute_crc16(ORIGINAL_PASS)
target_crc8 = calculate_crc8(ORIGINAL_PASS)
print(f"[+] 原始密码: {ORIGINAL_PASS.decode()}")
print(f"[+] 目标 CRC16: {target_crc16:#06x} ({target_crc16})")
print(f"[+] 目标 CRC8:  {target_crc8:#04x} ({target_crc8})\n")
# --- 步骤2:模拟处理 prefix 后的状态 ---
state16 = 0xFFFF  # CRC16 初始状态
state8 = 0        # CRC8 初始状态
for b in prefix:
    state16 ^= b
    for _ in range(8):
        if state16 & 1:
            state16 = (state16 >> 1) ^ 0xA001
        else:
            state16 >>= 1
    state16 &= 0xFFFF
    state8 = crc8_table[(state8 ^ b) & 0xFF]
print(f"[i] 前缀 '{prefix.decode()}' 处理后:")
print(f"    CRC16 状态: {state16:#06x}")
print(f"    CRC8 状态:  {state8:#04x}\n")
# --- 步骤3:穷举第13、14字节,并反推第15字节使 CRC8 匹配 ---
print("[*] 开始搜索满足条件的后缀 (b13, b14, b15)...")
# 可打印 ASCII 字符集 (避免特殊字符导致传输问题)
PRINTABLE = set(range(0x20, 0x7F))  # 空格到 ~
solution = None
for b13 in PRINTABLE:
    # === 更新 CRC16 状态 ===
    s16_1 = state16 ^ b13
    for _ in range(8):
        if s16_1 & 1:
            s16_1 = (s16_1 >> 1) ^ 0xA001
        else:
            s16_1 >>= 1
    s16_1 &= 0xFFFF
    # === 更新 CRC8 状态 ===
    s8_1 = crc8_table[(state8 ^ b13) & 0xFF]
    for b14 in PRINTABLE:
        s16_2 = s16_1 ^ b14
        for _ in range(8):
            if s16_2 & 1:
                s16_2 = (s16_2 >> 1) ^ 0xA001
            else:
                s16_2 >>= 1
        s16_2 &= 0xFFFF
        s8_2 = crc8_table[(s8_1 ^ b14) & 0xFF]
        # === 反向计算 b15 使得最终 CRC8 匹配 ===
        k = table_inv[target_crc8]  # 找到表中输出=target_crc8 的索引
        b15 = (s8_2 ^ k) & 0xFF     # 因为 crc8_next = table[s ^ b] => b = s ^ k
        if b15 not in PRINTABLE:
            continue  # 必须是可打印字符
        # === 检查 CRC16 是否也匹配 ===
        s16_3 = s16_2 ^ b15
        for _ in range(8):
            if s16_3 & 1:
                s16_3 = (s16_3 >> 1) ^ 0xA001
            else:
                s16_3 >>= 1
        s16_3 &= 0xFFFF
        tail = bytes([b13, b14, b15])
        full_pass = prefix + tail
        if s16_3 == target_crc16 and full_pass != ORIGINAL_PASS:
            solution = full_pass.decode('latin1')
            break
    if solution:
        break
# --- 结果输出 ---
if solution:
    print(f"\n✅ 找到有效 payload!")
    print(f"原密码: {ORIGINAL_PASS.decode()}")
    print(f"新密码: {solution}")
    print(f"长度一致: {len(solution) == TARGET_PASS_LEN}")
    print(f"CRC16 匹配: {compute_crc16(solution.encode()) == target_crc16}")
    print(f"CRC8 匹配:  {calculate_crc8(solution.encode()) == target_crc8}")
    print(f"内容不同:  {solution != ORIGINAL_PASS.decode()}")
    # 自动验证
    print(f"\n🔍 本地验证结果:")
    print(f"  CRC16('{solution}') = {compute_crc16(solution.encode()):#06x}")
    print(f"  CRC8 ('{solution}') = {calculate_crc8(solution.encode()):#04x}")
  |