Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
seiya-git committed Oct 13, 2023
1 parent afb14c3 commit 3543953
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 20 deletions.
27 changes: 12 additions & 15 deletions py-test/lib/FsTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ def get_data_from_cnmt(nca):
f.rewind()
cnmt.rewind()

# titleid,titleversion,base_ID,keygeneration,rightsId,RSV,RGV,ctype,metasdkversion,exesdkversion,hasHtmlManual,Installedsize,DeltaSize,ncadata

title_id = cnmt.readInt64()
data['title_id'] = (str(hx(title_id.to_bytes(8, byteorder='big')))[2:-1]).upper()

Expand All @@ -37,7 +35,6 @@ def get_data_from_cnmt(nca):
cnmt.rewind()
cnmt.seek(0x20)

# Why Base id? It's return Update ID
base_id = cnmt.readInt64()
data['base_id'] = (str(hx(base_id.to_bytes(8, byteorder='big')))[2:-1]).upper()

Expand Down Expand Up @@ -118,15 +115,15 @@ def get_data_from_cnmt(nca):
return data

def parse_cnmt_type_n(type_n):
if type_n == b'1':
if type_n == b'01':
return 'SystemProgram'
if type_n == b'2':
if type_n == b'02':
return 'SystemData'
if type_n == b'3':
if type_n == b'03':
return 'SystemUpdate'
if type_n == b'4':
if type_n == b'04':
return 'BootImagePackage'
if type_n == b'5':
if type_n == b'05':
return 'BootImagePackageSafe'
if type_n == b'80':
return 'GAME'
Expand All @@ -139,18 +136,18 @@ def parse_cnmt_type_n(type_n):
return 'Unknown'

def get_metacontent_type(nca_type_number):
if nca_type_number == b'0':
if nca_type_number == b'00':
return 'Meta'
if nca_type_number == b'1':
if nca_type_number == b'01':
return 'Program'
if nca_type_number == b'2':
if nca_type_number == b'02':
return 'Data'
if nca_type_number == b'3':
if nca_type_number == b'03':
return 'Control'
if nca_type_number == b'4':
if nca_type_number == b'04':
return 'HtmlDocument'
if nca_type_number == b'5':
if nca_type_number == b'05':
return 'LegalInformation'
if nca_type_number == b'6':
if nca_type_number == b'06':
return 'DeltaFragment'
return 'Unknown'
2 changes: 1 addition & 1 deletion py-test/lib/Header.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ def __init__(self, f):
self.blockSizeExponent = f.readInt8()
self.numberOfBlocks = f.readInt32()
self.decompressedSize = f.readInt64()
self.compressedBlockSizeList = [f.readInt32() for _ in range(self.numberOfBlocks)]
self.compressedBlockSizeList = [f.readInt32() for _ in range(self.numberOfBlocks)]
39 changes: 39 additions & 0 deletions py-test/lib/Hex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from string import ascii_letters, digits, punctuation

def bufferToHex(buffer, start, count):
accumulator = ''
for item in range(count):
accumulator += '%02X' % buffer[start + item] + ' '
return accumulator

def bufferToAscii(buffer, start, count):
accumulator = ''
for item in range(count):
char = chr(buffer[start + item])
if char in ascii_letters or \
char in digits or \
char in punctuation or \
char == ' ':
accumulator += char
else:
accumulator += '.'
return accumulator

def dump(data, size = 16):
bytesRead = len(data)
index = 0
hexFormat = '{:'+str(size*3)+'}'
asciiFormat = '{:'+str(size)+'}'

print()
while index < bytesRead:

hex = bufferToHex(data, index, size)
ascii = bufferToAscii(data, index, size)

print(hexFormat.format(hex), end='')
print('|',asciiFormat.format(ascii),'|')

index += size
if bytesRead - index < size:
size = bytesRead - index
71 changes: 67 additions & 4 deletions py-test/lib/VerifyTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@

import Fs
import io
from lib import Hex

import zstandard
from lib import FsTools
from lib import Header, BlockDecompressorReader

def readInt64(f, byteorder='little', signed = False):
return int.from_bytes(f.read(8), byteorder=byteorder, signed=signed)

def readInt128(f, byteorder='little', signed = False):
return int.from_bytes(f.read(16), byteorder=byteorder, signed=signed)

def verify_nca_key(self, nca):
print('[:WARN:] NOT IMPLEMENTED!')
Expand Down Expand Up @@ -58,12 +67,66 @@ def verify_enforcer(f):
return False

def verify_ncz(self, target):
for nca in self:
if nca._path.endswith('.cnmt.nca'):
cnmtData = FsTools.get_data_from_cnmt(nca)
for f in self:
if f._path.endswith('.cnmt.nca'):
cnmtData = FsTools.get_data_from_cnmt(f)

if f._path == target:
f.seek(0)
UNCOMPRESSABLE_HEADER_SIZE = 0x4000
header = f.read(UNCOMPRESSABLE_HEADER_SIZE)

magic = f.read(0x8)
sectionCount = readInt64(f)
sections = [Header.Section(f) for _ in range(sectionCount)]

if sections[0].offset - UNCOMPRESSABLE_HEADER_SIZE > 0:
fakeSection = Header.FakeSection(UNCOMPRESSABLE_HEADER_SIZE, sections[0].offset-UNCOMPRESSABLE_HEADER_SIZE)
sections.insert(0, fakeSection)

nca_size = UNCOMPRESSABLE_HEADER_SIZE
for i in range(sectionCount):
nca_size += sections[i].size

pos = f.tell()
blockMagic = f.read(8)
f.seek(pos)
useBlockCompression = blockMagic == b'NCZBLOCK'
blockSize = -1

count = 0
checkstarter = 0

if useBlockCompression:
BlockHeader = Header.Block(f)
decompressor = BlockDecompressorReader.BlockDecompressorReader(f, BlockHeader)

pos = f.tell()

if not useBlockCompression:
decompressor = zstandard.ZstdDecompressor().stream_reader(f)

if cnmtData['title_id'].endswith('000'):
for s in sections:
count += 1
if count == 2:
break
checkstarter += s.size
test = int(checkstarter / 16384)
for i in (range(test + 1)):
decompressor.seek(16384, 1)

chunk = decompressor.read(16384)

b1 = chunk[:32]
b2 = chunk[32:64]

if sum(b1) !=0 and sum(b2) == 0:
return True
else:
return 'ncz'

# end
# Failed
return False

def pr_noenc_check(self, file = None, mode = 'rb'):
Expand Down
4 changes: 4 additions & 0 deletions py-test/verif.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ def decrypt_verify(nspx):
tvmsg = f'> {file}\t -> is CORRECT'
vmsg += tvmsg
print(tvmsg)
elif file.endswith('.ncz') and correct == 'ncz':
tvmsg = f'> {file}\t\t -> ncz file needs HASH check'
vmsg += tvmsg
print(tvmsg)
elif file.endswith('.tik') and correct == 'ncz':
tvmsg = f'> {file}\t -> is EXISTS'
vmsg += tvmsg
Expand Down

0 comments on commit 3543953

Please sign in to comment.