mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-25 21:01:01 -04:00
Added methods to fakesign a TMD or Ticket
This commit is contained in:
parent
535de7f228
commit
a56fa6e051
@ -5,6 +5,7 @@
|
||||
|
||||
import io
|
||||
import binascii
|
||||
import hashlib
|
||||
from dataclasses import dataclass as _dataclass
|
||||
from .crypto import decrypt_title_key
|
||||
from typing import List
|
||||
@ -162,8 +163,7 @@ class Ticket:
|
||||
|
||||
def dump(self) -> bytes:
|
||||
"""
|
||||
Dumps the Ticket object back into bytes. This also sets the raw Ticket attribute of Ticket object to the
|
||||
dumped data, and triggers load() again to ensure that the raw data and object match.
|
||||
Dumps the Ticket object back into bytes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@ -226,6 +226,37 @@ class Ticket:
|
||||
ticket_data += title_limit_data
|
||||
return ticket_data
|
||||
|
||||
def fakesign(self) -> None:
|
||||
"""
|
||||
Fakesigns this Ticket for the trucha bug.
|
||||
|
||||
This is done by brute-forcing a Ticket body hash starting with 00, causing it to pass signature verification on
|
||||
older IOS versions that incorrectly check the hash using strcmp() instead of memcmp(). The signature will also
|
||||
be erased and replaced with all NULL bytes.
|
||||
|
||||
This modifies the Ticket object in place. You will need to call this method after any changes, and before
|
||||
dumping the Ticket object back into bytes.
|
||||
"""
|
||||
# Clear the signature, so that the hash derived from it is guaranteed to always be
|
||||
# '0000000000000000000000000000000000000000'.
|
||||
self.signature = b'\x00' * 256
|
||||
current_int = 0
|
||||
test_hash = ''
|
||||
while test_hash[:2] != '00':
|
||||
current_int += 1
|
||||
# We're using the first 2 bytes of this unused region of the Ticket as a 16-bit integer, and incrementing
|
||||
# that to brute-force the hash we need.
|
||||
data_to_edit = self.unknown2
|
||||
data_to_edit = int.to_bytes(current_int, 2) + data_to_edit[2:]
|
||||
self.unknown2 = data_to_edit
|
||||
# Trim off the first 320 bytes, because we're only looking for the hash of the Ticket's body.
|
||||
# This is a try-except because an OverflowError will be thrown if the number being used to brute-force the
|
||||
# hash gets too big, as it is only a 16-bit integer. If that happens, then fakesigning has failed.
|
||||
try:
|
||||
test_hash = hashlib.sha1(self.dump()[320:]).hexdigest()
|
||||
except OverflowError:
|
||||
raise Exception("An error occurred during fakesigning. Ticket could not be fakesigned!")
|
||||
|
||||
def get_title_id(self) -> str:
|
||||
"""
|
||||
Gets the Title ID of the ticket's associated title.
|
||||
|
@ -234,3 +234,18 @@ class Title:
|
||||
"""
|
||||
# Load the decrypted content.
|
||||
self.content.load_content(dec_content, index, self.ticket.get_title_key())
|
||||
|
||||
def fakesign(self) -> None:
|
||||
"""
|
||||
Fakesigns this Title for the trucha bug.
|
||||
|
||||
This is done by brute-forcing a TMD and Ticket body hash starting with 00, causing it to pass signature
|
||||
verification on older IOS versions that incorrectly check the hash using strcmp() instead of memcmp(). The TMD
|
||||
and Ticket signatures will also be erased and replaced with all NULL bytes.
|
||||
|
||||
This modifies the TMD and Ticket objects that are part of this Title in place. You will need to call this method
|
||||
after any changes to the TMD or Ticket, and before dumping the Title object into a WAD to ensure that the WAD
|
||||
is properly fakesigned.
|
||||
"""
|
||||
self.tmd.fakesign()
|
||||
self.ticket.fakesign()
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import io
|
||||
import binascii
|
||||
import hashlib
|
||||
import struct
|
||||
from typing import List
|
||||
from ..types import _ContentRecord
|
||||
@ -159,8 +160,7 @@ class TMD:
|
||||
|
||||
def dump(self) -> bytes:
|
||||
"""
|
||||
Dumps the TMD object back into bytes. This also sets the raw TMD attribute of TMD object to the dumped data,
|
||||
and triggers load() again to ensure that the raw data and object match.
|
||||
Dumps the TMD object back into bytes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@ -227,6 +227,33 @@ class TMD:
|
||||
tmd_data += content_data
|
||||
return tmd_data
|
||||
|
||||
def fakesign(self) -> None:
|
||||
"""
|
||||
Fakesigns this TMD for the trucha bug.
|
||||
|
||||
This is done by brute-forcing a TMD body hash starting with 00, causing it to pass signature verification on
|
||||
older IOS versions that incorrectly check the hash using strcmp() instead of memcmp(). The signature will also
|
||||
be erased and replaced with all NULL bytes.
|
||||
|
||||
This modifies the TMD object in place. You will need to call this method after any changes, and before dumping
|
||||
the TMD object back into bytes.
|
||||
"""
|
||||
# Clear the signature, so that the hash derived from it is guaranteed to always be
|
||||
# '0000000000000000000000000000000000000000'.
|
||||
self.signature = b'\x00' * 256
|
||||
current_int = 0
|
||||
test_hash = ''
|
||||
while test_hash[:2] != '00':
|
||||
current_int += 1
|
||||
self.minor_version = current_int
|
||||
# Trim off the first 320 bytes, because we're only looking for the hash of the TMD's body.
|
||||
# This is a try-except because an OverflowError will be thrown if the number being used to brute-force the
|
||||
# hash gets too big, as it is only a 16-bit integer. If that happens, then fakesigning has failed.
|
||||
try:
|
||||
test_hash = hashlib.sha1(self.dump()[320:]).hexdigest()
|
||||
except OverflowError:
|
||||
raise Exception("An error occurred during fakesigning. TMD could not be fakesigned!")
|
||||
|
||||
def get_title_region(self) -> str:
|
||||
"""
|
||||
Gets the region of the TMD's associated title.
|
||||
|
Loading…
x
Reference in New Issue
Block a user