mirror of
https://github.com/grp/Wii.py.git
synced 2025-06-18 23:05:48 -04:00
fixes in U8.py - now actualyl makes U8 files, not garbage stupidity. also fixes to IMET and a few other things.
This commit is contained in:
parent
3512fb6535
commit
27f07bdb2e
61
U8.py
61
U8.py
@ -38,7 +38,7 @@ class U8():
|
|||||||
|
|
||||||
if(os.path.isdir(file)):
|
if(os.path.isdir(file)):
|
||||||
node.type = 0x0100
|
node.type = 0x0100
|
||||||
self.data_offset = recursion
|
node.data_offset = recursion - 1
|
||||||
recursion += 1
|
recursion += 1
|
||||||
files = sorted(os.listdir(file))
|
files = sorted(os.listdir(file))
|
||||||
#if(sorted(files) == ["banner.bin", "icon.bin", "sound.bin"]):
|
#if(sorted(files) == ["banner.bin", "icon.bin", "sound.bin"]):
|
||||||
@ -60,10 +60,9 @@ class U8():
|
|||||||
data = f.read()
|
data = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
sz = len(data)
|
sz = len(data)
|
||||||
while len(data) % 32 != 0:
|
data += "\x00" * (align(sz, 64) - sz)
|
||||||
data += "\x00"
|
node.data_offset = len(self.data)
|
||||||
self.data += data
|
self.data += data
|
||||||
node.data_offset = len(data)
|
|
||||||
node.size = sz
|
node.size = sz
|
||||||
node.type = 0x0000
|
node.type = 0x0000
|
||||||
if(is_root != 1):
|
if(is_root != 1):
|
||||||
@ -74,11 +73,11 @@ class U8():
|
|||||||
|
|
||||||
This creates valid U8 archives for all purposes."""
|
This creates valid U8 archives for all purposes."""
|
||||||
header = self.U8Header()
|
header = self.U8Header()
|
||||||
self.rootnode = self.U8Node()
|
rootnode = self.U8Node()
|
||||||
|
|
||||||
header.tag = "U\xAA8-"
|
header.tag = "U\xAA8-"
|
||||||
header.rootnode_offset = 0x20
|
header.rootnode_offset = 0x20
|
||||||
header.zeroes = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
header.zeroes = "\x00" * 16
|
||||||
|
|
||||||
self.nodes = []
|
self.nodes = []
|
||||||
self.strings = "\x00"
|
self.strings = "\x00"
|
||||||
@ -88,13 +87,16 @@ class U8():
|
|||||||
self._pack(".", 0, 1)
|
self._pack(".", 0, 1)
|
||||||
os.chdir(origdir)
|
os.chdir(origdir)
|
||||||
|
|
||||||
header.header_size = (len(self.nodes) + 1) * len(self.rootnode) + len(self.strings)
|
header.header_size = (len(self.nodes) + 1) * len(rootnode) + len(self.strings)
|
||||||
header.data_offset = align(header.header_size + header.rootnode_offset, 0x40)
|
print "\nstff starts: " + str(align(header.header_size + header.rootnode_offset, 64))
|
||||||
self.rootnode.size = len(self.nodes) + 1
|
print header.header_size + header.rootnode_offset
|
||||||
self.rootnode.type = 0x0100
|
header.data_offset = align(header.header_size + header.rootnode_offset, 64)
|
||||||
|
rootnode.size = len(self.nodes) + 1
|
||||||
|
rootnode.type = 0x0100
|
||||||
|
|
||||||
for node in self.nodes:
|
for i in range(len(self.nodes)):
|
||||||
node.data_offset += header.data_offset
|
if(self.nodes[i].type == 0x0000):
|
||||||
|
self.nodes[i].data_offset += header.data_offset
|
||||||
|
|
||||||
if(fn == ""):
|
if(fn == ""):
|
||||||
if(self.f[len(self.f) - 4:] == "_out"):
|
if(self.f[len(self.f) - 4:] == "_out"):
|
||||||
@ -102,15 +104,16 @@ class U8():
|
|||||||
else:
|
else:
|
||||||
fn = self.f
|
fn = self.f
|
||||||
|
|
||||||
f = open(fn, "wb")
|
fd = open(fn, "wb")
|
||||||
f.write(header.pack())
|
fd.write(header.pack())
|
||||||
f.write(self.rootnode.pack())
|
fd.write(rootnode.pack())
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
f.write(node.pack())
|
fd.write(node.pack())
|
||||||
f.write(self.strings)
|
fd.write(self.strings)
|
||||||
f.write("\x00" * (header.data_offset - header.rootnode_offset - header.header_size))
|
fd.write("\x00" * (header.data_offset - header.rootnode_offset - header.header_size))
|
||||||
f.write(self.data)
|
print (header.data_offset - header.rootnode_offset - header.header_size)
|
||||||
f.close()
|
fd.write(self.data)
|
||||||
|
fd.close()
|
||||||
|
|
||||||
return fn
|
return fn
|
||||||
|
|
||||||
@ -136,7 +139,7 @@ class U8():
|
|||||||
offset += len(rootnode)
|
offset += len(rootnode)
|
||||||
|
|
||||||
nodes = []
|
nodes = []
|
||||||
for i in xrange(rootnode.size - 1):
|
for i in range(rootnode.size - 1):
|
||||||
node = self.U8Node()
|
node = self.U8Node()
|
||||||
node.unpack(data[offset:offset + len(node)])
|
node.unpack(data[offset:offset + len(node)])
|
||||||
offset += len(node)
|
offset += len(node)
|
||||||
@ -296,7 +299,7 @@ class IMET():
|
|||||||
self.sizes = Struct.uint32[3] #icon, banner, sound
|
self.sizes = Struct.uint32[3] #icon, banner, sound
|
||||||
self.unk2 = Struct.uint32
|
self.unk2 = Struct.uint32
|
||||||
self.names = Struct.string(84, encoding = "utf-16-be", stripNulls = True)[7]
|
self.names = Struct.string(84, encoding = "utf-16-be", stripNulls = True)[7]
|
||||||
self.zeroes2 = Struct.uint8[904]
|
self.zeroes2 = Struct.uint8[840]
|
||||||
self.hash = Struct.string(16)
|
self.hash = Struct.string(16)
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
self.f = f
|
self.f = f
|
||||||
@ -365,4 +368,16 @@ class IMET():
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
imet.unpack(data[:len(imet)])
|
imet.unpack(data[:len(imet)])
|
||||||
return imet.names[1]
|
name = imet.names[1]
|
||||||
|
topop = []
|
||||||
|
for i in range(len(name)):
|
||||||
|
if(name[i] == "\x00"):
|
||||||
|
topop.append(i)
|
||||||
|
name = list(name)
|
||||||
|
popped = 0 #don't ask me why I did this
|
||||||
|
for pop in topop:
|
||||||
|
name.pop(pop - popped)
|
||||||
|
popped += 1
|
||||||
|
|
||||||
|
name = ''.join(name)
|
||||||
|
return name
|
||||||
|
30
nand.py
30
nand.py
@ -6,7 +6,7 @@ from Crypto.Cipher import AES
|
|||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
|
from title import *
|
||||||
|
|
||||||
|
|
||||||
class NAND:
|
class NAND:
|
||||||
@ -95,9 +95,9 @@ class NAND:
|
|||||||
cmfp.write(value)
|
cmfp.write(value)
|
||||||
cmfp.close()
|
cmfp.close()
|
||||||
return cnt
|
return cnt
|
||||||
def importTitle(self, prefix, tmd, tik):
|
def importTitle(self, prefix, tmd, tik, is_decrypted = False, result_decrypted = False):
|
||||||
"""When passed a prefix (the directory to obtain the .app files from, sorted by content id), a TMD instance, and a Ticket instance, this will add that title to the NAND base folder specified in the constructor."""
|
"""When passed a prefix (the directory to obtain the .app files from, sorted by content id), a TMD instance, and a Ticket instance, this will add that title to the NAND base folder specified in the constructor. Unless is_decrypted is set, the contents are assumed to be encrypted. If result_decrypted is True, then the contents will not end up decrypted."""
|
||||||
self.ES.AddTitleStart(tmd, None, None)
|
self.ES.AddTitleStart(tmd, None, None, is_decrypted, result_decrypted, use_version = True)
|
||||||
self.ES.AddTitleTMD(tmd)
|
self.ES.AddTitleTMD(tmd)
|
||||||
self.ES.AddTicket(tik)
|
self.ES.AddTicket(tik)
|
||||||
contents = tmd.getContents()
|
contents = tmd.getContents()
|
||||||
@ -167,7 +167,7 @@ class ESClass:
|
|||||||
hashout += cmfp.read(20)
|
hashout += cmfp.read(20)
|
||||||
cmfp.close()
|
cmfp.close()
|
||||||
return hashout
|
return hashout
|
||||||
def AddTitleStart(self, tmd, certs, crl):
|
def AddTitleStart(self, tmd, certs, crl, is_decrypted = False, result_decrypted = True, use_version = False):
|
||||||
if(not os.path.isdir(self.f + "/title/%08x" % (tmd.tmd.titleid >> 32))):
|
if(not os.path.isdir(self.f + "/title/%08x" % (tmd.tmd.titleid >> 32))):
|
||||||
os.mkdir(self.f + "/title/%08x" % (tmd.tmd.titleid >> 32))
|
os.mkdir(self.f + "/title/%08x" % (tmd.tmd.titleid >> 32))
|
||||||
if(not os.path.isdir(self.f + "/title/%08x/%08x" % (tmd.tmd.titleid >> 32, tmd.tmd.titleid & 0xFFFFFFFF))):
|
if(not os.path.isdir(self.f + "/title/%08x/%08x" % (tmd.tmd.titleid >> 32, tmd.tmd.titleid & 0xFFFFFFFF))):
|
||||||
@ -180,6 +180,9 @@ class ESClass:
|
|||||||
os.mkdir(self.f + "/ticket/%08x" % (tmd.tmd.titleid >> 32))
|
os.mkdir(self.f + "/ticket/%08x" % (tmd.tmd.titleid >> 32))
|
||||||
self.workingcids = array.array('L')
|
self.workingcids = array.array('L')
|
||||||
self.wtitleid = tmd.tmd.titleid
|
self.wtitleid = tmd.tmd.titleid
|
||||||
|
self.is_decrypted = is_decrypted
|
||||||
|
self.result_decrypted = result_decrypted
|
||||||
|
self.use_version = use_version
|
||||||
return
|
return
|
||||||
def AddTicket(self, tik):
|
def AddTicket(self, tik):
|
||||||
"""Adds ticket to the title being added."""
|
"""Adds ticket to the title being added."""
|
||||||
@ -261,15 +264,26 @@ class ESClass:
|
|||||||
outfp = open(filestr, "wb")
|
outfp = open(filestr, "wb")
|
||||||
data = fp.read()
|
data = fp.read()
|
||||||
titlekey = tik.getTitleKey()
|
titlekey = tik.getTitleKey()
|
||||||
tmpdata = Crypto().DecryptContent(titlekey, contents[idx].index, data)
|
if(self.is_decrypted):
|
||||||
if(Crypto().ValidateHash(tmpdata, contents[idx].hash) == 0):
|
tmpdata = data
|
||||||
|
else:
|
||||||
|
tmpdata = Crypto().DecryptContent(titlekey, contents[idx].index, data)
|
||||||
|
if(Crypto().ValidateSHAHash(tmpdata, contents[idx].hash) == 0):
|
||||||
"Decryption failed! SHA1 mismatch."
|
"Decryption failed! SHA1 mismatch."
|
||||||
return -44
|
return -44
|
||||||
|
if(self.result_decrypted != True):
|
||||||
|
if(self.is_decrypted):
|
||||||
|
tmpdata = Crypto().EncryptContent(titlekey, contents[idx].index, data)
|
||||||
|
else:
|
||||||
|
tmpdata = data
|
||||||
|
|
||||||
fp.close()
|
fp.close()
|
||||||
outfp.write(tmpdata)
|
outfp.write(tmpdata)
|
||||||
outfp.close()
|
outfp.close()
|
||||||
if(self.tmdadded):
|
if(self.tmdadded and self.use_version):
|
||||||
tmd.rawdump(self.f + "/title/%08x/%08x/content/title.tmd.%d" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF, tmd.tmd.title_version))
|
tmd.rawdump(self.f + "/title/%08x/%08x/content/title.tmd.%d" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF, tmd.tmd.title_version))
|
||||||
|
elif(self.tmdadded):
|
||||||
|
tmd.rawdump(self.f + "/title/%08x/%08x/content/title.tmd" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||||
if(self.ticketadded):
|
if(self.ticketadded):
|
||||||
tik.rawdump(self.f + "/ticket/%08x/%08x.tik" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
tik.rawdump(self.f + "/ticket/%08x/%08x.tik" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||||
self.AddTitleCancel()
|
self.AddTitleCancel()
|
||||||
|
14
title.py
14
title.py
@ -59,12 +59,12 @@ class Ticket:
|
|||||||
out += " Title ID: %08x-%08x\n" % (self.getTitleID() >> 32, self.getTitleID() & 0xFFFFFFFF)
|
out += " Title ID: %08x-%08x\n" % (self.getTitleID() >> 32, self.getTitleID() & 0xFFFFFFFF)
|
||||||
|
|
||||||
out += " Title key IV: "
|
out += " Title key IV: "
|
||||||
out += hexdump(report, struct.pack(">Q", self.getTitleID()) + "\x00\x00\x00\x00\x00\x00\x00\x00")
|
out += hexdump(struct.pack(">Q", self.getTitleID()) + "\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
out += "\n"
|
out += "\n"
|
||||||
|
|
||||||
out += " Title key (encrypted): "
|
out += " Title key (encrypted): "
|
||||||
out += hexdump(self.tik.enctitlekey)
|
out += hexdump(self.tik.enctitlekey)
|
||||||
report.write("\n")
|
out += "\n"
|
||||||
|
|
||||||
out += " Title key (decrypted): "
|
out += " Title key (decrypted): "
|
||||||
out += hexdump(self.getTitleKey())
|
out += hexdump(self.getTitleKey())
|
||||||
@ -153,11 +153,11 @@ class TMD:
|
|||||||
out = ""
|
out = ""
|
||||||
out += " TMD:\n"
|
out += " TMD:\n"
|
||||||
out += " Versions: (todo) %u, CA CRL (todo) %u, Signer CRL (todo) %u, System %u-%u\n" % (0, 0, 0, self.getIOSVersion() >> 32, self.getIOSVersion() & 0xFFFFFFFF)
|
out += " Versions: (todo) %u, CA CRL (todo) %u, Signer CRL (todo) %u, System %u-%u\n" % (0, 0, 0, self.getIOSVersion() >> 32, self.getIOSVersion() & 0xFFFFFFFF)
|
||||||
out += " Title ID: %08x-%08x\n" % (item.titleid >> 32, item.titleid & 0xFFFFFFFF)
|
out += " Title ID: %08x-%08x\n" % (self.getTitleID() >> 32, self.getTitleID() & 0xFFFFFFFF)
|
||||||
out += " Title Type: %u\n" % tmd.tmd.title_type
|
out += " Title Type: %u\n" % self.tmd.title_type
|
||||||
out += " Group ID: '%02u'\n" % tmd.tmd.group_id
|
out += " Group ID: '%02u'\n" % self.tmd.group_id
|
||||||
out += " Access Rights: 0x%08x\n" % tmd.tmd.access_rights
|
out += " Access Rights: 0x%08x\n" % self.tmd.access_rights
|
||||||
out += " Title Version: 0x%04x\n" % item.version
|
out += " Title Version: 0x%04x\n" % self.tmd.title_version
|
||||||
out += " Boot Index: %u\n" % self.getBootIndex()
|
out += " Boot Index: %u\n" % self.getBootIndex()
|
||||||
out += " Contents: \n"
|
out += " Contents: \n"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user