Initial commit

This commit is contained in:
Hector Martin
2016-11-23 14:35:12 +09:00
commit 5b1c4f85b6
296 changed files with 39925 additions and 0 deletions

1736
pywii/Alameda/Alameda.py Normal file

File diff suppressed because it is too large Load Diff

335
pywii/Common/Struct.py Normal file
View File

@@ -0,0 +1,335 @@
import struct, sys
class StructType(tuple):
def __getitem__(self, value):
return [self] * value
def __call__(self, value, endian='<'):
if isinstance(value, str):
return struct.unpack(endian + tuple.__getitem__(self, 0), value[:tuple.__getitem__(self, 1)])[0]
else:
return struct.pack(endian + tuple.__getitem__(self, 0), value)
class StructException(Exception):
pass
class Struct(object):
__slots__ = ('__attrs__', '__baked__', '__defs__', '__endian__', '__next__', '__sizes__', '__values__')
int8 = StructType(('b', 1))
uint8 = StructType(('B', 1))
int16 = StructType(('h', 2))
uint16 = StructType(('H', 2))
int32 = StructType(('l', 4))
uint32 = StructType(('L', 4))
int64 = StructType(('q', 8))
uint64 = StructType(('Q', 8))
float = StructType(('f', 4))
@classmethod
def string(cls, len, offset=0, encoding=None, stripNulls=False, value=''):
return StructType(('string', (len, offset, encoding, stripNulls, value)))
LE = '<'
BE = '>'
__endian__ = '<'
def __init__(self, func=None, unpack=None, **kwargs):
self.__defs__ = []
self.__sizes__ = []
self.__attrs__ = []
self.__values__ = {}
self.__next__ = True
self.__baked__ = False
if func == None:
self.__format__()
else:
sys.settrace(self.__trace__)
func()
for name in func.func_code.co_varnames:
value = self.__frame__.f_locals[name]
self.__setattr__(name, value)
self.__baked__ = True
if unpack != None:
if isinstance(unpack, tuple):
self.unpack(*unpack)
else:
self.unpack(unpack)
if len(kwargs):
for name in kwargs:
self.__values__[name] = kwargs[name]
def __trace__(self, frame, event, arg):
self.__frame__ = frame
sys.settrace(None)
def __setattr__(self, name, value):
if name in self.__slots__:
return object.__setattr__(self, name, value)
if self.__baked__ == False:
if not isinstance(value, list):
value = [value]
attrname = name
else:
attrname = '*' + name
self.__values__[name] = None
for sub in value:
if isinstance(sub, Struct):
sub = sub.__class__
try:
if issubclass(sub, Struct):
sub = ('struct', sub)
except TypeError:
pass
type_, size = tuple(sub)
if type_ == 'string':
self.__defs__.append(Struct.string)
self.__sizes__.append(size)
self.__attrs__.append(attrname)
self.__next__ = True
if attrname[0] != '*':
self.__values__[name] = size[3]
elif self.__values__[name] == None:
self.__values__[name] = [size[3] for val in value]
elif type_ == 'struct':
self.__defs__.append(Struct)
self.__sizes__.append(size)
self.__attrs__.append(attrname)
self.__next__ = True
if attrname[0] != '*':
self.__values__[name] = size()
elif self.__values__[name] == None:
self.__values__[name] = [size() for val in value]
else:
if self.__next__:
self.__defs__.append('')
self.__sizes__.append(0)
self.__attrs__.append([])
self.__next__ = False
self.__defs__[-1] += type_
self.__sizes__[-1] += size
self.__attrs__[-1].append(attrname)
if attrname[0] != '*':
self.__values__[name] = 0
elif self.__values__[name] == None:
self.__values__[name] = [0 for val in value]
else:
try:
self.__values__[name] = value
except KeyError:
raise AttributeError(name)
def __getattr__(self, name):
if self.__baked__ == False:
return name
else:
try:
return self.__values__[name]
except KeyError:
raise AttributeError(name)
def __len__(self):
ret = 0
arraypos, arrayname = None, None
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size] + offset
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arrayname = attrs
arraypos = 0
size = len(self.__values__[attrs[1:]][arraypos])
size = len(self.__values__[attrs])
ret += size
return ret
def unpack(self, data, pos=0):
for name in self.__values__:
if not isinstance(self.__values__[name], Struct):
self.__values__[name] = None
elif self.__values__[name].__class__ == list and len(self.__values__[name]) != 0:
if not isinstance(self.__values__[name][0], Struct):
self.__values__[name] = None
arraypos, arrayname = None, None
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size] + offset
temp = data[pos:pos+size]
if len(temp) != size:
raise StructException('Expected %i byte string, got %i' % (size, len(temp)))
if encoding != None:
temp = temp.decode(encoding)
if stripNulls:
temp = temp.rstrip('\0')
if attrs[0] == '*':
name = attrs[1:]
if self.__values__[name] == None:
self.__values__[name] = []
self.__values__[name].append(temp)
else:
self.__values__[attrs] = temp
pos += size
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arrayname = attrs
arraypos = 0
name = attrs[1:]
self.__values__[attrs][arraypos].unpack(data, pos)
pos += len(self.__values__[attrs][arraypos])
arraypos += 1
else:
self.__values__[attrs].unpack(data, pos)
pos += len(self.__values__[attrs])
else:
values = struct.unpack(self.__endian__+sdef, data[pos:pos+size])
pos += size
j = 0
for name in attrs:
if name[0] == '*':
name = name[1:]
if self.__values__[name] == None:
self.__values__[name] = []
self.__values__[name].append(values[j])
else:
self.__values__[name] = values[j]
j += 1
return self
def pack(self):
arraypos, arrayname = None, None
ret = ''
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size]+offset
if attrs[0] == '*':
if arrayname != attrs:
arraypos = 0
arrayname = attrs
temp = self.__values__[attrs[1:]][arraypos]
arraypos += 1
else:
temp = self.__values__[attrs]
if encoding != None:
temp = temp.encode(encoding)
temp = temp[:size]
ret += temp + ('\0' * (size - len(temp)))
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arraypos = 0
arrayname = attrs
ret += self.__values__[attrs[1:]][arraypos].pack()
arraypos += 1
else:
ret += self.__values__[attrs].pack()
else:
values = []
for name in attrs:
if name[0] == '*':
if arrayname != name:
arraypos = 0
arrayname = name
values.append(self.__values__[name[1:]][arraypos])
arraypos += 1
else:
values.append(self.__values__[name])
ret += struct.pack(self.__endian__+sdef, *values)
return ret
def __getitem__(self, value):
return [('struct', self.__class__)] * value
if __name__=='__main__':
class TestStruct(Struct):
__endian__ = Struct.LE
def __format__(self):
self.foo, self.bar = Struct.uint32, Struct.float
self.baz = Struct.string(8)
self.omg = Struct.uint32
self.wtf = Struct.string(self.omg)
class HaxStruct(Struct):
__endian__ = Struct.LE
def __format__(self):
self.thing1 = Struct.uint32
self.thing2 = Struct.uint32
self.hax = HaxStruct
test = TestStruct()
test.unpack('\xEF\xBE\xAD\xDE\x00\x00\x80\x3Fdeadbeef\x04\x00\x00\x00test\xCA\xFE\xBA\xBE\xBE\xBA\xFE\xCA')
assert test.foo == 0xDEADBEEF
assert test.bar == 1.0
assert test.baz == 'deadbeef'
assert test.omg == 4
assert test.wtf == 'test'
assert test.hax.thing1 == 0xBEBAFECA
assert test.hax.thing2 == 0xCAFEBABE
print 'Tests successful'
"""
@Struct.LE
def TestStruct():
foo, bar = Struct.uint32, Struct.float
baz = Struct.string(8)
omg = Struct.uint32
wtf = Struct.string(omg)
@Struct.LE
def HaxStruct():
thing1 = Struct.uint32
thing2 = Struct.uint32
hax = HaxStruct()
test = TestStruct()
test.foo = 0xCAFEBABE
test.bar = 0.0
thing = test.hax.thing1
test.hax.thing1 = test.hax.thing2
test.hax.thing2 = thing
assert test.pack() == '\xBE\xBA\xFE\xCA\0\0\0\0deadbeef\x04\x00\x00\x00test\xBE\xBA\xFE\xCA\xCA\xFE\xBA\xBE'
"""

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env python
from wii import *

367
pywii/Common/pywii/ec.py Normal file
View File

@@ -0,0 +1,367 @@
#!/usr/bin/python
# Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
# Copyright 2008 Hector Martin <marcan@marcansoft.com>
# Licensed under the terms of the GNU GPL, version 2
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
from array import array
from struct import pack, unpack
from Crypto.Util.number import bytes_to_long, long_to_bytes
# y**2 + x*y = x**3 + x + b
ec_b = "\x00\x66\x64\x7e\xde\x6c\x33\x2c\x7f\x8c\x09\x23\xbb\x58\x21"+\
"\x3b\x33\x3b\x20\xe9\xce\x42\x81\xfe\x11\x5f\x7d\x8f\x90\xad"
def hexdump(s,sep=""):
return sep.join(map(lambda x: "%02x"%ord(x),s))
def bhex(s,sep=""):
return hexdump(long_to_bytes(s,30),sep)
fastelt = False
try:
import _ec
fastelt = True
except ImportError:
#print "C Elliptic Curve functions not available. EC certificate checking will be much slower."
pass
class ByteArray(array):
def __new__(cls, initializer=None):
return super(ByteArray, cls) .__new__(cls,'B',initializer)
def __init__(self,initializer=None):
array.__init__(self)
def __setitem__(self,item,value):
if isinstance(item, slice):
array.__setitem__(self, item, [x & 0xFF for x in value])
else:
array.__setitem__(self, item, value & 0xFF)
def __long__(self):
return bytes_to_long(self.tostring())
def __str__(self):
return ''.join(["%02x"%ord(x) for x in self.tostring()])
def __repr__(self):
return "ByteArray('%s')"%''.join(["\\x%02x"%ord(x) for x in self.tostring()])
class ELT_PY:
SIZEBITS=233
SIZE=(SIZEBITS+7)/8
square = ByteArray("\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55")
def __init__(self, initializer=None):
if isinstance(initializer, long) or isinstance(initializer, int):
self.d = ByteArray(long_to_bytes(initializer,self.SIZE))
elif isinstance(initializer, str):
self.d = ByteArray(initializer)
elif isinstance(initializer, ByteArray):
self.d = ByteArray(initializer)
elif isinstance(initializer, array):
self.d = ByteArray(initializer)
elif isinstance(initializer, ELT):
self.d = ByteArray(initializer.d)
elif initializer is None:
self.d = ByteArray([0]*self.SIZE)
else:
raise TypeError("Invalid initializer type")
if len(self.d) != self.SIZE:
raise ValueError("ELT size must be 30")
def __cmp__(self, other):
if other == 0: #exception
if self:
return 1
else:
return 0
if not isinstance(other,ELT):
return NotImplemented
return cmp(self.d,other.d)
def __long__(self):
return long(self.d)
def __repr__(self):
return repr(self.d).replace("ByteArray","ELT")
def __str__(self):
return str(self.d)
def __nonzero__(self):
for x in self.d:
if x != 0:
return True
return False
def __len__(self):
return self.SIZE
def __add__(self,other):
if not isinstance(other,ELT):
return NotImplemented
new = ELT(self)
for x in range(self.SIZE):
new[x] ^= other[x]
return new
def _mul_x(self):
carry = self[0]&1
x = 0
d = ELT()
for i in range(self.SIZE-1):
y = self[i + 1]
d[i] = x ^ (y >> 7)
x = y << 1
d[29] = x ^ carry
d[20] ^= carry << 2
return d
def __mul__(self,other):
if not isinstance(other,ELT):
return NotImplemented
d = ELT()
i = 0
mask = 1
for n in range(self.SIZEBITS):
d = d._mul_x()
if (self[i] & mask) != 0:
d += other
mask >>= 1
if mask == 0:
mask = 0x80
i+=1
return d
def __pow__(self,other):
if other == -1:
return 1/self
if other < 1:
return NotImplemented
if other % 2 == 0:
return self._square()**(other/2)
x = self
for i in range(other-1):
x *= self
return x
def _square(self):
wide = ByteArray([0]*self.SIZE*2)
for i in range(self.SIZE):
wide[2*i] = self.square[self[i] >> 4]
wide[2*i + 1] = self.square[self[i] & 0xf]
for i in range(self.SIZE):
x = wide[i]
wide[i + 19] ^= x >> 7;
wide[i + 20] ^= x << 1;
wide[i + 29] ^= x >> 1;
wide[i + 30] ^= x << 7;
x = wide[30] & 0xFE;
wide[49] ^= x >> 7;
wide[50] ^= x << 1;
wide[59] ^= x >> 1;
wide[30] &= 1;
return ELT(wide[self.SIZE:])
def _itoh_tsujii(self,b,j):
t = ELT(self)
return t**(2**j) * b
def __rdiv__(self,other):
if isinstance(other,ELT):
return 1/self * other
elif other == 1:
t = self._itoh_tsujii(self, 1)
s = t._itoh_tsujii(self, 1)
t = s._itoh_tsujii(s, 3)
s = t._itoh_tsujii(self, 1)
t = s._itoh_tsujii(s, 7)
s = t._itoh_tsujii(t, 14)
t = s._itoh_tsujii(self, 1)
s = t._itoh_tsujii(t, 29)
t = s._itoh_tsujii(s, 58)
s = t._itoh_tsujii(t, 116)
return s**2
else:
return NotImplemented
def __getitem__(self,item):
return self.d[item]
def __setitem__(self,item,value):
self.d[item] = value
def tobignum(self):
return bytes_to_long(self.d.tostring())
def tobytes(self):
return self.d.tostring()
class ELT_C(ELT_PY):
def __mul__(self,other):
if not isinstance(other,ELT):
return NotImplemented
return ELT(_ec.elt_mul(self.d.tostring(),other.d.tostring()))
def __rdiv__(self,other):
if other != 1:
return ELT_PY.__rdiv__(self,other)
return ELT(_ec.elt_inv(self.d.tostring()))
def _square(self):
return ELT(_ec.elt_square(self.d.tostring()))
if fastelt:
ELT = ELT_C
else:
ELT = ELT_PY
class Point:
def __init__(self,x,y=None):
if isinstance(x,str) and (y is None) and (len(x) == 60):
self.x = ELT(x[:30])
self.y = ELT(x[30:])
elif isinstance(x,Point):
self.x = ELT(x.x)
self.y = ELT(x.y)
else:
self.x = ELT(x)
self.y = ELT(y)
def on_curve(self):
return (self.x**3 + self.x**2 + self.y**2 + self.x*self.y + ELT(ec_b)) == 0
def __cmp__(self, other):
if other == 0:
if self.x or self.y:
return 1
else:
return 0
elif isinstance(other, Point):
ca = cmp(self.x,other.x)
if ca != 0:
return ca
return cmp(self.y,other.y)
return NotImplemented
def _double(self):
if self.x == 0:
return Point(0,0)
s = self.y/self.x + self.x
rx = s**2 + s
rx[29] ^= 1;
ry = s * rx + rx + self.x**2
return Point(rx,ry)
def __add__(self, other):
if not isinstance(other,Point):
return NotImplemented
if self == 0:
return Point(other)
if other == 0:
return Point(self)
u = self.x + other.x
if u == 0:
u = self.y + other.y
if u == 0:
return self._double()
else:
return Point(0,0)
s = (self.y + other.y) / u
t = s**2 + s + other.x
t[29] ^= 1
rx = t+self.x
ry = s*t+self.y+rx
return Point(rx,ry)
def __mul__(self, other):
bts = long_to_bytes(other,30)
d = Point(0,0)
for i in range(30):
mask = 0x80
while mask != 0:
d = d._double()
if ((ord(bts[i]) & mask) != 0):
d += self
mask >>=1
return d
#def __mul__(self, other):
#if not (isinstance(other,long) or isinstance(other,int)):
#return NotImplemented
#d = Point(0,0)
#s = Point(self)
#while other != 0:
#if other & 1:
#d += s
#s = s._double()
#other >>= 1
#return d
def __rmul__(self, other):
return self * other
def __str__(self):
return "(%s,%s)"%(str(self.x),str(self.y))
def __repr__(self):
return "Point"+str(self)
def __nonzero__(self):
return self.x or self.y
def tobytes(self):
return self.x.tobytes() + self.y.tobytes()
#only for prime N
#segher, your math makes my head hurt. But it works.
def bn_inv(a,N):
return pow(a,N-2,N)
# order of the addition group of points
ec_N = bytes_to_long(
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+\
"\x13\xe9\x74\xe7\x2f\x8a\x69\x22\x03\x1d\x26\x03\xcf\xe0\xd7")
# base point
ec_G = Point(
"\x00\xfa\xc9\xdf\xcb\xac\x83\x13\xbb\x21\x39\xf1\xbb\x75\x5f"+
"\xef\x65\xbc\x39\x1f\x8b\x36\xf8\xf8\xeb\x73\x71\xfd\x55\x8b"+
"\x01\x00\x6a\x08\xa4\x19\x03\x35\x06\x78\xe5\x85\x28\xbe\xbf"+
"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52")
def generate_ecdsa(k, sha):
k = bytes_to_long(k)
if k >= ec_N:
raise Exception("Invalid private key")
e = bytes_to_long(sha)
m = open("/dev/random","rb").read(30)
if len(m) != 30:
raise Exception("Failed to get random data")
m = bytes_to_long(m) % ec_N
r = (m * ec_G).x.tobignum() % ec_N
kk = ((r*k)+e)%ec_N
s = (bn_inv(m,ec_N) * kk)%ec_N
r = long_to_bytes(r,30)
s = long_to_bytes(s,30)
return r,s
def check_ecdsa(q,r,s,sha):
q = Point(q)
r = bytes_to_long(r)
s = bytes_to_long(s)
e = bytes_to_long(sha)
s_inv = bn_inv(s,ec_N)
w1 = (e*s_inv)%ec_N
w2 = (r*s_inv)%ec_N
r1 = w1 * ec_G + w2 * q
rx = r1.x.tobignum()%ec_N
return rx == r
def priv_to_pub(k):
k = bytes_to_long(k)
q = k * ec_G
return q.tobytes()
def gen_priv_key():
k = open("/dev/random","rb").read(30)
if len(k) != 30:
raise Exception("Failed to get random data")
k = bytes_to_long(k)
k = k % ec_N
return long_to_bytes(k,30)

1757
pywii/Common/pywii/wii.py Normal file

File diff suppressed because it is too large Load Diff

10
pywii/README Normal file
View File

@@ -0,0 +1,10 @@
Python library to deal with Wii formats.
Currently has decent support for discs, partitions (including
accessing the partition data using read() and write(), with
caching), wads, and the structures contained within (certs,
tiks, tmds, etc)
Stuff may be broken. Some things are unfinished.
It also makes breakfast.

94
pywii/breakfast.py Normal file
View File

@@ -0,0 +1,94 @@
import zlib, time, base64, sys
class WaffleBatter:
def __init__(self):
self.cooking_time = 100
self.batter = "eNp9VbGu3DgM7PMVhBs2sq4VDnHKwxUu1DLehQhBxeukD7iPvyEl78tLXuJisbbJ4Qw5lIn+dJUfri+/i+n92Lbr70siblreWFLejtE/zQhHZpW4C+OGW0pKoWuOUvVb6VlG/DUtJAsO8tC3SGFkpvKUy19xyO0ynlHl54LhYEIpteTnyOmiIcwa9BHLGIzHWvFSN0D+lFwaFzyM2ks4NjaKdb04NujEPWe8NTV4SPohvSWvSe3IUsn4kkQ5V3DRt+JtQyNq7GiEUpT+nt84SnSZqBOtq+SqpZsAoq1K97fPEbWWCcUSXwjJyBvNoR7+rN3lht1nRNDEF2r7DIRTR3+RsT/PBRFsini0VHsPEL9bUSXAOTeBqO59RrDWv1yz1IkRKHXtVhVqJt0ydoz5VV9i9oxHTIYXEGz9tri8QKSZV8gfmcLggEqcJoO2nXcGXyR9ekL4uymiuyM50QNsDnYOdU0SrMHhnBy2iQgcmEPOd1GReXG5xB/JuQ9vG8LmiNpe50SDVZA+Z6/fIOsfG5K4jeRGuWwO8SbRsC3nPkkILVkHyySxLHzu8335niZKdeOidXST6IvDXI+bBHo/IdH6OjtpJNN/q720zAVjypwuZTcqhMK3j5ni7QWLr+zCzU4Mh9E9JarAcYc1GLKvPQHkGZ2crdlj/rUdfsyazZcTOXQtGI0ko3icBvh+/i19sUBOzbYxE/PUat1BEEV9a9xu+yN6Ns/W/sgJ22pGz07NpZUR7wjQ0OprQsoNp8lricDGqfpUL7o5KHc7SYrJNa9Emizkkr62l95ByOas/16rh+8zIHqpIiCCzuDbVrFl+oHIlGTxy97LJjgL8vJRGPOIKjciEEDkw3E4+649OhcIOpdRw8TzJt0qnOFHDi8IMMFpqTDUrFeC7ebJd+2Y5tQB+OsHQPrkyPaB6OksLkWEzb6lhIH5ONLIn309dBt31whH+WbXvtsv803g07orZaNeyudfMRx2v81bk9d9H/vr6mNX5i//A5YHk94="
class Waffle:
def __init__(self, waffle):
self.waffle = waffle
def display(self, file=sys.stdout):
file.write(self.waffle)
class WaffleIron:
def __init__(self):
self.power = False
self.time = 0
self.full = False
self.contents = False
pass
def switchPower(self, power):
self.power = power
def fill(self, contents):
if not self.power:
raise RuntimeError("Turn on the iron first!")
if not isinstance(contents, WaffleBatter):
raise ValueError("Iron can only be filled with batter!")
self.contents = contents
self.time = time.time()
return self.contents.cooking_time
def contentsAreCooked(self):
return time.time() > (self.time+self.contents.cooking_time)
def getTimeLeft(self):
return max(0,(self.time+self.contents.cooking_time) - time.time())
def getContents(self):
if self.contentsAreCooked():
batter = self.contents.batter
cookedbatter = zlib.decompress(base64.b64decode(batter))
self.contents = Waffle(cookedbatter)
else:
raise RuntimeError("Waffle is not yet cooked!")
return self.contents
class BreakfastType:
def __init__(self):
raise NotImplementedError("BreakfastType is abstract")
class Waffles(BreakfastType):
def __init__(self):
pass
def make(self):
batter = WaffleBatter()
iron = WaffleIron()
iron.switchPower(True)
cooktime = iron.fill(batter)
cm, cs = divmod(cooktime,60)
if cm > 0:
print "Cooking time will be approximately %d minute%s and %d second%s"%(cm, 's'*(cm!=1), cs, 's'*(cs!=1))
else:
print "Cooking time will be approximately %d second%s"%(cs, 's'*(cs!=1))
while not iron.contentsAreCooked():
left = iron.getTimeLeft()
m,s = divmod(left+0.99,60)
sys.stdout.write("%02d:%02d"%(m,s))
sys.stdout.flush()
time.sleep(0.5)
sys.stdout.write("\x08"*5)
sys.stdout.flush()
print
waffle = iron.getContents()
iron.switchPower(False)
return waffle
class BreakfastMaker:
preferredBreakfasts = {'bushing':Waffles}
def __init__(self):
pass
def makeBreakfastFor(self, user):
if not user in self.preferredBreakfasts:
raise ValueError("I don't know how to make breakfast for %s!"%user)
maker = self.preferredBreakfasts[user]
breakfast = maker().make()
return breakfast
print "Breakfast Maker v0.2"
user = raw_input("Please enter your username: ")
maker = BreakfastMaker()
print "Making breakfast for %s..."%user
breakfast = maker.makeBreakfastFor(user)
print
print "Your breakfast is ready!"
print
breakfast.display()
print "\a"

248
pywii/ecmodule/_ecmodule.c Normal file
View File

@@ -0,0 +1,248 @@
// Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
// Copyright 2008 Hector Martin <marcan@marcansoft.com>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include "Python.h"
#include <stdint.h>
typedef uint8_t u8;
typedef uint32_t u32;
/* ----------------------------------------------------- */
static void elt_copy(u8 *d, const u8 *a)
{
memcpy(d, a, 30);
}
static void elt_zero(u8 *d)
{
memset(d, 0, 30);
}
static int elt_is_zero(const u8 *d)
{
u32 i;
for (i = 0; i < 30; i++)
if (d[i] != 0)
return 0;
return 1;
}
static void elt_add(u8 *d, const u8 *a, const u8 *b)
{
u32 i;
for (i = 0; i < 30; i++)
d[i] = a[i] ^ b[i];
}
static void elt_mul_x(u8 *d, const u8 *a)
{
u8 carry, x, y;
u32 i;
carry = a[0] & 1;
x = 0;
for (i = 0; i < 29; i++) {
y = a[i + 1];
d[i] = x ^ (y >> 7);
x = y << 1;
}
d[29] = x ^ carry;
d[20] ^= carry << 2;
}
static void elt_mul(u8 *d, const u8 *a, const u8 *b)
{
u32 i, n;
u8 mask;
elt_zero(d);
i = 0;
mask = 1;
for (n = 0; n < 233; n++) {
elt_mul_x(d, d);
if ((a[i] & mask) != 0)
elt_add(d, d, b);
mask >>= 1;
if (mask == 0) {
mask = 0x80;
i++;
}
}
}
static const u8 square[16] =
"\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55";
static void elt_square_to_wide(u8 *d, const u8 *a)
{
u32 i;
for (i = 0; i < 30; i++) {
d[2*i] = square[a[i] >> 4];
d[2*i + 1] = square[a[i] & 15];
}
}
static void wide_reduce(u8 *d)
{
u32 i;
u8 x;
for (i = 0; i < 30; i++) {
x = d[i];
d[i + 19] ^= x >> 7;
d[i + 20] ^= x << 1;
d[i + 29] ^= x >> 1;
d[i + 30] ^= x << 7;
}
x = d[30] & ~1;
d[49] ^= x >> 7;
d[50] ^= x << 1;
d[59] ^= x >> 1;
d[30] &= 1;
}
static void elt_square(u8 *d, const u8 *a)
{
u8 wide[60];
elt_square_to_wide(wide, a);
wide_reduce(wide);
elt_copy(d, wide + 30);
}
static void itoh_tsujii(u8 *d, const u8 *a, const u8 *b, u32 j)
{
u8 t[30];
elt_copy(t, a);
while (j--) {
elt_square(d, t);
elt_copy(t, d);
}
elt_mul(d, t, b);
}
static void elt_inv(u8 *d, const u8 *a)
{
u8 t[30];
u8 s[30];
itoh_tsujii(t, a, a, 1);
itoh_tsujii(s, t, a, 1);
itoh_tsujii(t, s, s, 3);
itoh_tsujii(s, t, a, 1);
itoh_tsujii(t, s, s, 7);
itoh_tsujii(s, t, t, 14);
itoh_tsujii(t, s, a, 1);
itoh_tsujii(s, t, t, 29);
itoh_tsujii(t, s, s, 58);
itoh_tsujii(s, t, t, 116);
elt_square(d, s);
}
/* ----------------------------------------------------- */
static PyObject *
_ec_elt_mul(PyObject *self /* Not used */, PyObject *args)
{
const char *a, *b;
char d[30];
int la, lb;
if (!PyArg_ParseTuple(args, "s#s#", &a, &la, &b, &lb))
return NULL;
if(la != 30 || lb != 30) {
PyErr_SetString(PyExc_ValueError, "ELT lengths must be 30");
return NULL;
}
elt_mul(d,a,b);
return Py_BuildValue("s#", d, 30);
}
static PyObject *
_ec_elt_inv(PyObject *self /* Not used */, PyObject *args)
{
const char *a;
char d[30];
int la;
if (!PyArg_ParseTuple(args, "s#", &a, &la))
return NULL;
if(la != 30) {
PyErr_SetString(PyExc_ValueError, "ELT length must be 30");
return NULL;
}
elt_inv(d,a);
return Py_BuildValue("s#", d, 30);
}
static PyObject *
_ec_elt_square(PyObject *self /* Not used */, PyObject *args)
{
const char *a;
char d[30];
int la;
if (!PyArg_ParseTuple(args, "s#", &a, &la))
return NULL;
if(la != 30) {
PyErr_SetString(PyExc_ValueError, "ELT length must be 30");
return NULL;
}
elt_square(d,a);
return Py_BuildValue("s#", d, 30);
}
/* List of methods defined in the module */
static struct PyMethodDef _ec_methods[] = {
{"elt_mul", (PyCFunction)_ec_elt_mul, METH_VARARGS, "Multiply two ELTs"},
{"elt_inv", (PyCFunction)_ec_elt_inv, METH_VARARGS, "Take the inverse of an ELT"},
{"elt_square", (PyCFunction)_ec_elt_square, METH_VARARGS, "Efficiently square an ELT"},
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called init_ec) */
static char _ec_module_documentation[] =
"Faster C versions of some ELT functions"
;
void
init_ec()
{
PyObject *m, *d;
/* Create the module and add the functions */
m = Py_InitModule4("_ec", _ec_methods,
_ec_module_documentation,
(PyObject*)NULL,PYTHON_API_VERSION);
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module _ec");
}

9
pywii/ecmodule/setup.py Normal file
View File

@@ -0,0 +1,9 @@
from distutils.core import setup, Extension
module1 = Extension('_ec',
sources = ['_ecmodule.c'])
setup (name = 'ELT_C',
version = '0.1',
description = 'C ELT functions',
ext_modules = [module1])

11
pywii/pywii-tools/addhash.py Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env python
import sys
import re
import pywii as wii
hash = wii.SHA.new(open(sys.argv[2]).read()).digest().encode("hex")
f = open(sys.argv[1], "r")
data = f.read()
f.close()
data = re.sub('@SHA1SUM@', hash, data)
open(sys.argv[3], "w").write(data)

15
pywii/pywii-tools/arclist.py Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env python
import sys, os, os.path, struct
import pywii as wii
arc = open(sys.argv[1], "rb")
tag, fstoff, fstsize, dataoff = struct.unpack(">IIII16x",arc.read(0x20))
arc.seek(fstoff)
fst = arc.read(fstsize)
fst = wii.WiiFST(fst)
fst.show()

26
pywii/pywii-tools/arcpack.py Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env python
import sys, os, os.path, struct
import pywii as wii
fstb = wii.WiiFSTBuilder(0x20)
fstb.addfrom(sys.argv[2])
arc = open(sys.argv[1],"wb")
# dummy generate to get length
fstlen = len(fstb.fst.generate())
dataoff = wii.align(0x20+fstlen,0x20)
fst = fstb.fst.generate(dataoff)
hdr = struct.pack(">IIII16x",0x55AA382d,0x20,fstlen,dataoff)
arc.write(hdr)
arc.write(fst)
wii.falign(arc,0x20)
for f in fstb.files:
data = open(f, "rb").read()
arc.write(data)
wii.falign(arc,0x20)
arc.close()

26
pywii/pywii-tools/certinfo.py Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
args = sys.argv[1:]
if args[0] == "-dpki":
wii.loadkeys_dpki()
args.pop(0)
else:
wii.loadkeys()
certfile = args.pop(0)
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "Certification file %s: " % certfile
cert = wii.WiiCert(open(certfile, "rb").read())
cert.showinfo(" ")
cert.showsig(certs," ")
print "Certificates:"
for cert in certlist:
cert.showinfo(" - ")
cert.showsig(certs," ")

28
pywii/pywii-tools/discinfo.py Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
isofile = sys.argv[1]
disc = wii.WiiDisc(isofile,readonly=True)
disc.showinfo()
partitions = disc.read_partitions()
parts = range(len(partitions))
try:
pnum = int(sys.argv[2])
partitions[pnum]
parts = [pnum]
except:
pass
for partno in parts:
part = wii.WiiCachedPartition(disc,partno)
part.showinfo()
pdat = wii.WiiPartitionData(part)
pdat.showinfo()

35
pywii/pywii-tools/dpkisign.py Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii
pywii.loadkeys_dpki()
args = sys.argv[1:]
mode = args.pop(0)
infile = args.pop(0)
outfile = args.pop(0)
certfile = args.pop(0)
issuer = args.pop(0)
if sys.argv[1] == "-cetk":
signed = pywii.WiiTik(open(infile, "rb").read())
elif sys.argv[1] == "-tmd":
signed = pywii.WiiTmd(open(infile, "rb").read())
else:
print "EYOUFAILIT"
sys.exit(1)
certs, certlist = pywii.parse_certs(open(certfile).read())
signed.update_issuer(issuer)
if not signed.sign(certs):
print "dpki signing failed"
sys.exit(1)
open(outfile, "wb").write(signed.data)
print "successfully signed %s" % outfile
sys.exit(0)

57
pywii/pywii-tools/ecchecksig.py Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python
import sys
import pywii as wii
if len(sys.argv) != 3:
print "Usage: %s keyfile.[priv|pub] infile"%sys.argv[0]
sys.exit(1)
if sys.argv[1] == "-":
k = sys.stdin.read()
else:
k = open(sys.argv[1],"rb").read()
if len(k) not in (30,60):
print "Failed to read key"
sys.exit(2)
if len(k) == 30:
print "Key is a private key, generating public key..."
q = wii.ec.priv_to_pub(k)
else:
q = k
print "Public key:"
pq = q.encode('hex')
print "X =",pq[:30]
print " ",pq[30:60]
print "Y =",pq[60:90]
print " ",pq[90:]
print
indata = open(sys.argv[2],"rb").read()
if len(indata) < 64 or indata[:4] != "SIG0":
print "Invalid header"
sys.exit(3)
r = indata[4:34]
s = indata[34:64]
sha = wii.SHA.new(indata[64:]).digest()
print "SHA1: %s"%sha.encode('hex')
print
print "Signature:"
print "R =",r[:15].encode('hex')
print " ",r[15:].encode('hex')
print "S =",s[:15].encode('hex')
print " ",s[15:].encode('hex')
print
if wii.ec.check_ecdsa(q,r,s,sha):
print "Signature is VALID"
else:
print "Signature is INVALID"
sys.exit(4)

33
pywii/pywii-tools/ecgenpriv.py Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env python
import sys, os
import pywii as wii
if len(sys.argv) != 2:
print "Usage: %s keyfile.priv"%sys.argv[0]
sys.exit(1)
print "Generating private key..."
k = wii.ec.gen_priv_key()
print "Private key:"
pk = k.encode('hex')
print "K =",pk[:30]
print " ",pk[30:]
print
print "Corresponding public key:"
q = wii.ec.priv_to_pub(k)
pq = q.encode('hex')
print "X =",pq[:30]
print " ",pq[30:60]
print "Y =",pq[60:90]
print " ",pq[90:]
fd = open(sys.argv[1],"wb")
os.fchmod(fd.fileno(), 0o600)
fd.write(k)
fd.close()
print "Saved private key to %s"%sys.argv[1]

30
pywii/pywii-tools/ecpriv2pub.py Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python
import sys
import pywii as wii
if len(sys.argv) not in (2,3):
print "Usage: %s keyfile.priv [keyfile.pub]"%sys.argv[0]
sys.exit(1)
if sys.argv[1] == "-":
k = sys.stdin.read()
else:
k = open(sys.argv[1],"rb").read()
if len(k) != 30:
print "Failed to read private key"
sys.exit(2)
print "Public key:"
q = wii.ec.priv_to_pub(k)
pq = q.encode('hex')
print "X =",pq[:30]
print " ",pq[30:60]
print "Y =",pq[60:90]
print " ",pq[90:]
if len(sys.argv) == 3:
fd = open(sys.argv[2],"wb")
fd.write(q)
fd.close()
print "Saved public key to %s"%sys.argv[2]

35
pywii/pywii-tools/ecsign.py Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env python
import sys
import pywii as wii
if len(sys.argv) != 4:
print "Usage: %s keyfile.priv infile outfile"%sys.argv[0]
sys.exit(1)
if sys.argv[1] == "-":
k = sys.stdin.read()
else:
k = open(sys.argv[1],"rb").read()
if len(k) != 30:
print "Failed to read private key"
sys.exit(2)
indata = open(sys.argv[2],"rb").read()
sha = wii.SHA.new(indata).digest()
print "SHA1: %s"%sha.encode('hex')
print
print "Signature:"
r,s = wii.ec.generate_ecdsa(k,sha)
print "R =",r[:15].encode('hex')
print " ",r[15:].encode('hex')
print "S =",s[:15].encode('hex')
print " ",s[15:].encode('hex')
outdata = "SIG0" + r + s + indata
fd = open(sys.argv[3],"wb")
fd.write(outdata)
fd.close()

59
pywii/pywii-tools/extract.py Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
def parseint(d):
if len(d) > 2 and d[0:2].lower()=='0x':
return int(d,16)
return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <file to extract to> [Partition offset] [length]"%sys.argv[0]
sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4]
partno = int(partno)
part_offset = 0
data_offset = 0
copy_length = None
if len(sys.argv) >= 5:
part_offset = parseint(sys.argv[4])
if len(sys.argv) == 6:
copy_length = parseint(sys.argv[5])
if copy_length is not None and copy_length < 0:
print "Error: negative copy length"
sys.exit(1)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False, checkhash=False)
if part_offset >= part.data_bytes:
print "Error: Offset past end of partition"
sys.exit(1)
if copy_length is None:
copy_length = part.data_bytes - part_offset
if copy_length > (part.data_bytes - part_offset):
print "Error: Length too large"
sys.exit(1)
dataf = open(data_name, "wb")
left = copy_length
offset = part_offset
while left > 0:
blocklen = min(left, 4*1024*1024)
d = part.read(offset, blocklen)
if len(d) != blocklen:
print "Part EOF reached!"
sys.exit(1)
dataf.write(d)
offset += blocklen
left -= blocklen
dataf.close()

26
pywii/pywii-tools/extractdol.py Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/python
import sys, os, os.path
sys.path.append(os.path.realpath(os.path.dirname(sys.argv[0]))+"/../Common")
import pywii as wii
wii.loadkeys(os.environ["HOME"]+os.sep+".wii")
if len(sys.argv) != 4:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <dol output>"%sys.argv[0]
sys.exit(1)
iso_name, partno, dol_name = sys.argv[1:4]
partno = int(partno)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False)
partdata = wii.WiiPartitionData(part)
dolf = open(dol_name, "wb")
dolf.write(partdata.dol)
dolf.close()

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
def parseint(d):
if len(d) > 2 and d[0:2].lower()=='0x':
return int(d,16)
return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <root path to extract to> "%sys.argv[0]
sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4]
partno = int(partno)
part_offset = 0
data_offset = 0
copy_length = None
if len(sys.argv) >= 5:
part_offset = parseint(sys.argv[4])
if len(sys.argv) == 6:
copy_length = parseint(sys.argv[5])
if copy_length is not None and copy_length < 0:
print "Error: negative copy length"
sys.exit(1)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False, checkhash=False)
if part_offset >= part.data_bytes:
print "Error: Offset past end of partition"
sys.exit(1)
if copy_length is None:
copy_length = part.data_bytes - part_offset
if copy_length > (part.data_bytes - part_offset):
print "Error: Length too large"
sys.exit(1)
dataf = open(data_name, "wb")
left = copy_length
offset = part_offset
while left > 0:
blocklen = min(left, 4*1024*1024)
d = part.read(offset, blocklen)
if len(d) != blocklen:
print "Part EOF reached!"
sys.exit(1)
dataf.write(d)
offset += blocklen
left -= blocklen
dataf.close()

24
pywii/pywii-tools/getappldr.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
if len(sys.argv) != 5:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <apploader text> <apploader trailer>"%sys.argv[0]
sys.exit(1)
iso_name, partno, app_name, trail_name = sys.argv[1:5]
partno = int(partno)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False)
partdata = wii.WiiPartitionData(part)
apploader = partdata.apploader
apploader.showinfo()
open(app_name,"wb").write(apploader.text)
open(trail_name,"wb").write(apploader.trailer)

68
pywii/pywii-tools/inject.py Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
def parseint(d):
if len(d) > 2 and d[0:2].lower()=='0x':
return int(d,16)
return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <file to inject> [Partition offset] [data offset] [length]"%sys.argv[0]
sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4]
partno = int(partno)
part_offset = 0
data_offset = 0
copy_length = None
if len(sys.argv) >= 5:
part_offset = parseint(sys.argv[4])
if len(sys.argv) >= 6:
data_offset = parseint(sys.argv[5])
if len(sys.argv) == 7:
copy_length = parseint(sys.argv[6])
data_len = os.stat(data_name).st_size
if copy_length == None:
copy_length = data_len - data_offset
copy_end = data_offset + copy_length
if copy_length < 0:
print "Error: negative copy length"
sys.exit(1)
if copy_end > data_len:
print "Error: data file is too small"
sys.exit(1)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False, checkhash=False)
dataf = open(data_name, "rb")
dataf.seek(data_offset)
left = copy_length
offset = part_offset
while left > 0:
blocklen = min(left, 4*1024*1024)
d = dataf.read(blocklen)
if len(d) != blocklen:
print "File EOF reached!"
sys.exit(1)
part.write(offset, d)
offset += blocklen
left -= blocklen
part.flush()
part.update()
part.tmd.null_signature()
part.tmd.brute_sha()
part.updatetmd()

31
pywii/pywii-tools/injectdol.py Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
if len(sys.argv) != 4:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <dol to inject>"%sys.argv[0]
sys.exit(1)
iso_name, partno, dol_name = sys.argv[1:4]
partno = int(partno)
doldata = open(dol_name, "rb").read()
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False)
partdata = wii.WiiPartitionData(part)
partdata.replacedol(doldata)
part.flush()
part.update()
part.tmd.null_signature()
part.tmd.brute_sha()
part.updatetmd()
part.showinfo()

28
pywii/pywii-tools/partsetios.py Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
if len(sys.argv) != 4:
print "Usage:"
print " python %s <encrypted ISO> <partition number> <IOS version>"%sys.argv[0]
print " IOS version should be just the minor number (16, 33, etc) in decimal"
sys.exit(1)
iso_name, partno, ios = sys.argv[1:4]
partno = int(partno)
iosno = int(ios)
disc = wii.WiiDisc(iso_name)
disc.showinfo()
part = wii.WiiCachedPartition(disc, partno, cachesize=32, debug=False)
part.tmd.sys_version = 0x100000000 + iosno
part.tmd.update()
part.tmd.null_signature()
part.tmd.brute_sha()
part.updatetmd()
part.showinfo()

1
pywii/pywii-tools/pywii Symbolic link
View File

@@ -0,0 +1 @@
../Common/pywii

20
pywii/pywii-tools/rsapatch.py Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
def hexdump(s):
return ' '.join(map(lambda x: "%02x"%x,map(ord,s)))
isofile = sys.argv[1]
disc = WiiDisc(isofile)
disc.showinfo()
part = WiiPartition(disc,int(sys.argv[2]))
part.showinfo()
part.tmd.update_signature(file("signthree.bin").read())
part.tmd.brute_sha()
part.updatetmd()
part.showinfo()

10
pywii/pywii-tools/saveinfo.py Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
savefile = sys.argv[1]
save = wii.WiiSave(savefile)
save.showcerts()

17
pywii/pywii-tools/tikfix.py Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
tikfile = sys.argv[1]
print "fixing Tik file %s " % tikfile
tik = wii.WiiTik(open(tikfile, "rb").read())
tik.null_signature()
tik.brute_sha()
tik.update()
f = open(tikfile,"wb")
f.write(tik.data)
f.close()

28
pywii/pywii-tools/tikinfo.py Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
args = sys.argv[1:]
if args[0] == "-dpki":
wii.loadkeys_dpki()
args.pop(0)
else:
wii.loadkeys()
tikfile = args.pop(0)
certs = None
if len(args) > 0:
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "ETicket file %s:"%tikfile
tik = wii.WiiTik(open(tikfile, "rb").read())
tik.showinfo(" ")
if certs is not None:
tik.showsig(certs," ")
print "Certificates:"
for cert in certlist:
cert.showinfo(" - ")
cert.showsig(certs," ")

18
pywii/pywii-tools/tmdfix.py Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
tmdfile = sys.argv[1]
print "TMD file %s:"%tmdfile
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.null_signature()
tmd.brute_sha()
tmd.update()
tmd.parse()
tmd.showinfo(" ")
f = open(tmdfile,"wb")
f.write(tmd.data)
f.close()

28
pywii/pywii-tools/tmdinfo.py Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
args = sys.argv[1:]
if args[0] == "-dpki":
wii.loadkeys_dpki()
args.pop(0)
else:
wii.loadkeys()
tmdfile = args.pop(0)
certs = None
if len(args) > 0:
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "TMD file %s:"%tmdfile
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.showinfo(" ")
if certs is not None:
tmd.showsig(certs," ")
print "Certificates:"
for cert in certlist:
cert.showinfo(" - ")
cert.showsig(certs," ")

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
from Crypto.Hash import SHA
wii.loadkeys()
args = sys.argv[1:]
tmdfile = args.pop(0)
indir = args.pop(0)
print "updating content records of TMD file %s" % tmdfile
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
for i, cr in enumerate(tmd.get_content_records()):
data = open(os.path.join(indir, "%08X" % cr.cid), "rb").read()
cr.sha = SHA.new(data).digest()
cr.size = len(data)
tmd.update_content_record(i, cr)
tmd.null_signature()
tmd.brute_sha()
tmd.update()
f = open(tmdfile, "wb")
f.write(tmd.data)
f.close()

23
pywii/pywii-tools/tmdvers.py Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
args = sys.argv[1:]
tmdfile = args.pop(0)
if len(args) == 2:
newvers = int(args.pop(0)) << 8 | int(args.pop(0))
else:
newvers = int(args.pop(0), 16)
print "setting version of TMD file %s to 0x%04x" % (tmdfile, newvers)
tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.title_version = newvers
tmd.update()
f = open(tmdfile,"wb")
f.write(tmd.data)
f.close()

16
pywii/pywii-tools/wadinfo.py Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
args = sys.argv[1:]
if args[0] == "-dpki":
wii.loadkeys_dpki()
args.pop(0)
else:
wii.loadkeys()
wadfile = args.pop(0)
wad = wii.WiiWad(wadfile)
wad.showinfo()

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
wii.loadkeys()
wadfile = sys.argv[1]
indir = sys.argv[2]
tmd = wii.WiiTmd(open(indir+os.sep+"tmd", "rb").read())
tik = wii.WiiTik(open(indir+os.sep+"cetk", "rb").read())
certs, certlist = wii.parse_certs(open(os.path.join(indir, "certs"), "rb").read())
footer = open(indir+os.sep+"footer", "rb").read()
wad = wii.WiiWadMaker(wadfile, tmd, tik, certlist, footer, nandwad=True)
for i,ct in enumerate(tmd.get_content_records()):
data = open(indir+os.sep+"%08X"%ct.cid, "rb").read()
wad.adddata(data,ct.cid)
wad.finish()
if not wad.tik.signcheck(wad.certs):
wad.tik.null_signature()
wad.tik.brute_sha()
wad.updatetik()
if not wad.tmd.signcheck(wad.certs):
wad.tmd.null_signature()
wad.tmd.brute_sha()
wad.updatetmd()

40
pywii/pywii-tools/wadpack.py Executable file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
args = sys.argv[1:]
if args[0] == "-dpki":
wii.loadkeys_dpki()
args.pop(0)
else:
wii.loadkeys()
wadfile = args.pop(0)
indir = args.pop(0)
tmd = wii.WiiTmd(open(os.path.join(indir, "tmd"), "rb").read())
tik = wii.WiiTik(open(os.path.join(indir, "cetk"), "rb").read())
certs, certlist = wii.parse_certs(open(os.path.join(indir, "certs"), "rb").read())
footer = open(os.path.join(indir, "footer"), "rb").read()
wad = wii.WiiWadMaker(wadfile, tmd, tik, certlist, footer)
for i,ct in enumerate(tmd.get_content_records()):
data = open(os.path.join(indir, "%08X" % ct.cid), "rb").read()
wad.adddata(data,ct.cid)
wad.finish()
if not wad.tik.signcheck(wad.certs):
wad.tik.null_signature()
wad.tik.brute_sha()
wad.updatetik()
if not wad.tmd.signcheck(wad.certs):
wad.tmd.null_signature()
wad.tmd.brute_sha()
wad.updatetmd()

44
pywii/pywii-tools/wadunpack.py Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env python
import sys, os, os.path
import pywii as wii
args = sys.argv[1:]
if args[0] == "-dpki":
wii.loadkeys_dpki()
args.pop(0)
else:
wii.loadkeys()
wadfile = args.pop(0)
outdir = args.pop(0)
wad = wii.WiiWad(wadfile)
wad.showinfo()
if not os.path.isdir(outdir):
os.mkdir(outdir)
for ct in wad.tmd.get_content_records():
data = wad.getcontent(ct.index)
f = open(os.path.join(outdir, "%08X" % ct.cid),"wb")
f.write(data)
f.close()
f = open(os.path.join(outdir, "cetk"),"wb")
f.write(wad.tik.data)
f.close()
f = open(os.path.join(outdir, "tmd"),"wb")
f.write(wad.tmd.data)
f.close()
f = open(os.path.join(outdir, "certs"),"wb")
for cert in wad.certlist:
f.write(cert.data)
wii.falign(f,0x40)
f.close()
f = open(os.path.join(outdir, "footer"),"wb")
f.write(wad.footer)
f.close()