# CSAW 2015 Hackingtime

This writeups is based off of this writeup:

```
http://bruce30262.logdown.com/posts/301384--csaw-ctf-2015-hacking-time
```

Let's take a look at the binary the gave us:

```
$ file HackingTime.nes
HackingTime.nes: iNES ROM dump, 2x16k PRG, 1x8k CHR, [Vert.]
```

So we are give an NES ROM image. This means we are going to need an NES ROM/Debugger. I used the Windows version of FCEUX which you can get here:

```
http://www.fceux.com/web/download.html
```

Now when we launch the ROM with the debugger, we are presented with a little story, then tasked with figuring out a password (`f`

is basically `A`

). Let's just select the password `0123456789ABCDEFGHIJKM`

(don't check it) and see what the memory looks like with Debug>Hex Editor:

```
000000: 4A 91 00 40 00 30 31 32 33 34 35 36 37 38 39 41
000010: 42 43 44 45 45 46 47 48 49 4A 4B 4C 4D 00 00 00
000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000030: 00 00 00 00 00 00 4D 00 00 BB 97 C0 00 17 23 1C
```

So we can see that our password is stored in hex starting at 0x5 with `0x30`

and goes all the way to 0x1C with `4D`

. We can also see that it has a null byte before and after the string. So our string in total is 24 characters, and even if we leave it blank it still has the hex value 0x20 so it's just a space character. So we can assume that the password is 24 characters long. Let's give it the password and see how the memory changes:

```
000000: 4A 91 00 40 00 30 31 32 33 34 35 36 37 38 39 41
000010: 42 43 44 45 45 46 47 48 49 4A 4B 4C 4D 00 3F FF
000020: A2 F0 65 AC 26 9F DF CF 35 CF 3F 45 5C 98 E9 3B
000030: CF 32 80 ED 32 0E 4D 00 00 BB 97 C0 00 17 23 1C
```

So we can see that the memory has changed, starting at 0x1E, directly after the null byte after our password, we see 24 bytes of data has been written, the same length as our password. So it looks like the password algorithm reads the password from memory here, runs it through an algorithm, and then stores the output in memory starting at 0x1E. We can find the code for the algorithm by setting a read breakpoint at 0x5 or at any part of the password. To set a read breakpoint, just right click and set the breakpoint. Then just reenter the password, and we can see the 6502 assembly code for the password algorithm:

```
00:82F1:A0 00 LDY #$00
00:82F3:A9 00 LDA #$00
00:82F5:85 3B STA $003B = #$00
>00:82F7:B9 05 00 LDA $0005,Y @ $0005 = #$30
00:82FA:AA TAX
00:82FB:2A ROL
00:82FC:8A TXA
00:82FD:2A ROL
00:82FE:AA TAX
00:82FF:2A ROL
00:8300:8A TXA
00:8301:2A ROL
00:8302:AA TAX
00:8303:2A ROL
00:8304:8A TXA
00:8305:2A ROL
00:8306:48 PHA
00:8307:A5 3B LDA $003B = #$00
00:8309:AA TAX
00:830A:6A ROR
00:830B:8A TXA
00:830C:6A ROR
00:830D:AA TAX
00:830E:6A ROR
00:830F:8A TXA
00:8310:6A ROR
00:8311:85 3B STA $003B = #$00
00:8313:68 PLA
00:8314:18 CLC
00:8315:65 3B ADC $003B = #$00
00:8317:59 5E 95 EOR $955E,Y @ $955E = #$70
00:831A:85 3B STA $003B = #$00
00:831C:AA TAX
00:831D:2A ROL
00:831E:8A TXA
00:831F:2A ROL
00:8320:AA TAX
00:8321:2A ROL
00:8322:8A TXA
00:8323:2A ROL
00:8324:AA TAX
00:8325:2A ROL
00:8326:8A TXA
00:8327:2A ROL
00:8328:AA TAX
00:8329:2A ROL
00:832A:8A TXA
00:832B:2A ROL
00:832C:59 76 95 EOR $9576,Y @ $9576 = #$20
00:832F:99 1E 00 STA $001E,Y @ $001E = #$00
00:8332:C8 INY
00:8333:C0 18 CPY #$18
00:8335:D0 C0 BNE $82F7
00:8337:A0 00 LDY #$00
00:8339:B9 1E 00 LDA $001E,Y @ $001E = #$00
00:833C:D0 08 BNE $8346
00:833E:C8 INY
00:833F:C0 18 CPY #$18
00:8341:D0 F6 BNE $8339
00:8343:A9 01 LDA #$01
00:8345:60 RTS -----------------------------------------
```

Let's break this up into pieces to reverse. To help with this, I've set execute breakpoints at the memory address `8307`

, `8311`

, `8317`

, `831A`

, `832C`

, and `832F`

.

```
00:82F1:A0 00 LDY #$00
00:82F3:A9 00 LDA #$00
00:82F5:85 3B STA $003B = #$00
```

This code just loads the accumulator and y registers with the value `0x0`

, and then also stores the same value in the memory location 0x3B, which we can see with the hex editor is that value (it's stored a few bytes over from the password output), which we will be using later. So effectively this converts into the following Python code:

```
i = 0
y = 0
```

```
00:82F7:B9 05 00 LDA $0005,Y @ $0005 = #$30
00:82FA:AA TAX
00:82FB:2A ROL
00:82FC:8A TXA
00:82FD:2A ROL
00:82FE:AA TAX
00:82FF:2A ROL
00:8300:8A TXA
00:8301:2A ROL
00:8302:AA TAX
00:8303:2A ROL
00:8304:8A TXA
00:8305:2A ROL
00:8306:48 PHA
```

So we can see here that it loads the password character from memory into the accumulator register, then rotates it by to the left. Let's check it by hand:

```
0x30: 00110000
Shifted by 1 to the left
0x60: 01100000
Shifted by 2 to the left
0xc0: 11000000
Shifted by 3 to the left
0x81: 10000001
```

As we can see, the value we got by doing it by hand is the same that is currently in the accumulator register, so we should be correct. Lastly we see that there is a `PHA`

instruction, which pushes whatever is in the Accumulator register to the stack, since we need to clear the accumulator register for other operations however still hold the value 0x81. So this assembly code converts to the following python code:

```
x = RotateLeft(inp[i], 3)
```

```
00:8307:A5 3B LDA $003B = #$00
00:8309:AA TAX
00:830A:6A ROR
00:830B:8A TXA
00:830C:6A ROR
00:830D:AA TAX
00:830E:6A ROR
00:830F:8A TXA
00:8310:6A ROR
>00:8311:85 3B STA $003B = #$00
```

Here we can see that the value of whatever is stored at 0x3B is being loaded into the accumulator register, shifted to the right twice, then written to 0x3B. We know that the value stored at 0x3B is zero, and zero shifted to the right or left however many times is still zero, so the value of the accumulator register should be 0 (which it is). This assembly code converts into the following python code:

```
y = BitVecVal(0, 8)
y = BitVecVal(0, 8)
```

```
00:8313:68 PLA
00:8314:18 CLC
00:8315:65 3B ADC $003B = #$00
```

Here we can see that it pulls the 0x81 function back from the stack and into the accumulator register, then adds the value of 0x3B to it, and stores the output in the accumulator register. Since the value at 0x3B is zero, the accumulator remains at the value of 0x81. So this translates into the following python code:

```
x = x + y
```

```
00:8317:59 5E 95 EOR $955E,Y @ $955E = #$70
00:831A:85 3B STA $003B = #$00
```

Here we can see it xors the accumulator register with the value stored in memory at 0x955E, which we can see from the hex editor is this

```
70 30 53 A1 D3 70 3F 64 B3 16 E4 04 5F 3A EE 42 B1 A1 37 15 6E 88 2A AB
```

So we can see that just like our password this has 24 bytes. In addition to that we can see that it is xoring our first character (well where it is in the encryption process) with the first character of the hex string, so it should xor our second character with the second bit, third with the third, etc. Let's do the xor by hand:

```
0x81: 10000001
0x70: 01110000
Xor: 11110001 = 0xF1
```

so when we did the xor, we see that we got the value 0xF1, which is the same as the value stored in the accumulator register, so that checks out. Lastly we see that it writes the value of the accumulator to 0x3B, so this assembly code converts to the following python code:

```
xor1 = "703053A1D3703F64B316E4045F3AEE42B1A137156E882AAB".decode("hex")
x = x ^ xor1[i]
y = x
```

```
00:831C:AA TAX
00:831D:2A ROL
00:831E:8A TXA
00:831F:2A ROL
00:8320:AA TAX
00:8321:2A ROL
00:8322:8A TXA
00:8323:2A ROL
00:8324:AA TAX
00:8325:2A ROL
00:8326:8A TXA
00:8327:2A ROL
00:8328:AA TAX
00:8329:2A ROL
00:832A:8A TXA
00:832B:2A ROL
```

So we can see again that it is shifting the accumulator register over to the left, this time by 4. At the start of this operation, the accumulator register is equal to 0xF1, so let's work this out by hand and check it:

```
0xF1: 11110001
Shifted 1 to the left
0xE3: 11100011
Shifted 2 to the left
0xC7: 11000111
Shifted 3 to the left
0x8F: 10001111
Shifted 4 to the left
0x1F: 00011111
```

So at the end, we should have the value 0x1F in the accumulator register which we do. So this assembly code converts to the following python code:

```
x = RotateLeft(x, 4)
```

```
00:832C:59 76 95 EOR $9576,Y @ $9576 = #$20
>00:832F:99 1E 00 STA $001E,Y @ $001E = #$00
```

Here we see another `EOR`

instruction which xors the accumulator register with the value stored at 9576:

```
20 AC 7A 25 D7 9C C2 1D 58 D0 13 25 96 6A DC 7E 2E B4 B4 10 CB 1D C2 66
```

We can also see that it xors the bytes in the same order as the previous xor, so the first character by 0x20, second by 0xAC, third by 0x7A. After that we see that it writes the value stored in the accumulator register to the memory address 0x1E, which we can see is the next byte after the null terminator that ends out password, which is where we would expect the output of the function to go to (based upon our previous findings). So this converts to the following python code:

```
xor2 = "20AC7A25D79CC21D58D01325966ADC7E2EB4B410CB1DC266".decode("hex")
x = x ^ xor2[i]
```

```
00:8332:C8 INY
00:8333:C0 18 CPY #$18
00:8335:D0 C0 BNE $82F7
00:8337:A0 00 LDY #$00
00:8339:B9 1E 00 LDA $001E,Y @ $001F = #$FF
00:833C:D0 08 BNE $8346
00:833E:C8 INY
00:833F:C0 18 CPY #$18
00:8341:D0 F6 BNE $8339
00:8343:A9 01 LDA #$01
```

I didn't set a breakpoint after this, however, we don't need to to see what it is doing. First it increments the `Y`

register by one, then checks to see if it is equal to 0x18 (which is the same length as our password). If it isn't then it jumps back to the start of this function and runs the encryption algorithm. After that it will load a zero into the Y register, load the value of the output of the encryption algorithm (this case stored at 0x1E) and compare them. If not it will branch to a function at 0x8346 which essentially just fails us (if we go there, we fail the password check). If it doesn't fail, then it simply loop through checking the output for each character of the password. So essentially this checks to see if the output of the encryption algorithm is zero for all of the characters, and does the work of a for loop which converts to the following python code:

```
for i in xrange(24):
if x[i] != 0:
break
```

So we know how the encryption algorithm works, and what output we need. Now we can just use z3 solver, which is a theorem prover designed by Microsoft to find the input needed to get the output we need (24 zeros). Quick Z3 solver intro, you can give it a formula, it will tell you if it can be solved, and some values to solve it:

```
$ python
Python 2.7.13 (default, Jan 19 2017, 14:48:08)
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from z3 import *
>>> x = Int('x')
>>> y = Int('y')
>>> z = Solver()
>>> z.add(x > y, y < 5)
>>> z.check()
sat
>>> z.model()
[y = 4, x = 5]
```

As we can see, we established two integers and a solver, added a constraint to the solver, checked the solver to ensure that it is satisfiable, then modeled it to see what values will actually satisfy it. keep in mind since the registers is 6502 assembly can only have 8 bits, we have to treat them as only capable of 8 bits in our python. Now we can use this tool in the same manner to find what input will give us 24 zeroes, with having the encryption algorithm be the constraints. here is the python code for it:

```
#First import the z3 library
from z3 import *
#Import the two hex strings which we will be xoring
xor1 = [ 0x70, 0x30, 0x53, 0xA1, 0xD3, 0x70, 0x3F, 0x64, 0xB3, 0x16, 0xE4, 0x04, 0x5F, 0x3A, 0xEE, 0x42, 0xB1, 0xA1, 0x37, 0x15, 0x6E, 0x88, 0x2A, 0xAB]
xor2 = [ 0x20, 0xAC, 0x7A, 0x25, 0xD7, 0x9C, 0xC2, 0x1D, 0x58, 0xD0, 0x13, 0x25, 0x96, 0x6A, 0xDC, 0x7E, 0x2E, 0xB4, 0xB4, 0x10, 0xCB, 0x1D, 0xC2, 0x66]
def decrypt(inp, z):
#Define the encryption algorithm constraints
y = BitVecVal(0, 8)
for i in xrange(24):
x = RotateLeft(inp[i], 3)
y = RotateRight(y, 2)
x = x + y
x = x ^ xor1[i]
y = x
x = RotateLeft(x, 4)
x = x ^ xor2[i]
z.add(x == 0)
#Check if the conditions are satisfiable, if it is model it and get the password
if z.check() == sat:
print "The condition is: " + str(z.check())
solve = z.model()
cred = ""
#Sort out the data, and print the passord
for i in xrange(24):
cred = cred + chr(int(str(solve[inp[i]])))
print cred
else:
#Something failed and the condition isn't satisifiable, I would recogmend crying
print "The condition is: " + str(z.check())
#Establish the solver, and the input array
z = Solver()
inp = []
#We need to add an 8 bit vector for every character in our password
for i in xrange(24):
b = BitVec("%d" % i, 8)
inp.append(b)
#Now pass the list, and the solver to the decrypt function
decrypt(inp, z)
```

and when we run it:

```
$ python rev.py
The condition is: sat
NOHACK4UXWRATHOFKFUHRERX
```

So we get the string `NOHACK4UXWRATHOFKFUHRERX`

which happens to be the password, and also the flag for this challenge. Just like that we solved this challenge!