mirror of
https://github.com/grp/Wii.py.git
synced 2025-06-18 14:55:35 -04:00
Added some new commands to other.py, fixed some non-matching capitalization styles (the new form for all future capitalizations is likeThis not LikeThis, nor like_this.) and removed the wx and png dependancies on quite a few modules. I'll add some interfacing to the other.py classes from nand.py some time soon. I have confirmed that CONF works 100%.
This commit is contained in:
parent
f332764450
commit
7200db92c0
2
U8.py
2
U8.py
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
from Struct import Struct
|
||||
|
1
Wii.py
1
Wii.py
@ -5,6 +5,7 @@ from savedata import *
|
||||
from banner import *
|
||||
from disc import *
|
||||
from nand import *
|
||||
from other import *
|
||||
from title import *
|
||||
from TPL import *
|
||||
from U8 import *
|
||||
|
28
common.py
28
common.py
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
from Struct import Struct
|
||||
@ -20,39 +18,39 @@ class Crypto:
|
||||
def __init__(self):
|
||||
self.align = 64
|
||||
return
|
||||
def DecryptData(self, key, iv, data, align = True):
|
||||
def decryptData(self, key, iv, data, align = True):
|
||||
"""Decrypts some data (aligns to 64 bytes, if needed)."""
|
||||
if((len(data) % self.align) != 0 and align):
|
||||
return AES.new(key, AES.MODE_CBC, iv).decrypt(data + ("\x00" * (self.align - (len(data) % self.align))))
|
||||
else:
|
||||
return AES.new(key, AES.MODE_CBC, iv).decrypt(data)
|
||||
def EncryptData(self, key, iv, data, align = True):
|
||||
def encryptData(self, key, iv, data, align = True):
|
||||
"""Encrypts some data (aligns to 64 bytes, if needed)."""
|
||||
if((len(data) % self.align) != 0 and align):
|
||||
return AES.new(key, AES.MODE_CBC, iv).encrypt(data + ("\x00" * (self.align - (len(data) % self.align))))
|
||||
else:
|
||||
return AES.new(key, AES.MODE_CBC, iv).encrypt(data)
|
||||
def DecryptContent(self, titlekey, idx, data):
|
||||
def decryptContent(self, titlekey, idx, data):
|
||||
"""Decrypts a Content."""
|
||||
iv = struct.pack(">H", idx) + "\x00" * 14
|
||||
return self.DecryptData(titlekey, iv, data)
|
||||
def DecryptTitleKey(self, commonkey, tid, enckey):
|
||||
return self.decryptData(titlekey, iv, data)
|
||||
def decryptTitleKey(self, commonkey, tid, enckey):
|
||||
"""Decrypts a Content."""
|
||||
iv = struct.pack(">Q", tid) + "\x00" * 8
|
||||
return self.DecryptData(commonkey, iv, enckey, False)
|
||||
def EncryptContent(self, titlekey, idx, data):
|
||||
return self.decryptData(commonkey, iv, enckey, False)
|
||||
def encryptContent(self, titlekey, idx, data):
|
||||
"""Encrypts a Content."""
|
||||
iv = struct.pack(">H", idx) + "\x00" * 14
|
||||
return self.EncryptData(titlekey, iv, data)
|
||||
def CreateSHAHash(self, data): #tested WORKING (without padding)
|
||||
return self.encryptData(titlekey, iv, data)
|
||||
def createSHAHash(self, data): #tested WORKING (without padding)
|
||||
return hashlib.sha1(data).digest()
|
||||
def CreateSHAHashHex(self, data):
|
||||
def createSHAHashHex(self, data):
|
||||
return hashlib.sha1(data).hexdigest()
|
||||
def CreateMD5HashHex(self, data):
|
||||
def createMD5HashHex(self, data):
|
||||
return hashlib.md5(data).hexdigest()
|
||||
def CreateMD5Hash(self, data):
|
||||
def createMD5Hash(self, data):
|
||||
return hashlib.md5(data).digest()
|
||||
def ValidateSHAHash(self, data, hash):
|
||||
def validateSHAHash(self, data, hash):
|
||||
"""Validates a hash. Not checking currently because we have some...issues with hashes."""
|
||||
return 1 #hack
|
||||
if((len(data) % self.align) != 0):
|
||||
|
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
|
||||
import zlib
|
||||
from Crypto.Cipher import AES
|
||||
|
4
disc.py
4
disc.py
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
|
||||
import time
|
||||
from title import *
|
||||
@ -124,7 +122,7 @@ class WOD: #WiiOpticalDisc
|
||||
print 'IV %s (len %i)\n' % (hexdump(blockIV), len(blockIV))
|
||||
blockData = block[0x0400:0x7FFF]
|
||||
|
||||
return Crypto().DecryptData(self.partitionKey, blockIV, blockData, True)
|
||||
return Crypto().decryptData(self.partitionKey, blockIV, blockData, True)
|
||||
|
||||
def readPartition(self, offset, size):
|
||||
|
||||
|
2
nand.py
2
nand.py
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
from binascii import *
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
|
138
other.py
138
other.py
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
from binascii import *
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
@ -11,8 +9,7 @@ from common import *
|
||||
from title import *
|
||||
|
||||
class CONF:
|
||||
""" This class deal with setting.txt wich hold some wii info like game area and wii serial number """
|
||||
|
||||
"""This class deals with setting.txt which holds some important information like region and serial number """
|
||||
def __init__(self, f):
|
||||
self.conf = ''
|
||||
self.keys = {}
|
||||
@ -27,7 +24,7 @@ class CONF:
|
||||
return
|
||||
|
||||
self.conf = self.fp.read(0x100)
|
||||
self.conf = self.xorConf(self.conf)
|
||||
self.conf = self.XORConf(self.conf)
|
||||
self.fp.seek(0)
|
||||
|
||||
keys = self.conf.split('\r\n')
|
||||
@ -43,19 +40,23 @@ class CONF:
|
||||
self.keys[keyName] = keyVal
|
||||
|
||||
def getKeysCount(self):
|
||||
"""Gets how many keys exist."""
|
||||
return self.totalKeys
|
||||
|
||||
def getKeysName(self):
|
||||
"""Returns the list of key names."""
|
||||
return self.keyNames
|
||||
|
||||
def getKeyValue(self, key):
|
||||
"""Returns the value of the key ``key''."""
|
||||
try:
|
||||
return self.keys[key.upper()]
|
||||
except KeyError:
|
||||
return 'Key not found'
|
||||
|
||||
def setKeyValue(self, key, value):
|
||||
if self.getKeyValue(key.upper()) != 'Key not found':
|
||||
"""Sets the value of key ``key'' to ``value''."""
|
||||
if(self.keyExist(key)):
|
||||
self.keys[key.upper()] = value.upper()
|
||||
|
||||
self.conf = ''
|
||||
@ -67,18 +68,20 @@ class CONF:
|
||||
self.conf += '\r\n'
|
||||
|
||||
self.fp.seek(0)
|
||||
self.fp.write(self.xorConf(self.conf))
|
||||
self.fp.write(self.XORConf(self.conf))
|
||||
self.fp.write('\x00' * (0x100 - len(self.conf)))
|
||||
|
||||
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||
|
||||
def keyExist(self, key):
|
||||
"""Returns 1 if key ``key'' exists, 0 otherwise."""
|
||||
if self.getKeyValue(key.upper()) != 'Key not found':
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def addKey(self, key, value):
|
||||
"""Adds key ``key'' with value ``value'' to the list."""
|
||||
if self.lastKeyOffset + len(key) + 1 + len(value) + 2 > 0x100:
|
||||
return -1
|
||||
if not self.keyExist(key):
|
||||
@ -93,18 +96,20 @@ class CONF:
|
||||
self.lastKeyOffset += len(key) + 1 + len(value) + 2
|
||||
|
||||
self.fp.seek(0)
|
||||
self.fp.write(self.xorConf(self.conf))
|
||||
self.fp.write(self.XORConf(self.conf))
|
||||
|
||||
def xorConf(self, conf):
|
||||
xorKey = 0x73B5DBFA
|
||||
def XORConf(self, conf):
|
||||
"""Encrypts/decrypts the setting.txt file."""
|
||||
XORKey = 0x73B5DBFA
|
||||
out = ''
|
||||
for x in range(len(conf)):
|
||||
out += chr(ord(conf[x]) ^ xorKey & 0xFF)
|
||||
xorKey = (xorKey << 1) | (xorKey >> 31)
|
||||
out += chr(ord(conf[x]) ^ XORKey & 0xFF)
|
||||
XORKey = (XORKey << 1) | (XORKey >> 31)
|
||||
|
||||
return out
|
||||
|
||||
def delKey(self, key):
|
||||
def DeleteKey(self, key):
|
||||
"""Deletes the key ``key''."""
|
||||
try:
|
||||
del self.keys[key.upper()]
|
||||
self.keyNames.remove(key.upper())
|
||||
@ -119,14 +124,16 @@ class CONF:
|
||||
self.conf += '\r\n'
|
||||
|
||||
self.fp.seek(0)
|
||||
self.fp.write(self.xorConf(self.conf))
|
||||
self.fp.write(self.XORConf(self.conf))
|
||||
self.fp.write('\x00' * (0x100 - len(self.conf)))
|
||||
|
||||
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||
except KeyError:
|
||||
return 'Key not found'
|
||||
|
||||
def delKeyByValue(self, value):
|
||||
# This function is fucking dangerous. It deletes all keys with that value. Really not a good idea.
|
||||
def deleteKeyByValue(self, value):
|
||||
"""Deletes all keys with value ``value''. WATCH OUT, YOU MIGHT ACCIDENTALLY DELETE WRONG KEYS."""
|
||||
try:
|
||||
for key in self.keys.keys():
|
||||
if self.keys.get(key) == value:
|
||||
@ -142,15 +149,73 @@ class CONF:
|
||||
self.conf += '='
|
||||
self.conf += self.keys[key]
|
||||
self.conf += '\r\n'
|
||||
|
||||
|
||||
self.fp.seek(0)
|
||||
self.fp.write(self.xorConf(self.conf))
|
||||
self.fp.write(self.XORConf(self.conf))
|
||||
self.fp.write('\x00' * (0x100 - len(self.conf)))
|
||||
|
||||
self.lastKeyOffset = self.conf.rfind('\r\n') + 2
|
||||
except KeyError:
|
||||
return 'Key not found'
|
||||
|
||||
def getRegion(self):
|
||||
"""gets the Region key. (Shortcut for getKeyValue("GAME"))"""
|
||||
return self.getKeyValue("GAME")
|
||||
|
||||
def getArea(self):
|
||||
"""gets the Area key. (Shortcut for getKeyValue("AREA"))"""
|
||||
return self.getKeyValue("AREA")
|
||||
|
||||
def getVideoMode(self):
|
||||
"""gets the Video Mode key. (Shortcut for getKeyValue("VIDEO"))"""
|
||||
return self.getKeyValue("VIDEO")
|
||||
|
||||
def getSerialCode(self):
|
||||
"""gets the Serial Code key. (Shortcut for getKeyValue("CODE"))"""
|
||||
return self.getKeyValue("CODE")
|
||||
|
||||
def getDVDModel(self): # Might not be model =/
|
||||
"""gets the DVD Model (?) key. (Shortcut for getKeyValue("DVD"))"""
|
||||
return self.getKeyValue("DVD")
|
||||
|
||||
def getHardwareModel(self):
|
||||
"""gets the Hardware Model key. (Shortcut for getKeyValue("MODEL"))"""
|
||||
return self.getKeyValue("MODEL")
|
||||
|
||||
def getSerialNumber(self):
|
||||
"""gets the Serial Number key. (Shortcut for getKeyValue("SERNO"))"""
|
||||
return self.getKeyValue("SERNO")
|
||||
|
||||
|
||||
def setRegion(self, value):
|
||||
"""sets the Region key. (Shortcut for setKeyValue("GAME", value))"""
|
||||
return self.setKeyValue("GAME", value)
|
||||
|
||||
def setArea(self, value):
|
||||
"""sets the Area key. (Shortcut for setKeyValue("AREA", value))"""
|
||||
return self.setKeyValue("AREA", value)
|
||||
|
||||
def setVideoMode(self, value):
|
||||
"""sets the Video Mode key. (Shortcut for setKeyValue("VIDEO", value))"""
|
||||
return self.setKeyValue("VIDEO", value)
|
||||
|
||||
def setSerialCode(self, value):
|
||||
"""sets the Serial Code key. (Shortcut for setKeyValue("CODE", value))"""
|
||||
return self.setKeyValue("CODE", value)
|
||||
|
||||
def setDVDModel(self, value): # Might not be model =/
|
||||
"""sets the DVD Model (?) key. (Shortcut for setKeyValue("DVD", value))"""
|
||||
return self.setKeyValue("DVD", value)
|
||||
|
||||
def setHardwareModel(self, value):
|
||||
"""sets the Hardware Model key. (Shortcut for setKeyValue("MODEL", value))"""
|
||||
return self.setKeyValue("MODEL", value)
|
||||
|
||||
def setSerialNumber(self, value):
|
||||
"""sets the Serial Number key. (Shortcut for setKeyValue("SERNO", value))"""
|
||||
return self.setKeyValue("SERNO", value)
|
||||
|
||||
|
||||
class iplsave:
|
||||
"""This class performs all iplsave.bin related things. It includes functions to add a title to the list, remove a title based upon position or title, and move a title from one position to another."""
|
||||
class IPLSAVE_Entry(Struct):
|
||||
@ -201,17 +266,19 @@ class iplsave:
|
||||
fp.close()
|
||||
self.UpdateMD5()
|
||||
|
||||
def UpdateMD5(self):
|
||||
def updateMD5(self):
|
||||
"""Updates the MD5 hash in the iplsave.bin file. Used by other functions here."""
|
||||
fp = open(self.f, "rb")
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
md5 = Crypto().CreateMD5Hash(data)
|
||||
md5 = Crypto().createMD5Hash(data)
|
||||
fp = open(self.f, "wb")
|
||||
fp.write(data)
|
||||
fp.write(md5)
|
||||
fp.close()
|
||||
|
||||
def AddTitleBase(self, x, y, page, tid, movable, type, overwrite, clear, isdisc):
|
||||
def addTitleBase(self, x, y, page, tid, movable, type, overwrite, clear, isdisc):
|
||||
"""A base AddTitle function that is used by others. Don't use this."""
|
||||
if((x + (y * 4) + (page * 12)) >= 0x30):
|
||||
print "Too far!"
|
||||
return None
|
||||
@ -222,7 +289,7 @@ class iplsave:
|
||||
baseipl_ent.type1 = fp.read(1)
|
||||
fp.close()
|
||||
if((baseipl_ent.type1 != "\0") and (not overwrite)):
|
||||
return self.AddTitle(x + 1, y, page, tid, movable, type)
|
||||
return self.addTitleBase(x + 1, y, page, tid, movable, type, overwrite, clear, isdisc)
|
||||
fp = open(self.f, "wb")
|
||||
fp.write(data)
|
||||
fp.seek(16 + ((x + (y * 4) + (page * 12))) * 16)
|
||||
@ -250,19 +317,23 @@ class iplsave:
|
||||
fp.write(a2b_hex("%04X" % baseipl_ent.flags))
|
||||
fp.write(a2b_hex("%016X" % baseipl_ent.titleid))
|
||||
fp.close()
|
||||
self.UpdateMD5()
|
||||
self.updateMD5()
|
||||
return (x + (y * 4) + (page * 12))
|
||||
|
||||
def AddTitle(self, x, y, page, tid, movable, type):
|
||||
return self.AddTitleBase(x, y, page, tid, movable, type, 0, 0, 0)
|
||||
def addTitle(self, x, y, page, tid, movable, type):
|
||||
"""Adds a title with title ID ``tid'' at location (x,y) on page ``page''. ``movable'' specifies whether the title is movable, and ``type'' specifies the type of title (00 for most titles.)"""
|
||||
return self.addTitleBase(x, y, page, tid, movable, type, 0, 0, 0)
|
||||
|
||||
def AddDisc(self, x, y, page, movable):
|
||||
return self.AddTitleBase(x, y, page, 0, movable, 0, 0, 0, 1)
|
||||
def addDisc(self, x, y, page, movable):
|
||||
"""Adds the Disc Channel at location (x,y) on page ``page''. ``movable'' specifies whether it can be moved."""
|
||||
return self.addTitleBase(x, y, page, 0, movable, 0, 0, 0, 1)
|
||||
|
||||
def DeletePosition(self, x, y, page):
|
||||
return self.AddTitleBase(x, y, page, 0, 0, 0, 1, 1, 0)
|
||||
def deletePosition(self, x, y, page):
|
||||
"""Deletes the title at (x,y) on page ``page''"""
|
||||
return self.addTitleBase(x, y, page, 0, 0, 0, 1, 1, 0)
|
||||
|
||||
def DeleteTitle(self, tid):
|
||||
def deleteTitle(self, tid):
|
||||
"""Deletes the title with title ID ``tid''"""
|
||||
fp = open(self.f, "rb")
|
||||
baseipl_ent = self.IPLSAVE_Entry
|
||||
for i in range(0x30):
|
||||
@ -273,10 +344,11 @@ class iplsave:
|
||||
baseipl_ent.flags = fp.read(2)
|
||||
baseipl_ent.titleid = fp.read(8)
|
||||
if(baseipl_ent.titleid == a2b_hex("%016X" % tid)):
|
||||
self.DeletePosition(i, 0, 0)
|
||||
self.deletePosition(i, 0, 0)
|
||||
fp.close()
|
||||
|
||||
def MoveTitle(self, x1, y1, page1, x2, y2, page2):
|
||||
def moveTitle(self, x1, y1, page1, x2, y2, page2):
|
||||
"""Moves a title from (x1,y1) on page ``page1'' to (x2,y2) on page ``page2''"""
|
||||
fp = open(self.f, "rb")
|
||||
baseipl_ent = self.IPLSAVE_Entry
|
||||
fp.seek(16 + ((x1 + (y1 * 4) + (page1 * 12)) * 16))
|
||||
@ -286,5 +358,5 @@ class iplsave:
|
||||
baseipl_ent.flags = fp.read(2)
|
||||
baseipl_ent.titleid = fp.read(8)
|
||||
fp.close()
|
||||
self.DeletePosition(x1, y1, page1)
|
||||
return self.AddTitle(x2, y2, page2, baseipl_ent.titleid, (baseipl_ent.flags - 0xE) ^ 1, baseipl_ent.type2)
|
||||
self.deletePosition(x1, y1, page1)
|
||||
return self.addTitle(x2, y2, page2, baseipl_ent.titleid, (baseipl_ent.flags - 0xE) ^ 1, baseipl_ent.type2)
|
||||
|
@ -1,6 +1,4 @@
|
||||
import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
|
||||
from hashlib import md5
|
||||
from Crypto.Cipher import AES
|
||||
@ -157,7 +155,7 @@ class Savegame():
|
||||
print 'Extracted %s (%ib)' % (name, fileHdr.size)
|
||||
|
||||
fileBuffer = self.fd.read(fileHdr.size)
|
||||
fileBuffer = Crypto().DecryptData(self.sdKey, fileIV, fileBuffer, True)
|
||||
fileBuffer = Crypto().decryptData(self.sdKey, fileIV, fileBuffer, True)
|
||||
try:
|
||||
open(name, 'w+b').write(fileBuffer)
|
||||
except:
|
||||
@ -176,7 +174,7 @@ class Savegame():
|
||||
|
||||
def analyzeHeader(self):
|
||||
headerBuffer = self.fd.read(0xF0C0)
|
||||
headerBuffer = Crypto().DecryptData(self.sdKey, self.sdIv, headerBuffer, True)
|
||||
headerBuffer = Crypto().decryptData(self.sdKey, self.sdIv, headerBuffer, True)
|
||||
|
||||
self.hdr = self.savegameHeader().unpack(headerBuffer[:0x20])
|
||||
|
||||
|
20
title.py
20
title.py
@ -1,6 +1,4 @@
|
||||
import os, struct, subprocess, fnmatch, shutil, urllib, array
|
||||
import wx
|
||||
import png
|
||||
|
||||
from Struct import Struct
|
||||
|
||||
@ -53,7 +51,7 @@ class Ticket:
|
||||
if(self.tik.commonkey_index == 1): #korean, kekekekek!
|
||||
commonkey = koreankey
|
||||
|
||||
self.titlekey = Crypto().DecryptTitleKey(commonkey, self.tik.titleid, self.tik.enctitlekey)
|
||||
self.titlekey = Crypto().decryptTitleKey(commonkey, self.tik.titleid, self.tik.enctitlekey)
|
||||
def getTitleKey(self):
|
||||
"""Returns a string containing the title key."""
|
||||
return self.titlekey
|
||||
@ -87,7 +85,7 @@ class Ticket:
|
||||
self.rsamod = self.rsamod = "\x00" * 256
|
||||
for i in range(65536):
|
||||
self.tik.unk2 = i
|
||||
if(Crypto().CreateSHAHashHex(self.tik.pack())[:2] == "00"):
|
||||
if(Crypto().createSHAHashHex(self.tik.pack())[:2] == "00"):
|
||||
break
|
||||
if(i == 65535):
|
||||
raise ValueError("Failed to fakesign. Aborting...")
|
||||
@ -204,7 +202,7 @@ class TMD:
|
||||
data += self.tmd.pack()
|
||||
for i in range(self.tmd.numcontents):
|
||||
data += self.contents[i].pack()
|
||||
if(Crypto().CreateSHAHashHex(data)[:2] == "00"):
|
||||
if(Crypto().createSHAHashHex(data)[:2] == "00"):
|
||||
break
|
||||
if(i == 65535):
|
||||
raise ValueError("Failed to fakesign! Aborting...")
|
||||
@ -271,7 +269,7 @@ class NUS:
|
||||
certs += rawtik[0x2A4 + 0x300:] #CA (tik)
|
||||
certs += rawtmd[0x328:0x328 + 0x300] #CP
|
||||
|
||||
if(Crypto().CreateMD5HashHex(certs) != "7ff50e2733f7a6be1677b6f6c9b625dd"):
|
||||
if(Crypto().createMD5HashHex(certs) != "7ff50e2733f7a6be1677b6f6c9b625dd"):
|
||||
raise ValueError("Failed to create certs! MD5 mistatch.")
|
||||
|
||||
open("cert", "wb").write(certs)
|
||||
@ -301,8 +299,8 @@ class NUS:
|
||||
|
||||
if(decrypt):
|
||||
data = open("%08x.app" % output, "rb").read(content.size)
|
||||
tmpdata = Crypto().DecryptContent(titlekey, content.index, data)
|
||||
if(Crypto().ValidateSHAHash(tmpdata, content.hash) == 0):
|
||||
tmpdata = Crypto().decryptContent(titlekey, content.index, data)
|
||||
if(Crypto().validateSHAHash(tmpdata, content.hash) == 0):
|
||||
raise ValueError("Decryption failed! SHA1 mismatch.")
|
||||
open("%08x.app" % output, "wb").write(tmpdata)
|
||||
|
||||
@ -330,10 +328,10 @@ class WAD:
|
||||
|
||||
if(decrypted):
|
||||
if(fakesign):
|
||||
content.hash = str(Crypto().CreateSHAHash(tmpdata))
|
||||
content.hash = str(Crypto().createSHAHash(tmpdata))
|
||||
content.size = len(tmpdata)
|
||||
|
||||
encdata = Crypto().EncryptContent(titlekey, content.index, tmpdata)
|
||||
encdata = Crypto().encryptContent(titlekey, content.index, tmpdata)
|
||||
else:
|
||||
encdata = tmpdata
|
||||
|
||||
@ -427,7 +425,7 @@ class WAD:
|
||||
if(tmpsize % 16 != 0):
|
||||
tmpsize += 16 - (tmpsize % 16)
|
||||
tmptmpdata = fd.read(tmpsize)
|
||||
tmpdata = Crypto().DecryptContent(titlekey, contents[i].index, tmptmpdata)
|
||||
tmpdata = Crypto().decryptContent(titlekey, contents[i].index, tmptmpdata)
|
||||
open("%08x.app" % contents[i].index, "wb").write(tmpdata)
|
||||
if(tmpsize % 64 != 0):
|
||||
fd.seek(64 - (tmpsize % 64), 1)
|
||||
|
Loading…
Reference in New Issue
Block a user