Translation
parent
ce951f71c8
commit
2431a1f00c
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 atlas44
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,14 @@
|
|||
# web-cfw-loader
|
||||
Fusee Launcher, in a browser!
|
||||
|
||||
# Description
|
||||
This 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.
|
||||
|
||||
# Forked
|
||||
This is also a fork of [web-fusee-launcher](https://github.com/atlas44/web-fusee-launcher), which I fixed up a bit, added hekate 5 and 4, and did some CSS stuff.
|
||||
|
||||
# Instant CFW Payload
|
||||
This site uses a payload made by me that instantly boots CFW with hekate. you can find it [here](https://github.com/ElijahZAwesome/hekate-ipl-instant-boot-edition).
|
||||
|
||||
# Try it out
|
||||
Either use a web server to host the files (must be on https!) or you can try the [demo](https://elijahzawesome.github.io/web-cfw-loader/).
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
|
@ -0,0 +1,158 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<link href="favicon.png" rel="icon" type="image/x-icon" />
|
||||
<title>Switch Payload Loader v1.3</title>
|
||||
|
||||
<!-- JQuery: needed for some Bootstrap Components -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||
|
||||
<!-- Bootstrap 3 framework -->
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<!-- Optional theme -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="container-fluid">
|
||||
<div class="row" id="title">
|
||||
<h1>Nintendo Switch Payload Lader</h1>
|
||||
<h4>Fusee Launcher portiert zu JavaScript mit der Hilfe von WebUSB.</h4>
|
||||
</div>
|
||||
|
||||
<div class="row margin-top-md">
|
||||
<div class="col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||
<div class="btn-group" role="group" aria-label="...">
|
||||
<a class="btn btn-info disabled" href="#">English</a>
|
||||
<a class="btn btn-info" href="./it_IT/index.html">Italiano</a>
|
||||
<a class="btn btn-info" href="./pt_BR/index.html">Português</a>
|
||||
<a class="btn btn-info" href="./de_DE/index.html">Deutsch</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row margin-top-md" id="infodiv">
|
||||
<div class="col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p>Aus irgendeinem Grund funktionieren hochgeladene Payloads nicht. Ich versuche zurzeit dies zu reparieren.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p>Es wurde einigermaßen getestet. Auch wenn bisher keine Fehler gefunden wurden, bin ich nicht schuldig, falls es zu Problemen kommt!</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p>Dies funktioniert nicht auf Windows durch Probleme mit Chrome und WebUSB (und wahrscheinlich anderen Gründen!)</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p>Dies funktioniert bisher mit keinem Browser AUßER Chrome! Das liegt daran, dass die anderen Browser WebUSB nicht supporten!</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p>In Linux können Sie einen "Zugriff abgelehnt" Fehler bekommen! Falls Sie dieses Problem haben, können Sie eine Datei unter: <code>/etc/udev/rules.d/50-switch.rules</code>mit dem folgenden Inhalt:<br><code>SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0955\", MODE=\"0664\", GROUP=\"plugdev\"</code>erstellen.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<p>Tests ergeben, dass es zurzeit auf Linux, OSX, Android (unrooted) und Chromebooks funktioniert. Ihr Ergebnis kann variieren.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h4>Anleitung:</h4>
|
||||
<ul>
|
||||
<li>Setzen Sie die Switch in den RCM und verbinden Sie es mit ihrem Gerät.</li>
|
||||
<li>Wählen Sie entweder einer der vorliegenden Payloads oder laden Sie Ihr eigenes Payload hoch.</li>
|
||||
<li>Drücken Sie: "Payload senden"</li>
|
||||
<li>Auf dem Erlaubnisbildschirm müssen Sie "APX" auswählen und zustimmen.</li>
|
||||
<li>Falls alles richtig läuft, sollte das Payload gesendet sein!</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="class=col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||
<h1>Konfiguration des Payloadversandes</h1>
|
||||
|
||||
<form id="mainForm">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<h4>Wähle Payload:</h4>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6">
|
||||
<select class="pull-right" id="payloadSelect" onchange="onSelectChange()">
|
||||
<option value="instaboot">Boote die CFW direkt (5.0.x)</option>
|
||||
<option value="hekate v5">Hekate für 5.0.x Switches</option>
|
||||
<option value="hekate v4">Hekate für 4.0.x Switches</option>
|
||||
<option value="fusee">(Re)Switched Test Payload (fusee)</option>
|
||||
<option value="uploaded">Eigenes Payload hochladen</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" id="uploadContainer" style="display: none">
|
||||
<div class="row-xs-12">
|
||||
<input style="float: right" type="file" id="payloadUpload" accept=".bin"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row divider-line"></div>
|
||||
|
||||
<div class="row margin-top-md">
|
||||
<div class="col-xs-10">
|
||||
<h4>Erhalt Payload Byte-Array (nicht senden)</h4>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<input class="pull-right" type="checkbox" name="shouldDebug" id="shouldDebug">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row divider-line"></div>
|
||||
</form>
|
||||
|
||||
<div class="row margin-top-md">
|
||||
<div class="col-xs-12">
|
||||
<button class="btn btn-primary btn-lg pull-right" id="goButton">Sende Payload!</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="class=col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||
<h3>Protokoll:</h3>
|
||||
<div id="output"></div>
|
||||
<button class="btn btn-primary pull-right margin-top-md" id="clearlogsbutton" onclick="clearLog();">Clear Logs</button><br><br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="./payloads.js"></script>
|
||||
<script src="./main.js"></script>
|
||||
</body>
|
||||
|
||||
<div class="row margin-top-md" id="page-footer">
|
||||
<div class="col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||
<div id="disclaimer">
|
||||
<p>Der Quellcode kann hier gefunden werden: <a href="https://github.com/ElijahZAwesome/web-cfw-loader/">GitHub</a> (oder indem man sich den Quellcode direkt ankuckt, da kein Backend existiert!).</p>
|
||||
<p>Portiert von <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.</p>
|
||||
<p>Danke an ktemkin und ReSwitched, aber auch <br><a href="https://atlas44.s3-us-west-2.amazonaws.com/web-fusee-launcher/index.html">Atlas44 und seine Webseite</a>, als einen Startpunkt für dieses Projekt. </p>
|
||||
<p>Zuletzt danke an <a href="https://github.com/falquinho">falquinho</a> für sein Bootstraplayout und Übersetzung in Portugiesisch, <a href="https://github.com/Filo97">Filo97</a> für die italienische Übersetzung und <a href="https://github.com/tumGER"> tumGER </a>für seine deutsche Übersetzung!.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,204 @@
|
|||
const intermezzo = new Uint8Array([
|
||||
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,
|
||||
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,
|
||||
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
|
||||
]);
|
||||
|
||||
|
||||
|
||||
const RCM_PAYLOAD_ADDRESS = 0x40010000;
|
||||
const INTERMEZZO_LOCATION = 0x4001F000;
|
||||
const PAYLOAD_LOAD_BLOCK = 0x40020000;
|
||||
|
||||
|
||||
|
||||
function createRCMPayload(intermezzo, payload) {
|
||||
const rcmLength = 0x30298;
|
||||
|
||||
const intermezzoAddressRepeatCount = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDRESS) / 4;
|
||||
|
||||
const rcmPayloadSize = Math.ceil((0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000 + payload.byteLength) / 0x1000) * 0x1000;
|
||||
|
||||
const rcmPayload = new Uint8Array(new ArrayBuffer(rcmPayloadSize))
|
||||
const rcmPayloadView = new DataView(rcmPayload.buffer);
|
||||
|
||||
rcmPayloadView.setUint32(0x0, rcmLength, true);
|
||||
|
||||
for (let i = 0; i < intermezzoAddressRepeatCount; i++) {
|
||||
rcmPayloadView.setUint32(0x2A8 + i * 4, INTERMEZZO_LOCATION, true);
|
||||
}
|
||||
|
||||
rcmPayload.set(intermezzo, 0x2A8 + (0x4 * intermezzoAddressRepeatCount));
|
||||
rcmPayload.set(payload, 0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000);
|
||||
|
||||
return rcmPayload;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function bufferToHex(data) {
|
||||
let result = "";
|
||||
for (let i = 0; i < data.byteLength; i++)
|
||||
result += data.getUint8(i).toString(16).padStart(2, "0");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function write(device, data) {
|
||||
let length = data.length;
|
||||
let writeCount = 0;
|
||||
const packetSize = 0x1000;
|
||||
|
||||
while (length) {
|
||||
const dataToTransmit = Math.min(length, packetSize);
|
||||
length -= dataToTransmit;
|
||||
|
||||
const chunk = data.slice(0, dataToTransmit);
|
||||
data = data.slice(dataToTransmit);
|
||||
await device.transferOut(1, chunk);
|
||||
writeCount++;
|
||||
}
|
||||
|
||||
return writeCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function readFileAsArrayBuffer(file) {
|
||||
return new Promise((res, rej) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
res(e.target.result);
|
||||
}
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function logOutput(...message) {
|
||||
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + message.join(" ") + "<br>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
function clearLog() {
|
||||
document.getElementById("output").innerHTML = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
let device;
|
||||
|
||||
|
||||
|
||||
async function launchPayload(payload) {
|
||||
await device.open();
|
||||
logOutput(`Verbunden mit ${device.manufacturerName} ${device.productName}`);
|
||||
|
||||
await device.claimInterface(0);
|
||||
|
||||
const deviceID = await device.transferIn(1, 16);
|
||||
logOutput(`Geräte ID: ${bufferToHex(deviceID.data)}`);
|
||||
|
||||
const rcmPayload = createRCMPayload(intermezzo, payload);
|
||||
logOutput("Sende das Payload...");
|
||||
const writeCount = await write(device, rcmPayload);
|
||||
logOutput("Payload wurde gesendet!");
|
||||
|
||||
if (writeCount % 2 !== 1) {
|
||||
logOutput("Wechsele zu einem größeren Puffer...");
|
||||
await device.transferOut(1, new ArrayBuffer(0x1000));
|
||||
}
|
||||
|
||||
logOutput("Schwachstelle wird ausgelöst...");
|
||||
const vulnerabilityLength = 0x7000;
|
||||
const smash = await device.controlTransferIn({
|
||||
requestType: 'standard',
|
||||
recipient: 'interface',
|
||||
request: 0x00,
|
||||
value: 0x00,
|
||||
index: 0x00
|
||||
}, vulnerabilityLength);
|
||||
}
|
||||
|
||||
|
||||
|
||||
document.getElementById("goButton").addEventListener("click", async () => {
|
||||
clearLog();
|
||||
var debugCheckbox = document.getElementById("shouldDebug");
|
||||
const payloadType = document.getElementById("payloadSelect").value;
|
||||
|
||||
let payload;
|
||||
if (payloadType === "hekate v5") {
|
||||
payload = hekate5;
|
||||
|
||||
} else if (payloadType === "hekate v4") {
|
||||
payload = hekate4;
|
||||
|
||||
} else if (payloadType === "fusee") {
|
||||
payload = fusee;
|
||||
|
||||
} else if (payloadType === "instaboot") {
|
||||
payload = instaboot;
|
||||
|
||||
} else if (payloadType === "uploaded") {
|
||||
const file = document.getElementById("payloadUpload").files[0];
|
||||
if (!file) {
|
||||
alert("Du musst eine Datei hochladen, um einen eigenen Payload zu nutzen");
|
||||
return;
|
||||
}
|
||||
logOutput("Nutze das hochgeladene Payload: \"" + file.name + "\"");
|
||||
payload = new Uint8Array(await readFileAsArrayBuffer(file));
|
||||
} else {
|
||||
logOutput("<span style='color:red'>Du versuchst eine Payload-Art zu nutzen, die nicht existiert!</span>");
|
||||
return;
|
||||
}
|
||||
|
||||
if(debugCheckbox.checked) {
|
||||
logOutput("Protokolliere Payload-Bytes...");
|
||||
|
||||
var payloadToLog = "";
|
||||
for (var i = 0; i < payload.length; i++) {
|
||||
payloadToLog += "0x" + payload[i].toString(16) + ", ".toUpperCase();
|
||||
}
|
||||
payloadToLog = payloadToLog;
|
||||
logOutput(payloadToLog);
|
||||
return;
|
||||
}
|
||||
|
||||
logOutput("Fordere Zugriff auf das Gerät...");
|
||||
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
|
||||
|
||||
logOutput(`<span style='color:blue'>Bereit den Start von ${payloadType} vor...</span>`);
|
||||
launchPayload(payload);
|
||||
});
|
||||
|
||||
|
||||
|
||||
function onSelectChange() {
|
||||
if (document.getElementById("payloadSelect").value === "uploaded")
|
||||
document.getElementById("uploadContainer").style.display = "block"
|
||||
else
|
||||
document.getElementById("uploadContainer").style.display = "none"
|
||||
}
|
||||
|
||||
|
||||
|
||||
function openInfo() {
|
||||
if(document.getElementById("infodiv").innerHTML != "") {
|
||||
document.getElementById("infodiv").innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function openInstructions() {
|
||||
if(document.getElementById("infodiv").innerHTML != "") {
|
||||
document.getElementById("infodiv").innerHTML = "";
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,45 @@
|
|||
@import url('https://fonts.googleapis.com/css?family=Open+Sans');
|
||||
|
||||
body {
|
||||
margin-top: 0px;
|
||||
margin-left: 0px;
|
||||
margin-right: auto;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
#title {
|
||||
text-align: center;
|
||||
font-size: 1.5vw;
|
||||
padding-top: 10vw;
|
||||
padding-bottom: 10vw;
|
||||
background-size: cover;
|
||||
background-color: black;
|
||||
background-image: url("https://icdn1.digitaltrends.com/image/nintendo-switch-review-photos-pdx-580.jpg");
|
||||
color: white;
|
||||
margin-top: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#output {
|
||||
height: 200px;
|
||||
border: 1px solid black;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#page-footer {
|
||||
padding: 32px;
|
||||
background: #222528;
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
#disclaimer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.divider-line {
|
||||
border-bottom: 1px solid gainsboro;
|
||||
}
|
||||
|
||||
.margin-top-md {
|
||||
margin-top: 24px;
|
||||
}
|
Loading…
Reference in New Issue