Wednesday, September 23, 2015

Writeup - CSAW 2015 : Reversing 200 - HackingTime

Firstly, we are greeted with a .nes file with the name HackingTime. The .nes file extension is used for Nintendo Entertainment System ROM files used in emulators. Knowing this, why don’t we load it up in an emulator and try it out. The emulator that I used and would highly recommend is FCEUX as it has a built in debugger and other handy tools for memory analysis.

After loading up the ROM, the game plays through very linearly until you end up at a lockdown screen where you are asked to input a 24 character password to proceed.
Let’s bring up the debugger to figure out where we are in the program. Pressing the Step Into button will put you at the current instruction.

The NES uses the MOS 6502 instruction set, so to understand what is going on, I used this page from nesdev:
For the most part, the debugger will show us that we are stuck in a loop while we wait for input to change the values of the passcode. So where are these passcode values stored? Well, FCEUX also uses has a hexeditor to show the program’s memory during execution.
As you can see, the passcode input is stored at addresses 00005 – 00001D. Returning to the debugger, I set a breakpoint on these addresses to see what was happening when we actually checked if it was the passcode.
After we set the breakpoints, trying the passcode will break on the comparison portion of the program. The section of code that is triggered on passcode attempt is as follows:
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 = #$41
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

Long story short, the passcode is taken a letter at the time and has a lot of bitwise rolls and XORs with other values. The result the operations is stored at 00001E-000036. The important thing to note from the code is that there is a variable that is altered with each input and carried across each iteration of the loop to further alter the other values of the passcode to produce a result that is isn’t really compared to another string. The only thing that is checked is in fact a zero flag, so how do we find out what values would set the zero flag after the end of the loop? Well, this can be done by trial and error fairly easily actually. If you watch in the hexeditor the results of the loop, all you have to do is find the value that will store a zero in memory. I recommend setting the CPU Speed on Turbo for this as it expedites the process.
So, after the loop is done, instead of jumping back to tell us our passcode is incorrect. It grabs that last element in our encoded array (the element at 000035) and compares it to 0. Finding that it is 0, it will tell you your passcode is correct and is the flag. {NOHACK4UXWRATHOFKRUHRERX}