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 Crypto.Cipher import AES
from Struct import Struct
from common import *
@ -549,11 +548,11 @@ class TPL():
def RGB5A3(self, (w, h), jar):
out = [0 for i in range(w * h)]
i = 0
for y in range(0, h, 4):
for x in range(0, w, 4):
for y1 in range(y, y + 4):
for x1 in range(x, x + 4):
if(y1 >= h or x1 >= w):
for y1 in range(0, h, 4):
for x1 in range(0, w, 4):
for y in range(y1, y1 + 4):
for x in range(x1, x1 + 4):
if(y >= h or x >= w):
continue
pixel = jar[i]
i += 1
@ -570,7 +569,7 @@ class TPL():
a = 255 - (((pixel >> 12) & 0x07) * 64) / 7
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)
def RGB565(self, (w, h), jar):
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 common import *
@ -253,7 +252,7 @@ class IMD5():
imd5.zeroes[i] = 0x00
imd5.tag = "IMD5"
imd5.size = len(data)
imd5.crypto = str(hashlib.md5(data).digest())
imd5.crypto = str(Crypto().createMD5Hash(data))
data = imd5.pack() + data
if(fn != ""):
@ -321,7 +320,7 @@ class IMET():
imet.hash = "\x00" * 16
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

View File

@ -1,6 +1,6 @@
#!/usr/bin/python
import sys, struct, re, hashlib, os
import sys, struct, re, os
''' STOLEN FROM COMEX '''
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
from Crypto.Cipher import AES
from Struct import Struct
from common import *

151
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
from title import *
from Crypto.Cipher import AES
from Struct import Struct
from common import *
@ -126,15 +125,14 @@ class WOD: #WiiOpticalDisc
except:
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):
if len(block) != 0x8000:
raise Exception('Block size too big/small')
blockIV = block[0x3d0:0x3dF + 1]
print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
blockData = block[0x0400:0x7FFF]
blockIV = block[0x3d0:0x3e0]
#print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
blockData = block[0x0400:0x8000]
return Crypto().decryptData(self.partitionKey, blockIV, blockData, True)
@ -144,18 +142,16 @@ class WOD: #WiiOpticalDisc
readLen = (align(size, 0x7C00)) / 0x7C00
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))
if readLen == 0:
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)
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
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 :|
self.fp.seek(self.partitionOffset + 0x2A4 + offset)
return self.fp.read(size)
def parseFst(self, fst, names, i, isLast):
fileName = names[struct.unpack(">I", fst[12 * i:12 * i + 4])[0] & 0x00ffffff]
fileSize = struct.unpack(">I", fst[12 * i + 8:12 * i + 8 + 4])[0]
class fstObject(object):
#TODO: add ability to extract file by path
def __init__(self, name, iso=None):
''' do init stuff here '''
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:
for j in range(1, fileSize):
self.parseFst(fst, names, j, (j == fileSize - 1))
return fileSize
if fst[12 * i]:
parentDir = struct.unpack(">I", fst[12 * i + 4:12 * i + 4 + 4])[0]
isLast = struct.unpack(">I", fst[12 * parentDir + 8:12 * parentDir + 8 + 4] == fileSize)[0]
for j in range(1, fileSize):
self.parseFst(fst, names, j, (j == fileSize - 1))
return fileSize
j = 1
while(j<size):
j = self.parseFst(fst, names, j, fstDir)
return size
if fst[12 * i] == '\x01':
newDir = self.fstObject(fileName)
j = i+1
while(j<size):
j = self.parseFst(fst, names, j, newDir)
fstDir.addChild(newDir)
return size
else:
fileOffset = 4 * struct.unpack(">I", fst[12 * i + 4, 12 * i + 4 + 4])
markContent(fileOffset, fileSize)
open(fileName, 'w+b').write(self.readPartition(fileOffset, fileSize))
"""def parseFst(self, buffer):
rootFiles = struct.unpack('>I', buffer[8:12])[0]
namesTable = buffer[12 * (rootFiles):]
open('fst.bin', 'w+b').write(buffer)
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('..')"""
fileOffset = 4 * struct.unpack(">I", fst[(12*i + 4):(12*i + 4) + 4])[0]
newFile = self.fstObject(fileName)
newFile.type = 0
newFile.fileOffset = fileOffset
newFile.size = size
newFile.nameOff = nameOff
fstDir.addChild(newFile)
#self.markContent(fileOffset, size)
return i+1
def openPartition(self, index):
if index > self.partitionCount:
if index+1 > self.partitionCount:
raise ValueError('Partition index too big')
self.partitionOpen = index
@ -258,8 +285,6 @@ class WOD: #WiiOpticalDisc
def getFst(self):
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
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 hashlib import md5
from Crypto.Cipher import AES
from Struct import Struct
from struct import *
from common import *
from title import *
class LOC:
class locDat:
class locHeader(Struct):
def __format__(self):
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.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('\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 Crypto.Cipher import AES
from Struct import Struct
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 common import *
@ -180,7 +178,7 @@ class Savegame():
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')
#print 'Reashed md5 : %s' % hexdump(hashlib.md5(headerBuffer).digest())
#print 'Reashed md5 : %s' % hexdump(Crypto().createMD5Hash(headerBuffer))
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