Merge branch 'master' of git@github.com:icefire/Wii.py

This commit is contained in:
icefire 2009-06-23 00:34:26 -07:00
commit 4d1ee39820
9 changed files with 133 additions and 91 deletions

15
TPL.py
View File

@ -1,7 +1,6 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
from PIL import Image from PIL import Image
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from common import * from common import *
@ -549,11 +548,11 @@ class TPL():
def RGB5A3(self, (w, h), jar): def RGB5A3(self, (w, h), jar):
out = [0 for i in range(w * h)] out = [0 for i in range(w * h)]
i = 0 i = 0
for y in range(0, h, 4): for y1 in range(0, h, 4):
for x in range(0, w, 4): for x1 in range(0, w, 4):
for y1 in range(y, y + 4): for y in range(y1, y1 + 4):
for x1 in range(x, x + 4): for x in range(x1, x1 + 4):
if(y1 >= h or x1 >= w): if(y >= h or x >= w):
continue continue
pixel = jar[i] pixel = jar[i]
i += 1 i += 1
@ -570,7 +569,7 @@ class TPL():
a = 255 - (((pixel >> 12) & 0x07) * 64) / 7 a = 255 - (((pixel >> 12) & 0x07) * 64) / 7
rgba = (r<<0) | (g<<8) | (b<<16) | (a<<24) rgba = (r<<0) | (g<<8) | (b<<16) | (a<<24)
out[y1*w+x1] = rgba out[y*w+x] = rgba
return ''.join(Struct.uint32(p) for p in out) return ''.join(Struct.uint32(p) for p in out)
def RGB565(self, (w, h), jar): def RGB565(self, (w, h), jar):
out = [0 for i in range(w * h)] out = [0 for i in range(w * h)]

7
U8.py
View File

@ -1,6 +1,5 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from common import * from common import *
@ -253,7 +252,7 @@ class IMD5():
imd5.zeroes[i] = 0x00 imd5.zeroes[i] = 0x00
imd5.tag = "IMD5" imd5.tag = "IMD5"
imd5.size = len(data) imd5.size = len(data)
imd5.crypto = str(hashlib.md5(data).digest()) imd5.crypto = str(Crypto().createMD5Hash(data))
data = imd5.pack() + data data = imd5.pack() + data
if(fn != ""): if(fn != ""):
@ -321,7 +320,7 @@ class IMET():
imet.hash = "\x00" * 16 imet.hash = "\x00" * 16
tmp = imet.pack() tmp = imet.pack()
imet.hash = hashlib.md5(tmp[0x40:0x640]).digest() #0x00 or 0x40? imet.hash = Crypto().createMD5Hash(tmp[0x40:0x640]) #0x00 or 0x40?
data = imet.pack() + data data = imet.pack() + data

View File

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
import sys, struct, re, hashlib, os import sys, struct, re, os
''' STOLEN FROM COMEX ''' ''' STOLEN FROM COMEX '''
def nullterm(str_plus): def nullterm(str_plus):

View File

@ -1,7 +1,6 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
import zlib import zlib
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from common import * from common import *

155
disc.py
View File

@ -1,8 +1,7 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
import time import time
from title import * from title import *
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from common import * from common import *
@ -126,15 +125,14 @@ class WOD: #WiiOpticalDisc
except: except:
self.markedBlocks.append(blockStart + x) self.markedBlocks.append(blockStart + x)
print '%s (%i blocks marked)' % (self.markedBlocks, len(self.markedBlocks)) #print '%s (%i blocks marked)' % (self.markedBlocks, len(self.markedBlocks))
def decryptBlock(self, block): def decryptBlock(self, block):
if len(block) != 0x8000: if len(block) != 0x8000:
raise Exception('Block size too big/small') raise Exception('Block size too big/small')
blockIV = block[0x3d0:0x3dF + 1] blockIV = block[0x3d0:0x3e0]
print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV)) #print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
blockData = block[0x0400:0x7FFF] blockData = block[0x0400:0x8000]
return Crypto().decryptData(self.partitionKey, blockIV, blockData, True) return Crypto().decryptData(self.partitionKey, blockIV, blockData, True)
@ -144,18 +142,16 @@ class WOD: #WiiOpticalDisc
readLen = (align(size, 0x7C00)) / 0x7C00 readLen = (align(size, 0x7C00)) / 0x7C00
blob = '' blob = ''
print 'Read at 0x%x (Start on %i block, ends at %i block) for %i bytes' % (offset, readStart, readStart + readLen, size) #print 'Read at 0x%x (Start on %i block, ends at %i block) for %i bytes' % (offset, readStart, readStart + readLen, size)
self.fp.seek(self.partitionOffset + 0x20000 + (0x8000 * readStart)) self.fp.seek(self.partitionOffset + 0x20000 + (0x8000 * readStart))
if readLen == 0:
for x in range(readLen + 1):
blob += self.decryptBlock(self.fp.read(0x8000)) blob += self.decryptBlock(self.fp.read(0x8000))
else:
for x in range(readLen + 1):
blob += self.decryptBlock(self.fp.read(0x8000))
self.markContent(offset, size) self.markContent(offset, size)
print 'Read from 0x%x to 0x%x' % (offset, offset + size) #print 'Read from 0x%x to 0x%x' % (offset, offset + size)
offset -= readStart * 0x7C00 offset -= readStart * 0x7C00
return blob[offset:offset + size] return blob[offset:offset + size]
@ -166,60 +162,91 @@ class WOD: #WiiOpticalDisc
# FIXMII : Needs testing, extracting the tmd cause to have 10 null bytes in the end instead of 10 useful bytes at start :| # FIXMII : Needs testing, extracting the tmd cause to have 10 null bytes in the end instead of 10 useful bytes at start :|
self.fp.seek(self.partitionOffset + 0x2A4 + offset) self.fp.seek(self.partitionOffset + 0x2A4 + offset)
return self.fp.read(size) return self.fp.read(size)
class fstObject(object):
def parseFst(self, fst, names, i, isLast): #TODO: add ability to extract file by path
def __init__(self, name, iso=None):
fileName = names[struct.unpack(">I", fst[12 * i:12 * i + 4])[0] & 0x00ffffff] ''' do init stuff here '''
fileSize = struct.unpack(">I", fst[12 * i + 8:12 * i + 8 + 4])[0] self.parent = None
self.type = 1 #directory: 1, file:0
self.name = name
self.nameOff = 0
self.fileOffset = 0
self.size = 0
self.children = []
self.iso = iso
def addChild(self, child):
if self.type == 0:
raise Exception('I am not a directory.')
child.parent = self
self.children.append(child)
def getISO(self):
if(self.parent == None):
return self.iso
return self.parent.getISO()
def getList(self, pad=0):
if self.type == 0:
return ("\t" * pad) + self.getPath() + "\n"
str = "%s[%s]\n" % ("\t" * (pad), self.getPath())
for child in self.children:
str += child.getList(pad+1)
return str
def count(self):
if self.type == 0:
return 1
i = 0
for child in self.children:
i += child.count()
return i
def getPath(self):
if(self.parent == None):
return "/"
if(self.type == 1):
return self.parent.getPath() + self.name + "/"
return self.parent.getPath() + self.name
def write(self, cwd):
if(self.type==0):
print cwd + self.getPath()
#print self.nameOff
open(cwd + self.getPath(), 'w+b').write(self.getISO().readPartition(self.fileOffset, self.size))
if(self.type==1):
if(self.parent != None):
try:
os.makedirs(cwd + self.getPath())
except:
j = None
for child in self.children:
child.write(cwd)
def parseFst(self, fst, names, i, fstDir):
size = struct.unpack(">I", fst[(12*i + 8):(12*i + 8) + 4])[0]
nameOff = struct.unpack(">I", fst[(12*i):(12*i) + 4])[0] & 0x00ffffff
fileName = names[nameOff:]
fileName = fileName[:fileName.find('\0')]
if i == 0: if i == 0:
for j in range(1, fileSize): j = 1
self.parseFst(fst, names, j, (j == fileSize - 1)) while(j<size):
return fileSize j = self.parseFst(fst, names, j, fstDir)
return size
if fst[12 * i]: if fst[12 * i] == '\x01':
parentDir = struct.unpack(">I", fst[12 * i + 4:12 * i + 4 + 4])[0] newDir = self.fstObject(fileName)
isLast = struct.unpack(">I", fst[12 * parentDir + 8:12 * parentDir + 8 + 4] == fileSize)[0] j = i+1
while(j<size):
for j in range(1, fileSize): j = self.parseFst(fst, names, j, newDir)
self.parseFst(fst, names, j, (j == fileSize - 1)) fstDir.addChild(newDir)
return size
return fileSize
else: else:
fileOffset = 4 * struct.unpack(">I", fst[12 * i + 4, 12 * i + 4 + 4]) fileOffset = 4 * struct.unpack(">I", fst[(12*i + 4):(12*i + 4) + 4])[0]
markContent(fileOffset, fileSize) newFile = self.fstObject(fileName)
open(fileName, 'w+b').write(self.readPartition(fileOffset, fileSize)) newFile.type = 0
newFile.fileOffset = fileOffset
"""def parseFst(self, buffer): newFile.size = size
rootFiles = struct.unpack('>I', buffer[8:12])[0] newFile.nameOff = nameOff
namesTable = buffer[12 * (rootFiles):] fstDir.addChild(newFile)
#self.markContent(fileOffset, size)
open('fst.bin', 'w+b').write(buffer) return i+1
for i in range(1, rootFiles):
fstTableEntry = buffer[12 * i:12 * (i + 1)]
if fstTableEntry[0] == '\x01':
fileType = 1
else:
fileType = 0
temp = struct.unpack('>I', fstTableEntry[0x0:0x4])[0]
nameOffset = struct.unpack('>I', fstTableEntry[0x0:0x4])[0] & 0x00ffffff
fileName = namesTable[nameOffset:].split('\x00')[0]
#print '%s' % namesTable[nameOffset:]
#print '%s %s\n' % (namesTable[nameOffset:].split('\x00')[0], namesTable[nameOffset:].split('\x00')[1])
fileOffset = 4 * (struct.unpack('>I', fstTableEntry[0x4:0x8])[0])
fileLenght = struct.unpack('>I', fstTableEntry[0x8:0x0c])[0]
if fileName == '':
time.sleep(5)
print '%s [%i] [0x%X] [0x%X] [0x%X]' % (fileName, fileType, fileOffset, fileLenght, nameOffset)
os.chdir('..')"""
def openPartition(self, index): def openPartition(self, index):
if index > self.partitionCount: if index+1 > self.partitionCount:
raise ValueError('Partition index too big') raise ValueError('Partition index too big')
self.partitionOpen = index self.partitionOpen = index
@ -258,8 +285,6 @@ class WOD: #WiiOpticalDisc
def getFst(self): def getFst(self):
fstBuf = self.readPartition(self.fstOffset, self.fstSize) fstBuf = self.readPartition(self.fstOffset, self.fstSize)
fileNumber = 1000#struct.unpack(">I", fstBuf[0x8:0xc])
self.parseFst(fstBuf, fstBuf[12 * fileNumber], 0, 0)
return fstBuf return fstBuf
def getIsoBootmode(self): def getIsoBootmode(self):

View File

@ -1,15 +1,13 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
from binascii import * from binascii import *
from hashlib import md5
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from struct import * from struct import *
from common import * from common import *
from title import * from title import *
class LOC: class locDat:
class locHeader(Struct): class locHeader(Struct):
def __format__(self): def __format__(self):
self.magic = Struct.string(4) self.magic = Struct.string(4)
@ -35,7 +33,7 @@ class LOC:
locHdr.md5 = '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93' locHdr.md5 = '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93'
locHdr.unknown = '\xA1\x6C\x2A\xEB' locHdr.unknown = '\xA1\x6C\x2A\xEB'
locHdr.md5 = hashlib().md5(locHdr.pack()).digest() locHdr.md5 = Crypto().createMD5Hash(locHdr.pack())
self.fp.write(locHdr.pack()) self.fp.write(locHdr.pack())
self.fp.write('\x00\x00\x00\x00' * 240) self.fp.write('\x00\x00\x00\x00' * 240)

View File

@ -1,7 +1,6 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
from binascii import * from binascii import *
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from struct import * from struct import *

View File

@ -1,7 +1,5 @@
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import os, struct, subprocess, fnmatch, shutil, urllib, array
from hashlib import md5
from Crypto.Cipher import AES
from Struct import Struct from Struct import Struct
from common import * from common import *
@ -180,7 +178,7 @@ class Savegame():
self.hdr = self.savegameHeader().unpack(headerBuffer[:0x20]) self.hdr = self.savegameHeader().unpack(headerBuffer[:0x20])
#headerBuffer.replace(self.hdr.md5hash, '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93') #headerBuffer.replace(self.hdr.md5hash, '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93')
#print 'Reashed md5 : %s' % hexdump(hashlib.md5(headerBuffer).digest()) #print 'Reashed md5 : %s' % hexdump(Crypto().createMD5Hash(headerBuffer))
self.bnr = self.savegameBanner().unpack(headerBuffer[0x20:]) self.bnr = self.savegameBanner().unpack(headerBuffer[0x20:])

25
tests/testDISC.py Normal file
View File

@ -0,0 +1,25 @@
from disc import *
from title import *
from Struct import Struct
import os
iso = WOD('/enter/other/wii/SUPER_MARIO_GALAXY.iso')
iso.openPartition(1)
#print '%s' % iso
#iso.decryptAll()
#open('appldr.bin', 'w+b').write(iso.getPartitionApploader())
fstBuf = iso.getFst()
open('fst.bin', 'w+b').write(fstBuf)
fileNumber = struct.unpack(">I", fstBuf[0x8:0xc])[0]
fileObject = iso.fstObject("", iso)
iso.parseFst(fstBuf, fstBuf[12 * fileNumber:], 0, fileObject)
print fileObject.getList()
fileObject.write(os.getcwd() + "/" + iso.discHdr.discId + iso.discHdr.gameCode + iso.discHdr.region)
#open('h3.bin', 'w+b').write(iso.getPartitionH3Table())
#isoTik = Ticket('tik.bin')
#print '%s' % isoTik
#open('main.dol', 'w+b').write(iso.getPartitionMainDol())
#isoTmd = TMD(iso.getPartitionTmd())
#print isoTmd