Compare commits

6 Commits

Author SHA1 Message Date
Archie Halliwell
a31c3bbcc6 fix order so it is the same as in master 2025-04-14 21:35:09 +09:00
Archie Halliwell
9a46141a82 fix TypeError 2025-04-14 21:35:09 +09:00
Archie Halliwell
561041a71c fix freetype dependencies 2025-04-14 21:35:09 +09:00
Archie Halliwell
43de8436d6 fix issue #19 2025-04-14 21:35:09 +09:00
Hector Martin
1536182957 Alameda fixes 2021-03-22 11:49:55 +09:00
Hector Martin
cad274a7fb WIP: Quick and dirty python3 port 2021-03-22 11:14:07 +09:00
41 changed files with 2424 additions and 2468 deletions

View File

@@ -1,85 +1,3 @@
# ARCHIVED
This repository is archived and will not accept any further contributions.
Like most Wii homebrew software, this software depends on [libogc](https://github.com/devkitPro/libogc).
After development of The Homebrew Channel had already started, we discovered that large portions of libogc
were stolen directly from the Nintendo SDK or games using the Nintendo SDK (decompiled and cleaned up).
We thought that at least significant parts of libogc, such as its threading implementation, were original,
and reluctantly continued to use the project while distancing ourselves from it.
It has recently been revealed that the threading/OS implementation in libogc is, in fact,
[stolen from RTEMS](https://github.com/derek57/libogc). The authors of libogc didn't just steal proprietary
Nintendo code, but also saw it fit to steal an *open source* RTOS and remove all attribution and copyright
information. This goes far beyond ignorance about the copyright implications of reverse engineering Nintendo
binaries, and goes straight into outright deliberate, malicious code theft and copyright infringement.
The current developers of libogc are [not interested](https://github.com/devkitPro/libogc/issues/201) in
tracking this issue, finding a solution, nor informing the community of the problematic copyright status of
the project. When we filed an issue about it, they immediately closed it, replied with verbal abuse, and then
completely deleted it from public view.
For this reason, we consider it impossible to legally and legitimately compile this software at this point,
and cannot encourage any further development.
The Wii homebrew community was all built on top of a pile of lies and copyright infringement, and it's all
thanks to shagkur (who did the stealing) and the rest of the team (who enabled it and did nothing when it was
discovered). Together, the developers deceived everyone into believing their work was original.
Please demand that the leaders and major contributors to console or other proprietary device SDKs and
toolkits that you use and work with do things legally, and do not tolerate this kind of behavior.
If you wish to check for yourself, for example, you can compare
[this](https://github.com/devkitPro/libogc/blob/52c525a13fd1762c10395c78875e3260f94368b5/libogc/lwp_threads.c#L580)
function in libogc to
[this](https://github.com/atgreen/RTEMS/blob/2f200c7e642c214accb7cc6bd7f0f1784deec833/c/src/exec/score/src/thread.c#L385)
function in a really old version of RTEMS. While the code has been simplified and many identifiers renamed, it
is clear that the libogc version is a direct descendant of the RTEMS version. It is not possible for two code
implementations to end up this similar purely by chance.
**Update**: The libogc developers have restored the issue and are now claiming that the code
[was not stolen](https://mardy.it/blog/2025/04/no-libogc-did-not-steal-rtems-code.html). What they are in fact
arguing is that the code was not copied verbatim and then changed to obfuscate its origin, but rather that it was
developed by "referencing" RTEMS. Indeed, the original commits of the code to libogc are a less complete copy
of RTEMS than the current version. What that means is that, instead of literally duplicating RTEMS and then
reducing it, they instead *piecewise* incorporated RTEMS code by re-typing or copyediting it line by line,
over time. This is equivalent to opening up a copy of The Lord of the Rings, pulling up a blank document, and
meticulously re-typing the whole story in different words, with different names for the characters, while
preserving the entirety of the plot. Unfortunately for shagkur and the other libogc authors, this is still
plagiarism and copyright infringement. It doesn't matter that they didn't literally Ctrl-C and Ctrl-V the
entirety of RTEMS. The end result is, very clearly, still plagiarized.
Feel free to check out another example:
[this RTEMS function](https://github.com/atgreen/RTEMS/blob/2f200c7e642c214accb7cc6bd7f0f1784deec833/c/src/exec/score/src/thread.c#L1141)
is 1:1 identical to
[this libogc function](https://github.com/devkitPro/libogc/blob/52c525a13fd1762c10395c78875e3260f94368b5/libogc/lwp_threads.c#L388),
other than slightly renamed identifiers, different code formatting, and the `prependit` parameter in the
libogc version and `if` branch (which does seem to be a novel addition). It would be clear in any court of
law that this constitutes copyright infringement, regardless of whether it was achieved in one shot or
incrementally over time. It is simply not possible for this kind of non-trivial code to wind up completely
identical like this, purely on accident. This kind of conduct is, in fact, the same conduct that led libogc
to contain large parts of decompiled Nintendo SDK code verbatim. We just thought that that was a result of a
lack of understanding (or caring) of how copyright works when it related to reverse engineering proprietary
binary code, but it seems shagkur believes that he is entitled to manually copy and re-type *any* code, even
open source code, and the mere action of doing so erases its original copyright.
WinterMute is also is not innocent, and not just by virtue of being complicit with shagkur and enabling his
plagiarism behavior. He, himself, was previously
[caught](https://github.com/devkitPro/libnds/commit/426a369220dcb43320e203f9087de74e43452d84#diff-f376c160388ca187fe35e962eb047fe606338869b515128a6257d3a7a6694ff0R17-R25)
referencing the official Nintendo DS ("nitro") SDK while writing code for libnds\*. WinterMute has a huge
siege mentality issue when it comes to DevkitPro, which is why nobody has been able to get through to him,
as any criticism of his work or the way he manages his project has always been met with extreme hostility.
This is why nothing has ever been done about these issues with the project, even after all these years.
\* Edited to note: This should not be taken to imply that any or all of libnds itself is tainted with SDK
code. The commit in question itself only adds fairly standard cache maintenance functions, and is not itself
evidence that there was substantial copying. It just reflects poorly on WinterMute that he was referencing
the leaked SDK, especially for something as trivial as this. For a more thorough take on the general
mismanagement of the devkitPro project as a whole, please read
[this](https://heyquark.com/brew/2020/07/13/leaving-devkitpro/) blog post. The stories told there track
very closely with our experience with that team way back in the Wii days, and it seems nothing has changed
nor improved after all these years.
# The Homebrew Channel # The Homebrew Channel
This repository contains the public release of the source code for This repository contains the public release of the source code for

View File

@@ -14,14 +14,14 @@ export ALAMEDA := $(CURDIR)/../../pywii/Alameda
export PNG2TPL := $(CURDIR)/tools/png2tpl$(EXE) export PNG2TPL := $(CURDIR)/tools/png2tpl$(EXE)
export MKBNS := $(CURDIR)/tools/mkbns$(EXE) export MKBNS := $(CURDIR)/tools/mkbns$(EXE)
export LZ77 := $(CURDIR)/tools/lz77$(EXE) export LZ77 := $(CURDIR)/tools/lz77$(EXE)
export ADDIMD5 := python2 $(CURDIR)/tools/addimd5.py export ADDIMD5 := python3 $(CURDIR)/tools/addimd5.py
export ARCPACK := python2 $(PYWII)/arcpack.py export ARCPACK := python3 $(PYWII)/arcpack.py
export SOX := sox export SOX := sox
all: channel.imet all: channel.imet
channel.imet: build/data.arc names.txt tools/join-imet.py channel.imet: build/data.arc names.txt tools/join-imet.py
python2 tools/join-imet.py $@ build/data.arc build/icon.arc build/banner.arc build/sound.bns names.txt python3 tools/join-imet.py $@ build/data.arc build/icon.arc build/banner.arc build/sound.bns names.txt
build/data.arc : build/data/meta/icon.bin build/data/meta/banner.bin build/data/meta/sound.bin build/data.arc : build/data/meta/icon.bin build/data/meta/banner.bin build/data/meta/sound.bin
$(ARCPACK) $@ build/data $(ARCPACK) $@ build/data
@@ -45,9 +45,9 @@ build/%.raw : sound/%.wav
$(SOX) $< -r 32000 -c 2 -e signed-integer -b 16 -t raw $@ $(SOX) $< -r 32000 -c 2 -e signed-integer -b 16 -t raw $@
testi : channel.imet testi : channel.imet
python2 $(ALAMEDA)/Alameda.py channel.imet icon python3 $(ALAMEDA)/Alameda.py channel.imet icon
testb : channel.imet testb : channel.imet
python2 $(ALAMEDA)/Alameda.py channel.imet banner python3 $(ALAMEDA)/Alameda.py channel.imet banner
$(PNG2TPL): tools/*.c $(PNG2TPL): tools/*.c
$(MAKE) -C tools png2tpl$(EXE) $(MAKE) -C tools png2tpl$(EXE)

View File

@@ -19,7 +19,7 @@ endif
../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS) : mk$(TYPE).py ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS) : mk$(TYPE).py
@[ ! -d ../build/$(TYPE)/arc/anim ] && mkdir -p ../build/$(TYPE)/arc/anim || true @[ ! -d ../build/$(TYPE)/arc/anim ] && mkdir -p ../build/$(TYPE)/arc/anim || true
@[ ! -d ../build/$(TYPE)/arc/blyt ] && mkdir -p ../build/$(TYPE)/arc/blyt || true @[ ! -d ../build/$(TYPE)/arc/blyt ] && mkdir -p ../build/$(TYPE)/arc/blyt || true
python2 mk$(TYPE).py ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS) python3 mk$(TYPE).py ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS)
../build/$(TYPE).arc : $(TPLS) ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS) ../build/$(TYPE).arc : $(TPLS) ../build/$(TYPE)/arc/blyt/$(TYPE).brlyt $(ANIMS)
$(ARCPACK) ../build/$(TYPE).arc ../build/$(TYPE) $(ARCPACK) ../build/$(TYPE).arc ../build/$(TYPE)

View File

@@ -244,7 +244,7 @@ class BubbleInstance:
for i in tps: for i in tps:
if len(i.Triplets) > 0: if len(i.Triplets) > 0:
if i.Triplets[-1][0] >= self.Start: if i.Triplets[-1][0] >= self.Start:
print "WTF at %s: %f >= %f"%(self.Picture.Name,i.Triplets[-1][0],self.Start) print("WTF at %s: %f >= %f"%(self.Picture.Name,i.Triplets[-1][0],self.Start))
raise RuntimeError("We Have A Problem") raise RuntimeError("We Have A Problem")
brlan.Anim[self.Picture.Name][Brlan.A_COORD][Brlan.C_X].Triplets.append((self.Start, self.X, 0)) brlan.Anim[self.Picture.Name][Brlan.A_COORD][Brlan.C_X].Triplets.append((self.Start, self.X, 0))
@@ -293,15 +293,15 @@ class BubbleCollection:
#print "Freeing instance: [%f-%f]"%(user.Start,user.End) #print "Freeing instance: [%f-%f]"%(user.Start,user.End)
tis[i] = pic, None tis[i] = pic, None
def printinstances(self): def printinstances(self):
print "Type Instances:" print("Type Instances:")
for tid, tis in enumerate(self.TypeInstances): for tid, tis in enumerate(self.TypeInstances):
print " Type Instances for type %d (%s):"%(tid, self.BubbleTypes[tid][0].Name) print(" Type Instances for type %d (%s):"%(tid, self.BubbleTypes[tid][0].Name))
for i, ti in enumerate(tis): for i, ti in enumerate(tis):
pic, user = ti pic, user = ti
if user is None: if user is None:
print " %d: Picture %s, free"%(i,pic.Name) print(" %d: Picture %s, free"%(i,pic.Name))
else: else:
print " %d: Picture %s, user: %s [%f-%f]"%(i,pic.Name,repr(user),user.Start,user.End) print(" %d: Picture %s, user: %s [%f-%f]"%(i,pic.Name,repr(user),user.Start,user.End))
def render(self): def render(self):
for t,c in self.BubbleTypes: for t,c in self.BubbleTypes:
t.makemat(self.Brlyt) t.makemat(self.Brlyt)
@@ -330,9 +330,9 @@ class BubbleCollection:
i.render(self.Brlan) i.render(self.Brlan)
#self.printinstances() #self.printinstances()
print "Fake Start",fakeStart print("Fake Start",fakeStart)
print "Loop Start",loopStart print("Loop Start",loopStart)
print "Loop End",loopEnd print("Loop End",loopEnd)
col = BubbleCollection(brlyt, brlan, bubblepane) col = BubbleCollection(brlyt, brlan, bubblepane)
col.addtype(BubbleType("abubble1", 48, 48),1) col.addtype(BubbleType("abubble1", 48, 48),1)
@@ -374,10 +374,10 @@ for i in col.Instances:
col.render() col.render()
brldata = brlyt.Pack() brldata = brlyt.Pack()
open(sys.argv[1],"w").write(brldata) open(sys.argv[1],"wb").write(brldata)
bradata = brlan.Pack(loopStart) bradata = brlan.Pack(loopStart)
open(sys.argv[2],"w").write(bradata) open(sys.argv[2],"wb").write(bradata)
bradata = brlan.Pack(loopStart, loopEnd) bradata = brlan.Pack(loopStart, loopEnd)
open(sys.argv[3],"w").write(bradata) open(sys.argv[3],"wb").write(bradata)

View File

@@ -111,7 +111,7 @@ brlyt.RootPane.Add(tit)
brldata = brlyt.Pack() brldata = brlyt.Pack()
open(sys.argv[1],"w").write(brldata) open(sys.argv[1],"wb").write(brldata)
brlan = Brlan() brlan = Brlan()
@@ -177,6 +177,6 @@ brlan.Anim['shadow'][Brlan.A_COORD][Brlan.C_X].repsimple(0, 960, 2, -45, -0.1, 4
bradata = brlan.Pack(60*16) bradata = brlan.Pack(60*16)
for a,b,c in brlan.Anim['waveb'][Brlan.A_COORD][Brlan.C_X].Triplets: for a,b,c in brlan.Anim['waveb'][Brlan.A_COORD][Brlan.C_X].Triplets:
print a,b,c print(a,b,c)
open(sys.argv[2],"w").write(bradata) open(sys.argv[2],"wb").write(bradata)

View File

@@ -1,12 +1,12 @@
import md5, sys, struct import hashlib, sys, struct
data= open(sys.argv[1]).read() data= open(sys.argv[1], "rb").read()
digest = md5.new(data).digest() digest = hashlib.md5(data).digest()
hdr = struct.pack(">4sI8x","IMD5",len(data)) hdr = struct.pack(">4sI8x",b"IMD5",len(data))
f2 = open(sys.argv[2],"w") f2 = open(sys.argv[2],"wb")
f2.write(hdr) f2.write(hdr)
f2.write(digest) f2.write(digest)
f2.write(data) f2.write(data)

View File

@@ -1,8 +1,8 @@
import os, sys, struct, md5 import os, sys, struct, hashlib
output, datafile, iconarc, bannerarc, soundbns, namesfile = sys.argv[1:] output, datafile, iconarc, bannerarc, soundbns, namesfile = sys.argv[1:]
data = open(datafile,"r").read() data = open(datafile,"rb").read()
names={} names={}
@@ -11,7 +11,7 @@ for i in open(namesfile,"r"):
while b[-1] == "\n": while b[-1] == "\n":
b = b[:-1] b = b[:-1]
b = b.replace("\\n","\n") b = b.replace("\\n","\n")
names[a] = b.decode("utf-8") names[a] = b
def getsize(x): def getsize(x):
return os.stat(x).st_size return os.stat(x).st_size
@@ -20,29 +20,29 @@ def pad(x,l):
if len(x) > l: if len(x) > l:
raise ValueError("%d > %d",len(x),l) raise ValueError("%d > %d",len(x),l)
n = l-len(x) n = l-len(x)
return x + "\x00"*n return x + b"\x00"*n
imet = "\x00"*0x40 imet = b"\x00"*0x40
imet += struct.pack(">4sIIIIII","IMET",0x600,3,getsize(iconarc),getsize(bannerarc),getsize(soundbns),1) imet += struct.pack(">4sIIIIII",b"IMET",0x600,3,getsize(iconarc),getsize(bannerarc),getsize(soundbns),1)
for i in ["jp", "en", "de", "fr", "sp", "it", "nl", "cn", None, "ko"]: for i in ["jp", "en", "de", "fr", "sp", "it", "nl", "cn", None, "ko"]:
try: try:
imet += pad(names[i].encode("UTF-16BE"),0x54) imet += pad(names[i].encode("UTF-16BE"),0x54)
except KeyError: except KeyError:
imet += "\x00"*0x54 imet += b"\x00"*0x54
imet += "\x00"*(0x600 - len(imet)) imet += b"\x00"*(0x600 - len(imet))
imet = imet[:-16] + md5.new(imet).digest() imet = imet[:-16] + hashlib.md5(imet).digest()
open(output,"w").write(imet) open(output,"wb").write(imet)
f = open(sys.argv[1],"w") f = open(sys.argv[1],"wb")
f.write(imet) f.write(imet)
f.write(data) f.write(data)
fsize = f.tell() fsize = f.tell()
if (fsize % 20) != 0: if (fsize % 20) != 0:
f.write("\x00"*(20-(fsize%20))) f.write(b"\x00"*(20-(fsize%20)))
f.close() f.close()

File diff suppressed because it is too large Load Diff

View File

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

@@ -1,3 +1,3 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
from wii import * from .wii import *

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python2 #!/usr/bin/python3
# Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org> # Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
# Copyright 2008 Hector Martin <marcan@marcansoft.com> # Copyright 2008 Hector Martin <marcan@marcansoft.com>
# Licensed under the terms of the GNU GPL, version 2 # Licensed under the terms of the GNU GPL, version 2
@@ -12,11 +12,11 @@ except ImportError:
from Crypto.Util.number import bytes_to_long, long_to_bytes from Crypto.Util.number import bytes_to_long, long_to_bytes
# y**2 + x*y = x**3 + x + b # 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"+\ ec_b = (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" b"\x3b\x33\x3b\x20\xe9\xce\x42\x81\xfe\x11\x5f\x7d\x8f\x90\xad")
def hexdump(s,sep=""): def hexdump(s,sep=""):
return sep.join(map(lambda x: "%02x"%ord(x),s)) return sep.join(["%02x"%ord(x) for x in s])
def bhex(s,sep=""): def bhex(s,sep=""):
return hexdump(long_to_bytes(s,30),sep) return hexdump(long_to_bytes(s,30),sep)
@@ -41,20 +41,20 @@ class ByteArray(array):
else: else:
array.__setitem__(self, item, value & 0xFF) array.__setitem__(self, item, value & 0xFF)
def __long__(self): def __long__(self):
return bytes_to_long(self.tostring()) return bytes_to_long(self.tobytes())
def __str__(self): def __str__(self):
return ''.join(["%02x"%ord(x) for x in self.tostring()]) return ''.join(["%02x"%x for x in self.tobytes()])
def __repr__(self): def __repr__(self):
return "ByteArray('%s')"%''.join(["\\x%02x"%ord(x) for x in self.tostring()]) return "ByteArray('%s')"%''.join(["\\x%02x"%x for x in self.tobytes()])
class ELT_PY: class ELT_PY:
SIZEBITS=233 SIZEBITS=233
SIZE=(SIZEBITS+7)/8 SIZE=(SIZEBITS+7)/8
square = ByteArray("\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55") square = ByteArray(b"\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55")
def __init__(self, initializer=None): def __init__(self, initializer=None):
if isinstance(initializer, long) or isinstance(initializer, int): if isinstance(initializer, int) or isinstance(initializer, int):
self.d = ByteArray(long_to_bytes(initializer,self.SIZE)) self.d = ByteArray(long_to_bytes(initializer,self.SIZE))
elif isinstance(initializer, str): elif isinstance(initializer, bytes):
self.d = ByteArray(initializer) self.d = ByteArray(initializer)
elif isinstance(initializer, ByteArray): elif isinstance(initializer, ByteArray):
self.d = ByteArray(initializer) self.d = ByteArray(initializer)
@@ -80,12 +80,12 @@ class ELT_PY:
return cmp(self.d,other.d) return cmp(self.d,other.d)
def __long__(self): def __long__(self):
return long(self.d) return int(self.d)
def __repr__(self): def __repr__(self):
return repr(self.d).replace("ByteArray","ELT") return repr(self.d).replace("ByteArray","ELT")
def __str__(self): def __bytes__(self):
return str(self.d) return bytes(self.d)
def __nonzero__(self): def __bool__(self):
for x in self.d: for x in self.d:
if x != 0: if x != 0:
return True return True
@@ -184,21 +184,21 @@ class ELT_PY:
def __setitem__(self,item,value): def __setitem__(self,item,value):
self.d[item] = value self.d[item] = value
def tobignum(self): def tobignum(self):
return bytes_to_long(self.d.tostring()) return bytes_to_long(self.d.tobytes())
def tobytes(self): def tobytes(self):
return self.d.tostring() return self.d.tobytes()
class ELT_C(ELT_PY): class ELT_C(ELT_PY):
def __mul__(self,other): def __mul__(self,other):
if not isinstance(other,ELT): if not isinstance(other,ELT):
return NotImplemented return NotImplemented
return ELT(_ec.elt_mul(self.d.tostring(),other.d.tostring())) return ELT(_ec.elt_mul(self.d.tobytes(),other.d.tobytes()))
def __rdiv__(self,other): def __rdiv__(self,other):
if other != 1: if other != 1:
return ELT_PY.__rdiv__(self,other) return ELT_PY.__rdiv__(self,other)
return ELT(_ec.elt_inv(self.d.tostring())) return ELT(_ec.elt_inv(self.d.tobytes()))
def _square(self): def _square(self):
return ELT(_ec.elt_square(self.d.tostring())) return ELT(_ec.elt_square(self.d.tobytes()))
if fastelt: if fastelt:
ELT = ELT_C ELT = ELT_C
@@ -207,7 +207,7 @@ else:
class Point: class Point:
def __init__(self,x,y=None): def __init__(self,x,y=None):
if isinstance(x,str) and (y is None) and (len(x) == 60): if isinstance(x,bytes) and (y is None) and (len(x) == 60):
self.x = ELT(x[:30]) self.x = ELT(x[:30])
self.y = ELT(x[30:]) self.y = ELT(x[30:])
elif isinstance(x,Point): elif isinstance(x,Point):
@@ -292,7 +292,7 @@ class Point:
return "(%s,%s)"%(str(self.x),str(self.y)) return "(%s,%s)"%(str(self.x),str(self.y))
def __repr__(self): def __repr__(self):
return "Point"+str(self) return "Point"+str(self)
def __nonzero__(self): def __bool__(self):
return self.x or self.y return self.x or self.y
def tobytes(self): def tobytes(self):
return self.x.tobytes() + self.y.tobytes() return self.x.tobytes() + self.y.tobytes()
@@ -305,15 +305,15 @@ def bn_inv(a,N):
# order of the addition group of points # order of the addition group of points
ec_N = bytes_to_long( ec_N = bytes_to_long(
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+\ b"\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") b"\x13\xe9\x74\xe7\x2f\x8a\x69\x22\x03\x1d\x26\x03\xcf\xe0\xd7")
# base point # base point
ec_G = Point( ec_G = Point(
"\x00\xfa\xc9\xdf\xcb\xac\x83\x13\xbb\x21\x39\xf1\xbb\x75\x5f"+ b"\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"+ b"\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"+ b"\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") b"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52")
def generate_ecdsa(k, sha): def generate_ecdsa(k, sha):
k = bytes_to_long(k) k = bytes_to_long(k)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
# Copyright 2008 Hector Martin <marcan@marcansoft.com> # Copyright 2008 Hector Martin <marcan@marcansoft.com>
# Licensed under the terms of the GNU GPL, version 2 # Licensed under the terms of the GNU GPL, version 2
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
@@ -21,7 +21,7 @@ except ImportError:
from Crypto.Util.number import bytes_to_long, long_to_bytes from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.Signature import pkcs1_15 from Crypto.Signature import pkcs1_15
import ec from . import ec
WII_RSA4096 = 0 WII_RSA4096 = 0
WII_RSA2048 = 1 WII_RSA2048 = 1
@@ -30,13 +30,13 @@ WII_ECDSA = 2
sigtypes = [ "RSA-4096", "RSA-2048", "EC-DSA" ] sigtypes = [ "RSA-4096", "RSA-2048", "EC-DSA" ]
def load_rsa_key(issuer): def load_rsa_key(issuer):
print "Loading private key for %s" % issuer print("Loading private key for %s" % issuer)
path = os.path.join(os.environ["HOME"], ".wii", "dpki", issuer + ".pem") path = os.path.join(os.environ["HOME"], ".wii", "dpki", issuer + ".pem")
return RSA.importKey(open(path, "r").read()) return RSA.importKey(open(path, "r").read())
signkeyfuncs = [ load_rsa_key, load_rsa_key, None ] signkeyfuncs = [ load_rsa_key, load_rsa_key, None ]
NULL_IV = "\x00"*16 NULL_IV = b"\x00"*16
keylist = [ keylist = [
"common-key", "common-key",
@@ -86,13 +86,13 @@ known_titles_noregion = {
} }
def hexdump(s,sep=" "): def hexdump(s,sep=" "):
return sep.join(map(lambda x: "%02x"%ord(x),s)) return sep.join(["%02x"%x for x in s])
def strcmp(s1,s2): def strcmp(s1,s2):
clen = min(len(s1),len(s2)) clen = min(len(s1),len(s2))
for i in range(clen): for i in range(clen):
if s1[i] == "\0" and s2[i] == "\0": if s1[i] == 0 and s2[i] == 0:
return True return True
if s1[i] != s2[i]: if s1[i] != s2[i]:
return False return False
@@ -101,10 +101,10 @@ def strcmp(s1,s2):
def ascii(s): def ascii(s):
s2 = "" s2 = ""
for c in s: for c in s:
if ord(c)<0x20 or ord(c)>0x7e: if c<0x20 or c>0x7e:
s2 += "." s2 += "."
else: else:
s2 += c s2 += chr(c)
return s2 return s2
def pad(s,c,l): def pad(s,c,l):
@@ -114,15 +114,10 @@ def pad(s,c,l):
def chexdump(s): def chexdump(s):
for i in range(0,len(s),16): for i in range(0,len(s),16):
print "%08x %s %s |%s|"%(i,pad(hexdump(s[i:i+8],' ')," ",23),pad(hexdump(s[i+8:i+16],' ')," ",23),pad(ascii(s[i:i+16])," ",16)) print("%08x %s %s |%s|"%(i,pad(hexdump(s[i:i+8],' ')," ",23),pad(hexdump(s[i+8:i+16],' ')," ",23),pad(ascii(s[i:i+16])," ",16)))
def getcstring(s): def getcstring(s):
s2 = "" return s.split(b"\x00")[0].decode("ascii")
for c in s:
if c == "\x00":
break
s2 += c
return s2
def align(n,a): def align(n,a):
if a == 0: if a == 0:
@@ -132,10 +127,10 @@ def align(n,a):
return n return n
def rangel(n,s): def rangel(n,s):
return range(n,n+s) return list(range(n,n+s))
def xrangel(n,s): def xrangel(n,s):
return xrange(n,n+s) return range(n,n+s)
def falign(f,a): def falign(f,a):
f.seek(align(f.tell(),a)) f.seek(align(f.tell(),a))
@@ -200,7 +195,7 @@ def loadkeys(path = None):
try: try:
keys[key] = open(path + os.sep + key, "rb").read() keys[key] = open(path + os.sep + key, "rb").read()
except: except:
print "Warning: failed to load key %s"%key print("Warning: failed to load key %s"%key)
def loadkeys_dpki(path = None): def loadkeys_dpki(path = None):
if path is None: if path is None:
@@ -210,7 +205,7 @@ def loadkeys_dpki(path = None):
def parse_certs(blob): def parse_certs(blob):
certs = {} certs = {}
certlist = [] certlist = []
while blob != "": while blob != b"":
cert = WiiCert(blob) cert = WiiCert(blob)
certs[cert.name] = cert certs[cert.name] = cert
certlist.append(cert) certlist.append(cert)
@@ -250,7 +245,7 @@ class WiiPKAlgo:
code = ">"+codes[bytes] code = ">"+codes[bytes]
matchlen = len(match) matchlen = len(match)
for pad in xrange(0, 256**bytes): for pad in range(0, 256**bytes):
pad += 0x4612512415125316 pad += 0x4612512415125316
pad %= 256**bytes pad %= 256**bytes
padsig = signature + pack(code, pad) padsig = signature + pack(code, pad)
@@ -270,11 +265,11 @@ class WiiRSA(WiiPKAlgo):
def get_digest(self, signature): def get_digest(self, signature):
lsig = bytes_to_long(signature) lsig = bytes_to_long(signature)
if lsig >= self.n: if lsig >= self.n:
print "Warning: signature larger than modulus, using sig%modulus as signature" print("Warning: signature larger than modulus, using sig%modulus as signature")
ldec = pow(lsig, self.e, self.n) ldec = pow(lsig, self.e, self.n)
dec = long_to_bytes(ldec) dec = long_to_bytes(ldec)
pad = len(signature) - len(dec) pad = len(signature) - len(dec)
dec = "\x00"*pad+dec dec = b"\x00"*pad+dec
return dec[-20:] return dec[-20:]
def sign(self, data, key): def sign(self, data, key):
@@ -340,11 +335,11 @@ class WiiDisc:
return self.partitions return self.partitions
def showinfo(self): def showinfo(self):
print "Game %s, maker %s, magic %08x: %s"%(self.gamecode, self.makercode, self.magic, self.gamename) print("Game %s, maker %s, magic %08x: %s"%(self.gamecode, self.makercode, self.magic, self.gamename))
self.read_partitions() self.read_partitions()
print "%d partitions in ISO:"%len(self.partitions) print("%d partitions in ISO:"%len(self.partitions))
for p_num,p_dat in enumerate(self.partitions): for p_num,p_dat in enumerate(self.partitions):
print " [%2d] 0x%010x (%08x)"%(p_num,p_dat[0],p_dat[1]) print(" [%2d] 0x%010x (%08x)"%(p_num,p_dat[0],p_dat[1]))
class WiiSigned: class WiiSigned:
sigsizes = [512, 256, 60] sigsizes = [512, 256, 60]
@@ -370,7 +365,7 @@ class WiiSigned:
def update(self): def update(self):
self.data = pack(">I",self.sigtype+0x10000) + self.signature self.data = pack(">I",self.sigtype+0x10000) + self.signature
self.data += "\x00" * (self.body_offset - len(self.data)) self.data += b"\x00" * (self.body_offset - len(self.data))
self.data += self.body self.data += self.body
def parse(self): def parse(self):
@@ -388,7 +383,7 @@ class WiiSigned:
raise ValueError("Signature type %s does not match certificate type %s!"%(sigtypes[self.sigtype],sigtypes[cert.key_type])) raise ValueError("Signature type %s does not match certificate type %s!"%(sigtypes[self.sigtype],sigtypes[cert.key_type]))
return cert.pkalgo.get_digest(self.sigtype, self.signature) return cert.pkalgo.get_digest(self.sigtype, self.signature)
def brute_sha(self, match = "\x00", fillshort = None): def brute_sha(self, match = b"\x00", fillshort = None):
l = len(match) l = len(match)
if fillshort is None: if fillshort is None:
@@ -408,7 +403,7 @@ class WiiSigned:
if len(issuer) > 39: if len(issuer) > 39:
raise ValueError("issuer name too long!") raise ValueError("issuer name too long!")
self.issuer = issuer.split("-") self.issuer = issuer.split("-")
self.body = issuer + "\x00" * (0x40 - len(issuer)) + self.body[0x40:] self.body = issuer + b"\x00" * (0x40 - len(issuer)) + self.body[0x40:]
self.update() self.update()
def update_signature(self, sig): def update_signature(self, sig):
@@ -416,7 +411,7 @@ class WiiSigned:
self.data = pack(">I",self.sigtype+0x10000) + self.signature + self.data[len(sig) + 4:] self.data = pack(">I",self.sigtype+0x10000) + self.signature + self.data[len(sig) + 4:]
def null_signature(self): def null_signature(self):
self.signature = "\x00"*len(self.signature) self.signature = b"\x00"*len(self.signature)
self.data = pack(">I",self.sigtype+0x10000) + self.signature + self.data[len(self.signature) + 4:] self.data = pack(">I",self.sigtype+0x10000) + self.signature + self.data[len(self.signature) + 4:]
def sign(self,certs): def sign(self,certs):
@@ -453,22 +448,22 @@ class WiiSigned:
if cert.pkalgo.can_get_digest: if cert.pkalgo.can_get_digest:
signhash = cert.pkalgo.get_digest(self.signature) signhash = cert.pkalgo.get_digest(self.signature)
if myhash == signhash: if myhash == signhash:
print it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)) print(it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
elif strcmp(myhash, signhash): elif strcmp(myhash, signhash):
print it+"%s signed by %s using %s: %s [BUG]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)) print(it+"%s signed by %s using %s: %s [BUG]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
print it+" Signature hash: %s"%hexdump(signhash) print(it+" Signature hash: %s"%hexdump(signhash))
else: else:
print it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)) print(it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
print it+" Signature hash: %s"%hexdump(signhash) print(it+" Signature hash: %s"%hexdump(signhash))
else: else:
sigok = cert.pkalgo.check_digest(self.signature,myhash) sigok = cert.pkalgo.check_digest(self.signature,myhash)
if sigok: if sigok:
print it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)) print(it+"%s signed by %s using %s: %s [OK]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
else: else:
print it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)) print(it+"%s signed by %s using %s: %s [FAIL]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
except KeyError: except KeyError:
print it+"%s signed by %s using %s: %s [ISSUER NOT FOUND]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)) print(it+"%s signed by %s using %s: %s [ISSUER NOT FOUND]"%(self.type, "-".join(self.issuer), sigtypes[self.sigtype], hexdump(myhash)))
class WiiTik(WiiSigned): class WiiTik(WiiSigned):
def __init__(self, data): def __init__(self, data):
@@ -480,7 +475,7 @@ class WiiTik(WiiSigned):
def parse(self): def parse(self):
self.title_key_enc = self.body[0x7f:0x8f] self.title_key_enc = self.body[0x7f:0x8f]
self.title_id = self.body[0x9c:0xa4] self.title_id = self.body[0x9c:0xa4]
self.title_key_iv = self.title_id + "\x00"*8 self.title_key_iv = self.title_id + b"\x00"*8
self.common_key_index = ord(self.body[0xb1:0xb2]) self.common_key_index = ord(self.body[0xb1:0xb2])
try: try:
@@ -489,7 +484,7 @@ class WiiTik(WiiSigned):
elif self.common_key_index == 1: elif self.common_key_index == 1:
key = keys["korean-key"] key = keys["korean-key"]
else: else:
print "WARNING: OLD FAKESIGNED TICKET WITH BAD KEY OFFSET, ASSUMING NORMAL COMMON KEY" print("WARNING: OLD FAKESIGNED TICKET WITH BAD KEY OFFSET, ASSUMING NORMAL COMMON KEY")
key = keys["common-key"] key = keys["common-key"]
aes = AES.new(key, AES.MODE_CBC, self.title_key_iv) aes = AES.new(key, AES.MODE_CBC, self.title_key_iv)
self.title_key = aes.decrypt(self.title_key_enc) self.title_key = aes.decrypt(self.title_key_enc)
@@ -505,13 +500,13 @@ class WiiTik(WiiSigned):
return 0x164 return 0x164
def showinfo(self, it=""): def showinfo(self, it=""):
print it+"ETicket: " print(it+"ETicket: ")
print it+" Title ID: "+repr(self.title_id) print(it+" Title ID: "+repr(self.title_id))
print it+" Title key IV: "+hexdump(self.title_key_iv) print(it+" Title key IV: "+hexdump(self.title_key_iv))
print it+" Title key (encrypted): "+hexdump(self.title_key_enc) print(it+" Title key (encrypted): "+hexdump(self.title_key_enc))
print it+" Common key index: %d" % self.common_key_index print(it+" Common key index: %d" % self.common_key_index)
if self.title_key is not None: if self.title_key is not None:
print it+" Title key (decrypted): "+hexdump(self.title_key) print(it+" Title key (decrypted): "+hexdump(self.title_key))
class WiiPartitionOffsets: class WiiPartitionOffsets:
def __init__(self, data): def __init__(self, data):
@@ -528,9 +523,9 @@ class WiiPartitionOffsets:
self.data_size = unpack(">I",self.data[0x18:0x1c])[0]<<2 self.data_size = unpack(">I",self.data[0x18:0x1c])[0]<<2
def showinfo(self, it=""): def showinfo(self, it=""):
print it+"TMD @ 0x%x [0x%x], Certs @ 0x%x [0x%x], H3 @ 0x%x, Data @ 0x%x [0x%x]"%( print(it+"TMD @ 0x%x [0x%x], Certs @ 0x%x [0x%x], H3 @ 0x%x, Data @ 0x%x [0x%x]"%(
self.tmd_offset, self.tmd_size, self.cert_offset, self.cert_size, self.tmd_offset, self.tmd_size, self.cert_offset, self.cert_size,
self.h3_offset, self.data_offset, self.data_size) self.h3_offset, self.data_offset, self.data_size))
def update(self): def update(self):
self.data = pack(">II",self.tmd_size, self.tmd_offset>>2) self.data = pack(">II",self.tmd_size, self.tmd_offset>>2)
@@ -600,20 +595,20 @@ class WiiTmd(WiiSigned):
self.update() self.update()
def showinfo(self,it=""): def showinfo(self,it=""):
print it+"TMD: " print(it+"TMD: ")
print it+" Versions: %d, CA CRL %d, Signer CRL %d, System %d-%d"%( print(it+" Versions: %d, CA CRL %d, Signer CRL %d, System %d-%d"%(
self.version,self.ca_crl_version,self.signer_crl_version,self.sys_version>>32,self.sys_version&0xffffffff) self.version,self.ca_crl_version,self.signer_crl_version,self.sys_version>>32,self.sys_version&0xffffffff))
print it+" Title ID: %s-%s (%s-%s)"%(hexdump(self.title_id[:4],''),hexdump(self.title_id[4:],''),repr(self.title_id[:4]),repr(self.title_id[4:])) print(it+" Title ID: %s-%s (%s-%s)"%(hexdump(self.title_id[:4],''),hexdump(self.title_id[4:],''),repr(self.title_id[:4]),repr(self.title_id[4:])))
print it+" Title Type: %d"%self.title_type print(it+" Title Type: %d"%self.title_type)
print it+" Group ID: %s"%repr(self.group_id) print(it+" Group ID: %s"%repr(self.group_id))
print it+" Access Rights: 0x%08x"%self.access_rights print(it+" Access Rights: 0x%08x"%self.access_rights)
print it+" Title Version: 0x%x"%self.title_version print(it+" Title Version: 0x%x"%self.title_version)
print it+" Boot Index: %d"%self.boot_index print(it+" Boot Index: %d"%self.boot_index)
print it+" Contents:" print(it+" Contents:")
print it+" ID Index Type Size Hash" print(it+" ID Index Type Size Hash")
for ct in self.get_content_records(): for ct in self.get_content_records():
print it+" %08X %-5d 0x%-5x %-12s %s"%(ct.cid, ct.index, ct.ftype, "0x%x"%ct.size,hexdump(ct.sha)) print(it+" %08X %-5d 0x%-5x %-12s %s"%(ct.cid, ct.index, ct.ftype, "0x%x"%ct.size,hexdump(ct.sha)))
class WiiCert(WiiSigned): class WiiCert(WiiSigned):
key_sizes = [516, 260, 60] key_sizes = [516, 260, 60]
@@ -638,7 +633,7 @@ class WiiCert(WiiSigned):
self.pkalgo = self.pk_types[self.key_type](self.key) self.pkalgo = self.pk_types[self.key_type](self.key)
def showinfo(self,it=""): def showinfo(self,it=""):
print it+"%s (%s)"%(self.name,sigtypes[self.key_type]) print(it+"%s (%s)"%(self.name,sigtypes[self.key_type]))
class WiiRootCert: class WiiRootCert:
def __init__(self, data): def __init__(self, data):
@@ -650,7 +645,7 @@ class WiiRootCert:
self.key_type = 0 self.key_type = 0
def showinfo(self,it=""): def showinfo(self,it=""):
print it+"%s (%s)"%(self.name,sigtypes[self.key_type]) print(it+"%s (%s)"%(self.name,sigtypes[self.key_type]))
class WiiPartition: class WiiPartition:
BLOCKS_PER_SUBGROUP = 8 BLOCKS_PER_SUBGROUP = 8
@@ -732,37 +727,37 @@ class WiiPartition:
self.f.write(self.offsets.data) self.f.write(self.offsets.data)
def showinfo(self,it=""): def showinfo(self,it=""):
print it+"Wii Partition at 0x%010x:"%(self.offset) print(it+"Wii Partition at 0x%010x:"%(self.offset))
self.offsets.showinfo(" ") self.offsets.showinfo(" ")
self.tik.showinfo(it+" ") self.tik.showinfo(it+" ")
self.tik.showsig(self.certs,it+" ") self.tik.showsig(self.certs,it+" ")
self.tmd.showinfo(it+" ") self.tmd.showinfo(it+" ")
self.tmd.showsig(self.certs,it+" ") self.tmd.showsig(self.certs,it+" ")
if self.checkh4hash(): if self.checkh4hash():
print it+" H4 hash check passed" print(it+" H4 hash check passed")
else: else:
print it+" H4 check failed: SHA1(H3) = "+hexdump(self.geth4hash()) print(it+" H4 check failed: SHA1(H3) = "+hexdump(self.geth4hash()))
print it+" Data:" print(it+" Data:")
print it+" Blocks: %d"%self.data_blocks print(it+" Blocks: %d"%self.data_blocks)
print it+" Subgroups: %d (plus %d blocks)"%(self.data_subgroups,self.extra_subgroup_blocks) print(it+" Subgroups: %d (plus %d blocks)"%(self.data_subgroups,self.extra_subgroup_blocks))
print it+" Groups: %d (plus %d blocks)"%(self.data_groups,self.extra_group_blocks) print(it+" Groups: %d (plus %d blocks)"%(self.data_groups,self.extra_group_blocks))
self.showcerts(it+" ") self.showcerts(it+" ")
def showcerts(self,it=""): def showcerts(self,it=""):
print it+"Certificates: " print(it+"Certificates: ")
for cert in self.certlist: for cert in self.certlist:
cert.showinfo(it+" - ") cert.showinfo(it+" - ")
cert.showsig(self.certs,it+" ") cert.showsig(self.certs,it+" ")
def geth4hash(self): def geth4hash(self):
return SHA.new(''.join(self.h3) + "\x00"*self.TAIL_H3).digest() return SHA.new(b''.join(self.h3) + b"\x00"*self.TAIL_H3).digest()
def checkh4hash(self): def checkh4hash(self):
return self.geth4hash() == self.tmd.get_content_records()[0].sha return self.geth4hash() == self.tmd.get_content_records()[0].sha
def updateh3(self): def updateh3(self):
self._seek(self.offsets.h3_offset) self._seek(self.offsets.h3_offset)
self.f.write(''.join(self.h3)) self.f.write(b''.join(self.h3))
def updateh4(self): def updateh4(self):
cr = self.tmd.get_content_records()[0] cr = self.tmd.get_content_records()[0]
@@ -903,7 +898,7 @@ class WiiPartition:
else: else:
raise ValueError("Attempted to read group past the end of the partition data") raise ValueError("Attempted to read group past the end of the partition data")
data = "" data = b""
for i in range(nblocks): for i in range(nblocks):
data += self.readblock(blockoff+i) data += self.readblock(blockoff+i)
return data return data
@@ -919,7 +914,7 @@ class WiiPartition:
if groupnum == self.data_groups and self.extra_group_blocks > 0 and len(data) == (self.extra_group_blocks * self.PLAIN_BLOCK_SIZE): if groupnum == self.data_groups and self.extra_group_blocks > 0 and len(data) == (self.extra_group_blocks * self.PLAIN_BLOCK_SIZE):
blocks = self.extra_group_blocks blocks = self.extra_group_blocks
writesize = blocks * self.CIPHER_BLOCK_SIZE writesize = blocks * self.CIPHER_BLOCK_SIZE
data += "\x00" * (self.PLAIN_BLOCK_SIZE * self.BLOCKS_PER_GROUP - blocks) data += b"\x00" * (self.PLAIN_BLOCK_SIZE * self.BLOCKS_PER_GROUP - blocks)
else: else:
raise ValueError("Attempted to write group past the end of the partition data") raise ValueError("Attempted to write group past the end of the partition data")
else: else:
@@ -930,12 +925,12 @@ class WiiPartition:
h0 = [] h0 = []
h1 = [] h1 = []
h2 = "" h2 = b""
for subgroup in range(self.SUBGROUPS_PER_GROUP): for subgroup in range(self.SUBGROUPS_PER_GROUP):
bh1 = "" bh1 = b""
sh0 = [] sh0 = []
for block in range(self.BLOCKS_PER_SUBGROUP): for block in range(self.BLOCKS_PER_SUBGROUP):
bh0 = "" bh0 = b""
for chunk in range(self.DATA_CHUNKS_PER_BLOCK): for chunk in range(self.DATA_CHUNKS_PER_BLOCK):
offset = subgroup * self.PLAIN_SUBGROUP_SIZE + block * self.PLAIN_BLOCK_SIZE + chunk * self.DATA_CHUNK_SIZE offset = subgroup * self.PLAIN_SUBGROUP_SIZE + block * self.PLAIN_BLOCK_SIZE + chunk * self.DATA_CHUNK_SIZE
bh0 += SHA.new(data[offset:offset+self.DATA_CHUNK_SIZE]).digest() bh0 += SHA.new(data[offset:offset+self.DATA_CHUNK_SIZE]).digest()
@@ -946,16 +941,16 @@ class WiiPartition:
h2 += SHA.new(bh1).digest() h2 += SHA.new(bh1).digest()
h3 = SHA.new(h2).digest() h3 = SHA.new(h2).digest()
data_out = "" data_out = b""
for subgroup in range(self.SUBGROUPS_PER_GROUP): for subgroup in range(self.SUBGROUPS_PER_GROUP):
for block in range(self.BLOCKS_PER_SUBGROUP): for block in range(self.BLOCKS_PER_SUBGROUP):
shablock = "" shablock = ""
shablock += h0[subgroup][block] shablock += h0[subgroup][block]
shablock += "\x00"*20 shablock += b"\x00"*20
shablock += h1[subgroup] shablock += h1[subgroup]
shablock += "\x00"*32 shablock += b"\x00"*32
shablock += h2 shablock += h2
shablock += "\x00"*32 shablock += b"\x00"*32
assert len(shablock) == self.SHA_SIZE, "sha block size messed up" assert len(shablock) == self.SHA_SIZE, "sha block size messed up"
aes = AES.new(self.tik.title_key, AES.MODE_CBC, NULL_IV) aes = AES.new(self.tik.title_key, AES.MODE_CBC, NULL_IV)
shablock = aes.encrypt(shablock) shablock = aes.encrypt(shablock)
@@ -1019,7 +1014,7 @@ class WiiCachedPartition(WiiPartition):
def _dprint(self, s, *args): def _dprint(self, s, *args):
if self.debug: if self.debug:
print s%tuple(args) print(s%tuple(args))
def _readblock(self, blocknum): def _readblock(self, blocknum):
self._dprint("_readblock(0x%x)",blocknum) self._dprint("_readblock(0x%x)",blocknum)
@@ -1174,7 +1169,7 @@ class WiiCachedPartition(WiiPartition):
hb = self.readblock(bstart - 1) hb = self.readblock(bstart - 1)
hb = hb[:hdroff] + data[:header] + hb[hdroff+header:] hb = hb[:hdroff] + data[:header] + hb[hdroff+header:]
self.writeblock(bstart - 1, hb) self.writeblock(bstart - 1, hb)
for block in xrange(bnum): for block in range(bnum):
self.writeblock(block+bstart, data[header+block*self.PLAIN_BLOCK_SIZE:header+(block+1)*self.PLAIN_BLOCK_SIZE]) self.writeblock(block+bstart, data[header+block*self.PLAIN_BLOCK_SIZE:header+(block+1)*self.PLAIN_BLOCK_SIZE])
if footer: if footer:
fb = self.readblock(bstart+bnum) fb = self.readblock(bstart+bnum)
@@ -1246,11 +1241,11 @@ class WiiApploader:
self.extrafooter = data[0x20+self.textsize+self.trailersize:] self.extrafooter = data[0x20+self.textsize+self.trailersize:]
def showinfo(self, it=""): def showinfo(self, it=""):
print it+"Apploader:" print(it+"Apploader:")
print it+" Date: %s"%self.date print(it+" Date: %s"%self.date)
print it+" Entrypoint: 0x%08x"%self.entry print(it+" Entrypoint: 0x%08x"%self.entry)
print it+" Text size: 0x%x"%self.textsize print(it+" Text size: 0x%x"%self.textsize)
print it+" Trailer size: 0x%x"%self.trailersize print(it+" Trailer size: 0x%x"%self.trailersize)
class WiiPartitionData: class WiiPartitionData:
def __init__(self, partition): def __init__(self, partition):
@@ -1291,11 +1286,11 @@ class WiiPartitionData:
self.dol = dol self.dol = dol
self.part.write(self.doloff, dol) self.part.write(self.doloff, dol)
def showinfo(self,it=""): def showinfo(self,it=""):
print it+"Partition data:" print(it+"Partition data:")
print it+" Game Name: %s"%self.gamename print(it+" Game Name: %s"%self.gamename)
print it+" Offsets: DOL @ 0x%x [0x%x], Apploader @ 0x%x [0x%x], FST @ 0x%x [0x%x]"%(self.doloff, self.dolsize, 0x2440, self.apploadersize, self.fstoff, self.fstsize) print(it+" Offsets: DOL @ 0x%x [0x%x], Apploader @ 0x%x [0x%x], FST @ 0x%x [0x%x]"%(self.doloff, self.dolsize, 0x2440, self.apploadersize, self.fstoff, self.fstsize))
self.apploader.showinfo(it+" ") self.apploader.showinfo(it+" ")
print it+"FST:" print(it+"FST:")
self.fst.show(it+" ") self.fst.show(it+" ")
class FakeFile: class FakeFile:
@@ -1381,7 +1376,7 @@ class WiiWad:
self.f.seek(4) self.f.seek(4)
wt = self.f.read(2) wt = self.f.read(2)
if wt == "\x00\x00": if wt == b"\x00\x00":
self.read_boot2hdr() self.read_boot2hdr()
else: else:
self.read_hdr() self.read_hdr()
@@ -1389,7 +1384,7 @@ class WiiWad:
certdata = self.f.read(self.cert_len) certdata = self.f.read(self.cert_len)
self.certlist = [] self.certlist = []
self.certs = {} self.certs = {}
while certdata != "": while certdata != b"":
cert = WiiCert(certdata) cert = WiiCert(certdata)
self.certs[cert.name] = cert self.certs[cert.name] = cert
self.certlist.append(cert) self.certlist.append(cert)
@@ -1415,8 +1410,8 @@ class WiiWad:
self.f.write(self.tik.data) self.f.write(self.tik.data)
def showinfo(self,it=""): def showinfo(self,it=""):
print it+"Wii Wad:" print(it+"Wii Wad:")
print it+" Header 0x%x Type %s Certs 0x%x Tik 0x%x TMD 0x%x Data 0x%x @ 0x%x Footer 0x%x"%(self.hdr_len, repr(self.wadtype), self.cert_len, self.tik_len, self.tmd_len, self.data_len, self.data_off, self.footer_len) print(it+" Header 0x%x Type %s Certs 0x%x Tik 0x%x TMD 0x%x Data 0x%x @ 0x%x Footer 0x%x"%(self.hdr_len, repr(self.wadtype), self.cert_len, self.tik_len, self.tmd_len, self.data_len, self.data_off, self.footer_len))
self.tik.showinfo(it+" ") self.tik.showinfo(it+" ")
self.tik.showsig(self.certs,it+" ") self.tik.showsig(self.certs,it+" ")
self.tmd.showinfo(it+" ") self.tmd.showinfo(it+" ")
@@ -1426,15 +1421,15 @@ class WiiWad:
d = self.getcontent(ct.index) d = self.getcontent(ct.index)
sha = SHA.new(d).digest() sha = SHA.new(d).digest()
if sha != ct.sha: if sha != ct.sha:
print it+" SHA-1 for content %08x is invalid:"%ct.cid, hexdump(sha) print(it+" SHA-1 for content %08x is invalid:"%ct.cid, hexdump(sha))
print it+" Expected:",hexdump(ct.sha) print(it+" Expected:",hexdump(ct.sha))
allok=False allok=False
if allok: if allok:
print it+" All content SHA-1 hashes are valid" print(it+" All content SHA-1 hashes are valid")
self.showcerts(it+" ") self.showcerts(it+" ")
def showcerts(self,it=""): def showcerts(self,it=""):
print it+"Certificates: " print(it+"Certificates: ")
for cert in self.certlist: for cert in self.certlist:
cert.showinfo(it+" - ") cert.showinfo(it+" - ")
cert.showsig(self.certs,it+" ") cert.showsig(self.certs,it+" ")
@@ -1447,7 +1442,7 @@ class WiiWad:
if encrypted: if encrypted:
return data return data
iv = pack(">H",index)+"\x00"*14 iv = pack(">H",index)+b"\x00"*14
aes = AES.new(self.tik.title_key, AES.MODE_CBC, iv) aes = AES.new(self.tik.title_key, AES.MODE_CBC, iv)
return aes.decrypt(data)[:ct.size] return aes.decrypt(data)[:ct.size]
@@ -1470,14 +1465,14 @@ class WiiWadMaker(WiiWad):
self.tik_len = len(self.tik.data) self.tik_len = len(self.tik.data)
# if boot2, set type to "ib" # if boot2, set type to "ib"
if self.tmd.title_id == "\x00\x00\x00\x01\x00\x00\x00\x01": if self.tmd.title_id == b"\x00\x00\x00\x01\x00\x00\x00\x01":
if nandwad: if nandwad:
self.wadtype = 0 self.wadtype = 0
self.ALIGNMENT = 0 self.ALIGNMENT = 0
else: else:
self.wadtype = "ib" self.wadtype = b"ib"
else: else:
self.wadtype = "Is" self.wadtype = b"Is"
self.data_len = 0 self.data_len = 0
self.footer = footer self.footer = footer
@@ -1509,16 +1504,16 @@ class WiiWadMaker(WiiWad):
cr.size = len(data) cr.size = len(data)
self.tmd.update_content_record(i,cr) self.tmd.update_content_record(i,cr)
if len(data)%16 != 0: if len(data)%16 != 0:
data += "\x00"*(16-len(data)%16) data += b"\x00"*(16-len(data)%16)
falign(self.f,0x40) falign(self.f,0x40)
iv = pack(">H",cr.index)+"\x00"*14 iv = pack(">H",cr.index)+b"\x00"*14
aes = AES.new(self.tik.title_key, AES.MODE_CBC, iv) aes = AES.new(self.tik.title_key, AES.MODE_CBC, iv)
self.f.write(aes.encrypt(data)) self.f.write(aes.encrypt(data))
falign(self.f,0x40) falign(self.f,0x40)
def adddata_encrypted(self, data): def adddata_encrypted(self, data):
if len(data)%16 != 0: if len(data)%16 != 0:
data += "\x00"*(16-len(data)%16) data += b"\x00"*(16-len(data)%16)
falign(self.f,0x40) falign(self.f,0x40)
self.f.write(data) self.f.write(data)
falign(self.f,0x40) falign(self.f,0x40)
@@ -1531,7 +1526,7 @@ class WiiWadMaker(WiiWad):
falign(self.f,self.ALIGNMENT) falign(self.f,self.ALIGNMENT)
self.f.truncate() self.f.truncate()
if pad: if pad:
self.f.write("\x00"*0x40) self.f.write(b"\x00"*0x40)
self.updatetmd() self.updatetmd()
self.f.seek(0) self.f.seek(0)
if self.wadtype == 0: if self.wadtype == 0:
@@ -1641,9 +1636,9 @@ class WiiFSTFile:
self.off = off self.off = off
self.size = size self.size = size
def show(self, it=""): def show(self, it=""):
print "%s%s @ 0x%x [0x%x]"%(it,self.name,self.off,self.size) print("%s%s @ 0x%x [0x%x]"%(it,self.name,self.off,self.size))
def generate(self, offset, stringoff, parent, dataoff, wiigcm=False): def generate(self, offset, stringoff, parent, dataoff, wiigcm=False):
stringdata = self.name + "\x00" stringdata = self.name.encode("ascii") + b"\x00"
off = self.off+dataoff off = self.off+dataoff
if wiigcm: if wiigcm:
off >>= 2 off >>= 2
@@ -1688,9 +1683,9 @@ class WiiFSTDir:
raise ValueError("WTF") raise ValueError("WTF")
def show(self, it=""): def show(self, it=""):
if self.name == "": if self.name == "":
print it+"/" print(it+"/")
else: else:
print it+self.name+"/" print(it+self.name+"/")
for i in self.entries: for i in self.entries:
i.show(it+self.name+"/") i.show(it+self.name+"/")
def dump(self): def dump(self):
@@ -1698,15 +1693,15 @@ class WiiFSTDir:
def add(self,x): def add(self,x):
self.entries.append(x) self.entries.append(x)
def generate(self, offset, stringoff, parent, dataoff, wiigcm=False): def generate(self, offset, stringoff, parent, dataoff, wiigcm=False):
stringdata = self.name + "\x00" stringdata = self.name.encode("ascii") + b"\x00"
myoff = offset myoff = offset
mysoff = stringoff mysoff = stringoff
stringoff+=len(stringdata) stringoff+=len(stringdata)
offset += 1 offset += 1
subdata="" subdata=b""
for e in self.entries: for e in self.entries:
d, s = e.generate(offset, stringoff, myoff, dataoff, wiigcm) d, s = e.generate(offset, stringoff, myoff, dataoff, wiigcm)
offset += len(d)/12 offset += len(d)//12
stringoff += len(s) stringoff += len(s)
stringdata += s stringdata += s
subdata += d subdata += d

View File

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

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path, struct import sys, os, os.path, struct
import pywii as wii import pywii as wii

View File

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

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -15,12 +15,12 @@ certfile = args.pop(0)
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read()) certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "Certification file %s: " % certfile print("Certification file %s: " % certfile)
cert = wii.WiiCert(open(certfile, "rb").read()) cert = wii.WiiCert(open(certfile, "rb").read())
cert.showinfo(" ") cert.showinfo(" ")
cert.showsig(certs," ") cert.showsig(certs," ")
print "Certificates:" print("Certificates:")
for cert in certlist: for cert in certlist:
cert.showinfo(" - ") cert.showinfo(" - ")
cert.showsig(certs," ") cert.showsig(certs," ")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -11,7 +11,7 @@ disc.showinfo()
partitions = disc.read_partitions() partitions = disc.read_partitions()
parts = range(len(partitions)) parts = list(range(len(partitions)))
try: try:
pnum = int(sys.argv[2]) pnum = int(sys.argv[2])

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python2 #!/usr/bin/python3
import sys, os, os.path import sys, os, os.path
sys.path.append(os.path.realpath(os.path.dirname(sys.argv[0]))+"/../Common") sys.path.append(os.path.realpath(os.path.dirname(sys.argv[0]))+"/../Common")
@@ -7,8 +7,8 @@ import pywii as wii
wii.loadkeys(os.environ["HOME"]+os.sep+".wii") wii.loadkeys(os.environ["HOME"]+os.sep+".wii")
if len(sys.argv) != 4: if len(sys.argv) != 4:
print "Usage:" print("Usage:")
print " python %s <encrypted ISO> <partition number> <dol output>"%sys.argv[0] print(" python %s <encrypted ISO> <partition number> <dol output>"%sys.argv[0])
sys.exit(1) sys.exit(1)
iso_name, partno, dol_name = sys.argv[1:4] iso_name, partno, dol_name = sys.argv[1:4]

View File

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

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -6,8 +6,8 @@ import pywii as wii
wii.loadkeys() wii.loadkeys()
if len(sys.argv) != 5: if len(sys.argv) != 5:
print "Usage:" print("Usage:")
print " python %s <encrypted ISO> <partition number> <apploader text> <apploader trailer>"%sys.argv[0] print(" python %s <encrypted ISO> <partition number> <apploader text> <apploader trailer>"%sys.argv[0])
sys.exit(1) sys.exit(1)
iso_name, partno, app_name, trail_name = sys.argv[1:5] iso_name, partno, app_name, trail_name = sys.argv[1:5]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -11,8 +11,8 @@ def parseint(d):
return int(d) return int(d)
if len(sys.argv) < 4 or len(sys.argv) > 7: if len(sys.argv) < 4 or len(sys.argv) > 7:
print "Usage:" print("Usage:")
print " python %s <encrypted ISO> <partition number> <file to inject> [Partition offset] [data offset] [length]"%sys.argv[0] print(" python %s <encrypted ISO> <partition number> <file to inject> [Partition offset] [data offset] [length]"%sys.argv[0])
sys.exit(1) sys.exit(1)
iso_name, partno, data_name = sys.argv[1:4] iso_name, partno, data_name = sys.argv[1:4]
@@ -34,10 +34,10 @@ if copy_length == None:
copy_length = data_len - data_offset copy_length = data_len - data_offset
copy_end = data_offset + copy_length copy_end = data_offset + copy_length
if copy_length < 0: if copy_length < 0:
print "Error: negative copy length" print("Error: negative copy length")
sys.exit(1) sys.exit(1)
if copy_end > data_len: if copy_end > data_len:
print "Error: data file is too small" print("Error: data file is too small")
sys.exit(1) sys.exit(1)
disc = wii.WiiDisc(iso_name) disc = wii.WiiDisc(iso_name)
@@ -52,7 +52,7 @@ while left > 0:
blocklen = min(left, 4*1024*1024) blocklen = min(left, 4*1024*1024)
d = dataf.read(blocklen) d = dataf.read(blocklen)
if len(d) != blocklen: if len(d) != blocklen:
print "File EOF reached!" print("File EOF reached!")
sys.exit(1) sys.exit(1)
part.write(offset, d) part.write(offset, d)
offset += blocklen offset += blocklen

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -6,8 +6,8 @@ import pywii as wii
wii.loadkeys() wii.loadkeys()
if len(sys.argv) != 4: if len(sys.argv) != 4:
print "Usage:" print("Usage:")
print " python %s <encrypted ISO> <partition number> <dol to inject>"%sys.argv[0] print(" python %s <encrypted ISO> <partition number> <dol to inject>"%sys.argv[0])
sys.exit(1) sys.exit(1)
iso_name, partno, dol_name = sys.argv[1:4] iso_name, partno, dol_name = sys.argv[1:4]

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -6,9 +6,9 @@ import pywii as wii
wii.loadkeys() wii.loadkeys()
if len(sys.argv) != 4: if len(sys.argv) != 4:
print "Usage:" print("Usage:")
print " python %s <encrypted ISO> <partition number> <IOS version>"%sys.argv[0] 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" print(" IOS version should be just the minor number (16, 33, etc) in decimal")
sys.exit(1) sys.exit(1)
iso_name, partno, ios = sys.argv[1:4] iso_name, partno, ios = sys.argv[1:4]

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
def hexdump(s): def hexdump(s):
return ' '.join(map(lambda x: "%02x"%x,map(ord,s))) return ' '.join(["%02x"%x for x in list(map(ord,s))])
isofile = sys.argv[1] isofile = sys.argv[1]
disc = WiiDisc(isofile) disc = WiiDisc(isofile)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -6,7 +6,7 @@ import pywii as wii
wii.loadkeys() wii.loadkeys()
tikfile = sys.argv[1] tikfile = sys.argv[1]
print "fixing Tik file %s " % tikfile print("fixing Tik file %s " % tikfile)
tik = wii.WiiTik(open(tikfile, "rb").read()) tik = wii.WiiTik(open(tikfile, "rb").read())
tik.null_signature() tik.null_signature()
tik.brute_sha() tik.brute_sha()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -17,12 +17,12 @@ certs = None
if len(args) > 0: if len(args) > 0:
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read()) certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "ETicket file %s:"%tikfile print("ETicket file %s:"%tikfile)
tik = wii.WiiTik(open(tikfile, "rb").read()) tik = wii.WiiTik(open(tikfile, "rb").read())
tik.showinfo(" ") tik.showinfo(" ")
if certs is not None: if certs is not None:
tik.showsig(certs," ") tik.showsig(certs," ")
print "Certificates:" print("Certificates:")
for cert in certlist: for cert in certlist:
cert.showinfo(" - ") cert.showinfo(" - ")
cert.showsig(certs," ") cert.showsig(certs," ")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -6,7 +6,7 @@ import pywii as wii
wii.loadkeys() wii.loadkeys()
tmdfile = sys.argv[1] tmdfile = sys.argv[1]
print "TMD file %s:"%tmdfile print("TMD file %s:"%tmdfile)
tmd = wii.WiiTmd(open(tmdfile, "rb").read()) tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.null_signature() tmd.null_signature()
tmd.brute_sha() tmd.brute_sha()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -17,12 +17,12 @@ certs = None
if len(args) > 0: if len(args) > 0:
certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read()) certs, certlist = wii.parse_certs(open(args.pop(0), "rb").read())
print "TMD file %s:"%tmdfile print("TMD file %s:"%tmdfile)
tmd = wii.WiiTmd(open(tmdfile, "rb").read()) tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.showinfo(" ") tmd.showinfo(" ")
if certs is not None: if certs is not None:
tmd.showsig(certs," ") tmd.showsig(certs," ")
print "Certificates:" print("Certificates:")
for cert in certlist: for cert in certlist:
cert.showinfo(" - ") cert.showinfo(" - ")
cert.showsig(certs," ") cert.showsig(certs," ")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -14,7 +14,7 @@ args = sys.argv[1:]
tmdfile = args.pop(0) tmdfile = args.pop(0)
indir = args.pop(0) indir = args.pop(0)
print "updating content records of TMD file %s" % tmdfile print("updating content records of TMD file %s" % tmdfile)
tmd = wii.WiiTmd(open(tmdfile, "rb").read()) tmd = wii.WiiTmd(open(tmdfile, "rb").read())
for i, cr in enumerate(tmd.get_content_records()): for i, cr in enumerate(tmd.get_content_records()):

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii
@@ -14,7 +14,7 @@ if len(args) == 2:
else: else:
newvers = int(args.pop(0), 16) newvers = int(args.pop(0), 16)
print "setting version of TMD file %s to 0x%04x" % (tmdfile, newvers) print("setting version of TMD file %s to 0x%04x" % (tmdfile, newvers))
tmd = wii.WiiTmd(open(tmdfile, "rb").read()) tmd = wii.WiiTmd(open(tmdfile, "rb").read())
tmd.title_version = newvers tmd.title_version = newvers
tmd.update() tmd.update()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
import sys, os, os.path import sys, os, os.path
import pywii as wii import pywii as wii