mirror of
https://github.com/Maschell/JNUSLibDecryptor.git
synced 2024-11-24 04:59:15 +01:00
Using latest JNUSLib version
This commit is contained in:
parent
b5ee061a3a
commit
72a43e2820
@ -11,7 +11,7 @@ JNUSLib Decryptor 0.1 - Maschell
|
|||||||
|
|
||||||
usage:
|
usage:
|
||||||
-commonkey <WiiU common key> Optional. HexString. Will be used if no "common.key" in the folder
|
-commonkey <WiiU common key> Optional. HexString. Will be used if no "common.key" in the folder
|
||||||
of this .jar is found
|
of this .jar or in "~/.wiiu/common.key" is found
|
||||||
-file <regular expression> Decrypts the files that matches the given regular expression.
|
-file <regular expression> Decrypts the files that matches the given regular expression.
|
||||||
-help shows this text
|
-help shows this text
|
||||||
-in <input file> Input file. Expects a folder which contains the .app, and .tmd
|
-in <input file> Input file. Expects a folder which contains the .app, and .tmd
|
||||||
@ -20,7 +20,6 @@ usage:
|
|||||||
-overwrite Optional. Overwrites existing files
|
-overwrite Optional. Overwrites existing files
|
||||||
-titlekey <Ticket title key> Optional. HexString. Will be used if no "title.tik" in the folder is
|
-titlekey <Ticket title key> Optional. HexString. Will be used if no "title.tik" in the folder is
|
||||||
found
|
found
|
||||||
-whole Decrypts the whole content files.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Requires Java 8.
|
Requires Java 8.
|
||||||
|
2
pom.xml
2
pom.xml
@ -82,7 +82,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.Maschell</groupId>
|
<groupId>com.github.Maschell</groupId>
|
||||||
<artifactId>JNUSLib</artifactId>
|
<artifactId>JNUSLib</artifactId>
|
||||||
<version> 6d98a8b </version>
|
<version> 3eb299d </version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||||
|
@ -20,6 +20,7 @@ package de.mas.jnuslib.decryptor;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
@ -36,6 +37,7 @@ import de.mas.wiiu.jnus.NUSTitleLoaderLocal;
|
|||||||
import de.mas.wiiu.jnus.Settings;
|
import de.mas.wiiu.jnus.Settings;
|
||||||
import de.mas.wiiu.jnus.entities.TMD;
|
import de.mas.wiiu.jnus.entities.TMD;
|
||||||
import de.mas.wiiu.jnus.entities.Ticket;
|
import de.mas.wiiu.jnus.entities.Ticket;
|
||||||
|
import de.mas.wiiu.jnus.implementations.FSTDataProviderNUSTitle;
|
||||||
import de.mas.wiiu.jnus.utils.Utils;
|
import de.mas.wiiu.jnus.utils.Utils;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
@ -45,8 +47,10 @@ public class Main {
|
|||||||
private static final String OPTION_COMMON_KEY = "commonkey";
|
private static final String OPTION_COMMON_KEY = "commonkey";
|
||||||
private static final String OPTION_TITLEKEY = "titlekey";
|
private static final String OPTION_TITLEKEY = "titlekey";
|
||||||
private static final String OPTION_OVERWRITE = "overwrite";
|
private static final String OPTION_OVERWRITE = "overwrite";
|
||||||
private static final String OPTION_DECRYPT_WHOLE = "whole";
|
|
||||||
private static final String OPTION_FILE = "file";
|
private static final String OPTION_FILE = "file";
|
||||||
|
private static byte[] commonKey;
|
||||||
|
|
||||||
|
private static final String HOMEPATH = System.getProperty("user.home") + File.separator + ".wiiu";
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
System.out.println("JNUSLib Decryptor 0.1 - Maschell");
|
System.out.println("JNUSLib Decryptor 0.1 - Maschell");
|
||||||
@ -75,7 +79,9 @@ public class Main {
|
|||||||
String output = null;
|
String output = null;
|
||||||
boolean overwrite = false;
|
boolean overwrite = false;
|
||||||
byte[] titlekey = null;
|
byte[] titlekey = null;
|
||||||
readKey();
|
|
||||||
|
readKey(new File(HOMEPATH + File.separator + "common.key")).ifPresent(key -> Main.commonKey = key);
|
||||||
|
readKey(new File("common.key")).ifPresent(key -> Main.commonKey = key);
|
||||||
|
|
||||||
if (cmd.hasOption(OPTION_HELP)) {
|
if (cmd.hasOption(OPTION_HELP)) {
|
||||||
showHelp(options);
|
showHelp(options);
|
||||||
@ -93,7 +99,7 @@ public class Main {
|
|||||||
String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY);
|
String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY);
|
||||||
byte[] key = Utils.StringToByteArray(commonKey);
|
byte[] key = Utils.StringToByteArray(commonKey);
|
||||||
if (key.length == 0x10) {
|
if (key.length == 0x10) {
|
||||||
Settings.commonKey = key;
|
Main.commonKey = key;
|
||||||
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
|
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,21 +124,15 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String regex = ".*";
|
String regex = ".*";
|
||||||
if (cmd.hasOption(OPTION_DECRYPT_WHOLE)) {
|
|
||||||
decryptContents(input, output, overwrite, titlekey);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd.hasOption(OPTION_FILE)) {
|
if (cmd.hasOption(OPTION_FILE)) {
|
||||||
regex = cmd.getOptionValue(OPTION_FILE);
|
regex = cmd.getOptionValue(OPTION_FILE);
|
||||||
System.out.println("Decrypting files matching \"" + regex + "\"");
|
System.out.println("Decrypting files matching \"" + regex + "\"");
|
||||||
}
|
}
|
||||||
decryptFile(input, output, regex, overwrite, titlekey);
|
decryptFile(input, output, regex, overwrite, titlekey);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NUSTitle getTitle(String input, boolean overwrite, byte[] titlekey) throws IOException, Exception {
|
private static NUSTitle getTitle(String input, boolean overwrite, byte[] titlekey) throws IOException, Exception {
|
||||||
|
|
||||||
if (input == null) {
|
if (input == null) {
|
||||||
System.out.println("You need to provide an input file");
|
System.out.println("You need to provide an input file");
|
||||||
}
|
}
|
||||||
@ -143,24 +143,15 @@ public class Main {
|
|||||||
NUSTitle title = null;
|
NUSTitle title = null;
|
||||||
|
|
||||||
if (titlekey != null) {
|
if (titlekey != null) {
|
||||||
title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath(),
|
title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath(), Ticket.createTicket(titlekey,
|
||||||
Ticket.createTicket(titlekey, TMD.parseTMD(new File(inputFile.getAbsolutePath() + File.separator + Settings.TMD_FILENAME)).getTitleID()));
|
TMD.parseTMD(new File(inputFile.getAbsolutePath() + File.separator + Settings.TMD_FILENAME)).getTitleID(), Main.commonKey));
|
||||||
} else {
|
} else {
|
||||||
title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath());
|
title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath(), Main.commonKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void decryptContents(String input, String output, boolean overwrite, byte[] titleKey) throws IOException, Exception {
|
|
||||||
NUSTitle title = getTitle(input, overwrite, titleKey);
|
|
||||||
if (title == null) {
|
|
||||||
System.err.println("Failed to open title.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DecryptionService.getInstance(title).decryptAllPlainContents(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void decryptFile(String input, String output, String regex, boolean overwrite, byte[] titlekey) throws Exception {
|
private static void decryptFile(String input, String output, String regex, boolean overwrite, byte[] titlekey) throws Exception {
|
||||||
NUSTitle title = getTitle(input, overwrite, titlekey);
|
NUSTitle title = getTitle(input, overwrite, titlekey);
|
||||||
|
|
||||||
@ -180,21 +171,25 @@ public class Main {
|
|||||||
File outputFolder = new File(newOutput);
|
File outputFolder = new File(newOutput);
|
||||||
|
|
||||||
System.out.println("To the folder: " + outputFolder.getAbsolutePath());
|
System.out.println("To the folder: " + outputFolder.getAbsolutePath());
|
||||||
title.setSkipExistingFiles(!overwrite);
|
DecryptionService decryption = DecryptionService.getInstance(new FSTDataProviderNUSTitle(title));
|
||||||
DecryptionService decryption = DecryptionService.getInstance(title);
|
|
||||||
|
|
||||||
decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath());
|
decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath(), overwrite);
|
||||||
|
|
||||||
System.out.println("Decryption done");
|
System.out.println("Decryption done");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void readKey() throws IOException {
|
private static Optional<byte[]> readKey(File file) {
|
||||||
File file = new File("common.key");
|
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
byte[] key = Files.readAllBytes(file.toPath());
|
byte[] key;
|
||||||
Settings.commonKey = key;
|
try {
|
||||||
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
|
key = Files.readAllBytes(file.toPath());
|
||||||
|
if (key != null && key.length == 16) {
|
||||||
|
return Optional.of(key);
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Options getOptions() {
|
private static Options getOptions() {
|
||||||
@ -210,7 +205,6 @@ public class Main {
|
|||||||
.desc("Optional. HexString. Will be used if no \"title.tik\" in the folder is found").build());
|
.desc("Optional. HexString. Will be used if no \"title.tik\" in the folder is found").build());
|
||||||
options.addOption(Option.builder(OPTION_FILE).argName("regular expression").hasArg()
|
options.addOption(Option.builder(OPTION_FILE).argName("regular expression").hasArg()
|
||||||
.desc("Decrypts the files that matches the given regular expression.").build());
|
.desc("Decrypts the files that matches the given regular expression.").build());
|
||||||
options.addOption(Option.builder(OPTION_DECRYPT_WHOLE).desc("Decrypts the whole content files.").build());
|
|
||||||
|
|
||||||
options.addOption(OPTION_HELP, false, "shows this text");
|
options.addOption(OPTION_HELP, false, "shows this text");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user