def createJump(address, last_sum): header = ipl_header(0, 0, address, last_sum) block = header + bytearray.fromhex('00'*0x100) key = bytearray.fromhex('AA'*16) block_enc = kirk1_encrypt_cmac(block, aes_key=key, cmac_key=key) sha_buf = block[8:8+8] + block[:8] block_hash = SHA1.new(sha_buf).digest() hash_padding = bytearray(12) hash_enc = kirk4(block_hash + hash_padding, 0x6C) # pad with zeros to IPL block size minus the SHA1 hash at the end padding = bytearray(0x1000 - len(block_enc) - 0x20) return bytearray(block_enc + padding + hash_enc)
def createResetExploit(): # reset exploit; 0x32F6 is USB_HOST, ATA_HDD, MS_1, ATA, USB, AVC, VME, SC, ME reset bit header = ipl_header(0xBC10004C, 4, 0x10000005, 0) + struct.pack('<IIII', 0x32F6, 0, 0, 0) block = header + b'\x38\x00\xf0\x0b\x00\x00\x00\x00\x00\x80\x08\x40\x00\x08\x09\x24\x80\x11\x08\x7d\x04\x48\x09\x01\x21\x40\x00\x00\x00\x00\x10\xbd\x00\xe0\x0a\x40\x00\xe8\x0b\x40\x00\x05\x4c\x7d\x04\x00\x80\x11\x00\x05\x6c\x7d\x40\x53\x0a\x00\x25\x50\x48\x01\x00\x00\x5a\xbd\x03\x00\x80\x11\x40\x5b\x0b\x00\x25\x58\x68\x01\x00\x00\x7a\xbd\x40\x00\x08\x25\xf1\xff\x09\x15\x00\x00\x00\x00\x08\x00\xe0\x03\x0f\x00\x00\x00\x00\x80\x08\x40\x00\x10\x09\x24\x40\x12\x08\x7d\x04\x48\x09\x01\x00\xe0\x80\x40\x00\xe8\x80\x40\x21\x40\x00\x00\x00\x00\x01\xbd\x00\x00\x03\xbd\x40\x00\x08\x25\xfc\xff\x09\x15\x00\x00\x00\x00\x08\x00\xe0\x03\x00\x00\x00\x00\x10\xbc\x02\x3c\x40\x00\x44\x8c\x00\xff\x03\x3c\x24\x18\x83\x00\x02\x00\x60\x10\x10\x00\x02\x3c\x02\x12\x04\x00\x08\x00\xe0\x03\x00\x00\x00\x00\xf8\xff\xbd\x27\x04\x00\xbf\xaf\x2f\x00\xf0\x0f\x00\x00\x00\x00\x60\x00\x03\x3c\x2b\x10\x43\x00\x05\x3c\x03\x3c\x17\x00\x40\x14\xc0\xbf\x64\x34\x01\x80\x02\x3c\xc0\xbf\x63\x24\x88\x00\x40\xac\xac\x00\x44\xac\x00\x01\x43\xac\x34\x01\x43\xac\x10\x3c\x03\x3c\xc0\xbf\x63\x34\x58\x01\x43\xac\x00\x08\x03\x3c\x71\x40\x63\x24\x94\x01\x43\xac\x01\x00\x03\x24\x8c\x0a\x43\xac\x0a\x00\xf0\x0f\x00\x00\x00\x00\x21\x00\xf0\x0f\x00\x00\x00\x00\x04\x00\xbf\x8f\x01\x80\x19\x3c\x08\x00\x20\x03\x08\x00\xbd\x27\x01\x80\x02\x3c\xc0\xbf\x63\x24\x88\x00\x40\xac\xac\x00\x44\xac\xb8\x00\x43\xac\x10\x3c\x03\x3c\xc0\xbf\x63\x34\xcc\x00\x43\xac\x01\x00\x03\x24\x0c\x08\x43\xac\xed\xff\x00\x10\x00\x00\x00\x00' block += bytearray.fromhex('00'*(0x100 - len(block))) key = bytearray.fromhex('AA'*16) block_enc = kirk1_encrypt_cmac(block, aes_key=key, cmac_key=key) sha_buf = block[8:8+8+4] + block[:8] block_hash = SHA1.new(sha_buf).digest() hash_padding = bytearray(12) hash_enc = kirk4(block_hash + hash_padding, 0x6C) # pad with zeros to IPL block size minus the SHA1 hash at the end padding = bytearray(0x1000 - len(block_enc) - 0x20) return bytearray(block_enc + padding + hash_enc)
def createBlock(address, data, last_sum): header = ipl_header(address, len(data), 0, last_sum) block = header + data key = bytearray.fromhex('AA'*16) block_enc = kirk1_encrypt_cmac(block, aes_key=key, cmac_key=key) sha_buf = block[8:8+8+len(data)] + block[:8] block_hash = SHA1.new(sha_buf).digest() hash_padding = bytearray(12) hash_enc = kirk4(block_hash + hash_padding, 0x6C) # pad with zeros to IPL block size minus the SHA1 hash at the end padding = bytearray(0x1000 - len(block_enc) - 0x20) data_sum = 0 for i in range(int(len(data) / 4)): data_sum += int.from_bytes(data[i*4:(i+1)*4], byteorder='little') return bytearray(block_enc + padding + hash_enc), data_sum & 0xFFFFFFFF
def encrypt(prx, meta, id=None): xorbuf = expand_seed(meta['seed'], meta['key']) # encrypt as kirk1 encrypted = kirk.kirk1_encrypt_cmac(prx[0x150:], salt=prx[:0x80]) header = xor(encrypted[:0x40], xorbuf[0x50:]) header = kirk.kirk4(header, meta['key']) header = xor(header, xorbuf[0x10:0x50]) # calculate an id if id == None: id = Random.get_random_bytes(16) elif type(id) is str: id = '{:16.16}'.format(id).encode() id = kirk.kirk7(id, meta['key']) # create a prx header prx_header = prx_header_2() prx_header.set_elf_info(prx[:0x80]) prx_header.set_kirk_block(header) prx_header.set_kirk_metadata(encrypted[0x70:0x80]) prx_header.set_btcnf_id(id) prx_header.set_tag(prx[0xD0:0xD4]) # calculate SHA1 of header h = SHA1.new() h.update(prx_header.tag()) h.update(xorbuf[:0x10]) h.update(b'\x00' * 0x58) h.update(prx_header.btcnf_id()) h.update(prx_header.kirk_metadata()) h.update(prx_header.elf_info()) prx_header.set_sha1_hash(h.digest()) # encrypt the header and return the complete PRX prx_header.encrypt_header(meta['key']) return prx_header.prx() + encrypted[0x90 + 0x80:]
args = parser.parse_args() def ipl_header(block_destination, size, entry, hash): return struct.pack('<IIII', block_destination, size, entry, hash) with open(args.input, 'rb') as f: code = f.read() header = ipl_header(0xBC10004C, 4, 0x10000005, 0) + struct.pack( '<IIII', 0x32F6, 0, 0, 0 ) #reset exploit; 0x32F6 is USB_HOST, ATA_HDD, MS_1, ATA, USB, AVC, VME, SC, ME reset bit block = header + code key = bytearray.fromhex('AA' * 16) block_enc = kirk1_encrypt_cmac(block, aes_key=key, cmac_key=key) sha_buf = block[8:8 + 12] + block[:8] block_hash = SHA1.new(sha_buf).digest() hash_padding = bytearray(12) hash_enc = kirk4(block_hash + hash_padding, 0x6C) padding = bytearray( 0x1000 - len(block_enc) - 0x20) #pad with zeros to IPL block size minus the SHA1 hash at the end block_enc = bytearray(block_enc + padding + hash_enc) if args.xor: key = bytearray([ 0x8c, 0x64, 0xd0, 0x30, 0x44, 0x2d, 0xf5, 0x82, 0xb8, 0x72, 0x1e, 0xb4,