CRACK Solution
License Server
CRACK keygen

Prerequisites
Unlocks
152
Techniquekeygen
Rulenonzero
Sample152
Walkthrough
Recover the accepted input below, then submit it to the CRACK verifier.
Reject Samples
- 151
- 153
- 0
- 12
- 1520
- 15X
- abc
Verifier Listing
; crackme_02 "License Server": a keygen-me. Instead of reading a stored
; password, you reverse an ALGORITHM and compute the serial. The username is
; baked in as constants; the check derives the expected serial from it, then
; compares against the serial you type (as decimal digits). Technique: keygen
; (reverse the transform, do not read a constant). r0 = 1 on accept. Accept rule:
; nonzero.
;
; CONCEPT SUBSTITUTION (noted): the original keygen is username * 1337 XOR 0x5EED,
; a 16-bit result with two input fields. This core has 8-bit registers and ONE
; input buffer, so a 16-bit serial with a separate username field cannot be
; expressed at one input. We keep the SAME technique (reverse a multiply+XOR
; keygen, username baked in) at 8 bits over the single serial input:
;
; sum = (sum of username bytes) & 0xFF ; username "neo" baked below
; expected = ((sum * 3) ^ 0x5e) & 0xFF
; accept iff the typed decimal serial == expected
;
; "neo" = 0x6e 0x65 0x6f -> sum = 322 & 0xFF = 66 ; 66*3 = 198 ; 198 ^ 0x5e = 152.
; So the valid serial is "152".
; --- stage 1: keygen the expected serial from the baked username ---
mov r2, 0 ; r2 = sum of username bytes (mod 256)
add r2, 0x6e ; 'n'
add r2, 0x65 ; 'e'
add r2, 0x6f ; 'o'
mul r2, 3 ; sum * 3
xor r2, 0x5e ; ^ key -> r2 = expected serial byte (152)
; --- stage 2: parse the typed input as a decimal number (0..255) ---
; require at least one digit, and reject any non-digit character.
len r1
cmp r1, 0
jz bad ; empty input -> reject
; reject serials longer than 3 digits outright (255 is the 8-bit ceiling)
cmp r1, 3
jg bad
mov r3, 0 ; r3 = accumulated value
mov r7, 0 ; index
pl: cmp r7, r1
jge cmpser ; consumed every byte -> compare
ldb r0, [r7]
cmp r0, 0x30 ; '0'
jl bad ; below '0' -> not a digit
cmp r0, 0x39 ; '9'
jg bad ; above '9' -> not a digit
sub r0, 0x30 ; ASCII -> digit value 0..9
; r3 = r3*10 + digit, guarding the 8-bit ceiling so a wrapped value
; (e.g. "408" -> 152) can never masquerade as the real serial.
cmp r3, 25 ; r3 > 25 means r3*10 already exceeds 255
jg bad
mul r3, 10 ; shift the running value one decimal place
add r3, r0 ; add the new digit
cmp r3, r0 ; if the sum wrapped below the digit, it overflowed
jl bad
inc r7
jmp pl
; --- stage 3: the typed serial must equal the keygen output --------
cmpser: cmp r3, r2
jnz bad
mov r0, 1
ret
bad: mov r0, 0
ret