ntool/lib/ctr_cro.py
2023-03-26 23:48:17 +08:00

112 lines
4.1 KiB
Python

from .common import *
from .keys import *
class croHdr(Structure):
_pack_ = 1
_fields_ = [
('hdr_hash', c_uint8 * 0x20),
('sect0_hash', c_uint8 * 0x20),
('sect1_hash', c_uint8 * 0x20),
('sect2_hash', c_uint8 * 0x20),
('magic', c_char * 4),
('name_offset', c_uint32),
('next_cro', c_uint32),
('prev_cro', c_uint32),
('file_size', c_uint32),
('bss_size', c_uint32),
('unk1', c_uint32),
('unk2', c_uint32),
('segment_offset_nnroControlObject', c_uint32),
('segment_offset_OnLoad', c_uint32),
('segment_offset_OnExit', c_uint32),
('segment_offset_OnUnresolved', c_uint32),
('code_offset', c_uint32),
('code_size', c_uint32),
('data_offset', c_uint32),
('data_size', c_uint32),
('module_name_offset', c_uint32),
('module_name_size', c_uint32),
('segment_table_offset', c_uint32),
('segment_table_count', c_uint32),
('named_export_table_offset', c_uint32),
('named_export_table_count', c_uint32),
('indexed_export_table_offset', c_uint32),
('indexed_export_table_count', c_uint32),
('export_strings_offset', c_uint32),
('export_strings_size', c_uint32),
('export_tree_offset', c_uint32),
('export_tree_count', c_uint32),
('import_module_table_offset', c_uint32),
('import_module_table_count', c_uint32),
('import_patches_offset', c_uint32),
('import_patches_count', c_uint32),
('named_import_table_offset', c_uint32),
('named_import_table_count', c_uint32),
('indexed_import_table_offset', c_uint32),
('indexed_import_table_count', c_uint32),
('anonymous_import_table_offset', c_uint32),
('anonymous_import_table_count', c_uint32),
('import_strings_offset', c_uint32),
('import_strings_size', c_uint32),
('unk3_offset', c_uint32),
('unk3_count', c_uint32),
('relocation_patches_offset', c_uint32),
('relocation_patches_count', c_uint32),
('unk4_offset', c_uint32),
('unk4_count', c_uint32),
]
def __new__(cls, buf):
return cls.from_buffer_copy(buf)
def __init__(self, data):
pass
class croReader:
def __init__(self, file):
self.file = file
with open(file, 'rb') as f:
self.hdr = croHdr(f.read(0x138))
def verify(self):
f = open(self.file, 'rb')
hash_check = []
hash_check_info = [ # (name, offset to read from, size, expected hash)
('Header', 0x80, 0x100, bytes(self.hdr.hdr_hash)),
('Section 0', self.hdr.code_offset, self.hdr.code_size, bytes(self.hdr.sect0_hash)),
('Section 1', self.hdr.module_name_offset, self.hdr.data_offset - self.hdr.module_name_offset, bytes(self.hdr.sect1_hash)),
('Section 2', self.hdr.data_offset, self.hdr.data_size, bytes(self.hdr.sect2_hash)),
]
for name, off, size, hash_expected in hash_check_info:
f.seek(off)
h = hashlib.sha256()
h.update(f.read(size))
hash_check.append((name, h.digest() == hash_expected))
f.close()
print("Hashes:")
for i in hash_check:
print(' > {0:15} {1:4}'.format(i[0] + ':', 'GOOD' if i[1] else 'FAIL'))
def regen_hash(self): # Overwrites existing file
f = open(self.file, 'r+b')
hash_info = [ # (name, offset to read from, size, offset to put hash)
('Header', 0x80, 0x100, 0),
('Section 0', self.hdr.code_offset, self.hdr.code_size, 0x20),
('Section 1', self.hdr.module_name_offset, self.hdr.data_offset - self.hdr.module_name_offset, 0x40),
('Section 2', self.hdr.data_offset, self.hdr.data_size, 0x60),
]
for _, off, size, hash_off in hash_info:
f.seek(off)
h = hashlib.sha256()
h.update(f.read(size))
f.seek(hash_off)
f.write(h.digest())
f.close()
print(f'{self.file} rehashed')