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)):
|
||||
node.type = 0x0100
|
||||
self.data_offset = recursion
|
||||
node.data_offset = recursion - 1
|
||||
recursion += 1
|
||||
files = sorted(os.listdir(file))
|
||||
#if(sorted(files) == ["banner.bin", "icon.bin", "sound.bin"]):
|
||||
@ -60,10 +60,9 @@ class U8():
|
||||
data = f.read()
|
||||
f.close()
|
||||
sz = len(data)
|
||||
while len(data) % 32 != 0:
|
||||
data += "\x00"
|
||||
data += "\x00" * (align(sz, 64) - sz)
|
||||
node.data_offset = len(self.data)
|
||||
self.data += data
|
||||
node.data_offset = len(data)
|
||||
node.size = sz
|
||||
node.type = 0x0000
|
||||
if(is_root != 1):
|
||||
@ -74,11 +73,11 @@ class U8():
|
||||
|
||||
This creates valid U8 archives for all purposes."""
|
||||
header = self.U8Header()
|
||||
self.rootnode = self.U8Node()
|
||||
rootnode = self.U8Node()
|
||||
|
||||
header.tag = "U\xAA8-"
|
||||
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.strings = "\x00"
|
||||
@ -88,13 +87,16 @@ class U8():
|
||||
self._pack(".", 0, 1)
|
||||
os.chdir(origdir)
|
||||
|
||||
header.header_size = (len(self.nodes) + 1) * len(self.rootnode) + len(self.strings)
|
||||
header.data_offset = align(header.header_size + header.rootnode_offset, 0x40)
|
||||
self.rootnode.size = len(self.nodes) + 1
|
||||
self.rootnode.type = 0x0100
|
||||
header.header_size = (len(self.nodes) + 1) * len(rootnode) + len(self.strings)
|
||||
print "\nstff starts: " + str(align(header.header_size + header.rootnode_offset, 64))
|
||||
print header.header_size + header.rootnode_offset
|
||||
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:
|
||||
node.data_offset += header.data_offset
|
||||
for i in range(len(self.nodes)):
|
||||
if(self.nodes[i].type == 0x0000):
|
||||
self.nodes[i].data_offset += header.data_offset
|
||||
|
||||
if(fn == ""):
|
||||
if(self.f[len(self.f) - 4:] == "_out"):
|
||||
@ -102,15 +104,16 @@ class U8():
|
||||
else:
|
||||
fn = self.f
|
||||
|
||||
f = open(fn, "wb")
|
||||
f.write(header.pack())
|
||||
f.write(self.rootnode.pack())
|
||||
fd = open(fn, "wb")
|
||||
fd.write(header.pack())
|
||||
fd.write(rootnode.pack())
|
||||
for node in self.nodes:
|
||||
f.write(node.pack())
|
||||
f.write(self.strings)
|
||||
f.write("\x00" * (header.data_offset - header.rootnode_offset - header.header_size))
|
||||
f.write(self.data)
|
||||
f.close()
|
||||
fd.write(node.pack())
|
||||
fd.write(self.strings)
|
||||
fd.write("\x00" * (header.data_offset - header.rootnode_offset - header.header_size))
|
||||
print (header.data_offset - header.rootnode_offset - header.header_size)
|
||||
fd.write(self.data)
|
||||
fd.close()
|
||||
|
||||
return fn
|
||||
|
||||
@ -136,7 +139,7 @@ class U8():
|
||||
offset += len(rootnode)
|
||||
|
||||
nodes = []
|
||||
for i in xrange(rootnode.size - 1):
|
||||
for i in range(rootnode.size - 1):
|
||||
node = self.U8Node()
|
||||
node.unpack(data[offset:offset + len(node)])
|
||||
offset += len(node)
|
||||
@ -296,7 +299,7 @@ class IMET():
|
||||
self.sizes = Struct.uint32[3] #icon, banner, sound
|
||||
self.unk2 = Struct.uint32
|
||||
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)
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
@ -365,4 +368,16 @@ class IMET():
|
||||
return ""
|
||||
|
||||
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 common import *
|
||||
|
||||
from title import *
|
||||
|
||||
|
||||
class NAND:
|
||||
@ -95,9 +95,9 @@ class NAND:
|
||||
cmfp.write(value)
|
||||
cmfp.close()
|
||||
return cnt
|
||||
def importTitle(self, prefix, tmd, tik):
|
||||
"""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."""
|
||||
self.ES.AddTitleStart(tmd, None, None)
|
||||
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. 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, is_decrypted, result_decrypted, use_version = True)
|
||||
self.ES.AddTitleTMD(tmd)
|
||||
self.ES.AddTicket(tik)
|
||||
contents = tmd.getContents()
|
||||
@ -167,7 +167,7 @@ class ESClass:
|
||||
hashout += cmfp.read(20)
|
||||
cmfp.close()
|
||||
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))):
|
||||
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))):
|
||||
@ -180,6 +180,9 @@ class ESClass:
|
||||
os.mkdir(self.f + "/ticket/%08x" % (tmd.tmd.titleid >> 32))
|
||||
self.workingcids = array.array('L')
|
||||
self.wtitleid = tmd.tmd.titleid
|
||||
self.is_decrypted = is_decrypted
|
||||
self.result_decrypted = result_decrypted
|
||||
self.use_version = use_version
|
||||
return
|
||||
def AddTicket(self, tik):
|
||||
"""Adds ticket to the title being added."""
|
||||
@ -261,15 +264,26 @@ class ESClass:
|
||||
outfp = open(filestr, "wb")
|
||||
data = fp.read()
|
||||
titlekey = tik.getTitleKey()
|
||||
tmpdata = Crypto().DecryptContent(titlekey, contents[idx].index, data)
|
||||
if(Crypto().ValidateHash(tmpdata, contents[idx].hash) == 0):
|
||||
if(self.is_decrypted):
|
||||
tmpdata = data
|
||||
else:
|
||||
tmpdata = Crypto().DecryptContent(titlekey, contents[idx].index, data)
|
||||
if(Crypto().ValidateSHAHash(tmpdata, contents[idx].hash) == 0):
|
||||
"Decryption failed! SHA1 mismatch."
|
||||
return -44
|
||||
if(self.result_decrypted != True):
|
||||
if(self.is_decrypted):
|
||||
tmpdata = Crypto().EncryptContent(titlekey, contents[idx].index, data)
|
||||
else:
|
||||
tmpdata = data
|
||||
|
||||
fp.close()
|
||||
outfp.write(tmpdata)
|
||||
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))
|
||||
elif(self.tmdadded):
|
||||
tmd.rawdump(self.f + "/title/%08x/%08x/content/title.tmd" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||
if(self.ticketadded):
|
||||
tik.rawdump(self.f + "/ticket/%08x/%08x.tik" % (self.wtitleid >> 32, self.wtitleid & 0xFFFFFFFF))
|
||||
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 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 += " Title key (encrypted): "
|
||||
out += hexdump(self.tik.enctitlekey)
|
||||
report.write("\n")
|
||||
out += "\n"
|
||||
|
||||
out += " Title key (decrypted): "
|
||||
out += hexdump(self.getTitleKey())
|
||||
@ -153,11 +153,11 @@ class TMD:
|
||||
out = ""
|
||||
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 += " Title ID: %08x-%08x\n" % (item.titleid >> 32, item.titleid & 0xFFFFFFFF)
|
||||
out += " Title Type: %u\n" % tmd.tmd.title_type
|
||||
out += " Group ID: '%02u'\n" % tmd.tmd.group_id
|
||||
out += " Access Rights: 0x%08x\n" % tmd.tmd.access_rights
|
||||
out += " Title Version: 0x%04x\n" % item.version
|
||||
out += " Title ID: %08x-%08x\n" % (self.getTitleID() >> 32, self.getTitleID() & 0xFFFFFFFF)
|
||||
out += " Title Type: %u\n" % self.tmd.title_type
|
||||
out += " Group ID: '%02u'\n" % self.tmd.group_id
|
||||
out += " Access Rights: 0x%08x\n" % self.tmd.access_rights
|
||||
out += " Title Version: 0x%04x\n" % self.tmd.title_version
|
||||
out += " Boot Index: %u\n" % self.getBootIndex()
|
||||
out += " Contents: \n"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user