CRACK Solution

Two Rounds

CRACK rolling 2-round mixer

In-game screenshot of Two Rounds
In-game view
FamilyCRACK Graph0.915 DifficultyHard Ring05 IDz4_feistel

Prerequisites

REMAINDERTWO PHASE WAIT

Unlocks

None

Accepted input FE1STEL5
Techniquerolling 2-round mixer Rulenonzero SampleFE1STEL5

Walkthrough

Recover the accepted input below, then submit it to the CRACK verifier.

Reject Samples

  • FE1STEL4
  • GE1STEL5
  • FE1STEL
  • FE1STEL55
  • AAAAAAAA
Verifier Listing
; z4_feistel: "Two Rounds". A two-round rolling byte mixer where every output
; depends on the byte before it, so one character change cascades down the rest.
; Two forward passes with seeds and constants, then a per-position compare. Peel
; back round two, then round one, recovering each byte from the one before it.
; Technique: rolling 2-round (Feistel-style) mixer. Fully 8-bit; maps onto the
; byte core directly. r0 = 1 on accept. Accept rule: nonzero.
;
;   Round 1 (key = previous INPUT byte, seed 0x3B):
;       v = (input[i] + prev) & 0xFF ; v = rol(v, 3) ; r1[i] = v ^ 0x5A ; prev = input[i]
;   Round 2 (key = previous ROUND-1 byte, seed 0xA7):
;       w = r1[i] ^ prev ; r2[i] = (w + 0x1F) & 0xFF ; prev = r1[i]
;   Final per-position targets: 10 6F 0E B6 38 10 5F 9F
;
; r1[] is staged into scratch[0..7]; round 2 is folded into the final compares.
; sample "FE1STEL5" decodes to those eight targets (a 1 for I, a 5 for the last S).

        len   r2
        cmp   r2, 8
        jnz   bad           ; exactly 8 bytes

        ; ================= round 1: rolling on the previous input byte =======
        mov   r4, 0x3B      ; r4 = prev (seed)
        mov   r7, 0
r1loop: cmp   r7, 8
        jge   r2start
        ldb   r0, [r7]      ; r0 = input[r7] = c
        mov   r6, r0        ; remember c for the next prev
        add   r0, r4        ; v = (c + prev) & 0xFF
        rol   r0, 3         ; rotate left 3
        xor   r0, 0x5A      ; r1[i] = v ^ 0x5A
        stb   [r7], r0      ; scratch[i] = r1[i]
        mov   r4, r6        ; prev = c
        inc   r7
        jmp   r1loop

        ; ================= round 2: rolling on the previous round-1 byte =====
r2start: mov  r4, 0xA7      ; r4 = prev (seed)
        mov   r7, 0
r2loop: cmp   r7, 8
        jge   ok
        lds   r0, [r7]      ; r0 = r1[i]
        mov   r6, r0        ; remember r1[i] for the next prev
        xor   r0, r4        ; w = r1[i] ^ prev
        add   r0, 0x1F      ; r2[i] = (w + 0x1F) & 0xFF
        mov   r4, r6        ; prev = r1[i]

        ; --- compare r2[i] against the per-position target ------------------
        cmp   r7, 0
        jnz   t1
        cmp   r0, 0x10
        jnz   bad
        jmp   nextr2
t1:     cmp   r7, 1
        jnz   t2
        cmp   r0, 0x6F
        jnz   bad
        jmp   nextr2
t2:     cmp   r7, 2
        jnz   t3
        cmp   r0, 0x0E
        jnz   bad
        jmp   nextr2
t3:     cmp   r7, 3
        jnz   t4
        cmp   r0, 0xB6
        jnz   bad
        jmp   nextr2
t4:     cmp   r7, 4
        jnz   t5
        cmp   r0, 0x38
        jnz   bad
        jmp   nextr2
t5:     cmp   r7, 5
        jnz   t6
        cmp   r0, 0x10
        jnz   bad
        jmp   nextr2
t6:     cmp   r7, 6
        jnz   t7
        cmp   r0, 0x5F
        jnz   bad
        jmp   nextr2
t7:     cmp   r0, 0x9F      ; position 7
        jnz   bad

nextr2: inc   r7
        jmp   r2loop

ok:     mov   r0, 1
        ret
bad:    mov   r0, 0
        ret