Guest User

Untitled

a guest
Jun 21st, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.87 KB | None | 0 0
  1. import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
  2. import wx
  3. import png
  4.  
  5. from hashlib import md5
  6. from Crypto.Cipher import AES
  7. from Struct import Struct
  8.  
  9. from common import *
  10. from title import *
  11.  
  12. class Savegame():
  13. class savegameHeader(Struct):
  14. __endian__ = Struct.BE
  15. def __format__(self):
  16. self.savegameId = Struct.uint32[2]
  17. self.bannerSize = Struct.uint32
  18. self.permissions = Struct.uint8
  19. self.unknown1 = Struct.uint8
  20. self.md5hash = Struct.uint32[4]
  21. self.unknown2 = Struct.uint16
  22.  
  23. class savegameBanner(Struct):
  24. __endian__ = Struct.BE
  25. def __format__(self):
  26. self.magic = Struct.string(4)
  27. self.reserved = Struct.uint8[4]
  28. self.flags = Struct.uint32
  29. self.reserved = Struct.uint32[5]
  30. self.gameTitle = Struct.string(64)
  31. self.gameSubTitle = Struct.string(64)
  32. self.banner = Struct.uint8[24576]
  33. self.icon0 = Struct.uint8[4608]
  34. self.icon1 = Struct.uint8[4608]
  35. self.icon2 = Struct.uint8[4608]
  36. self.icon3 = Struct.uint8[4608]
  37. self.icon4 = Struct.uint8[4608]
  38. self.icon5 = Struct.uint8[4608]
  39. self.icon6 = Struct.uint8[4608]
  40. self.icon7 = Struct.uint8[4608]
  41.  
  42. class backupHeader(Struct):
  43. __endian__ = Struct.BE
  44. def __format__(self):
  45. self.hdrSize = Struct.uint32
  46. self.magic = Struct.string(2)
  47. self.version = Struct.uint16
  48. self.NGid = Struct.uint32
  49. self.filesCount = Struct.uint32
  50. self.filesSize = Struct.uint32
  51. self.unknown1 = Struct.uint32
  52. self.unknown2 = Struct.uint32
  53. self.totalSize = Struct.uint32
  54. self.unknown3 = Struct.uint8[64]
  55. self.unknown4 = Struct.uint32
  56. self.gameId = Struct.string(4)
  57. self.wiiMacAddr = Struct.uint8[6]
  58. self.unknown6 = Struct.uint16
  59. self.padding = Struct.uint32[4]
  60.  
  61. class fileHeader(Struct):
  62. __endian__ = Struct.BE
  63. def __format__(self):
  64. self.magic = Struct.uint32
  65. self.size = Struct.uint32
  66. self.permissions = Struct.uint8
  67. self.attribute = Struct.uint8
  68. self.type = Struct.uint8
  69. self.name = Struct.string(12, stripNulls=True) #Need a way to stop this to the 1st null char
  70. self.fileIV = Struct.uint32[4]
  71. self.unknown = Struct.uint8[10]
  72.  
  73. def __init__(self, f):
  74. self.f = f
  75. self.fd = open(f, 'r+b')
  76.  
  77. self.sdKey = '\xab\x01\xb9\xd8\xe1\x62\x2b\x08\xaf\xba\xd8\x4d\xbf\xc2\xa5\x5d'
  78. self.sdIv = '\x21\x67\x12\xe6\xaa\x1f\x68\x9f\x95\xc5\xa2\x23\x24\xdc\x6a\x98'
  79.  
  80. try:
  81. os.mkdir(self.f.replace(".", "_") + "_out")
  82. except:
  83. pass
  84.  
  85. os.chdir(self.f.replace(".", "_") + "_out")
  86.  
  87. self.iconCount = 1
  88.  
  89. def __str__(self):
  90. ret = ''
  91. ret += '\nSavegame header \n'
  92.  
  93. ret += 'Savegame ID : 0x%x%x\n' % (self.hdr.savegameId[0], self.hdr.savegameId[1])
  94. ret += 'Banner size : 0x%x\n' % self.hdr.bannerSize
  95. ret += 'Permissions : 0x%x\n' % self.hdr.permissions
  96. ret += 'Unknown : 0x%x\n' % self.hdr.unknown1
  97. ret += 'MD5 hash : 0x%x%x%x%x\n' % (self.hdr.md5hash[0], self.hdr.md5hash[1], self.hdr.md5hash[2], self.hdr.md5hash[3])
  98. ret += 'Unknown : 0x%x\n' % self.hdr.unknown2
  99.  
  100. ret += '\nBanner header \n'
  101.  
  102. ret += 'Flags : 0x%x\n' % self.bnr.flags
  103. ret += 'Game title : %s\n' % self.bnr.gameTitle
  104. ret += 'Game subtitle : %s\n' % self.bnr.gameSubTitle
  105.  
  106. ret += '\nBackup header \n'
  107.  
  108. ret += 'Header size : 0x%x (+ 0x10 of padding) version 0x%x\n' % (self.bkHdr.hdrSize, self.bkHdr.version)
  109. ret += 'Wii MAC address %02x:%02x:%02x:%02x:%02x:%02x\n' % (self.bkHdr.wiiMacAddr[0], self.bkHdr.wiiMacAddr[1], self.bkHdr.wiiMacAddr[2], self.bkHdr.wiiMacAddr[3], self.bkHdr.wiiMacAddr[4], self.bkHdr.wiiMacAddr[5])
  110. ret += 'Found %i files for %i bytes\n' % (self.bkHdr.filesCount, self.bkHdr.filesSize)
  111. ret += 'Total size : %i bytes\n' % self.bkHdr.totalSize
  112. if self.bkHdr.gameId[3] == 'P':
  113. ret += 'Region : PAL\n'
  114. elif self.bkHdr.gameId[3] == 'E':
  115. ret += 'Region : NTSC\n'
  116. elif self.bkHdr.gameId[3] == 'J':
  117. ret += 'Region : JAP\n'
  118. ret += 'Game ID : %s\n' % self.bkHdr.gameId
  119. ret += 'NG id : 0x%x\n' % self.bkHdr.NGid
  120.  
  121. return ret
  122.  
  123. def extractFile(self, index):
  124. if index > self.bkHdr.filesCount:
  125. raise ValueError
  126.  
  127. self.fd.seek(self.fileStartOffset)
  128.  
  129. for i in range(self.bkHdr.filesCount):
  130.  
  131. fileHdr = self.fd.read(0x80)
  132. fileHdr = self.fileHeader().unpack(fileHdr)
  133.  
  134. if fileHdr.magic != 0x03adf17e:
  135. raise ValueError('Wrong file magic')
  136.  
  137. fileHdr.size = align(fileHdr.size, 64)
  138.  
  139. print 'File name : %s (%ib)' % (fileHdr.name, fileHdr.size)
  140. print 'Type [%i] Attribute [%i] Permission [%i]' % (fileHdr.type, fileHdr.attribute, fileHdr.permissions)
  141. print 'File IV : 0x%x%x%x%x' % (fileHdr.fileIV[0], fileHdr.fileIV[1], fileHdr.fileIV[2], fileHdr.fileIV[3])
  142.  
  143. if fileHdr.type == 1:
  144. fileBuffer = self.fd.read(fileHdr.size)
  145. fileBuffer = Crypto().DecryptData(self.sdKey, struct.pack('>IIII', *fileHdr.fileIV), fileBuffer, True)
  146. open(fileHdr.name.rstrip('\0'), 'r+b').write(fileBuffer)
  147. elif fileHdr.type == 2:
  148. try:
  149. os.mkdir(fileHdr.name.rstrip('\0'))
  150. except:
  151. pass
  152.  
  153. def analyzeHeader(self):
  154. headerBuffer = self.fd.read(0xF0BF + 1)
  155. headerBuffer = Crypto().DecryptData(self.sdKey, self.sdIv, headerBuffer, True)
  156.  
  157. self.hdr = self.savegameHeader().unpack(headerBuffer[:0x20])
  158.  
  159. #MD5 check fail always ...
  160. #list(headerBuffer)[0x000E:0x001E] = '\x0e\x65\x37\x81\x99\xbe\x45\x17\xab\x06\xec\x22\x45\x1a\x57\x93'
  161. #print '0x%x%x%x%x %s' % (self.hdr.md5hash[0], self.hdr.md5hash[1], self.hdr.md5hash[2], self.hdr.md5hash[3], hashlib.md5(headerBuffer[:0x20]).hexdigest())
  162.  
  163. self.bnr = self.savegameBanner().unpack(headerBuffer[0x20:])
  164.  
  165. if self.bnr.magic != 'WIBN':
  166. raise ValueError ('Wrong magic, should be WIBN')
  167.  
  168. if self.hdr.bannerSize == 0xF0C0:
  169. self.iconCount += 7
  170.  
  171. bkHdrBuffer = self.fd.read(0x80)
  172. self.bkHdr = self.backupHeader().unpack(bkHdrBuffer)
  173.  
  174. if self.bkHdr.magic != 'Bk' or self.bkHdr.hdrSize != 0x70:
  175. raise ValueError ('Bk header error')
  176.  
  177. self.fileStartOffset = self.fd.tell()
  178.  
  179. def getBanner(self):
  180. open('bnr.bin', 'w+b').write(struct.pack('24576I', *self.bnr.banner))
  181.  
  182. def getIcon(self, index):
  183. if index < 0 or index > 7 or index > self.iconCount:
  184. return -1
  185. if index == 0:
  186. return self.bnr.icon0
  187. if index == 1:
  188. return self.bnr.icon1
  189. if index == 2:
  190. return self.bnr.icon2
  191. if index == 3:
  192. return self.bnr.icon3
  193. if index == 4:
  194. return self.bnr.icon4
  195. if index == 5:
  196. return self.bnr.icon5
  197. if index == 6:
  198. return self.bnr.icon6
  199. if index == 7:
  200. return self.bnr.icon7
  201.  
  202.  
  203. def getIconsCount(self):
  204. return self.iconCount
  205.  
  206. def getSaveString(self, string):
  207. if string == 'GAMEID':
  208. return self.bkHdr.gameId
  209. elif string == 'GAMETITLE':
  210. return self.bnr.gameTitle
  211. elif string == 'GAMESUBTITLE':
  212. return self.bnr.gameSubTitle
  213.  
  214. def getFilesCount(self):
  215. return self.bkHdr.filesCount
Add Comment
Please, Sign In to add comment