RikuNoctis

Realta Nua Mobile - Unpack

Jun 15th, 2015
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.20 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Fate Mobile DAT File Extractor v1.2
  4. # 2015/06/11
  5. #
  6. # Copyright (c) 2015 w酱
  7. # Copyright (c) 2015 Hintay <hintay(at)me.com>
  8. # Copyright (c) 2015 dorobo-hamster
  9.  
  10. import os, codecs, sys, hashlib
  11.  
  12. #This has only been tested on fate_000.dat.
  13. #Other files may be different so check the output for other files.
  14. ENCRYPTION_KEY = [0x5d, 0x55, 0x82, 0xf2, 0xbe, 0x45, 0x31, 0xeb,
  15.                   0x29, 0xbc, 0xf7, 0x2c, 0xe2, 0xb5, 0xc0, 0x5b]
  16.  
  17. def getFileInfo(input):
  18.     postfix = {1:'', 2:'_rin', 3:'_sakura', 4:''}
  19.     if(input == 5):
  20.         while True:
  21.             custom_fileinfo = raw_input('Please input fileinfo txt\'s filename without extension: ')
  22.             fileinfo_path = os.path.join('sys', '%s.txt' % custom_fileinfo)
  23.             if(os.path.exists(fileinfo_path)):
  24.                 break
  25.             else:
  26.                 print(u'%s not exits, please input again.' % fileinfo_path)
  27.     else:
  28.         fileinfo_path = os.path.join('sys', 'fileinfo%s.txt' % postfix[input])
  29.     fp = codecs.open(fileinfo_path, 'rb', 'utf-8')
  30.     lines = fp.readlines()
  31.     lst = []
  32.     for line in lines:
  33.         if '::' in line:
  34.             name, extension, container_name, offset, size, file_hash, encrypted = line.split('::')[:7]
  35.             offset = int(offset , 10)
  36.             size = int(size, 10)
  37.             lst.append((name, extension, offset, size, file_hash, encrypted))
  38.     return lst
  39.  
  40. def view_bar(num=1, sum=100, bar_word=":"):  
  41.     rate = float(num) / float(sum)
  42.     rate_num = int(rate * 100)
  43.     print('\r%d%%' % (rate_num))
  44. #    for i in range(0, rate_num):
  45. #        os.write(1, bar_word)
  46. #    sys.stdout.flush()
  47.  
  48. def decrypt(file_info, data):
  49.     print('Decrypt '+file_info['name']+'.'+file_info['extension'])
  50.     i = 0
  51.     offset = file_info['start']
  52.     data = bytearray(data)
  53.     while i < file_info['length']:        
  54.         data[i] = data[i]^(offset%256)^ENCRYPTION_KEY[offset%16]
  55.         i+=1
  56.         offset+=1
  57.     return data
  58.  
  59. def main(input):
  60.     if(input == 5):
  61.         while True:
  62.             filename = raw_input('Please input dat filename without extension: ')
  63.             if(os.path.exists('%s.dat'%filename)):
  64.                 break
  65.             else:
  66.                 print(u'%s.dat not exits, please input again.'%filename)
  67.     else:
  68.         filename = ''
  69.     datname = {1:'saber', 2:'rin', 3:'sakura', 4:'fate_000', 5:filename}
  70.  
  71.     lst = getFileInfo(input)
  72.     with open('%s.dat' % datname[input], 'rb') as fp:
  73.         if not os.path.exists('%s.dat_unpacked' % datname[input]):
  74.             os.makedirs('%s.dat_unpacked' % datname[input])
  75.         lstsum = len(lst)
  76.         for i in range(lstsum):
  77.             view_bar(i, lstsum)
  78.             (name, extension, offset, size, file_hash, encrypted) = lst[i]
  79.             fp.seek(offset)
  80.             dat = fp.read(size)
  81.             file_path = os.path.join(u'%s.dat_unpacked' % datname[input], '%s.%s' % (name , extension))
  82.             dest = open(file_path, 'wb')
  83.             if(encrypted == '1'):
  84.                 file_info = {'name':name, 'extension':extension, 'start':offset, 'length':size}
  85.                 dat = decrypt(file_info, dat)
  86.             dest.write(dat)
  87.             dest.close()
  88.  
  89.             # Verify output file's hash
  90.             try:
  91.                 hash_function = hashlib.md5()
  92.                 with open(file_path, mode='rb') as input_file:
  93.                     buf = input_file.read()
  94.                     hash_function.update(buf)
  95.                     new_hash = hash_function.hexdigest()
  96.                 if(new_hash != file_hash):
  97.                     raise
  98.             except:
  99.                 print(u'Hash validation failed, maybe the dat file is broken or the encryption key has been changed.')
  100.         fp.close()
  101.  
  102. if __name__ == '__main__':
  103.     print(u'1. saber.dat')
  104.     print(u'2. rin.dat')
  105.     print(u'3. sakura.dat')
  106.     print(u'4. fate_000.dat')
  107.     print(u'5. other .dat file')
  108.     while True:
  109.         input = int(input('Please select dat file what you want unpack: '))
  110.         if input == 1 or input == 2 or input == 3 or input == 4 or input == 5:
  111.             break
  112.         else:
  113.             print(u'Your input is incorrect, please input again.')
  114.     main(input)
Advertisement
Add Comment
Please, Sign In to add comment