-
-
Save shuffle2/59b03053e259144d6ae4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
from array import array | |
import sys | |
''' | |
password getsn looks to be 0x100 long | |
''' | |
# microcorruption's emulated dadd DOES NOT TAKE CARRY AS INPUT | |
def dadd(sr, src, dst): | |
rv = 0 | |
c = 0 | |
n = (sr >> 2) & 1 | |
for i in range(4): | |
s = (src >> (i * 4)) & 0xf | |
d = (dst >> (i * 4)) & 0xf | |
d += s + c | |
if d > 10: | |
if i == 3 and d & 0x8: | |
n = 1 | |
d -= 10 | |
c = 1 | |
else: | |
c = 0 | |
rv |= d << (i * 4) | |
return rv, (n << 2) | c | |
# dadd actually doesn't adhere to the msp430 spec, so make sure we're behaving like the emulator | |
# no sr.c as input, no sr.n or sr.z as output | |
# bcd digits > 0x9 are converted to bcd | |
assert dadd(0, 0x160e, 0x04a2) == (0x2116, 0), 'rv:%04x sr:%04x' % dadd(0, 0x160e, 0x04a2) | |
assert dadd(0, 0x3c01, 0x0845) == (0x4a46, 0), 'rv:%04x sr:%04x' % dadd(0, 0x3c01, 0x0845) | |
assert dadd(0, 0x9999, 0x9999) == (0x9998, 1), 'rv:%04x sr:%04x' % dadd(0, 0x9999, 0x9999) | |
assert dadd(0, 0x000e, 0x0000) == (0x0014, 0), 'rv:%04x sr:%04x' % dadd(0, 0x000e, 0x0000) | |
assert dadd(0, 0x0000, 0x0000) == (0x0000, 0), 'rv:%04x sr:%04x' % dadd(0, 0x0000, 0x0000) | |
assert dadd(0, 0x00ff, 0x00ff) == (0x0154, 0), 'rv:%04x sr:%04x' % dadd(0, 0x00ff, 0x00ff) | |
assert dadd(0, 0x8000, 0x8000) == (0x6000, 1), 'rv:%04x sr:%04x' % dadd(0, 0x8000, 0x8000) | |
# dst = dst - src | |
def sub(src, dst): | |
src = (~src) & 0xffff | |
dst &= 0xffff | |
rv = dst + src + 1 | |
n = 1 if rv & 0x8000 else 0 | |
c = 1 if rv > 0xffff else 0 | |
rv &= 0xffff | |
z = 1 if rv == 0 else 0 | |
# overflow isn't implemented in emulator | |
# but we use it to detect a case when n flag is set | |
v = 0 | |
if (dst ^ (src ^ 0x8000)) & 0x8000: | |
v = 1 if rv & 0x8000 == ((src ^ 0x8000) & 0x8000) else 0 | |
if n == 0: | |
n = v | |
v = 0 | |
#print 'd:%04x s:%04x rv:%05x' % (dst, src, rv) | |
#print 'v:%x n:%x z:%x c:%x' % (v, n, z, c) | |
return rv, (v << 8) | (n << 2) | (z << 1) | c | |
# the flags...barely make sense | |
assert sub(1234, 0x1000) == (0x0b2e, 1), 'rv:%04x sr:%04x' % sub(1234, 0x1000) | |
assert sub(1234, 0) == (0xfb2e, 4), 'rv:%04x sr:%04x' % sub(1234, 0) | |
assert sub(1234, 1234) == (0x0000, 3), 'rv:%04x sr:%04x' % sub(1234, 1234) | |
assert sub(1234, 0xfb2e) == (0xf65c, 5), 'rv:%04x sr:%04x' % sub(1234, 0xfb2e) | |
assert sub(1234, 0x8000) == (0x7b2e, 5), 'rv:%04x sr:%04x' % sub(1234, 0x8000) | |
def add(src, dst): | |
src &= 0xffff | |
dst &= 0xffff | |
rv = src + dst | |
c = 1 if rv > 0xffff else 0 | |
rv &= 0xffff | |
z = 1 if rv == 0 else 0 | |
n = 1 if rv & 0x8000 else 0 | |
v = 0 | |
return rv, (v << 8) | (n << 2) | (z << 1) | c | |
assert add(0x0000, 0x0000) == (0x0000, 2), 'rv:%04x sr:%04x' % add(0x0000, 0x0000) | |
assert add(0x0000, 0x7fff) == (0x7fff, 0), 'rv:%04x sr:%04x' % add(0x0000, 0x7fff) | |
assert add(0x7fff, 0x7fff) == (0xfffe, 4), 'rv:%04x sr:%04x' % add(0x7fff, 0x7fff) | |
assert add(0x8000, 0x8000) == (0x0000, 3), 'rv:%04x sr:%04x' % add(0x8000, 0x8000) | |
# rra/rrc are so terrible that i've stopped caring about tests | |
def rra(sr, dst): | |
dst &= 0xffff | |
sign = dst & 0x8000 | |
c = sr & 1 | |
rv = sign | (dst >> 1) | |
z = 0 | |
n = 1 if sign else (sr >> 2) & 1 | |
v = 0 | |
return rv, (v << 8) | (n << 2) | (z << 1) | c | |
def rrc(sr, dst): | |
dst &= 0xffff | |
sign = (sr & 1) << 15 | |
c = dst & 1 | |
rv = sign | (dst >> 1) | |
z = ((sr >> 1) & 1) if rv == 0 else 0 | |
n = 1 if sign else (sr >> 2) & 1 | |
v = 0 | |
return rv, (v << 8) | (n << 2) | (z << 1) | c | |
def bswap16(x): | |
assert x <= 0xffff | |
return ((x >> 8) & 0xff) | ((x & 0xff) << 8) | |
def decrypt(crypted, addr): | |
x, sr = sub(1234, bswap16(addr)) | |
x, sr = add(sr, x) | |
x, sr = rrc(sr, x) | |
x, sr = dadd(sr, addr, x) | |
x, sr = rra(sr, x) | |
x, sr = rrc(sr, x) | |
x, sr = dadd(sr, 0x3c01, x) | |
x, sr = add(sr, x) | |
x, sr = rrc(sr, x) | |
x, sr = add(0x100e, x) | |
x, sr = rrc(sr, x) | |
x, sr = rrc(sr, x) | |
return x ^ crypted | |
assert decrypt(0x0f7d, 0x160c + 2) == 0x8231 | |
data = array('H') | |
with open(sys.argv[1], 'rb') as f: | |
f.seek(0x4634 - 0x4400) | |
data.fromfile(f, 0x1100 / 2) | |
decrypted = array('H') | |
for i, b in enumerate(data): | |
o = 0x1400 + i * 2 | |
d = decrypt(b, o + 2) | |
decrypted.append(d) | |
if i == (0x20c / 2): | |
assert o == 0x160c | |
assert b == 0x0f7d | |
assert d == 0x8231 | |
with open(sys.argv[2], 'wb') as fo: | |
decrypted.tofile(fo) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment