Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- #
- # Fate Mobile DAT File Extractor v1.2
- # 2015/06/11
- #
- # Copyright (c) 2015 w酱
- # Copyright (c) 2015 Hintay <hintay(at)me.com>
- # Copyright (c) 2015 dorobo-hamster
- import os, codecs, sys, hashlib
- #This has only been tested on fate_000.dat.
- #Other files may be different so check the output for other files.
- ENCRYPTION_KEY = [0x5d, 0x55, 0x82, 0xf2, 0xbe, 0x45, 0x31, 0xeb,
- 0x29, 0xbc, 0xf7, 0x2c, 0xe2, 0xb5, 0xc0, 0x5b]
- def getFileInfo(input):
- postfix = {1:'', 2:'_rin', 3:'_sakura', 4:''}
- if(input == 5):
- while True:
- custom_fileinfo = raw_input('Please input fileinfo txt\'s filename without extension: ')
- fileinfo_path = os.path.join('sys', '%s.txt' % custom_fileinfo)
- if(os.path.exists(fileinfo_path)):
- break
- else:
- print(u'%s not exits, please input again.' % fileinfo_path)
- else:
- fileinfo_path = os.path.join('sys', 'fileinfo%s.txt' % postfix[input])
- fp = codecs.open(fileinfo_path, 'rb', 'utf-8')
- lines = fp.readlines()
- lst = []
- for line in lines:
- if '::' in line:
- name, extension, container_name, offset, size, file_hash, encrypted = line.split('::')[:7]
- offset = int(offset , 10)
- size = int(size, 10)
- lst.append((name, extension, offset, size, file_hash, encrypted))
- return lst
- def view_bar(num=1, sum=100, bar_word=":"):
- rate = float(num) / float(sum)
- rate_num = int(rate * 100)
- print('\r%d%%' % (rate_num))
- # for i in range(0, rate_num):
- # os.write(1, bar_word)
- # sys.stdout.flush()
- def decrypt(file_info, data):
- print('Decrypt '+file_info['name']+'.'+file_info['extension'])
- i = 0
- offset = file_info['start']
- data = bytearray(data)
- while i < file_info['length']:
- data[i] = data[i]^(offset%256)^ENCRYPTION_KEY[offset%16]
- i+=1
- offset+=1
- return data
- def main(input):
- if(input == 5):
- while True:
- filename = raw_input('Please input dat filename without extension: ')
- if(os.path.exists('%s.dat'%filename)):
- break
- else:
- print(u'%s.dat not exits, please input again.'%filename)
- else:
- filename = ''
- datname = {1:'saber', 2:'rin', 3:'sakura', 4:'fate_000', 5:filename}
- lst = getFileInfo(input)
- with open('%s.dat' % datname[input], 'rb') as fp:
- if not os.path.exists('%s.dat_unpacked' % datname[input]):
- os.makedirs('%s.dat_unpacked' % datname[input])
- lstsum = len(lst)
- for i in range(lstsum):
- view_bar(i, lstsum)
- (name, extension, offset, size, file_hash, encrypted) = lst[i]
- fp.seek(offset)
- dat = fp.read(size)
- file_path = os.path.join(u'%s.dat_unpacked' % datname[input], '%s.%s' % (name , extension))
- dest = open(file_path, 'wb')
- if(encrypted == '1'):
- file_info = {'name':name, 'extension':extension, 'start':offset, 'length':size}
- dat = decrypt(file_info, dat)
- dest.write(dat)
- dest.close()
- # Verify output file's hash
- try:
- hash_function = hashlib.md5()
- with open(file_path, mode='rb') as input_file:
- buf = input_file.read()
- hash_function.update(buf)
- new_hash = hash_function.hexdigest()
- if(new_hash != file_hash):
- raise
- except:
- print(u'Hash validation failed, maybe the dat file is broken or the encryption key has been changed.')
- fp.close()
- if __name__ == '__main__':
- print(u'1. saber.dat')
- print(u'2. rin.dat')
- print(u'3. sakura.dat')
- print(u'4. fate_000.dat')
- print(u'5. other .dat file')
- while True:
- input = int(input('Please select dat file what you want unpack: '))
- if input == 1 or input == 2 or input == 3 or input == 4 or input == 5:
- break
- else:
- print(u'Your input is incorrect, please input again.')
- main(input)
Advertisement
Add Comment
Please, Sign In to add comment