Lagos, Microcorruption CTF

I've been struggling to figure out how to best the Lagos level in CTF

I've been away from Microcorruption CTF for a while now, but I've taken a quick look at the Lagos level and haven't figured it out yet. I know there is a failure to check the bounds of user input, which is basically our "in", but I haven't successfully exploited it yet. You can pretty easily enter enough characters to overwrite code, and I suspect that you can manage to write enough code with instructions that happen to fall in the valid alphanumeric ranges to pull it off, but I haven't done the work to figure it out yet.

Here is my annotated source so far:

455e <login>
455e:  0b12           push	r11
4560:  3150 f0ff      add	#0xfff0, sp
4564:  3f40 7044      mov	#0x4470 "Enter the password to continue.", r15
4568:  b012 6046      call	#0x4660 <puts>
456c:  3f40 9044      mov	#0x4490 "Remember: passwords are between 8 and 16 characters.", r15
4570:  b012 6046      call	#0x4660 <puts>
4574:  3f40 c544      mov	#0x44c5 "Due to some users abusing our login system, we have", r15
4578:  b012 6046      call	#0x4660 <puts>
457c:  3f40 f944      mov	#0x44f9 "restricted passwords to only alphanumeric characters.", r15
4580:  b012 6046      call	#0x4660 <puts>
4584:  3e40 0002      mov	#0x200, r14
4588:  3f40 0024      mov	#0x2400, r15
458c:  b012 5046      call	#0x4650 <getsn>
4590:  5f42 0024      mov.b	&0x2400, r15            ; read a byte of input
4594:  0e43           clr	r14                     ; set index to zero
4596:  7c40 0900      mov.b	#0x9, r12
459a:  7d40 1900      mov.b	#0x19, r13
459e:  073c           jmp	#0x45ae <login+0x50>
45a0:  0b41           mov	sp, r11
45a2:  0b5e           add	r14, r11                ; r11 is stack pointer + index
45a4:  cb4f 0000      mov.b	r15, 0x0(r11)           ; write input byte to stack pointer + index
45a8:  5f4e 0024      mov.b	0x2400(r14), r15        ; load a byte of input to r15
45ac:  1e53           inc	r14                     ; move r14 to the next byte of input
45ae:  4b4f           mov.b	r15, r11                ; put the input in r11
45b0:  7b50 d0ff      add.b	#0xffd0, r11            ; subtract 47 from input
45b4:  4c9b           cmp.b	r11, r12                ; compare to 9 (check if it's one of 10 valid digits)
45b6:  f42f           jc	#0x45a0 <login+0x42>    ; then go to read next input byte
45b8:  7b50 efff      add.b	#0xffef, r11            ; subtract another 17 from input (now 64)
45bc:  4d9b           cmp.b	r11, r13                ; compare to 25 (check if it's one of 26 valid uppercase characters)
45be:  f02f           jc	#0x45a0 <login+0x42>    ; then go to read next input byte
45c0:  7b50 e0ff      add.b	#0xffe0, r11            ; subtract another 32 from input (now 96)
45c4:  4d9b           cmp.b	r11, r13                ; compare to 25 (check if it's one of 26 valid lowercase characters)
45c6:  ec2f           jc	#0x45a0 <login+0x42>    ; then go to read next input byte
45c8:  c143 0000      mov.b	#0x0, 0x0(sp)           ; else write zero to sp
45cc:  3d40 0002      mov	#0x200, r13
45d0:  0e43           clr	r14
45d2:  3f40 0024      mov	#0x2400, r15
45d6:  b012 8c46      call	#0x468c <memset>        ; zap 512 bytes to zero
45da:  0f41           mov	sp, r15
45dc:  b012 4644      call	#0x4446 <conditional_unlock_door> ; test the password
45e0:  0f93           tst	r15
45e2:  0324           jz	#0x45ea <login+0x8c>
45e4:  3f40 2f45      mov	#0x452f "Access granted.", r15
45e8:  023c           jmp	#0x45ee <login+0x90>
45ea:  3f40 3f45      mov	#0x453f "That password is not correct.", r15
45ee:  b012 6046      call	#0x4660 <puts>
45f2:  3150 1000      add	#0x10, sp
45f6:  3b41           pop	r11
45f8:  3041           ret

And here is some reference I pulled from the system's user guide:

Double Operand Instructions

15 14 13 12 11 10 09 08 07 06  05 04 03 02 01 00
Opcode      S-Reg       Ad B/W As    D-Reg

Single Operand Instructions

15 14 13 12 11 10 09 08 07 06  05 04 03 02 01 00
Opcode                     B/W Ad    D/S-Reg

There are obviously a lot more operators than that, so I'll be looking through those next.