You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅使用Z3工具完成指定CTF加密挑战的纯Z3实现求解

Solving Your CTF Encryption Challenge with Z3

Got it, let's work through how to model this problem correctly in Z3—your issue likely stems from either misconstraining input variables, incorrectly translating the encryption functions into Z3 logic, or missing endianness details when packing bytes into the FLAG values. Let's break this down step by step.

Step 1: Setup Z3 and Input Variables

First, we'll model the user input as a list of integers (since we're dealing with ASCII values and mod 26 operations, integers are easier to work with than BitVecs to avoid underflow/overflow issues). Each input character must be a lowercase letter (ASCII 97-122).

from z3 import *

# Initialize solver
s = Solver()

# Assume input is 20 characters (5 FLAG elements × 4 bytes each)
input_len = 20
input_chars = [Int(f'char_{i}') for i in range(input_len)]

# Add constraints: each character is a lowercase letter
for c in input_chars:
    s.add(And(c >= 97, c <= 122))

Step 2: Model the n1 Function

The n1 function uses modulo 26, which Z3 handles natively (note: Z3's % operator returns non-negative results for positive moduli, matching Python's behavior). We'll define a Z3-compatible version of n1:

def z3_n1(a1, a2, a3):
    # Exact translation of (a1 - a2 + a3) % 26 + a2
    mod_term = (a1 - a2 + a3) % 26
    # Ensure mod result is non-negative (redundant but explicit)
    s.add(mod_term >= 0)
    return mod_term + a2

Step 3: Model the ENC Function

You mentioned the ENC function checks if a1 is a lowercase letter. Let's assume the full logic (fill in the missing parts from your actual challenge code). For example, if ENC uses n1 with a fixed third parameter (like ASCII 'A' = 65) for valid lowercase inputs, we'd model it with Z3's If operator:

def z3_enc(a1, a2):
    # Replace with your actual ENC logic
    return If(
        And(a1 > 96, a1 <= 122),
        z3_n1(a1, a2, 65),  # Example: third parameter is 'A'
        a1  # Fallback for non-lowercase (we won't hit this due to input constraints)
    )

The FLAG elements are 32-bit integers—we need to define how the processed input bytes map to these values. You'll need to know if the packing is big-endian or little-endian (this is a common pitfall!). For example, if FLAG[0] = 0x726F756E is big-endian, it corresponds to bytes 0x72, 0x6F, 0x75, 0x6E ('r','o','u','n').

First, generate the processed bytes using z3_enc (adjust this to match how your challenge uses ENC—e.g., pairing input characters with previous ones, constants, etc.):

# Example: Process each input character with ENC using a fixed a2 (e.g., 'a' =97)
# Replace this with your actual processing logic
processed_bytes = [z3_enc(c, 97) for c in input_chars]

Then, add constraints that the packed processed bytes equal each FLAG element:

FLAG = [0x726F756E, 0xCABEE660, 0xDDC1997D, 0xAA93C38B, 0x87E21216]

# Pack 4 bytes into a 32-bit integer (adjust endianness as needed)
def pack_32bit(b0, b1, b2, b3, big_endian=True):
    if big_endian:
        return b0 * (2**24) + b1 * (2**16) + b2 * (2**8) + b3
    else:
        return b3 * (2**24) + b2 * (2**16) + b1 * (2**8) + b0

# Add constraints for each FLAG element
for i in range(5):
    start_idx = 4 * i
    b0 = processed_bytes[start_idx]
    b1 = processed_bytes[start_idx + 1]
    b2 = processed_bytes[start_idx + 2]
    b3 = processed_bytes[start_idx + 3]
    computed_flag = pack_32bit(b0, b1, b2, b3)
    s.add(computed_flag == FLAG[i])

Step 5: Solve and Extract the Input

Finally, run the solver and retrieve the solution if it exists:

if s.check() == sat:
    model = s.model()
    # Convert the solution to a string
    input_str = ''.join([chr(model[c].as_long()) for c in input_chars])
    print(f"Found valid input: {input_str}")
else:
    print("No solution exists—check your constraints or logic translation!")

Common Pitfalls to Fix

  • Incorrect Endianness: If you're not getting a solution, try flipping the endianness in pack_32bit.
  • Mismodeled ENC Logic: Double-check that your z3_enc function exactly matches the challenge's ENC code (especially any conditionals or parameters passed to n1).
  • BitVec vs Int: Using BitVecs can lead to issues with signed arithmetic or mod operations—stick to Int variables for this problem unless you explicitly handle BitVec constraints.
  • Input Length: Ensure your input length matches the required number of bytes to generate all FLAG elements.

内容的提问来源于stack exchange,提问作者Ahmed Ezzat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:03:47