Skip to content

Commit

Permalink
iOS-Restrictions-Recovery v0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
Emery Ferrari committed Jul 18, 2020
1 parent abe2bd4 commit 1190dd5
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 27 deletions.
26 changes: 18 additions & 8 deletions .classpath
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="X:/Libraries/Downloads/sshj-0.27.0.jar"/>
<classpathentry kind="lib" path="X:/Libraries/Downloads/slf4j-api-1.7.2.jar"/>
<classpathentry kind="lib" path="X:/Libraries/Downloads/slf4j-jdk14-1.7.2.jar"/>
<classpathentry kind="lib" path="X:/Libraries/Downloads/eddsa-0.3.0.jar"/>
<classpathentry kind="lib" path="X:/Libraries/Downloads/bcprov-jdk15on-1.64.jar"/>
<classpathentry kind="output" path="bin"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/bin/
/target/
6 changes: 6 additions & 0 deletions .project
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
8 changes: 8 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
4 changes: 4 additions & 0 deletions .settings/org.eclipse.m2e.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
29 changes: 29 additions & 0 deletions Keychain-Dumper_LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2011, Neohapsis, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 changes: 20 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,42 @@
# iOS Restrictions Recovery
# iOS-Restrictions-Recovery

by Emery Ferrari<br/>
A GUI/command-line tool that will recover the restrictions passcode from a device running iOS 7.0-11.4.1, either jailbroken or unjailbroken.
by Alyx Ferrari<br/>
A GUI/CLI tool that can find the Restrictions or Screen Time passcode of any iOS device running iOS 7.0 through iOS 13.x.

## Credit

slf4j Copyright (c) 2004-2017 QOS.ch<br/>
bc-java Copyright (c) 2000-2019 The Legion of the Bouncy Castle Inc.<br/>
sshj Copyright (c) 2010-2012 sshj contributors<br/><br/>
[keychain_dumper](https://github.com/ptoomey3/Keychain-Dumper/) was written by [ptoomey3](https://github.com/ptoomey3/).<br/>
The idea for the iTunes backup feature was given to me by:<br/>
[u/Starwarsfan2099](https://reddit.com/user/Starwarsfan2099) and<br/>
[u/KuroAMK](https://reddit.com/user/KuroAMK)<br/>
The code for the iTunes backup feature was loosely based on [this GitHub project](https://github.com/Starwarsfan2099/iOS-Restriction-Key-Cracker) by [u/Starwarsfan2099](https://reddit.com/user/Starwarsfan2099)

## Dependencies

To compile:<br/>
slf4j (slf4j-api-1.7.2 and slf4j-jdk14-1.7.2 are used for compilation of the release jars)<br/>
sshj (sshj-0.27.0 is used for compilation of the release jars)<br/>
ed25519-java (eddsa-0.3.0 is used for compilation of the release jars)<br/>
bc-java (bcprov-jdk15on-1.64 is used for compilation of the release jars)<br/><br/>
Note: The iproxy feature currently does not work.<br/>
To use the iproxy feature:<br/>
-macOS: homebrew, libimobiledevice<br/>
-Unix-based operating systems: libusbmuxd-tools<br/>
-Windows: Must have iproxy in your PATH environment variable
All dependencies are handled by Maven.<br/>
sshj<br/>
slf4j<br/>
ed25519><br/>
bcprov-jdk15on<br/>
bcpkix-jdk15on<br/>
jzlib

## Compilation/Execution

This tool can either be run from the .jar executable of the latest release in the Releases tab, or can be compiled using javac.
To run this program, you can either download the JAR from the Releases tab or generate one yourself with Maven.<br/>
Whether you use the Releases JAR or one generated yourself, if you want to use the iOS 12-13 features, keychain_dumper must be in the same directory as the JAR.<br/>
OpenSSH is required to use the iOS 12-13 features and the iOS 7.0-11.4.1 SSH features. If you're using checkra1n, iproxy will work as an alternative. If you're using any other jailbreak, OpenSSH is available on the default repos.

## Contacting me

I will respond to any PM I receive on Reddit.<br/>
[u/verystrangebeing](https://reddit.com/user/verystrangebeing/)

## Donate

All of my work is free and open-source. A donation would be greatly appreciated!<br/>
[Buy me a coffee!](buymeacoff.ee/alyxferrari/)<br/>
[PayPal](paypal.me/alyxferrari/)
Binary file added keychain_dumper
Binary file not shown.
48 changes: 48 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alyxferrari</groupId>
<artifactId>iosrr</artifactId>
<version>0.7</version>
<name>iOS-Restrictions-Recovery</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.66</version>
</dependency>
<dependency>
<groupId>net.i2p.crypto</groupId>
<artifactId>eddsa</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>sshj</artifactId>
<version>0.29.0</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
119 changes: 118 additions & 1 deletion src/com/emeryferrari/iosrr/Display.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import net.schmizz.sshj.*;
import net.schmizz.sshj.common.*;
import net.schmizz.sshj.transport.verification.*;
import net.schmizz.sshj.connection.channel.direct.*;
public class Display {
private Display() {}
private static final Display CLASS_OBJ = new Display();
Expand All @@ -13,16 +17,18 @@ private Display() {}
private static JButton SSH_BUTTON = new JButton(RRConst.SSH_BUTTON);
private static JButton IPROXY_BUTTON = new JButton(RRConst.IPROXY_BUTTON);
private static JButton ITUNES_BACKUP = new JButton(RRConst.ITUNES_BACKUP);
private static JButton KEYCHAIN_DUMPER = new JButton(RRConst.KEYCHAIN_DUMPER);
private static InfoPlist[] plists = null;
private static boolean initialized = false;
public static void createDisplay() {
if (!initialized) {
Display.FRAME.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Display.FRAME.setSize(800, 600);
Display.FRAME.setSize(550, 400);
Display.FRAME.setLayout(new BoxLayout(FRAME.getContentPane(), BoxLayout.Y_AXIS));
Display.KEY_SALT_BUTTON.addActionListener(Display.CLASS_OBJ.new KeySaltButtonListener());
Display.FILE_BUTTON.addActionListener(Display.CLASS_OBJ.new FileButtonListener());
Display.SSH_BUTTON.addActionListener(Display.CLASS_OBJ.new SSHButtonListener());
Display.KEYCHAIN_DUMPER.addActionListener(Display.CLASS_OBJ.new KeychainDumperListener());
Display.IPROXY_BUTTON.addActionListener(Display.CLASS_OBJ.new IproxyButtonListener());
Display.IPROXY_BUTTON.setEnabled(false);
Display.ITUNES_BACKUP.addActionListener(Display.CLASS_OBJ.new ItunesBackupListener());
Expand All @@ -33,9 +39,112 @@ public static void createDisplay() {
Display.FRAME.getContentPane().add(Display.KEY_SALT_BUTTON);
Display.FRAME.getContentPane().add(Display.FILE_BUTTON);
Display.FRAME.getContentPane().add(Display.SSH_BUTTON);
Display.FRAME.getContentPane().add(Display.KEYCHAIN_DUMPER);
Display.FRAME.getContentPane().add(Display.ITUNES_BACKUP);
Display.FRAME.setVisible(true);
}
public class KeychainDumperListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
new Thread() {
@Override
public void run() {
try {
int confirm = JOptionPane.showConfirmDialog(null, "This feature requires SQLite 3.x by Sam Bingner to be installed on your device. Do you consent to automatic installation of this package on your device?");
if (confirm == 0) {
String ip = JOptionPane.showInputDialog("Device IP address? OpenSSH must be installed on your device.");
String portStr = JOptionPane.showInputDialog("Device SSH server port? (press enter to default to 22)");
int port = 22;
if (!portStr.equals("")) {
port = Integer.parseInt(portStr);
}
String rootPass = JOptionPane.showInputDialog("What is your device's root password? (press enter to default to 'alpine')");
if (rootPass.equals("")) {
rootPass = "alpine";
}
Display.FRAME.getContentPane().removeAll();
Display.FRAME.getContentPane().add(new JLabel("Connecting to " + ip + ":" + port + " over SSH..."));
Display.refresh();
System.out.println("Connecting to " + ip + ":" + port + " over SSH...");
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect(ip, port);
Display.FRAME.getContentPane().add(new JLabel("Logging in as user 'root'..."));
System.out.println("Logging in as user 'root'...");
Display.refresh();
ssh.authPassword("root", rootPass);
Display.FRAME.getContentPane().add(new JLabel("Uploading keychain_dumper to device..."));
Display.refresh();
System.out.println("Uploading keychain_dumper to device...");
ssh.newSCPFileTransfer().upload("keychain_dumper", "/User/Documents/keychain_dumper");
Session session = ssh.startSession();
Display.FRAME.getContentPane().add(new JLabel("Giving keychain_dumper '+x' permissions..."));
System.out.println("Giving keychain_dumper '+x' permissions...");
Display.refresh();
session.exec("chmod +x /User/Documents/keychain_dumper");
Display.FRAME.getContentPane().add(new JLabel("Installing SQLite 3.x by Sam Bingner to the device..."));
System.out.println("Installing SQLite 3.x by Sam Bingner to the device...");
Display.refresh();
session = ssh.startSession();
session.exec("apt install sqlite3");
Display.FRAME.getContentPane().add(new JLabel("Disconnecting..."));
System.out.println("Disconnecting...");
Display.refresh();
ssh.disconnect();
ssh.close();
SSHClient ssh2 = new SSHClient();
ssh2.addHostKeyVerifier(new PromiscuousVerifier());
Display.FRAME.getContentPane().add(new JLabel("Reconnecting to " + ip + ":" + port + "..."));
System.out.println("Reconnecting to " + ip + ":" + port + "...");
Display.refresh();
ssh2.connect(ip, port);
Display.FRAME.getContentPane().add(new JLabel("Logging in as user 'root'..."));
System.out.println("Logging in as user 'root'...");
Display.refresh();
ssh2.authPassword("root", rootPass);
Session session2 = ssh2.startSession();
JOptionPane.showMessageDialog(null, "Please make sure your device is unlocked and on the home screen.");
Display.FRAME.getContentPane().add(new JLabel("Dumping your device's Keychain... (if this blocks, make sure your device is unlocked)"));
System.out.println("Dumping your device's Keychain... (if this blocks, make sure your device is unlocked)");
Display.refresh();
Session.Command cmd = session2.exec("./../mobile/Documents/keychain_dumper");
String keychain = IOUtils.readFully(cmd.getInputStream()).toString();
Display.FRAME.getContentPane().add(new JLabel("Disconnecting..."));
System.out.println("Disconnecting...");
Display.refresh();
ssh2.disconnect();
ssh2.close();
Display.FRAME.getContentPane().add(new JLabel("Parsing Keychain dump..."));
System.out.println("Parsing Keychain dump...");
Display.refresh();
String[] list = keychain.split("ParentalControls")[1].split("\n");
String password = null;
for (int i = 0; i < 20; i++) {
if (list[i].startsWith("Keychain Data: ")) {
password = list[i].split(": ")[1];
break;
}
}
Display.FRAME.getContentPane().add(new JLabel("Found Screen Time passcode! Passcode: " + password));
System.out.println("Found Screen Time passcode! Passcode: " + password);
Display.refresh();
JButton button = new JButton("Back");
button.addActionListener(new BackListener());
Display.FRAME.getContentPane().add(button);
Display.refresh();
JOptionPane.showMessageDialog(null, "Found Screen Time passcode! Passcode: " + password);
}
} catch (Exception ex) {
handleException(ex, true);
Display.FRAME.getContentPane().add(new JLabel("Failed to retrieve Screen Time passcode! If you're sure you've done everything correctly, create an issue on GitHub."));
JButton button = new JButton("Back");
button.addActionListener(new BackListener());
Display.FRAME.getContentPane().add(button);
Display.refresh();
}
}
}.start();
}
}
public class ItunesBackupListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
try {
Expand Down Expand Up @@ -128,6 +237,14 @@ public static void refresh() {
Display.FRAME.revalidate();
Display.FRAME.repaint();
}
public static void refreshThread() {
new Thread() {
@Override
public void run() {
Display.refresh();
}
}.start();
}
public static class BackListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
Display.FRAME.getContentPane().removeAll();
Expand Down
7 changes: 4 additions & 3 deletions src/com/emeryferrari/iosrr/RRConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
public class RRConst {
private RRConst() {}
public static final String NAME = "iOS-Restrictions-Recovery";
public static final String VERSION = "v0.6.4";
public static final String VERSION = "v0.7";
public static final String TITLE = "<html><body><font size=\"6\">" + NAME + " " + VERSION + "</font></body></html>";
public static final String DESC = "<html><body>Compatible <strong>only</strong> with <strong>iOS 7.0</strong> through <strong>iOS 11.4.1</strong></body></html>";
public static final String DESC = "<html><body>Compatible <strong>only</strong> with <strong>iOS 7.0</strong> through <strong>iOS 13.x</strong></body></html>";
public static final String KEY_SALT_BUTTON = "From key and salt";
public static final String FILE_BUTTON = "From property list file";
public static final String SSH_BUTTON = "From device via SSH";
public static final String SSH_BUTTON = "From device via SSH (iOS 7.0 through iOS 11.4.1)";
public static final String IPROXY_BUTTON = "From device via iproxy over USB";
public static final String ITUNES_BACKUP = "From unencrypted iTunes backup";
public static final String ITUNES_BACKUPS = "iTunes Backups:";
public static final String ITUNES_BACKUP_12 = "From encrypted iTunes backup (iOS 12 only)";
public static final String KEYCHAIN_DUMPER = "From device via SSH (iOS 12.0 through iOS 13.x)";
}
1 change: 0 additions & 1 deletion src/com/emeryferrari/iosrr/RestrictionsRecovery.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ public static void downloadViaSSH(String ip, int port, String password, boolean
if (RestrictionsRecovery.identifyHostOS() != OperatingSystem.OTHER) {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.loadKnownHosts();
ssh.connect(ip, port);
ssh.authPassword("root", password);
ssh.newSCPFileTransfer().download("/private/var/mobile/Library/Preferences/com.apple.restrictionspassword.plist", "password.plist");
Expand Down

0 comments on commit 1190dd5

Please sign in to comment.