Skip to content

Commit 262ff9c

Browse files
committed
Read the generator for both unjailbroken and jailbroken devices
1 parent b077ef6 commit 262ff9c

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

src/main/java/airsquared/blobsaver/app/Controller.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242

4343
import java.io.File;
4444
import java.util.Locale;
45-
import java.util.Optional;
4645
import java.util.concurrent.TimeUnit;
4746

4847
@SuppressWarnings({"TextBlockMigration"})
@@ -514,21 +513,21 @@ public void readInfo() {
514513
}
515514

516515
public void readApnonce() {
517-
Alert alert1 = new Alert(Alert.AlertType.CONFIRMATION);
516+
Alert alert1 = new Alert(Alert.AlertType.CONFIRMATION, "", ButtonType.CANCEL, new ButtonType("Jailbroken"), new ButtonType("Unjailbroken"));
518517
alert1.setHeaderText("Read apnonce from connected device");
519-
alert1.setContentText("blobsaver can read the apnonce from a connected device.\n\n" +
520-
"It is recommended, but not required to set a generator on your device prior to reading the apnonce. " +
521-
"blobsaver can read the generator from your device to confirm whether the generator was set properly (currently jailbroken devices only, it will return a random value on unjailbroken devices).\n\n" +
522-
"Please connect your device and hit \"OK\" to begin. Your device will enter recovery mode while retrieving the apnonce and will automatically reboot to normal mode when complete.\n\n" +
523-
"NOTE: an apnonce is only required for devices with an A12 processor or newer.");
524-
Optional<ButtonType> result = alert1.showAndWait();
525-
if (result.isEmpty() || !result.get().equals(ButtonType.OK)) return;
526-
final Alert alert2 = new Alert(Alert.AlertType.INFORMATION, "Entering recovery mode...\n\n" +
527-
"This can take up to 60 seconds", ButtonType.FINISH);
518+
alert1.setContentText("blobsaver can read both the ApNonce and generator from a connected device.\n\n" +
519+
"Please connect your device and click \"Jailbroken\" if your device has a generator set or \"Unjailbroken\" if you don't. Your device will enter recovery mode while retrieving the apnonce and will automatically reboot to normal mode when complete.\n\n");
520+
boolean jailbroken;
521+
if (alert1.showAndWait().isEmpty() || !alert1.getResult().getText().contains("ailbroken")) {
522+
return;
523+
} else {
524+
jailbroken = alert1.getResult().getText().equals("Jailbroken");
525+
}
526+
final Alert alert2 = new Alert(Alert.AlertType.INFORMATION, "[This should not be visible]", ButtonType.FINISH);
528527
alert2.setHeaderText("Reading apnonce from connected device...");
529528
Utils.forEachButton(alert2, button -> button.setDisable(true));
530529

531-
LibimobiledeviceUtil.GetApnonceTask task = LibimobiledeviceUtil.createGetApnonceTask();
530+
LibimobiledeviceUtil.GetApnonceTask task = LibimobiledeviceUtil.createApnonceTask(jailbroken);
532531
task.setOnSucceeded(event -> {
533532
apnonceField.setText(task.getApnonceResult());
534533
generatorField.setText(task.getGeneratorResult());

src/main/java/airsquared/blobsaver/app/LibimobiledeviceUtil.java

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,17 @@ public static void exitRecovery(Pointer irecvClient) throws LibimobiledeviceExce
6262
throwIfNeeded(Libirecovery.close(irecvClient), ErrorCodeType.irecv_error);
6363
}
6464

65-
public static GetApnonceTask createGetApnonceTask() {
66-
return new GetApnonceTask();
65+
public static GetApnonceTask createApnonceTask(boolean jailbroken) {
66+
return new GetApnonceTask(jailbroken);
6767
}
6868

6969
public static final class GetApnonceTask extends Task<Void> {
7070
private String apnonceResult, generatorResult;
71+
/**
72+
* If the device is jailbroken or has a generator set, no need to try to read the apnonce in normal mode.
73+
* If device doesn't have generator set, need to read the apnonce in normal mode to freeze it.
74+
*/
75+
private final boolean jailbroken;
7176

7277
public String getApnonceResult() {
7378
return apnonceResult;
@@ -77,24 +82,29 @@ public String getGeneratorResult() {
7782
return generatorResult;
7883
}
7984

85+
private GetApnonceTask(boolean jailbroken) {
86+
this.jailbroken = jailbroken;
87+
}
88+
8089
@Override
8190
protected Void call() throws LibimobiledeviceException {
91+
if (!jailbroken) {
92+
updateMessage("Reading ApNonce in normal mode...");
93+
System.out.println("Read in normal mode: " + LibimobiledeviceUtil.getApNonceNormalMode());
94+
}
8295
updateMessage("Entering recovery mode...\n\nThis can take up to 60 seconds");
8396
LibimobiledeviceUtil.enterRecovery();
84-
PointerByReference irecvClient = new PointerByReference();
85-
long endTime = System.currentTimeMillis() + 60_000; // timeout is 60 seconds
86-
int errorCode = -3;
87-
while (errorCode == -3 && System.currentTimeMillis() < endTime) {
88-
if (!sleep(1000)) {
89-
return null;
90-
}
91-
errorCode = Libirecovery.open(irecvClient);
92-
}
93-
throwIfNeeded(errorCode, ErrorCodeType.irecv_error);
97+
PointerByReference irecvClient = waitForRecovery();
98+
if (irecvClient == null) return null;
9499

100+
updateMessage("Reading ApNonce...");
95101
apnonceResult = getApnonce(irecvClient.getValue());
96102
Libirecovery.sendCommand(irecvClient.getValue(), "reset");
97103

104+
throwIfNeeded(Libirecovery.close(irecvClient.getValue()), ErrorCodeType.irecv_error);
105+
irecvClient = waitForRecovery();
106+
if (irecvClient == null) return null;
107+
98108
if (apnonceResult.equals(getApnonce(irecvClient.getValue()))) {
99109
Utils.runSafe(() -> updateMessage("Successfully got ApNonce, exiting recovery mode..."));
100110
} else {
@@ -106,8 +116,8 @@ protected Void call() throws LibimobiledeviceException {
106116
sleep(3000);
107117

108118
PointerByReference device = new PointerByReference();
109-
endTime = System.currentTimeMillis() + 80_000; // timeout is 80 seconds
110-
errorCode = -3;
119+
long endTime = System.currentTimeMillis() + 80_000; // timeout is 80 seconds
120+
int errorCode = -3;
111121
while (errorCode == -3 && System.currentTimeMillis() < endTime) {
112122
if (!sleep(1000)) {
113123
return null;
@@ -116,7 +126,7 @@ protected Void call() throws LibimobiledeviceException {
116126
}
117127
throwIfNeeded(errorCode, ErrorCodeType.idevice_error);
118128

119-
Utils.runSafe(() -> updateMessage("Please unlock your device"));
129+
updateMessage("Please unlock your device");
120130

121131
PointerByReference lockdown = new PointerByReference();
122132
endTime = System.currentTimeMillis() + 120_000; // timeout is 120 seconds
@@ -151,17 +161,32 @@ protected Void call() throws LibimobiledeviceException {
151161
return null;
152162
}
153163

154-
/**
155-
* @return false if task was cancelled during the Thread.sleep
156-
*/
157-
private boolean sleep(long millis) {
158-
try {
159-
Thread.sleep(millis);
160-
} catch (InterruptedException e) {
161-
return false;
164+
}
165+
166+
/**
167+
* @return false if task was cancelled during the Thread.sleep
168+
*/
169+
private static boolean sleep(long millis) {
170+
try {
171+
Thread.sleep(millis);
172+
} catch (InterruptedException e) {
173+
return false;
174+
}
175+
return true;
176+
}
177+
178+
private static PointerByReference waitForRecovery() throws LibimobiledeviceException {
179+
PointerByReference irecvClient = new PointerByReference();
180+
long endTime = System.currentTimeMillis() + 60_000; // timeout is 60 seconds
181+
int errorCode = -3;
182+
while (errorCode == -3 && System.currentTimeMillis() < endTime) {
183+
if (!sleep(1000)) {
184+
return null;
162185
}
163-
return true;
186+
errorCode = Libirecovery.open(irecvClient);
164187
}
188+
throwIfNeeded(errorCode, ErrorCodeType.irecv_error);
189+
return irecvClient;
165190
}
166191

167192
private static String getApnonce(Pointer irecv_client) {

0 commit comments

Comments
 (0)