<?php error_reporting(0); ini_set('display_errors'...
Создано: 16 сентября 2025 г.
Отвечено с использованием GPT-5 Thinking от Chat01
Создано: 16 сентября 2025 г.
Отвечено с использованием GPT-5 Thinking от Chat01
python# Let's implement the CRC functions matching the PHP code. def compute_crc16(data: bytes): checksum = 0xFFFF for b in data: checksum ^= b for _ in range(8): if checksum & 1: checksum = ((checksum >> 1) ^ 0xA001) & 0xFFFF else: checksum = (checksum >> 1) & 0xFFFF return checksum # CRC8 table from 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 ] def calculate_crc8(input_bytes: bytes): crc = 0 for b in input_bytes: crc = crc8_table[(crc ^ b) & 0xff] return crc & 0xff secret = b"Enj0yNSSCTF4th!" len(secret), compute_crc16(secret), calculate_crc8(secret) (15, 17262, 163)
pythonhex(compute_crc16(secret)), hex(calculate_crc8(secret)) ('0x436e', '0xa3')
pythonimport os, random def test_linear(): for _ in range(1000): delta = bytearray(15) # Set random few bits for i in range(3): pos = random.randrange(15) delta[pos] ^= 1 << random.randrange(8) d = bytes(delta) lhs = compute_crc16(bytes([a ^ b for a,b in zip(secret, d)])) ^ compute_crc16(secret) rhs = compute_crc16(d) if lhs != rhs: return False, (lhs, rhs, d) return True, None test_linear() (False, (24885, 56949, b'\x00\x00\x00\x00@\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00'))
pythondef test_linear2(): c16_zero = compute_crc16(b'') c8_zero = calculate_crc8(b'') for _ in range(1000): delta = bytearray(15) for i in range(3): pos = random.randrange(15) delta[pos] ^= 1 << random.randrange(8) d = bytes(delta) lhs = compute_crc16(bytes([a ^ b for a,b in zip(secret, d)])) ^ compute_crc16(secret) rhs = compute_crc16(d) ^ c16_zero if lhs != rhs: return False, (lhs, rhs, d) return True, None test_linear2() (False, (5925, 22426, b'\x00\x00\x00@\x00\x80\x00\x00\x02\x00\x00\x00\x00\x00\x00'))
pythondef test_linearity_general(): c16_zero = compute_crc16(b'') for L in [1,2,5,15]: for _ in range(200): m = bytes([random.randrange(256) for _ in range(L)]) d = bytes([random.randrange(256) for _ in range(L)]) lhs = compute_crc16(bytes([a ^ b for a,b in zip(m,d)])) rhs = compute_crc16(m) ^ compute_crc16(d) ^ c16_zero if lhs != rhs: return False, (L, m, d, lhs, rhs) return True, None test_linearity_general() (False, (1, b'9', b'\xdb', 2367, 46719))
pythonimport time target_crc16 = compute_crc16(secret) target_crc8 = calculate_crc8(secret) prefix = secret[:12] # keep first 12 same # Starting values after processing first 12 bytes: def process_state_crc16(state, b): state ^= b for _ in range(8): if state & 1: state = ((state >> 1) ^ 0xA001) & 0xFFFF else: state = (state >> 1) & 0xFFFF return state def process_state_crc8(state, b): return crc8_table[(state ^ b) & 0xff] # compute initial states after prefix state16 = 0xFFFF state8 = 0 for b in prefix: state16 = process_state_crc16(state16, b) state8 = process_state_crc8(state8, b) state16, hex(state16), state8, hex(state8) (33106, '0x8152', 220, '0xdc')
python# Build inverse table mapping for CRC8 step: for each current state s (0..255), and desired next_state t (0..255), # find b s.t. crc8_next = table[s ^ b] == t => b = s ^ table_inv[t], but table_inv is not a simple inverse due to not s^? # Actually we need b such that table[s ^ b] = t -> s ^ b must be index k s.t. table[k] = t -> k = table_inv[t], then b = s ^ k. # So if we precompute table_inv (mapping from t to k such that table[k] = t), since table is a permutation? Let's check uniqueness. # We'll compute inverse mapping; ensure it's bijection. table = crc8_table # Verify it's permutation: assert len(set(table)) == 256 table_inv = [0]*256 for i, val in enumerate(table): table_inv[val] = i def b15_for_crc8(current_state8, target8): k = table_inv[target8] b = current_state8 ^ k return b & 0xff # quick test: for random state8 and target, compute b, apply process_state_crc8 and see equals target for s in [0,1,123,220,255]: for t in [0,1,5,100,200,255]: b = b15_for_crc8(s,t) if process_state_crc8(s, b) != t: print("fail", s,t,b) raise SystemExit print("crc8 inverse ok")
pythontarget16 = compute_crc16(secret) target8 = calculate_crc8(secret) orig_tail = secret[12:] # b'th!' count=0 solution=None start=time.time() for b13 in range(256): s16_1 = process_state_crc16(state16, b13) s8_1 = process_state_crc8(state8, b13) for b14 in range(256): s16_2 = process_state_crc16(s16_1, b14) s8_2 = process_state_crc8(s8_1, b14) b15 = b15_for_crc8(s8_2, target8) s16_3 = process_state_crc16(s16_2, b15) if s16_3 == target16: tail = bytes([b13,b14,b15]) if tail != orig_tail: solution = tail break if solution: break end=time.time() solution, end-start (b'e\xa8-', 0.11774992942810059)
pythonnew = prefix + bytes([0x65,0xA8,0x2D]) # e, 0xA8, - new, len(new), compute_crc16(new), calculate_crc8(new), compute_crc16(secret), calculate_crc8(secret), new==secret (b'Enj0yNSSCTF4e\xa8-', 15, 17262, 163, 17262, 163, False)
pythonimport string printable = set(range(0x20,0x7f)) # space to ~ solutions=[] for b13 in printable: s16_1 = process_state_crc16(state16, b13) s8_1 = process_state_crc8(state8, b13) for b14 in printable: s16_2 = process_state_crc16(s16_1, b14) s8_2 = process_state_crc8(s8_1, b14) b15 = b15_for_crc8(s8_2, target8) if b15 not in printable: continue s16_3 = process_state_crc16(s16_2, b15) if s16_3 == target16: tail = bytes([b13,b14,b15]) if tail != orig_tail: solutions.append(tail) break if solutions: break solutions[:3], len(solutions) ([b'{(%'], 1)
pythonnew2 = prefix + b'{(%' len(new2), new2, compute_crc16(new2), calculate_crc8(new2), new2==secret (15, b'Enj0yNSSCTF4{(%', 17262, 163, False)
你这个关卡要的是:同长度、不同于明文的密码,且它的 CRC16、CRC8 都和 Enj0yNSSCTF4th! 一样。
直接给你一把可用的钥匙(15 字节,全部可见 ASCII):
Enj0yNSSCTF4{(%
说明(简要):
Enj0yNSSCTF4,穷举后 2 字节并用最后 1 字节“校正”CRC8,筛出同时命中的组合,得到 {(%。CRC16("Enj0yNSSCTF4{(%") == CRC16("Enj0yNSSCTF4th!")CRC8("Enj0yNSSCTF4{(%")  == CRC8("Enj0yNSSCTF4th!")提交方式(避免编码坑):
bashcurl -X POST -d 'pass=Enj0yNSSCTF4{(%' http://<你的题目地址>/
pass=Enj0yNSSCTF4{(% 的 application/x-www-form-urlencoded 请求即可。拿到的返回应该就是 都到这份上了,flag就给你了: ... 🎯