Build to /site instead. Makes things a bit safer.

This commit is contained in:
noirscape 2021-05-13 22:20:59 +02:00
parent 70e978cb54
commit af8d9426a2
6 changed files with 146 additions and 165 deletions

5
.gitignore vendored
View File

@ -1,4 +1 @@
hekate.bin.js site
lockpick.bin.js
tegraexplorer.bin.js
index.html

View File

@ -1,15 +0,0 @@
generate_files:
@python gen_contents.py
clean:
@rm hekate.bin.js
@rm lockpick.bin.js
@rm tegraexplorer.bin.js
@rm index.html
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.DEFAULT_GOAL := help

View File

@ -3,8 +3,3 @@ Fusee Launcher, in a browser!
# Description # Description
This is a fork of [web-fusee-launcher](https://github.com/atlas44/web-fusee-launcher), which is a port of [fusee-launcher](https://github.com/reswitched/fusee-launcher) to JavaScript using WebUSB. This has been mildly tested and appears to work on Linux, Android (unrooted), OSX and ChromeOS. Today, this only works on Chrome because only Chrome implements WebUSB. It also does NOT work on Windows because the WebUSB Windows implementation does not allow sending the required USB packet. This is a fork of [web-fusee-launcher](https://github.com/atlas44/web-fusee-launcher), which is a port of [fusee-launcher](https://github.com/reswitched/fusee-launcher) to JavaScript using WebUSB. This has been mildly tested and appears to work on Linux, Android (unrooted), OSX and ChromeOS. Today, this only works on Chrome because only Chrome implements WebUSB. It also does NOT work on Windows because the WebUSB Windows implementation does not allow sending the required USB packet.
# fork changes
* Hekate latest.
* You need to gen that automatically.

View File

@ -1,6 +1,7 @@
import requests import requests
import io import io
import shutil import shutil
import os
import zipfile import zipfile
bin_files = { bin_files = {
@ -98,7 +99,7 @@ def serialize_to_js(short_name: str, payload: io.BytesIO, filename: str):
final_str = "".join(final_str) final_str = "".join(final_str)
out_string = DEFAULT_SERIALIZED_CONTENTS.format(short_name, final_str) out_string = DEFAULT_SERIALIZED_CONTENTS.format(short_name, final_str)
with open(filename, "w") as outfile: with open(f"site/{filename}", "w") as outfile:
outfile.write(out_string) outfile.write(out_string)
def generate_js(program: str): def generate_js(program: str):
@ -130,14 +131,17 @@ def generate_html():
out_string = "".join(html_data_list) out_string = "".join(html_data_list)
with open("index.html", "w") as indexfile: with open("site/index.html", "w") as indexfile:
indexfile.write(out_string) indexfile.write(out_string)
def main(): def main():
os.makedirs("site", exist_ok=True)
generate_js("hekate") generate_js("hekate")
generate_js("tegraexplorer") generate_js("tegraexplorer")
generate_js("lockpick") generate_js("lockpick")
generate_html() generate_html()
shutil.copy("js/main.js", "site/main.js")
shutil.copy("js/fusee.bin.js", "site/fusee.bin.js")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -1,139 +1,139 @@
const intermezzo = new Uint8Array([ const intermezzo = new Uint8Array([
0x44, 0x00, 0x9F, 0xE5, 0x01, 0x11, 0xA0, 0xE3, 0x40, 0x20, 0x9F, 0xE5, 0x00, 0x20, 0x42, 0xE0, 0x44, 0x00, 0x9F, 0xE5, 0x01, 0x11, 0xA0, 0xE3, 0x40, 0x20, 0x9F, 0xE5, 0x00, 0x20, 0x42, 0xE0,
0x08, 0x00, 0x00, 0xEB, 0x01, 0x01, 0xA0, 0xE3, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0xA0, 0xE1, 0x08, 0x00, 0x00, 0xEB, 0x01, 0x01, 0xA0, 0xE3, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0xA0, 0xE1,
0x2C, 0x00, 0x9F, 0xE5, 0x2C, 0x10, 0x9F, 0xE5, 0x02, 0x28, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEB, 0x2C, 0x00, 0x9F, 0xE5, 0x2C, 0x10, 0x9F, 0xE5, 0x02, 0x28, 0xA0, 0xE3, 0x01, 0x00, 0x00, 0xEB,
0x20, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x04, 0x30, 0x90, 0xE4, 0x04, 0x30, 0x81, 0xE4, 0x20, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x04, 0x30, 0x90, 0xE4, 0x04, 0x30, 0x81, 0xE4,
0x04, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0x1A, 0x1E, 0xFF, 0x2F, 0xE1, 0x20, 0xF0, 0x01, 0x40, 0x04, 0x20, 0x52, 0xE2, 0xFB, 0xFF, 0xFF, 0x1A, 0x1E, 0xFF, 0x2F, 0xE1, 0x20, 0xF0, 0x01, 0x40,
0x5C, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40 0x5C, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40
]); ]);
const RCM_PAYLOAD_ADDRESS = 0x40010000; const RCM_PAYLOAD_ADDRESS = 0x40010000;
const INTERMEZZO_LOCATION = 0x4001F000; const INTERMEZZO_LOCATION = 0x4001F000;
const PAYLOAD_LOAD_BLOCK = 0x40020000; const PAYLOAD_LOAD_BLOCK = 0x40020000;
function createRCMPayload(intermezzo, payload) { function createRCMPayload(intermezzo, payload) {
const rcmLength = 0x30298; const rcmLength = 0x30298;
const intermezzoAddressRepeatCount = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDRESS) / 4; const intermezzoAddressRepeatCount = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDRESS) / 4;
const rcmPayloadSize = Math.ceil((0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000 + payload.byteLength) / 0x1000) * 0x1000; const rcmPayloadSize = Math.ceil((0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000 + payload.byteLength) / 0x1000) * 0x1000;
const rcmPayload = new Uint8Array(new ArrayBuffer(rcmPayloadSize)) const rcmPayload = new Uint8Array(new ArrayBuffer(rcmPayloadSize))
const rcmPayloadView = new DataView(rcmPayload.buffer); const rcmPayloadView = new DataView(rcmPayload.buffer);
rcmPayloadView.setUint32(0x0, rcmLength, true); rcmPayloadView.setUint32(0x0, rcmLength, true);
for (let i = 0; i < intermezzoAddressRepeatCount; i++) { for (let i = 0; i < intermezzoAddressRepeatCount; i++) {
rcmPayloadView.setUint32(0x2A8 + i * 4, INTERMEZZO_LOCATION, true); rcmPayloadView.setUint32(0x2A8 + i * 4, INTERMEZZO_LOCATION, true);
} }
rcmPayload.set(intermezzo, 0x2A8 + (0x4 * intermezzoAddressRepeatCount)); rcmPayload.set(intermezzo, 0x2A8 + (0x4 * intermezzoAddressRepeatCount));
rcmPayload.set(payload, 0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000); rcmPayload.set(payload, 0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000);
return rcmPayload; return rcmPayload;
} }
function bufferToHex(data) { function bufferToHex(data) {
let result = ""; let result = "";
for (let i = 0; i < data.byteLength; i++) for (let i = 0; i < data.byteLength; i++)
result += data.getUint8(i).toString(16).padStart(2, "0"); result += data.getUint8(i).toString(16).padStart(2, "0");
return result; return result;
} }
async function write(device, data) { async function write(device, data) {
let length = data.length; let length = data.length;
let writeCount = 0; let writeCount = 0;
const packetSize = 0x1000; const packetSize = 0x1000;
while (length) { while (length) {
const dataToTransmit = Math.min(length, packetSize); const dataToTransmit = Math.min(length, packetSize);
length -= dataToTransmit; length -= dataToTransmit;
const chunk = data.slice(0, dataToTransmit); const chunk = data.slice(0, dataToTransmit);
data = data.slice(dataToTransmit); data = data.slice(dataToTransmit);
await device.transferOut(1, chunk); await device.transferOut(1, chunk);
writeCount++; writeCount++;
} }
return writeCount; return writeCount;
} }
function readFileAsArrayBuffer(file) { function readFileAsArrayBuffer(file) {
return new Promise((res, rej) => { return new Promise((res, rej) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = e => { reader.onload = e => {
res(e.target.result); res(e.target.result);
} }
reader.readAsArrayBuffer(file); reader.readAsArrayBuffer(file);
}); });
} }
function logOutput(...message) { function logOutput(...message) {
document.getElementById("output").value += message.join(" ") + "\n"; document.getElementById("output").value += message.join(" ") + "\n";
} }
let device; let device;
async function launchPayload(payload) { async function launchPayload(payload) {
await device.open(); await device.open();
logOutput(`Connected to ${device.manufacturerName} ${device.productName}`); logOutput(`Connected to ${device.manufacturerName} ${device.productName}`);
await device.claimInterface(0); await device.claimInterface(0);
const deviceID = await device.transferIn(1, 16); const deviceID = await device.transferIn(1, 16);
logOutput(`Device ID: ${bufferToHex(deviceID.data)}`); logOutput(`Device ID: ${bufferToHex(deviceID.data)}`);
const rcmPayload = createRCMPayload(intermezzo, payload); const rcmPayload = createRCMPayload(intermezzo, payload);
logOutput("Sending payload..."); logOutput("Sending payload...");
const writeCount = await write(device, rcmPayload); const writeCount = await write(device, rcmPayload);
logOutput("Payload sent!"); logOutput("Payload sent!");
if (writeCount % 2 !== 1) { if (writeCount % 2 !== 1) {
logOutput("Switching to higher buffer..."); logOutput("Switching to higher buffer...");
await device.transferOut(1, new ArrayBuffer(0x1000)); await device.transferOut(1, new ArrayBuffer(0x1000));
} }
logOutput("Trigging vulnerability..."); logOutput("Trigging vulnerability...");
const vulnerabilityLength = 0x7000; const vulnerabilityLength = 0x7000;
const smash = await device.controlTransferIn({ const smash = await device.controlTransferIn({
requestType: 'standard', requestType: 'standard',
recipient: 'interface', recipient: 'interface',
request: 0x00, request: 0x00,
value: 0x00, value: 0x00,
index: 0x00 index: 0x00
}, vulnerabilityLength); }, vulnerabilityLength);
} }
document.getElementById("goButton").addEventListener("click", async () => { document.getElementById("goButton").addEventListener("click", async () => {
logOutput("Requesting access to device..."); logOutput("Requesting access to device...");
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] }); device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
const payloadType = document.forms.mainForm.payload.value; const payloadType = document.forms.mainForm.payload.value;
logOutput(`Preparing to launch ${payloadType}...`); logOutput(`Preparing to launch ${payloadType}...`);
let payload; let payload;
if (payloadType === "fusee.bin") { if (payloadType === "fusee.bin") {
payload = fusee; payload = fusee;
} else if (payloadType === "hekate.bin") { } else if (payloadType === "hekate.bin") {
payload = hekate; payload = hekate;
} else if (payloadType === "tegraexplorer.bin") { } else if (payloadType === "tegraexplorer.bin") {
payload = tegraexplorer; payload = tegraexplorer;
} else if (payloadType === "lockpick.bin") { } else if (payloadType === "lockpick.bin") {
payload = lockpick; payload = lockpick;
} else if (payloadType === "uploaded") { } else if (payloadType === "uploaded") {
const file = document.getElementById("payloadUpload").files[0]; const file = document.getElementById("payloadUpload").files[0];
if (!file) { if (!file) {
alert("You need to upload a file, to use an uploaded file."); alert("You need to upload a file, to use an uploaded file.");
return; return;
} }
payload = new Uint8Array(await readFileAsArrayBuffer(file)); payload = new Uint8Array(await readFileAsArrayBuffer(file));
} else { } else {
console.log("how?"); console.log("how?");
return; return;
} }
launchPayload(payload); launchPayload(payload);
}); });
document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded"); document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded");