From 7e308a35ebd1286fcebff1a3291a1e7c29d2b8ac Mon Sep 17 00:00:00 2001 From: NinjaCheetah <58050615+NinjaCheetah@users.noreply.github.com> Date: Sat, 3 Aug 2024 13:13:29 -0400 Subject: [PATCH 1/4] Save access rights as an int and not bytes --- src/libWiiPy/title/tmd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libWiiPy/title/tmd.py b/src/libWiiPy/title/tmd.py index 62c542d..faae570 100644 --- a/src/libWiiPy/title/tmd.py +++ b/src/libWiiPy/title/tmd.py @@ -50,7 +50,7 @@ class TMD: self.reserved1: bytes = b'' # Unknown data labeled "Reserved" on WiiBrew. self.ipc_mask: bytes = b'' self.reserved2: bytes = b'' # Other "Reserved" data from WiiBrew. - self.access_rights: bytes = b'' + self.access_rights: int = 0 self.title_version: int = 0 # The version of the associated title. self.title_version_converted: int = 0 # The title version in vX.X format. self.num_contents: int = 0 # The number of contents contained in the associated title. @@ -131,7 +131,7 @@ class TMD: self.reserved2 = tmd_data.read(18) # Access rights of the title; DVD-video and AHB access. tmd_data.seek(0x1D8) - self.access_rights = tmd_data.read(4) + self.access_rights = int.from_bytes(tmd_data.read(4)) # Version number straight from the TMD. tmd_data.seek(0x1DC) self.title_version = int.from_bytes(tmd_data.read(2)) @@ -203,7 +203,7 @@ class TMD: # "Reserved" 2. tmd_data += self.reserved2 # Access rights. - tmd_data += self.access_rights + tmd_data += int.to_bytes(self.access_rights, 4) # Title version. tmd_data += int.to_bytes(self.title_version, 2) # Number of contents. From 580ba8526f3d2b9d33b7c6482553bac659db442f Mon Sep 17 00:00:00 2001 From: NinjaCheetah <58050615+NinjaCheetah@users.noreply.github.com> Date: Sat, 3 Aug 2024 13:36:35 -0400 Subject: [PATCH 2/4] Add method to check for specific access rights in TMD --- src/libWiiPy/shared.py | 4 ++++ src/libWiiPy/title/tmd.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/libWiiPy/shared.py b/src/libWiiPy/shared.py index 6b28cbc..706d0ed 100644 --- a/src/libWiiPy/shared.py +++ b/src/libWiiPy/shared.py @@ -49,6 +49,10 @@ def _pad_bytes(data, alignment=64) -> bytes: return data +def _bitmask(x: int) -> int: + return 1 << x + + _wii_menu_versions = { "Prelaunch": [0, 1, 2], "1.0J": 64, diff --git a/src/libWiiPy/title/tmd.py b/src/libWiiPy/title/tmd.py index faae570..6c8e95a 100644 --- a/src/libWiiPy/title/tmd.py +++ b/src/libWiiPy/title/tmd.py @@ -8,7 +8,9 @@ import binascii import hashlib import struct from typing import List +from enum import Enum from ..types import _ContentRecord +from ..shared import _bitmask from .util import title_ver_dec_to_standard, title_ver_standard_to_dec @@ -367,6 +369,23 @@ class TMD: raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) + "' contents but index was '" + str(record) + "'!") + def get_access_right(self, flag: int) -> bool: + """ + Gets whether an access rights flag is enabled or not. This is done by checking the specified bit. Possible flags + and their corresponding bits are defined in the AccessFlags enum. + + Parameters + ---------- + flag : int + The flag to check. + + Returns + ------- + bool + Whether the flag is enabled. + """ + return bool(self.access_rights & _bitmask(flag)) + def set_title_id(self, title_id) -> None: """ Sets the Title ID property of the TMD. Recommended over setting the property directly because of input @@ -414,3 +433,8 @@ class TMD: self.title_version_converted = version_converted else: raise TypeError("Title version type is not valid! Type must be either integer or string.") + + +class AccessFlags(Enum): + AHB = 0 + DVD_VIDEO = 1 From 6220821a2ff719764a821c91501d21cf900a0588 Mon Sep 17 00:00:00 2001 From: NinjaCheetah <58050615+NinjaCheetah@users.noreply.github.com> Date: Sat, 3 Aug 2024 13:44:15 -0400 Subject: [PATCH 3/4] Cleaned up AccessFlags enum in TMD class --- src/libWiiPy/title/tmd.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libWiiPy/title/tmd.py b/src/libWiiPy/title/tmd.py index 6c8e95a..26a666b 100644 --- a/src/libWiiPy/title/tmd.py +++ b/src/libWiiPy/title/tmd.py @@ -8,7 +8,7 @@ import binascii import hashlib import struct from typing import List -from enum import Enum +from enum import IntEnum from ..types import _ContentRecord from ..shared import _bitmask from .util import title_ver_dec_to_standard, title_ver_standard_to_dec @@ -369,6 +369,10 @@ class TMD: raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) + "' contents but index was '" + str(record) + "'!") + class AccessFlags(IntEnum): + AHB = 0 + DVD_VIDEO = 1 + def get_access_right(self, flag: int) -> bool: """ Gets whether an access rights flag is enabled or not. This is done by checking the specified bit. Possible flags @@ -433,8 +437,3 @@ class TMD: self.title_version_converted = version_converted else: raise TypeError("Title version type is not valid! Type must be either integer or string.") - - -class AccessFlags(Enum): - AHB = 0 - DVD_VIDEO = 1 From fb87c2c58ccfb468e87f83c1436de2c00a2ac4d3 Mon Sep 17 00:00:00 2001 From: NinjaCheetah <58050615+NinjaCheetah@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:01:09 -0400 Subject: [PATCH 4/4] Added methods to check if a TMD, Ticket, and Title are fakesigned --- src/libWiiPy/title/ticket.py | 23 ++++++++++++++++++++++- src/libWiiPy/title/title.py | 19 +++++++++++++++++++ src/libWiiPy/title/tmd.py | 23 ++++++++++++++++++++++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/libWiiPy/title/ticket.py b/src/libWiiPy/title/ticket.py index 7f8ce13..8266bb7 100644 --- a/src/libWiiPy/title/ticket.py +++ b/src/libWiiPy/title/ticket.py @@ -252,6 +252,27 @@ class Ticket: except OverflowError: raise Exception("An error occurred during fakesigning. Ticket could not be fakesigned!") + def get_is_fakesigned(self) -> bool: + """ + Checks the Ticket object to see if it is currently fakesigned. For a description of fakesigning, refer to the + fakesign() method. + + Returns + ------- + bool: + True if the Ticket is fakesigned, False otherwise. + + See Also + -------- + libWiiPy.title.ticket.Ticket.fakesign() + """ + if self.signature != b'\x00' * 256: + return False + test_hash = hashlib.sha1(self.dump()[320:]).hexdigest() + if test_hash[:2] != '00': + return False + return True + def get_title_id(self) -> str: """ Gets the Title ID of the ticket's associated title. @@ -275,7 +296,7 @@ class Ticket: See Also -------- - commonkeys.get_common_key + libWiiPy.title.commonkeys.get_common_key """ match self.common_key_index: case 0: diff --git a/src/libWiiPy/title/title.py b/src/libWiiPy/title/title.py index a058592..9f5b5e6 100644 --- a/src/libWiiPy/title/title.py +++ b/src/libWiiPy/title/title.py @@ -316,3 +316,22 @@ class Title: """ self.tmd.fakesign() self.ticket.fakesign() + + def get_is_fakesigned(self): + """ + Checks the Title object to see if it is currently fakesigned. This ensures that both the TMD and Ticket are + fakesigned. For a description of fakesigning, refer to the fakesign() method. + + Returns + ------- + bool: + True if the Title is fakesigned, False otherwise. + + See Also + -------- + libWiiPy.title.title.Title.fakesign() + """ + if self.tmd.get_is_fakesigned and self.ticket.get_is_fakesigned(): + return True + else: + return False diff --git a/src/libWiiPy/title/tmd.py b/src/libWiiPy/title/tmd.py index 26a666b..65b4a47 100644 --- a/src/libWiiPy/title/tmd.py +++ b/src/libWiiPy/title/tmd.py @@ -257,6 +257,27 @@ class TMD: except OverflowError: raise Exception("An error occurred during fakesigning. TMD could not be fakesigned!") + def get_is_fakesigned(self) -> bool: + """ + Checks the TMD object to see if it is currently fakesigned. For a description of fakesigning, refer to the + fakesign() method. + + Returns + ------- + bool: + True if the TMD is fakesigned, False otherwise. + + See Also + -------- + libWiiPy.title.tmd.TMD.fakesign() + """ + if self.signature != b'\x00' * 256: + return False + test_hash = hashlib.sha1(self.dump()[320:]).hexdigest() + if test_hash[:2] != '00': + return False + return True + def get_title_region(self) -> str: """ Gets the region of the TMD's associated title. @@ -386,7 +407,7 @@ class TMD: Returns ------- bool - Whether the flag is enabled. + True if the flag is enabled, False otherwise. """ return bool(self.access_rights & _bitmask(flag))