Beispiel #1
0
    def insert_branch(self, to: int, _from: int, lk=0):
        """ Insert a branch instruction at _from\n
            to:    address to branch to\n
            _from: address to branch from\n
            lk:    0 | 1, is branch linking? """

        _from &= 0xFFFFFFFC
        to &= 0xFFFFFFFC
        self.seek(_from)
        write_uint32(self, (to - _from) & 0x3FFFFFD | 0x48000000 | lk)
Beispiel #2
0
    def set_variables(self, dolFile: DolFile):
        varOffset = self.find_variable_data(b"\x00\xDE\xDE\xDE")
        if varOffset is None:
            raise RuntimeError(
                tools.color_text("Variable codehandler data not found\n",
                                 defaultColor=tools.TREDLIT))

        self.set_hook_instruction(dolFile, self.hookAddress, varOffset, 0)

        self._rawData.seek(varOffset + 4)
        write_uint32(self._rawData,
                     ((self.hookAddress + 4) -
                      (self.initAddress +
                       (varOffset + 4))) & 0x3FFFFFD | 0x48000000 | 0)
Beispiel #3
0
 def encrypt_codes(self, key: int):
     self.geckoCodes.codeList.seek(0)
     i = 0
     while True:
         try:
             packet = read_uint32(self.geckoCodes.codeList)
             self.geckoCodes.codeList.seek(-4, 1)
             write_uint32(self.geckoCodes.codeList,
                          (packet ^ key) & 0xFFFFFFFF)
             key += (i << 3) & 0xFFFFFFFF
             if key > 0xFFFFFFFF:
                 key -= 0x100000000
             i += 1
         except:
             break
Beispiel #4
0
    def set_hook_instruction(self,
                             dolFile: DolFile,
                             address: int,
                             varOffset: int,
                             lk=0):
        self._rawData.seek(varOffset)
        dolFile.seek(address)
        ppc = read_uint32(dolFile)

        if ((((ppc >> 24) & 0xFF) > 0x47 and ((ppc >> 24) & 0xFF) < 0x4C) or
            (((ppc >> 24) & 0xFF) > 0x3F and ((ppc >> 24) & 0xFF) < 0x44)):
            to, conditional = dolFile.extract_branch_addr(address)
            if conditional:
                raise NotImplementedError(
                    "Hooking to a conditional non spr branch is unsupported")
            write_uint32(self._rawData,
                         (to - (self.initAddress + varOffset)) & 0x3FFFFFD
                         | 0x48000000 | lk)
        else:
            write_uint32(self._rawData, ppc)
Beispiel #5
0
    def complete_data(self, codeHandler: CodeHandler, initpoint: list):
        _upperAddr, _lowerAddr = ((self.initAddress >> 16) & 0xFFFF,
                                  self.initAddress & 0xFFFF)
        _key = random.randrange(0x100000000)
        self._rawData.seek(0)

        while sample := self._rawData.read(4):
            if sample == b"HEAP":  #Found keyword "HEAP". Goes with the resize of the heap
                self._rawData.seek(-4, 1)

                gpModInfoOffset = self._rawData.tell()
                gpModUpperAddr = _upperAddr + 1 if (
                    _lowerAddr + gpModInfoOffset
                ) > 0x7FFF else _upperAddr  #Absolute addressing

                if codeHandler.allocation == None:
                    codeHandler.allocation = (codeHandler.handlerLength +
                                              codeHandler.geckoCodes.size +
                                              7) & -8

                write_uint32(self._rawData, codeHandler.allocation)

            elif sample == b"LSIZ":  #Found keyword "LSIZ". Goes with the size of the loader
                self._rawData.seek(-4, 1)
                write_uint32(self._rawData, len(self._rawData.getbuffer()))

            elif sample == b"HSIZ":  #Found keyword "HSIZ". Goes with the size of the codehandler
                self._rawData.seek(-4, 1)
                write_sint32(self._rawData, codeHandler.handlerLength)

            elif sample == b"CSIZ":  #Found keyword "CSIZ". Goes with the size of the codes
                self._rawData.seek(-4, 1)
                write_sint32(self._rawData, codeHandler.geckoCodes.size)

            elif sample == b"HOOK":  #Found keyword "HOOK". Goes with the codehandler hook
                self._rawData.seek(-4, 1)
                write_uint32(self._rawData, codeHandler.hookAddress)

            elif sample == b"CRPT":  #Found keyword "CRPT". Boolean of the encryption
                self._rawData.seek(-4, 1)
                write_bool(self._rawData, self.encrypt, 4)

            elif sample == b"CYPT":  #Found keyword "CYPT". Encryption Key
                self._rawData.seek(-4, 1)

                gpKeyOffset = self._rawData.tell()
                gpKeyUpperAddr = _upperAddr + 1 if (
                    _lowerAddr +
                    gpKeyOffset) > 0x7FFF else _upperAddr  #Absolute addressing

                write_uint32(self._rawData, CodeHandler.encrypt_key(_key))
Beispiel #6
0
    def optimize_codelist(self, dolFile: DolFile):
        codelist = b"\x00\xD0\xC0\xDE" * 2
        skipcodes = 0

        self.codeList.seek(8)
        while codetype := self.codeList.read(4):
            info = self.codeList.read(4)
            address = 0x80000000 | (int.from_bytes(
                codetype, byteorder="big", signed=False) & 0x1FFFFFF)
            try:
                if skipcodes <= 0:
                    if (codetype.startswith(b"\x00")
                            or codetype.startswith(b"\x01")
                            or codetype.startswith(b"\x10")
                            or codetype.startswith(b"\x11")):
                        dolFile.seek(address)

                        counter = int.from_bytes(info[:-2],
                                                 byteorder="big",
                                                 signed=False)
                        value = info[2:]

                        while counter + 1 > 0:
                            dolFile.write(value[1:])
                            counter -= 1
                        continue

                    elif (codetype.startswith(b"\x02")
                          or codetype.startswith(b"\x03")
                          or codetype.startswith(b"\x12")
                          or codetype.startswith(b"\x13")):
                        dolFile.seek(address)

                        counter = int.from_bytes(info[:-2],
                                                 byteorder="big",
                                                 signed=False)
                        value = info[2:]

                        while counter + 1 > 0:
                            dolFile.write(value)
                            counter -= 1
                        continue

                    elif (codetype.startswith(b"\x04")
                          or codetype.startswith(b"\x05")
                          or codetype.startswith(b"\x14")
                          or codetype.startswith(b"\x15")):
                        dolFile.seek(address)
                        dolFile.write(info)
                        continue

                    elif (codetype.startswith(b"\x06")
                          or codetype.startswith(b"\x07")
                          or codetype.startswith(b"\x16")
                          or codetype.startswith(b"\x17")):
                        dolFile.seek(address)

                        arraylength = int.from_bytes(info,
                                                     byteorder="big",
                                                     signed=False)
                        padding = get_alignment(arraylength, 8)

                        dolFile.write(self.codeList.read(arraylength))

                        self.codeList.seek(padding, 1)
                        continue

                    elif (codetype.startswith(b"\x08")
                          or codetype.startswith(b"\x09")
                          or codetype.startswith(b"\x18")
                          or codetype.startswith(b"\x19")):
                        dolFile.seek(address)

                        value = int.from_bytes(info,
                                               byteorder="big",
                                               signed=False)
                        data = read_uint16(self.codeList)
                        size = (data & 0x3000) >> 12
                        counter = data & 0xFFF
                        address_increment = read_uint16(self.codeList)
                        value_increment = read_uint32(self.codeList)

                        while counter + 1 > 0:
                            if size == 0:
                                write_ubyte(dolFile, value & 0xFF)
                                dolFile.seek(-1, 1)
                            elif size == 1:
                                write_uint16(dolFile, value & 0xFFFF)
                                dolFile.seek(-2, 1)
                            elif size == 2:
                                write_uint32(dolFile, value)
                                dolFile.seek(-4, 1)
                            else:
                                raise ValueError(
                                    "Size type {} does not match 08 codetype specs"
                                    .format(size))

                            dolFile.seek(address_increment, 1)
                            value += value_increment
                            counter -= 1
                            if value > 0xFFFFFFFF:
                                value -= 0x100000000
                        continue

                    elif (codetype.startswith(b"\xC6")
                          or codetype.startswith(b"\xC7")
                          or codetype.startswith(b"\xC6")
                          or codetype.startswith(b"\xC7")):
                        dolFile.insert_branch(int.from_bytes(info,
                                                             byteorder="big",
                                                             signed=False),
                                              address,
                                              lk=address & 1)
                        continue

                if codetype.hex().startswith("2") or codetype.hex().startswith(
                        "3"):
                    skipcodes += 1

                elif codetype.startswith(b"\xE0"):
                    skipcodes -= 1

                elif codetype.startswith(b"\xF0"):
                    codelist += b"\xF0\x00\x00\x00\x00\x00\x00\x00"
                    break

                self.codeList.seek(-8, 1)
                codelist += self.codeList.read(
                    GCT.determine_codelength(codetype, info))

            except (RuntimeError, UnmappedAddressError):
                self.codeList.seek(-8, 1)
                codelist += self.codeList.read(
                    GCT.determine_codelength(codetype, info))
Beispiel #7
0
    def save(self, f):
        f.seek(0)
        f.write(b"\x00" * self.size)

        for i, section in enumerate(self.sections):
            if section["type"] == DolFile.SectionType.Data:
                entry = i + (DolFile.maxTextSections - len(self.textSections))
            else:
                entry = i

            f.seek(DolFile.offsetInfoLoc + (entry << 2))
            write_uint32(f, section["offset"])  #offset in file
            f.seek(DolFile.addressInfoLoc + (entry << 2))
            write_uint32(f, section["address"])  #game address
            f.seek(DolFile.sizeInfoLoc + (entry << 2))
            write_uint32(f, section["size"])  #size in file

            f.seek(section["offset"])
            f.write(section["data"].getbuffer())

        f.seek(DolFile.bssInfoLoc)
        write_uint32(f, self.bssAddress)
        write_uint32(f, self.bssSize)

        f.seek(DolFile.entryInfoLoc)
        write_uint32(f, self.entryPoint)
        align_byte_size(f, 256)