Hacking Tube

Site no longer updated. Migrated to https://bruce30262.github.io/

CSAW CTF 2015 -- Hacking Time

| Comments

Category: Reversing
Points: 200

This challenge gave us a NES ROM. After we launch it with NES debugger FCEUX, we found out that it eventually want us to input a password with 24 characters in length .

We can found that our input was stored at memory address 0x05 ~ 0x1D. At first I think that the program will just simply take our input and do some CMP operation, in order to check the password's correctness. But after doing some runtime analysis, I realize that there's no such operation, which means that the program might use some speical operations to check the password.

So I decide to set a hardware breakpoint. By using the method which mentioned in this artical, we can set a read breakpoint at address 0x05, which tells FCEUX to pause the program whenever there's a memory read operation at 0x05. Once it hit the breakpoint, we can start checking the assembly line by line and try to figure out what operation has been done for the password checking.

After some reversing and dynamic analysis, I finally figure out the password checking logic and implement it with the following python code:

s1 = "703053A1D3703F64B316E4045F3AEE42B1A137156E882AAB".decode('hex')
s2 = "20AC7A25D79CC21D58D01325966ADC7E2EB4B410CB1DC266".decode('hex')
xs = our_input

def check_password():
    b = 0
    s3 = [-1]*24
    for i in xrange(24):
        a = RotateLeft(xs[i], 3)
        b = RotateRight(b, 2)
        a += b
        a ^= ord(s[i])
        b = a
        a = RotateLeft(a, 4)
        a ^= ord(s2[i])
        s3[i] = a

    for i in xrange(24):
        if(s3[i] != 0):
            return False
    
    return True

Now we have the constraint system, time to summon the powerful Z3:

#!/usr/bin/env python


from z3 import *
import sys

s1 = "703053A1D3703F64B316E4045F3AEE42B1A137156E882AAB".decode('hex')
s2 = "20AC7A25D79CC21D58D01325966ADC7E2EB4B410CB1DC266".decode('hex')

def check(xs, s):
    b = BitVecVal(0, 8)
    for i in xrange(24):
        a = RotateLeft(xs[i], 3)
        b = RotateRight(b, 2)
        a += b
        a ^= ord(s1[i])
        b = a
        a = RotateLeft(a, 4)
        a ^= ord(s2[i])
        s.add(a == 0)
    
    if s.check() == sat:
        m = s.model()
        a = ""
        for i in xrange(24):
            a += chr(int(str((m[xs[i]]))))
            #print m[xs[i]]

            #print hex(int(str(m[xs[i]])))

        print a
    else:
        print "unsat"

def solv():
    s = Solver()
    xs = []
    for i in xrange(24):
        x = BitVec("x%d" % i, 8)
        s.add( 33 <= x )
        s.add( x <= 90 )
        xs.append(x)

    check(xs, s)

solv()

Finally, we get the password ( which is also the flag ): NOHACK4UXWRATHOFKFUHRERX

Comments

comments powered by Disqus