CRACK Solution
Check Digit
CRACK keygen (mod-97 check digit)

Prerequisites
Unlocks
21521
Techniquekeygen (mod-97 check digit)
Rulenonzero
Sample21521
Walkthrough
Recover the accepted input below, then submit it to the CRACK verifier.
Reject Samples
- 21522
- 21520
- 21421
- 31521
- 2152
- 215211
- ABCDE
Verifier Listing
; z2_keygen_mod97: username/serial keygen built on a mod-97 check digit, the
; same trick banks use on account numbers. One valid serial per username. The
; USERNAME is baked into this check as constants (the crackme proves the serial
; matches a fixed name); the player computes and enters the SERIAL.
;
; base = sum of the username's ASCII byte values
; check = base mod 97
; serial = the base printed as 3 ASCII digits, then the 2-digit check
;
; Baked username "re": sum = 'r'(114) + 'e'(101) = 215, 215 mod 97 = 21, so the
; one valid serial is "21521" (215 then 21). r0 = 1 on accept; rule: nonzero.
;
; SUBSTITUTION NOTE (8-bit faithful shrink): the original used base = sum * 257
; then serial = base*100 + (base mod 97), a 24-bit number that cannot live in a
; byte. This keeps the SAME technique: a base derived from the username, a
; mod-97 remainder appended as a self-check: scaled so the base is the raw
; username sum (which fits a byte) instead of sum*257. The mod-97 reduction is
; the teachable core and is computed by hand with a subtract loop.
len r2
cmp r2, 5
jnz bad ; serial is 5 ASCII digits: BBB CC
; every char must be a digit
mov r7, 0
dchk: cmp r7, 5
jge parse
ldb r0, [r7]
cmp r0, 0x30
jl bad
cmp r0, 0x39
jg bad
inc r7
jmp dchk
; --- parse the 3-digit base in r3 = d0*100 + d1*10 + d2 ----------
parse: mov r3, 0
mov r7, 0
ldb r0, [r7]
sub r0, 0x30
; r3 = r0 * 100
mov r4, 0
mov r1, 100
m100: cmp r1, 0
jz a100
add r4, r0
dec r1
jmp m100
a100: add r3, r4
mov r7, 1
ldb r0, [r7]
sub r0, 0x30
; r3 += r0 * 10
mov r4, 0
mov r1, 10
m10: cmp r1, 0
jz a10
add r4, r0
dec r1
jmp m10
a10: add r3, r4
mov r7, 2
ldb r0, [r7]
sub r0, 0x30
add r3, r0 ; r3 = base value (0..999 mod 256 in a byte)
; --- the baked username sum: "re" -> 215 -------------------------
; base must equal the username sum, or this serial is for another name
cmp r3, 215
jnz bad
; --- check = base mod 97 (hand math, subtract loop) --------------
mov r5, r3
mod97: cmp r5, 97
jl haveck
sub r5, 97
jmp mod97
; r5 = base mod 97 (here 21)
; --- parse the 2-digit supplied check in r6 ---------------------
haveck: mov r6, 0
mov r7, 3
ldb r0, [r7]
sub r0, 0x30
mov r4, 0
mov r1, 10
c10: cmp r1, 0
jz ca10
add r4, r0
dec r1
jmp c10
ca10: add r6, r4
mov r7, 4
ldb r0, [r7]
sub r0, 0x30
add r6, r0 ; r6 = supplied 2-digit check
cmp r6, r5
jnz bad
mov r0, 1
ret
bad: mov r0, 0
ret