For this challenge we got a NES ROM to reverse engineer.
The ROM memory could be viewed using Hex viewer, provided as part of FCEUX debug tools. I supplied a password ABCDABCDABCDABCDABCDABCD and found this is memory
Then set read memory access breakpoint for address 0x5 i.e. first byte of string. Now on continuing the game, the breakpoint is hit
The program counter is at 0x82F7, so we know what part of code to analyze. Then I found the Nintendo Entertainment System (NES) ROM loader module for IDA Pro, for analyzing the challenge ROM.
HackingTime_03e852ace386388eb88c39a02f88c773.nes: iNES ROM dump, 2x16k PRG, 1x8k CHR, [Vert.]I used FCEUX emulator to run the ROM file. The game asks for a password after few messages
The ROM memory could be viewed using Hex viewer, provided as part of FCEUX debug tools. I supplied a password ABCDABCDABCDABCDABCDABCD and found this is memory
Then set read memory access breakpoint for address 0x5 i.e. first byte of string. Now on continuing the game, the breakpoint is hit
The program counter is at 0x82F7, so we know what part of code to analyze. Then I found the Nintendo Entertainment System (NES) ROM loader module for IDA Pro, for analyzing the challenge ROM.
ROM:82F1 algorithm: ; CODE XREF: main_function+1C7 ROM:82F1 LDY #0 ROM:82F3 LDA #0 ROM:82F5 STA VAL ROM:82F7 ROM:82F7 process_loop: ; CODE XREF: algorithm+44 ROM:82F7 LDA 5,Y ; LDA INPUTKEY,A ROM:82FA TAX ; X = A ROM:82FB ROL A ; ROL A,1 ROM:82FC TXA ; A = X ROM:82FD ROL A ; ROL A, 1 ROM:82FE TAX ; X = A ROM:82FF ROL A ; ROL A, 1 ROM:8300 TXA ; A = X ROM:8301 ROL A ; ROL A,1 ROM:8302 TAX ; X = AThe PC 0x82F7, takes us to the actual validation algorithm used. The algorithm processes one byte at a time using multiple rotate operations and couple of XOR's with hardcoded arrays values. Good reference to instruction set is found here. The algorithm was rewritten in python and bruteforce gave the solution
import string CHECKA = [0x70, 0x30, 0x53, 0xa1, 0xd3, 0x70, 0x3f, 0x64, 0xb3, 0x16, 0xe4, 0x04, 0x5f, 0x3a, 0xee, 0x42, 0xb1, 0xa1, 0x37, 0x15, 0x6e, 0x88, 0x2a, 0xab] CHECKB = [0x20, 0xac, 0x7a, 0x25, 0xd7, 0x9c, 0xc2, 0x1d, 0x58, 0xd0, 0x13, 0x25, 0x96, 0x6a, 0xdc, 0x7e, 0x2e, 0xb4, 0xb4, 0x10, 0xcb, 0x1d, 0xc2, 0x66, 0x3b] CF = 0 def ROR(REG): global CF if CF: REG |= 0x100 CF = REG & 1 REG >>= 1 return REG def ROL(REG): global CF REG <<= 1 if CF: REG |= 1 CF = 1 if (REG > 0xFF) else 0 return REG & 0xFF STACK = 0 ADDR_3B = 0 KEY = '' for Y in range(24): for A in string.uppercase+string.digits: C = A VAL_3B = ADDR_3B A = ord(A) # ROM:82F7 LDA $5,Y X = A # ROM:82FA TAX A = ROL(A) # ROM:82FB ROL A A = X # ROM:82FC TXA A = ROL(A) # ROM:82FD ROL A X = A # ROM:82FE TAX A = ROL(A) # ROM:82FF ROL A A = X # ROM:8300 TXA A = ROL(A) # ROM:8301 ROL A X = A # ROM:8302 TAX A = ROL(A) # ROM:8303 ROL A A = X # ROM:8304 TXA A = ROL(A) # ROM:8305 ROL A STACK = A # ROM:8306 PHA A = VAL_3B # ROM:8307 LDA ROLL X = A # ROM:8309 TAX A = ROR(A) # ROM:830A ROR A A = X # ROM:830B TXA A = ROR(A) # ROM:830C ROR A X = A # ROM:830D TAX A = ROR(A) # ROM:830E ROR A A = X # ROM:830F TXA A = ROR(A) # ROM:8310 ROR A VAL_3B = A # ROM:8311 STA ROLL A = STACK # ROM:8313 PLA CF = 0 # ROM:8314 CLC A = (A + VAL_3B) & 0xFF # ROM:8315 ADC ROLL A = A ^ CHECKA[Y] # ROM:8317 EOR $955E,Y VAL_3B = A # ROM:831A STA ROLL X = A # ROM:831C TAX A = ROL(A) # ROM:831D ROL A A = X # ROM:831E TXA A = ROL(A) # ROM:831F ROL A X = A # ROM:8320 TAX A = ROL(A) # ROM:8321 ROL A A = X # ROM:8322 TXA A = ROL(A) # ROM:8323 ROL A X = A # ROM:8324 TAX A = ROL(A) # ROM:8325 ROL A A = X # ROM:8326 TXA A = ROL(A) # ROM:8327 ROL A X = A # ROM:8328 TAX A = ROL(A) # ROM:8329 ROL A A = X # ROM:832A TXA A = ROL(A) # ROM:832B ROL A A = A ^ CHECKB[Y] # ROM:832C EOR $9576,Y if A == 0: KEY += C ADDR_3B = VAL_3B break else: VAL_3B = 0 print KEYThe flag is NOHACK4UXWRATHOFKFUHRERX
No comments :
Post a Comment