From aca8b7ef1725d4590af3efddbf57706ea3b68167 Mon Sep 17 00:00:00 2001 From: CoocooFroggy Date: Wed, 11 Aug 2021 17:05:47 -0400 Subject: [PATCH 1/2] fIXeD fDr --- src/main/java/FutureRestoreWorker.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/FutureRestoreWorker.java b/src/main/java/FutureRestoreWorker.java index 8627ded..d9438ef 100644 --- a/src/main/java/FutureRestoreWorker.java +++ b/src/main/java/FutureRestoreWorker.java @@ -31,11 +31,13 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command(allArgsArray); + // Merge error stream into the OutputStream processBuilder.redirectErrorStream(true); processBuilder.directory(frGuiDirectory); futureRestoreProcess = processBuilder.start(); + // Remember that OutputStream is our input into FutureRestore — which needs none futureRestoreProcess.getOutputStream().close(); // futureRestoreProcess.getErrorStream().close(); @@ -89,7 +91,7 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all put("Connecting to FDR", "Connecting to FDR client..."); put("About to send NOR", "About to send NOR data..."); put("Connecting to ASR", "Connecting to ASR..."); - put("waiting for message", "Waiting for message from FDR..."); +// put("waiting for message", "Waiting for message from FDR..."); //Special messages put("Status: Restore Finished", "Restore Finished!"); From ac5c5c38e288ded5edffc477ead3417489291ed3 Mon Sep 17 00:00:00 2001 From: CoocooFroggy Date: Sun, 24 Oct 2021 17:47:43 -0400 Subject: [PATCH 2/2] - Fixed download beta FR for Linux - End FutureRestore and upload logs at 50 FDR loops - Tweaked no iBSS explanation - Set nonce basic implementation --- build.gradle | 6 +- src/main/java/FutureRestoreWorker.java | 62 ++++++++++--- src/main/java/Main.java | 10 +-- src/main/java/MainMenu.form | 10 +-- src/main/java/MainMenu.java | 118 +++++++++++++++---------- 5 files changed, 131 insertions(+), 75 deletions(-) diff --git a/build.gradle b/build.gradle index 49803a8..094e772 100644 --- a/build.gradle +++ b/build.gradle @@ -26,13 +26,13 @@ repositories { } dependencies { - implementation 'com.google.code.gson:gson:2.8.6' - implementation 'com.formdev:flatlaf:1.0' + implementation 'com.google.code.gson:gson:2.8.8' + implementation 'com.formdev:flatlaf:1.6.1' implementation group: 'org.tukaani', name: 'xz', version: '1.8' implementation group: 'org.rauschig', name: 'jarchivelib', version: '0.7.1' implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13' implementation 'com.github.Dansoftowner:jSystemThemeDetector:3.6' - implementation 'com.github.oshi:oshi-core:5.6.1' + implementation 'com.github.oshi:oshi-core:5.8.2' implementation group: 'commons-io', name: 'commons-io', version: '2.8.0' implementation 'com.github.rjeschke:txtmark:0.13' } diff --git a/src/main/java/FutureRestoreWorker.java b/src/main/java/FutureRestoreWorker.java index d9438ef..fccf418 100644 --- a/src/main/java/FutureRestoreWorker.java +++ b/src/main/java/FutureRestoreWorker.java @@ -19,12 +19,15 @@ public class FutureRestoreWorker { public static Process futureRestoreProcess; - static boolean hasRecoveryRestarted = false; + private static String[] allArgsArray; + private static String logName; + private static String logPath; + private static boolean hasRecoveryRestarted = false; - static void runFutureRestore(String futureRestoreFilePath, ArrayList allArgs, JPanel mainMenuView, JTextArea logTextArea, JProgressBar logProgressBar, JTextField currentTaskTextField, JButton startFutureRestoreButton, JButton stopFutureRestoreButton) throws IOException, InterruptedException, TimeoutException { + public static void runFutureRestore(String futureRestoreFilePath, ArrayList allArgs, JPanel mainMenuView, JTextArea logTextArea, JProgressBar logProgressBar, JTextField currentTaskTextField, JButton startFutureRestoreButton, JButton stopFutureRestoreButton) throws IOException, InterruptedException, TimeoutException { ArrayList argsAndFR = (ArrayList) allArgs.clone(); argsAndFR.add(0, futureRestoreFilePath); - String[] allArgsArray = Arrays.copyOf(argsAndFR.toArray(), argsAndFR.toArray().length, String[].class); + allArgsArray = Arrays.copyOf(argsAndFR.toArray(), argsAndFR.toArray().length, String[].class); String homeDirectory = System.getProperty("user.home"); File frGuiDirectory = new File(homeDirectory + "/FutureRestoreGUI"); @@ -52,10 +55,13 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all String dateTimeString = dateTime.toString().replaceAll(":", "."); System.out.println("Date and time is " + dateTimeString); - String logName = "FRLog_" + dateTimeString + ".txt"; - String logPath = frGuiLogsDirectory + "/" + logName; + logName = "FRLog_" + dateTimeString + ".txt"; + logPath = frGuiLogsDirectory + "/" + logName; FileWriter writer = new FileWriter(logPath); + // Count the number of FDR timeouts + int fdrTimeouts = 0; + String line; while ((line = reader.readLine()) != null) { //Parse messages @@ -98,6 +104,7 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all put("what=", null); put("code=", null); put("unknown option -- use-pwndfu", null); + put("timeout waiting for command", null); }}; for (Map.Entry entrySet : parseableMessages.entrySet()) { @@ -178,6 +185,25 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all "Ensure you're using a FutureRestore version which supports this argument, or turn off \"Pwned Restore.\"", "FutureRestore PWNDFU Unknown", JOptionPane.ERROR_MESSAGE); } + if (futureRestorePossibleMatch.equals("timeout waiting for command")) { + fdrTimeouts++; + if (fdrTimeouts > 50) { + logTextArea.append("Stopping FutureRestore—FDR looped over 50 times\n"); + futureRestoreProcess.destroy(); + logTextArea.append("FutureRestore process killed.\n"); + reader.close(); + writer.close(); + + uploadLogsIfNecessary(); + + SwingUtilities.invokeLater(() -> { + currentTaskTextField.setText("FDR looped over 50 times"); + startFutureRestoreButton.setEnabled(true); + stopFutureRestoreButton.setText("Stop FutureRestore"); + }); + return; + } + } } } } @@ -203,15 +229,7 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all System.out.println("FutureRestore process ended."); logTextArea.append("FutureRestore process ended.\n"); - if (MainMenu.properties.getProperty("upload_logs").equals("true")) { - //Make all args into a String - StringBuilder builder = new StringBuilder(); - for (String value : allArgsArray) { - builder.append(value + " "); - } - String fullCommand = builder.toString(); - uploadLog(logPath, logName, fullCommand); - } + uploadLogsIfNecessary(); SwingUtilities.invokeLater(() -> { // Clear text field if there was no real information @@ -223,6 +241,22 @@ static void runFutureRestore(String futureRestoreFilePath, ArrayList all } + public static void uploadLogsIfNecessary() throws IOException { + if (allArgsArray == null) { + allArgsArray = new String[]{"No FutureRestore args"}; + } + + if (MainMenu.properties.getProperty("upload_logs").equals("true")) { + //Make all args into a String + StringBuilder builder = new StringBuilder(); + for (String value : allArgsArray) { + builder.append(value).append(" "); + } + String fullCommand = builder.toString(); + uploadLog(logPath, logName, fullCommand); + } + } + /* * Utilities * */ diff --git a/src/main/java/Main.java b/src/main/java/Main.java index c475f1f..9cce8f5 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,14 +1,14 @@ public class Main { public static void main(String[] args) { - MainMenu.futureRestoreGUIVersion = "1.91"; + MainMenu.futureRestoreGUIVersion = "1.92"; MainMenu.main(); /* - | - — + — - | - "Are you confined like me?" + | + — + — + | + "I'm still waiting." */ diff --git a/src/main/java/MainMenu.form b/src/main/java/MainMenu.form index 4d77458..011ba3f 100644 --- a/src/main/java/MainMenu.form +++ b/src/main/java/MainMenu.form @@ -383,7 +383,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -405,10 +405,10 @@ - + - + @@ -416,7 +416,7 @@ - + diff --git a/src/main/java/MainMenu.java b/src/main/java/MainMenu.java index bf918df..1cb911d 100644 --- a/src/main/java/MainMenu.java +++ b/src/main/java/MainMenu.java @@ -58,9 +58,9 @@ public class MainMenu { private JButton nextButtonFiles; private JButton nextButtonOptions; private JCheckBox noIbssCheckBox; - private JCheckBox justBootCheckBox; + private JCheckBox setNonceCheckBox; private JLabel noIbssLabel; - private JLabel justBootLabel; + private JLabel setNonceLabel; private String futureRestoreFilePath; private String blobName; @@ -78,7 +78,7 @@ public class MainMenu { private boolean optionWaitState = false; private boolean optionPwndfuState = false; private boolean optionNoIbssState = false; - private boolean optionJustBootState = false; + private boolean optionSetNonceState = false; public MainMenu() { $$$setupUI$$$(); @@ -184,24 +184,24 @@ public MainMenu() { optionWaitState = waitWCheckBox.isSelected(); optionPwndfuState = pwndfuCheckBox.isSelected(); optionNoIbssState = noIbssCheckBox.isSelected(); - optionJustBootState = justBootCheckBox.isSelected(); + optionSetNonceState = setNonceCheckBox.isSelected(); if (optionPwndfuState) { noIbssCheckBox.setEnabled(true); noIbssLabel.setEnabled(true); - justBootCheckBox.setEnabled(true); - justBootLabel.setEnabled(true); + setNonceCheckBox.setEnabled(true); + setNonceLabel.setEnabled(true); } else { noIbssCheckBox.setSelected(false); noIbssCheckBox.setEnabled(false); noIbssLabel.setEnabled(false); - justBootCheckBox.setSelected(false); - justBootCheckBox.setEnabled(false); - justBootLabel.setEnabled(false); + setNonceCheckBox.setSelected(false); + setNonceCheckBox.setEnabled(false); + setNonceLabel.setEnabled(false); // Since we turn off the switches for pwndfu required items, also turn them off internally optionNoIbssState = false; - optionJustBootState = false; + optionSetNonceState = false; } }; debugDCheckBox.addActionListener(optionsListener); @@ -210,7 +210,7 @@ public MainMenu() { pwndfuCheckBox.addActionListener(optionsListener); noIbssCheckBox.addActionListener(optionsListener); - justBootCheckBox.addActionListener(optionsListener); + setNonceCheckBox.addActionListener(optionsListener); startFutureRestoreButton.addActionListener(e -> { // If FutureRestore is already running, just disable ourselves @@ -284,8 +284,8 @@ public MainMenu() { allArgs.add("--use-pwndfu"); if (optionNoIbssState) allArgs.add("--no-ibss"); - if (optionJustBootState) { - allArgs.add("--just-boot=\"-v\""); + if (optionSetNonceState) { + allArgs.add("--set-nonce"); } switch (sepState) { @@ -412,6 +412,12 @@ public MainMenu() { if (response == JOptionPane.YES_OPTION) { futureRestoreProcess.destroy(); messageToLog("FutureRestore process killed."); + try { + FutureRestoreWorker.uploadLogsIfNecessary(); + } catch (IOException ex) { + messageToLog("Unable to upload logs :("); + ex.printStackTrace(); + } killed = true; } } else { @@ -461,12 +467,12 @@ public MainMenu() { } } else if (osName.contains("linux")) { try { - JOptionPane.showMessageDialog(mainMenuView, "Linux OS detected. Ubuntu is the only OS with a working compiled FutureRestore build. Ensure you are running Ubuntu.", "Ubuntu Only", JOptionPane.INFORMATION_MESSAGE); +// JOptionPane.showMessageDialog(mainMenuView, "Linux OS detected. Ubuntu is the only OS with a working compiled FutureRestore build. Ensure you are running Ubuntu.", "Ubuntu Only", JOptionPane.INFORMATION_MESSAGE); Map result; if (properties.getProperty("futurerestore_beta").equals("false")) { - result = getLatestFrDownload("ubuntu"); + result = getLatestFrDownload("linux"); } else { - result = getLatestFrBetaDownload("ubuntu"); + result = getLatestFrBetaDownload("linux"); } urlString = result.get("link"); } catch (IOException e) { @@ -525,25 +531,25 @@ public static void main() { isDarkThemeUsed = detector.isDark(); //Must set L&F before we create instance of MainMenu if (isDarkThemeUsed) { - FlatDarculaLaf.install(); + FlatDarculaLaf.setup(); } else { // //Only set if not Mac // if (!System.getProperty("os.name").toLowerCase().contains("mac")) - FlatIntelliJLaf.install(); + FlatIntelliJLaf.setup(); } break; } case "light": { - //Good practice + // Good practice isDarkThemeUsed = false; -// //Only set if not Mac -// if (!System.getProperty("os.name").toLowerCase().contains("mac")) - FlatIntelliJLaf.install(); + /*// Only set if not Mac + if (!System.getProperty("os.name").toLowerCase().contains("mac"))*/ + FlatIntelliJLaf.setup(); break; } case "dark": { isDarkThemeUsed = true; - FlatDarculaLaf.install(); + FlatDarculaLaf.setup(); break; } @@ -635,7 +641,7 @@ public static void main() { }); } - /*UTILITIES*/ + /* UTILITIES */ static void turnDark(MainMenu mainMenuInstance) { JPanel mainMenuView = mainMenuInstance.mainMenuView; @@ -760,16 +766,16 @@ void runCommand(ArrayList allArgs, boolean fullFR) { String version = null; try { Process process = runtime.exec(futureRestoreFilePath); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + /*BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); Pattern pattern = Pattern.compile("Version: (.*)"); String s; - //Only check the first 5 lines + Only check the first 5 lines for (int i = 0; i < 5; i++) { s = bufferedReader.readLine(); Matcher matcher = pattern.matcher(s); - if (matcher.find()) + if (matcher.find()); version = matcher.group(1); - } + }*/ } catch (IOException ioException) { System.out.println("Unable to check FutureRestore version."); JOptionPane.showMessageDialog(mainMenuView, "Unable to run FutureRestore. Ensure you selected the correct FutureRestore executable.", "Error", JOptionPane.ERROR_MESSAGE); @@ -841,7 +847,7 @@ String getLatestFrTag() throws IOException { } Map getLatestFrDownload(String operatingSystem) throws IOException { - // operatingSystem = "mac", "windows", "ubuntu" + // operatingSystem = "mac", "windows", "linux" Map linkNameMap = new HashMap<>(); @@ -850,7 +856,16 @@ Map getLatestFrDownload(String operatingSystem) throws IOExcepti //Get asset for our operating system for (Map asset : assets) { String assetName = ((String) asset.get("name")); - if (assetName.toLowerCase().contains(operatingSystem)) { + // Linux can be linux or ubuntu in filename + if (operatingSystem.equals("linux")) { + if (assetName.toLowerCase().contains("linux") || assetName.toLowerCase().contains("ubuntu")) { + linkNameMap.put("link", (String) asset.get("browser_download_url")); + linkNameMap.put("name", assetName); + return linkNameMap; + } + } + // All other operating systems + else if (assetName.toLowerCase().contains(operatingSystem)) { linkNameMap.put("link", (String) asset.get("browser_download_url")); linkNameMap.put("name", assetName); return linkNameMap; @@ -862,7 +877,7 @@ Map getLatestFrDownload(String operatingSystem) throws IOExcepti } Map getLatestFrBetaDownload(String operatingSystem) throws IOException { - // operatingSystem = "mac", "windows", "ubuntu" + // operatingSystem = "mac", "windows", "linux" Map linkNameMap = new HashMap<>(); @@ -875,7 +890,14 @@ Map getLatestFrBetaDownload(String operatingSystem) throws IOExc //Get asset for our operating system for (Map artifact : artifacts) { String assetName = ((String) artifact.get("name")); - if (assetName.toLowerCase().contains(operatingSystem)) { + // Linux can be linux or ubuntu in filename + if (operatingSystem.equals("linux")) { + if (assetName.toLowerCase().contains("linux") || assetName.toLowerCase().contains("ubuntu")) { + linkNameMap.put("link", (String) artifact.get("archive_download_url")); + linkNameMap.put("name", assetName); + return linkNameMap; + } + } else if (assetName.toLowerCase().contains(operatingSystem)) { linkNameMap.put("link", (String) artifact.get("archive_download_url")); linkNameMap.put("name", assetName); return linkNameMap; @@ -961,7 +983,7 @@ void downloadFutureRestore(String urlString, String operatingSystem) { // Clean the area first File destinationDir = new File(finalFrPath + "extracted/"); if (destinationDir.exists()) { - if (destinationDir.listFiles().length > 0) { + if (destinationDir.listFiles() != null && Objects.requireNonNull(destinationDir.listFiles()).length > 0) { System.out.println("More than 0 files in dir. Cleaning"); try { FileUtils.cleanDirectory(destinationDir); @@ -1170,14 +1192,14 @@ boolean previewCommand(ArrayList allArgs) { if (properties.getProperty("preview_command").equals("true")) { StringBuilder commandStringBuilder = new StringBuilder(); // Surround FutureRestore's path in quotes - commandStringBuilder.append("\"" + futureRestoreFilePath + "\" "); + commandStringBuilder.append("\"").append(futureRestoreFilePath).append("\" "); for (String arg : allArgs) { if (!arg.startsWith("-")) { // If it's an argument that doesn't start with -, (so a file), surround it in quotes. - commandStringBuilder.append("\"" + arg + "\" "); + commandStringBuilder.append("\"").append(arg).append("\" "); continue; } - commandStringBuilder.append(arg + " "); + commandStringBuilder.append(arg).append(" "); } //Build the preview area @@ -1726,7 +1748,7 @@ public JTabbedPane getTabbedPane() { noIbssCheckBox = new JCheckBox(); noIbssCheckBox.setEnabled(false); noIbssCheckBox.setSelected(false); - noIbssCheckBox.setText("64 Bit Checkm8"); + noIbssCheckBox.setText("Don't Send iBSS"); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 2; @@ -1745,28 +1767,28 @@ public JTabbedPane getTabbedPane() { gbc.anchor = GridBagConstraints.NORTHWEST; gbc.insets = new Insets(0, 25, 10, 0); panel2.add(noIbssLabel, gbc); - justBootCheckBox = new JCheckBox(); - justBootCheckBox.setEnabled(false); - justBootCheckBox.setSelected(false); - justBootCheckBox.setText("Boot from Pwned DFU"); + setNonceCheckBox = new JCheckBox(); + setNonceCheckBox.setEnabled(false); + setNonceCheckBox.setSelected(false); + setNonceCheckBox.setText("Set Nonce to Blob's"); gbc = new GridBagConstraints(); gbc.gridx = 3; gbc.gridy = 2; gbc.weightx = 1.0; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(10, 0, 0, 0); - panel2.add(justBootCheckBox, gbc); - justBootLabel = new JLabel(); - justBootLabel.setEnabled(false); - Font justBootLabelFont = this.$$$getFont$$$("Menlo", -1, 10, justBootLabel.getFont()); - if (justBootLabelFont != null) justBootLabel.setFont(justBootLabelFont); - justBootLabel.setText("(--just-boot=\"-v\")"); + panel2.add(setNonceCheckBox, gbc); + setNonceLabel = new JLabel(); + setNonceLabel.setEnabled(false); + Font setNonceLabelFont = this.$$$getFont$$$("Menlo", -1, 10, setNonceLabel.getFont()); + if (setNonceLabelFont != null) setNonceLabel.setFont(setNonceLabelFont); + setNonceLabel.setText("(--set-nonce)"); gbc = new GridBagConstraints(); gbc.gridx = 3; gbc.gridy = 3; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.insets = new Insets(0, 25, 10, 0); - panel2.add(justBootLabel, gbc); + panel2.add(setNonceLabel, gbc); final JLabel label12 = new JLabel(); Font label12Font = this.$$$getFont$$$(null, -1, -1, label12.getFont()); if (label12Font != null) label12.setFont(label12Font);