reversefreehard

loicense

pingCTF

Task: License keygen for SmartAttend ELF with DWARF debug info, validates keys via 10x10 linear system. Solution: Reverse key format (11-char metadata + 10 IEEE-754 floats as hex), solve linear system from HWID ASCII values, bruteforce metadata for numerical stability.

$ ls tags/ techniques/
linear_system_solvingieee754_encodingmetadata_bruteforce

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

loicense - pingCTF

Description

License validation challenge with SmartAttend ELF binary.

Given an ELF binary SmartAttend with DWARF debug info and a remote checker that sends 100 random HWIDs. For each HWID, generate a valid license key. Pass all 100 rounds to get the flag.

Analysis

Binary Structure

The binary is a 64-bit ELF with full DWARF debug symbols, making reverse engineering straightforward with radare2:

SmartAttend: ELF 64-bit LSB executable, x86-64, with debug_info, not stripped

Key Format (from decode_signature_from_key)

License key structure (91 characters total):

  • 11 chars: Metadata prefix (alphanumeric: 0-9A-Z)
  • 80 chars: 10 IEEE-754 float32 values encoded as 8 hex digits each

HWID Structure

The 99-character HWID (charset 0-9A-Z) is split into 9 rows of 11 characters each.

Validation Model (from compute_system_loss / probe_signature_candidate)

The validation constructs a 10x10 linear system:

  1. Each HWID row provides coefficients: first 10 chars = coefficients, 11th char = RHS
  2. The metadata row (from key) provides the 10th equation
  3. Coefficients are raw ASCII values of characters (e.g., 'A' = 65, '0' = 48)
  4. The 10 float values from the key must satisfy all 10 equations

The system validates: A @ signature = b where:

  • A is 10x10 matrix from ASCII values of first 10 chars per row
  • b is 10-element vector from ASCII values of 11th char per row
  • signature is the 10 float values decoded from the key

Solution

Keygen Strategy

  1. Parse HWID into 9 rows of 11 ASCII values each
  2. Try multiple metadata candidates to find one that yields a well-conditioned 10x10 system
  3. Solve the linear system using numpy
  4. Encode solution floats as IEEE-754 hex
  5. Select metadata with smallest float32 residual for numerical stability

...

$ grep --similar

Similar writeups