IW 2016 CTF rev50 MIPS

@mrexcessive @ WHA

Internetwache 2016 CTF

rev50 SPIM

https://ctf.internetwache.org/tasks/rev/50

The problem

Decrypt the string IVyN5U3X)ZUMYCs

Source code provided

The solution

Source code provide as README.txt

I don't recognise this immediately, but searching for some opcode combinations confirmed it is MIPS
Ah... hence SPIM as the challenge title.

I do some annotating :

User Text Segment [00400000]..[00440000]
[00400000] 8fa40000  lw $4, 0($29)            ; 183: lw $a0 0($sp) # argc           $4 <- 0[sp==$29]
[00400004] 27a50004  addiu $5, $29, 4         ; 184: addiu $a1 $sp 4 # argv         $5 <- &4[sp]
[00400008] 24a60004  addiu $6, $5, 4          ; 185: addiu $a2 $a1 4 # envp         $6 <- &4[$5] = &8[sp]
[0040000c] 00041080  sll $2, $4, 2            ; 186: sll $v0 $a0 2                  $2 <- $4 << 2        ; ARGC * 4
[00400010] 00c23021  addu $6, $6, $2          ; 187: addu $a2 $a2 $v0               $6 <- $6 + v0        ; a2 = &8[sp] + (ARGC*4)

[00400014] 0c100009  jal 0x00400024 [main]    ; 188: jal main                       call 0x400018 (main)

error_exit:
[00400018] 00000000  nop                      ; 189: nop                            nop
[0040001c] 3402000a  ori $2, $0, 10           ; 191: li $v0 10                      $2 <- $0 | 0x10
[00400020] 0000000c  syscall                  ; 192: syscall # syscall 10 (exit)    SYSCALL (exit I guess)     EXIT end

main:
[00400024] 3c081001  lui $8, 4097 [flag]      ; 7: la $t0, flag                     $8 <- flag << 16,  0 to lower 16 bits     1001.0000
[00400028] 00004821  addu $9, $0, $0          ; 8: move $t1, $0                     $9 <- $0 + $0

for:
[0040002c] 3401000f  ori $1, $0, 15           ; 11: sgt $t2, $t1, 15                $1 <- $0 | 0xf
[00400030] 0029502a  slt $10, $1, $9                                                $10 <- ($1 < $9) ? 1 : 0
[00400034] 34010001  ori $1, $0, 1            ; 12: beq $t2, 1, exit                $1 <- $0 | 0x1
[00400038] 102a0007  beq $1, $10, 28 [exit-0x00400038]                              ($1 == $10) ? branch x7<<2 == 0x28 --> exit
[0040003c] 01095020  add $10, $8, $9          ; 14: add $t2, $t0, $t1               $10 <- $8 + $9
[00400040] 81440000  lb $4, 0($10)            ; 15: lb $a0, ($t2)                   $4 <- 0[$10]
[00400044] 00892026  xor $4, $4, $9           ; 16: xor $a0, $a0, $t1               $4 <- $4 ^ 0x9
[00400048] a1440000  sb $4, 0($10)            ; 17: sb $a0, 0($t2)                  0[$10] <- $4 (LSB)
[0040004c] 21290001  addi $9, $9, 1           ; 19: add $t1, $t1, 1                 $9 <- $9 + 1
[00400050] 0810000b  j 0x0040002c [for]       ; 20: j for                           JUMP --> 0x40002c -->^^^for

exit:
[00400054] 00082021  addu $4, $0, $8          ; 24: move $a0, $t0                   $4 <- $0 + $8
[00400058] 0c100019  jal 0x00400064 [printstring]; 25: jal printstring              call printstring ; not provided...
[0040005c] 3402000a  ori $2, $0, 10           ; 26: li $v0, 10                      $2 <- $0 | 0x0a
[00400060] 0000000c  syscall                  ; 27: syscall                         SYSCALL           EXIT end
[00400064] 34020004  ori $2, $0, 4            ; 30: li $v0, 4 l                     $2 <- $0 | 4
[0040006c] 03e00008  jr $31                   ; 32: jr $ra                          ret (jr $31)

After finishing the annotating and dry running a little, obvious it is some sort of stream xor.

Not vs. a fixed byte value, but against increasing sequence

00 01 02 03 04 ...

Python to decrypt

Input = "IVyN5U3X)ZUMYCs"

def xor(buf, key):
   """ Repeated key xor """
   encrypted = ""
   for i, cr in enumerate(buf):
      k = key[i % len(key)]
      op = (ord(cr) ^ ord(k))
      encrypted += chr(op)
   return encrypted

print xor(Input,"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e")

IW{M1P5_!S_FUN}