0%

[WMCTF 2024]K-Cessation chen_xing的WriteUp

2025-07-01 02:37By
chenx1ng
CRYPTO二分图着色

首先下载附件后.html中有中文版本的加密流程解析,每次都是从最后一位开始的解密,那么最后一位只可能是0或者1。
密文显示了wheel中的01序列的约束条件。先前积累的算法知识可以看出来这就一个很简单的二分图着色问题。写一个二分图着色算法分别尝试最后一位是0和1的两种情况,再通过hash值判断哪一个是我们需要的答案。

import hashlib import ast from collections import defaultdict, deque from typing import List with open('ciphertext.txt', 'r') as f: ciphertext = ast.literal_eval(f.readline().strip()) with open('flag_hash.txt', 'r') as f: hash_salt = f.read().strip() hash_val, salt = hash_salt.split(':') def decode(data:bytes) -> bytes: """将2进制码转换为字符""" out = bytearray() for b in data: b = b & 0b01111111 out.append(b) return bytes(out) def decrypt(wheel: List[int], distances: List[int]) -> bytes: k = 64 state = -1 bits = [] for d in distances: state = (state + d) % k bits.append(wheel[state]) bit_str = ''.join(map(str, bits)) byte_array = bytearray() for i in range(0, len(bit_str), 8): byte_bits = bit_str[i:i+8] if len(byte_bits) < 8: continue byte_val = int(byte_bits, 2) byte_array.append(byte_val) return bytes(byte_array) def compute_state_sequence(distances: List[int], k: int = 64) -> List[int]: states = [-1] for d in distances: s_prev = states[-1] s_next = (s_prev + d) % k states.append(s_next) return states def solve(states: List[int], distances: List[int], k: int = 64): graph = defaultdict(list) n = len(distances) for t in range(1, n + 1): s_prev = states[t-1] s_curr = states[t] d_val = distances[t-1] if d_val > 1: for d_step in range(1, d_val): p = (s_prev + d_step) % k i = s_curr graph[p].append(i) graph[i].append(p) color = [-1] * k is_bipartite = True groups = {0: set(), 1: set()} for node in range(k): if color[node] == -1: queue = deque([node]) color[node] = 0 groups[0].add(node) while queue: curr = queue.popleft() for neighbor in graph[curr]: if color[neighbor] == -1: color[neighbor] = 1 - color[curr] groups[color[neighbor]].add(neighbor) queue.append(neighbor) elif color[neighbor] == color[curr]: is_bipartite = False break if not is_bipartite: break if not is_bipartite: break return groups def recover_wheel_and_decrypt(): distances = ciphertext k = 64 states = compute_state_sequence(distances, k) groups = solve(states, distances, k) group0 = groups[0] group1 = groups[1] wheel_candidates = [] wheel1 = [0 if i in group0 else 1 for i in range(k)] wheel_candidates.append(wheel1) wheel2 = [1 if i in group0 else 0 for i in range(k)] wheel_candidates.append(wheel2) for wheel in wheel_candidates: encrypted_bytes = decrypt(wheel, distances) decrypted_bytes = decode(encrypted_bytes) candidate_text = decrypted_bytes.decode('ascii') candidate_flag = candidate_text.strip() h = hashlib.sha256((salt + candidate_flag).encode()).hexdigest() if h == hash_val: print(candidate_text) return candidate_text if __name__ == "__main__": recover_wheel_and_decrypt() # DoubleUmCtF[S33K1NG_tru7h-7h3_w1s3-f1nd_1n57e4d-17s_pr0f0und-4b5ence_n0w-g0_s0lv3-th3_3y3s-1n_N0ita] # NSSCTF{S33K1NG_tru7h-7h3_w1s3-f1nd_1n57e4d-17s_pr0f0und-4b5ence_n0w-g0_s0lv3-th3_3y3s-1n_N0ita}
还没有人赞赏,快来当第一个赞赏的人吧!
  
© 著作权归作者所有
加载失败
广告
×
评论区
添加新评论