CRACK Solution

Fletcher Gate

CRACK Fletcher-16 checksum

In-game screenshot of Fletcher Gate
In-game view
FamilyCRACK Graph0.894 DifficultyHard Ring05 IDz3_fletcher

Prerequisites

LOCKRING VM

Unlocks

BACKLOG

Accepted input FLETCH16
TechniqueFletcher-16 checksum Rulenonzero SampleFLETCH16

Walkthrough

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

Reject Samples

  • FLETCH17
  • FLETCH15
  • AAAAAAAA
  • FLETCH1
  • FLETCH166
Verifier Listing
; z3_fletcher: "Fletcher Gate". No byte is checked on its own. The routine
; runs a two-accumulator running checksum (Fletcher-16) over the whole input and
; gates on a single 16-bit value: s1 += c, then s2 += s1, each reduced mod 255.
; The packed digest is (s2 << 8) | s1, compared to 0x0C1F. Technique: Fletcher-16
; checksum. r0 = 1 on accept. Accept rule: nonzero.
;
; 8-BIT NOTE: Fletcher-16 is already two 8-BIT running sums (s1, s2 each in
; 0..254, reduced mod 255), so it maps onto the byte core with NO loss: the only
; "16-bit" part is PACKING them as (s2<<8)|s1, which is just two byte compares
; (high byte s2 == 0x0C, low byte s1 == 0x1F). Same algorithm, same difficulty.
;
; Adding (a + b) with a,b each 0..254 can reach 508, which overflows a byte, so
; the addmod helper recovers the lost carry by hand: if the byte add wrapped
; (result < a), the true value is result + 256 == result + 1 (mod 255); then a
; subtract-255 reduction brings it back into 0..254.
;
; sample "FLETCH16": s1 = 0x1F (31), s2 = 0x0C (12) -> digest 0x0C1F.

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

        mov   r3, 0         ; r3 = s1 (sum of bytes, mod 255)
        mov   r4, 0         ; r4 = s2 (sum of sums, mod 255)
        mov   r7, 0         ; index 0..7

floop:  cmp   r7, 8
        jge   final
        ldb   r6, [r7]      ; r6 = input[r7]

        ; --- s1 = (s1 + c) mod 255 -----------------------------------------
        ; reduce c into 0..254 first so both operands are < 255
        cmp   r6, 255
        jl    addc
        sub   r6, 255       ; 255 -> 0
addc:   mov   r5, r3        ; r5 = old s1
        add   r5, r6        ; r5 = (s1 + c) mod 256
        cmp   r5, r3        ; wrapped iff result < old s1
        jge   s1red
        inc   r5            ; +256 == +1 (mod 255)
s1red:  cmp   r5, 255
        jl    s1ok
        sub   r5, 255
s1ok:   mov   r3, r5        ; r3 = new s1 in 0..254

        ; --- s2 = (s2 + s1) mod 255 ----------------------------------------
        mov   r5, r4        ; r5 = old s2
        add   r5, r3        ; r5 = (s2 + s1) mod 256
        cmp   r5, r4        ; wrapped iff result < old s2
        jge   s2red
        inc   r5            ; +256 == +1 (mod 255)
s2red:  cmp   r5, 255
        jl    s2ok
        sub   r5, 255
s2ok:   mov   r4, r5        ; r4 = new s2 in 0..254

        inc   r7
        jmp   floop

final:  cmp   r3, 0x1F      ; low byte: s1 == 0x1F
        jnz   bad
        cmp   r4, 0x0C      ; high byte: s2 == 0x0C
        jnz   bad
        mov   r0, 1
        ret
bad:    mov   r0, 0
        ret