mirror of
https://github.com/tihmstar/futurerestore.git
synced 2024-12-21 17:25:30 +00:00
added support, for booting with custom bootargs from pwndfu
This commit is contained in:
parent
f068ddb057
commit
c90da707b1
|
@ -52,7 +52,7 @@ if [test -z "$LIBIPATCHER_FLAGS"]; then
|
|||
else
|
||||
AC_MSG_CHECKING([for futurerestore libipatcher])
|
||||
if test "$build_libipatcher" = "true"; then
|
||||
PKG_CHECK_MODULES(libipatcher, libipatcher >= 32)
|
||||
PKG_CHECK_MODULES(libipatcher, libipatcher >= 38)
|
||||
do_libipatcher=yes
|
||||
else
|
||||
do_libipatcher=no
|
||||
|
|
|
@ -125,9 +125,17 @@ int futurerestore::getDeviceMode(bool reRequest){
|
|||
void futurerestore::putDeviceIntoRecovery(){
|
||||
if (!_didInit) reterror(-1, "did not init\n");
|
||||
|
||||
#ifdef HAVE_LIBIPATCHER
|
||||
_enterPwnRecoveryRequested = _isPwnDfu;
|
||||
#endif
|
||||
|
||||
getDeviceMode(false);
|
||||
info("Found device in %s mode\n", _client->mode->string);
|
||||
if (_client->mode->index == MODE_NORMAL) {
|
||||
if (_client->mode->index == MODE_NORMAL){
|
||||
#ifdef HAVE_LIBIPATCHER
|
||||
if (_isPwnDfu)
|
||||
reterror(-501, "isPwnDfu enabled, but device was found in normal mode\n");
|
||||
#endif
|
||||
info("Entering recovery mode...\n");
|
||||
if (normal_enter_recovery(_client) < 0) {
|
||||
reterror(-2,"Unable to place device into recovery mode from %s mode\n", _client->mode->string);
|
||||
|
@ -136,7 +144,7 @@ void futurerestore::putDeviceIntoRecovery(){
|
|||
info("Device already in Recovery mode\n");
|
||||
}else if (_client->mode->index == MODE_DFU && _isPwnDfu &&
|
||||
#ifdef HAVE_LIBIPATCHER
|
||||
(_enterPwnRecoveryRequested = true)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
|
@ -420,7 +428,7 @@ pair<ptr_smart<char*>, size_t> getIPSWComponent(struct idevicerestore_client_t*
|
|||
}
|
||||
|
||||
|
||||
void futurerestore::enterPwnRecovery(plist_t build_identity){
|
||||
void futurerestore::enterPwnRecovery(plist_t build_identity, string bootargs){
|
||||
#ifndef HAVE_LIBIPATCHER
|
||||
reterror(-404, "compiled without libipatcher");
|
||||
#else
|
||||
|
@ -430,15 +438,8 @@ void futurerestore::enterPwnRecovery(plist_t build_identity){
|
|||
|
||||
if (dfu_client_new(_client) < 0)
|
||||
reterror(-91,"Unable to connect to DFU device\n");
|
||||
|
||||
irecv_get_mode(_client->dfu->client, &mode);
|
||||
|
||||
if (mode != IRECV_K_DFU_MODE) {
|
||||
info("NOTE: device is not in DFU mode, assuming recovery mode.\n");
|
||||
_client->mode = &idevicerestore_modes[MODE_RECOVERY];
|
||||
reterror(-91, "Device is in wrong mode\n");
|
||||
}
|
||||
|
||||
try {
|
||||
iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS");
|
||||
iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC");
|
||||
|
@ -453,14 +454,24 @@ void futurerestore::enterPwnRecovery(plist_t build_identity){
|
|||
|
||||
|
||||
auto iBEC = getIPSWComponent(_client, build_identity, "iBEC");
|
||||
iBEC = move(libipatcher::patchiBEC((char*)iBEC.first, iBEC.second, iBECKeys));
|
||||
iBEC = move(libipatcher::patchiBEC((char*)iBEC.first, iBEC.second, iBECKeys, bootargs));
|
||||
|
||||
|
||||
info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second);
|
||||
// FIXME: Did I do this right????
|
||||
irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBSS.first, (unsigned long)iBSS.second, 1);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
reterror(-92,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
||||
bool modeIsRecovery = false;
|
||||
if (mode != IRECV_K_DFU_MODE) {
|
||||
info("NOTE: device is not in DFU mode, assuming pwn recovery mode.\n");
|
||||
for (int i=IRECV_K_RECOVERY_MODE_1; i<=IRECV_K_RECOVERY_MODE_4; i++) {
|
||||
if (mode == i)
|
||||
modeIsRecovery = true;
|
||||
}
|
||||
if (!modeIsRecovery)
|
||||
reterror(-505, "device not in recovery mode\n");
|
||||
}else{
|
||||
info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second);
|
||||
// FIXME: Did I do this right????
|
||||
irecv_error_t err = irecv_send_buffer(_client->dfu->client, (unsigned char*)(char*)iBSS.first, (unsigned long)iBSS.second, 1);
|
||||
if (err != IRECV_E_SUCCESS) {
|
||||
reterror(-92,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
if (_client->build_major > 8) {
|
||||
|
@ -480,6 +491,8 @@ void futurerestore::enterPwnRecovery(plist_t build_identity){
|
|||
if (err != IRECV_E_SUCCESS) {
|
||||
reterror(-92,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
||||
}
|
||||
if (modeIsRecovery)
|
||||
irecv_send_command(_client->dfu->client, "go");
|
||||
}
|
||||
|
||||
dfu_client_free(_client);
|
||||
|
@ -922,6 +935,106 @@ error:
|
|||
return result ? abs(result) : err;
|
||||
}
|
||||
|
||||
int futurerestore::doJustBoot(const char *ipsw, string bootargs){
|
||||
int err = 0;
|
||||
//some memory might not get freed if this function throws an exception, but you probably don't want to catch that anyway.
|
||||
|
||||
struct idevicerestore_client_t* client = _client;
|
||||
int unused;
|
||||
int result = 0;
|
||||
plist_t buildmanifest = NULL;
|
||||
plist_t build_identity = NULL;
|
||||
|
||||
client->ipsw = strdup(ipsw);
|
||||
|
||||
getDeviceMode(true);
|
||||
info("Found device in %s mode\n", client->mode->string);
|
||||
|
||||
if (!(client->mode->index == MODE_DFU || client->mode->index == MODE_RECOVERY) || !_enterPwnRecoveryRequested)
|
||||
reterror(-6, "device not in DFU/Recovery mode\n");
|
||||
// discover the device type
|
||||
if (check_hardware_model(client) == NULL || client->device == NULL) {
|
||||
reterror(-2,"ERROR: Unable to discover device model\n");
|
||||
}
|
||||
info("Identified device as %s, %s\n", client->device->hardware_model, client->device->product_type);
|
||||
|
||||
// verify if ipsw file exists
|
||||
if (access(client->ipsw, F_OK) < 0) {
|
||||
error("ERROR: Firmware file %s does not exist.\n", client->ipsw);
|
||||
return -1;
|
||||
}
|
||||
info("Extracting BuildManifest from IPSW\n");
|
||||
if (ipsw_extract_build_manifest(client->ipsw, &buildmanifest, &unused) < 0) {
|
||||
reterror(-3,"ERROR: Unable to extract BuildManifest from %s. Firmware file might be corrupt.\n", client->ipsw);
|
||||
}
|
||||
/* check if device type is supported by the given build manifest */
|
||||
if (build_manifest_check_compatibility(buildmanifest, client->device->product_type) < 0) {
|
||||
reterror(-4,"ERROR: Could not make sure this firmware is suitable for the current device. Refusing to continue.\n");
|
||||
}
|
||||
/* print iOS information from the manifest */
|
||||
build_manifest_get_version_information(buildmanifest, client);
|
||||
|
||||
info("Product Version: %s\n", client->version);
|
||||
info("Product Build: %s Major: %d\n", client->build, client->build_major);
|
||||
|
||||
client->image4supported = is_image4_supported(client);
|
||||
info("Device supports Image4: %s\n", (client->image4supported) ? "true" : "false");
|
||||
|
||||
if (!(build_identity = getBuildidentityWithBoardconfig(buildmanifest, client->device->hardware_model, 0)))
|
||||
reterror(-5,"ERROR: Unable to find any build identities for IPSW\n");
|
||||
|
||||
|
||||
/* print information about current build identity */
|
||||
build_identity_print_information(build_identity);
|
||||
|
||||
|
||||
//check for enterpwnrecovery, because we could be in DFU mode
|
||||
if (!_enterPwnRecoveryRequested)
|
||||
reterror(-6, "enterPwnRecoveryRequested is not set, but required");
|
||||
|
||||
if (getDeviceMode(true) != MODE_DFU && getDeviceMode(false) != MODE_RECOVERY)
|
||||
reterror(-6, "unexpected device mode");
|
||||
enterPwnRecovery(build_identity, bootargs);
|
||||
|
||||
client->recovery_custom_component_function = get_custom_component;
|
||||
|
||||
for (int i=0;getDeviceMode(true) != MODE_RECOVERY && i<40; i++) putchar('.'),usleep(USEC_PER_SEC*0.5);
|
||||
putchar('\n');
|
||||
|
||||
if (!check_mode(client))
|
||||
reterror(-15, "failed to reconnect to device in recovery (iBEC) mode\n");
|
||||
|
||||
get_ecid(client, &client->ecid);
|
||||
|
||||
client->flags |= FLAG_BOOT;
|
||||
|
||||
if (client->mode->index == MODE_RECOVERY) {
|
||||
if (client->srnm == NULL) {
|
||||
reterror(-9,"ERROR: could not retrieve device serial number. Can't continue.\n");
|
||||
}
|
||||
if (irecv_send_command(client->recovery->client, "bgcolor 0 255 0") != IRECV_E_SUCCESS) {
|
||||
error("ERROR: Unable to set bgcolor\n");
|
||||
return -1;
|
||||
}
|
||||
info("[WARNING] Setting bgcolor to green! If you don't see a green screen, then your device didn't boot iBEC correctly\n");
|
||||
sleep(2); //show the user a green screen!
|
||||
client->image4supported = true; //dirty hack to not require apticket
|
||||
if (recovery_enter_restore(client, build_identity) < 0) {
|
||||
reterror(-10,"ERROR: Unable to place device into restore mode\n");
|
||||
}
|
||||
client->image4supported = false;
|
||||
recovery_client_free(client);
|
||||
}
|
||||
|
||||
info("Cleaning up...\n");
|
||||
|
||||
error:
|
||||
safeFree(client->sepfwdata);
|
||||
safePlistFree(buildmanifest);
|
||||
if (!result && !err) info("DONE\n");
|
||||
return result ? abs(result) : err;
|
||||
}
|
||||
|
||||
futurerestore::~futurerestore(){
|
||||
normal_client_free(_client);
|
||||
recovery_client_free(_client);
|
||||
|
|
|
@ -62,7 +62,7 @@ class futurerestore {
|
|||
bool _enterPwnRecoveryRequested = false;
|
||||
bool _rerestoreiOS9 = false;
|
||||
//methods
|
||||
void enterPwnRecovery(plist_t build_identity);
|
||||
void enterPwnRecovery(plist_t build_identity, std::string bootargs = "");
|
||||
|
||||
|
||||
public:
|
||||
|
@ -105,6 +105,7 @@ public:
|
|||
uint64_t getBasebandGoldCertIDFromDevice();
|
||||
|
||||
int doRestore(const char *ipsw);
|
||||
int doJustBoot(const char *ipsw, std::string bootargs = "");
|
||||
|
||||
~futurerestore();
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ static struct option longopts[] = {
|
|||
{ "latest-baseband", no_argument, NULL, '1' },
|
||||
{ "no-baseband", no_argument, NULL, '2' },
|
||||
#ifdef HAVE_LIBIPATCHER
|
||||
{ "use-pwndfu", no_argument, NULL, '3' },
|
||||
{ "use-pwndfu", no_argument, NULL, '3' },
|
||||
{ "just-boot", optional_argument, NULL, '4' },
|
||||
#endif
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
@ -94,6 +95,7 @@ int main(int argc, const char * argv[]) {
|
|||
const char *basebandManifestPath = NULL;
|
||||
const char *sepPath = NULL;
|
||||
const char *sepManifestPath = NULL;
|
||||
const char *bootargs = NULL;
|
||||
|
||||
vector<const char*> apticketPaths;
|
||||
|
||||
|
@ -142,6 +144,10 @@ int main(int argc, const char * argv[]) {
|
|||
case '3': // long option: "no-baseband";
|
||||
flags |= FLAG_IS_PWN_DFU;
|
||||
break;
|
||||
case '4': // long option: "just-boot";
|
||||
bootargs = (optarg) ? optarg : "";
|
||||
break;
|
||||
break;
|
||||
#endif
|
||||
case 'd': // long option: "debug"; can be called as short option
|
||||
idevicerestore_debug = 1;
|
||||
|
@ -172,13 +178,20 @@ int main(int argc, const char * argv[]) {
|
|||
if (!client.init()) reterror(-3,"can't init, no device found\n");
|
||||
|
||||
printf("futurerestore init done\n");
|
||||
if (bootargs && !(flags & FLAG_IS_PWN_DFU)) {
|
||||
reterror(-2,"--just-boot required --use-pwndfu\n");
|
||||
}
|
||||
|
||||
try {
|
||||
if (apticketPaths.size()) client.loadAPTickets(apticketPaths);
|
||||
|
||||
if (!((apticketPaths.size() && ipsw)
|
||||
&& ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND)))
|
||||
&& ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit()) )) {
|
||||
if (!(
|
||||
((apticketPaths.size() && ipsw)
|
||||
&& ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND)))
|
||||
&& ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit())
|
||||
) || (ipsw && bootargs && (flags & FLAG_IS_PWN_DFU))
|
||||
)) {
|
||||
|
||||
if (!(flags & FLAG_WAIT) || ipsw){
|
||||
error("missing argument\n");
|
||||
cmd_help();
|
||||
|
@ -190,53 +203,55 @@ int main(int argc, const char * argv[]) {
|
|||
}
|
||||
goto error;
|
||||
}
|
||||
devVals.deviceModel = (char*)client.getDeviceModelNoCopy();
|
||||
devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy();
|
||||
|
||||
if (flags & FLAG_LATEST_SEP){
|
||||
info("user specified to use latest signed sep\n");
|
||||
client.loadLatestSep();
|
||||
}else if (!client.is32bit()){
|
||||
client.loadSep(sepPath);
|
||||
client.setSepManifestPath(sepManifestPath);
|
||||
}
|
||||
|
||||
versVals.basebandMode = kBasebandModeWithoutBaseband;
|
||||
if (!client.is32bit() && !(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), &devVals, &versVals))){
|
||||
reterror(-3,"sep firmware isn't signed\n");
|
||||
}
|
||||
|
||||
if (flags & FLAG_NO_BASEBAND){
|
||||
printf("\nWARNING: user specified not to flash a baseband. This can make the restore fail if the device needs a baseband!\n");
|
||||
printf("if you added this flag by mistake you can press CTRL-C now to cancel\n");
|
||||
int c = 5;
|
||||
printf("continuing restore in ");
|
||||
while (c) {
|
||||
printf("%d ",c--);
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
}
|
||||
printf("\n");
|
||||
if (bootargs){
|
||||
|
||||
}else{
|
||||
if (flags & FLAG_LATEST_BASEBAND){
|
||||
info("user specified to use latest signed baseband (WARNING, THIS CAN CAUSE A NON-WORKING RESTORE)\n");
|
||||
client.loadLatestBaseband();
|
||||
}else{
|
||||
client.setBasebandPath(basebandPath);
|
||||
client.setBasebandManifestPath(basebandManifestPath);
|
||||
printf("Did set sep+baseband path and firmware\n");
|
||||
devVals.deviceModel = (char*)client.getDeviceModelNoCopy();
|
||||
devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy();
|
||||
|
||||
if (flags & FLAG_LATEST_SEP){
|
||||
info("user specified to use latest signed sep\n");
|
||||
client.loadLatestSep();
|
||||
}else if (!client.is32bit()){
|
||||
client.loadSep(sepPath);
|
||||
client.setSepManifestPath(sepManifestPath);
|
||||
}
|
||||
|
||||
versVals.basebandMode = kBasebandModeOnlyBaseband;
|
||||
if (!(devVals.bbgcid = client.getBasebandGoldCertIDFromDevice())){
|
||||
printf("[WARNING] using tsschecker's fallback to get BasebandGoldCertID. This might result in invalid baseband signing status information\n");
|
||||
versVals.basebandMode = kBasebandModeWithoutBaseband;
|
||||
if (!client.is32bit() && !(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), &devVals, &versVals))){
|
||||
reterror(-3,"sep firmware isn't signed\n");
|
||||
}
|
||||
if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), &devVals, &versVals))) {
|
||||
reterror(-3,"baseband firmware isn't signed\n");
|
||||
|
||||
if (flags & FLAG_NO_BASEBAND){
|
||||
printf("\nWARNING: user specified not to flash a baseband. This can make the restore fail if the device needs a baseband!\n");
|
||||
printf("if you added this flag by mistake you can press CTRL-C now to cancel\n");
|
||||
int c = 5;
|
||||
printf("continuing restore in ");
|
||||
while (c) {
|
||||
printf("%d ",c--);
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
}
|
||||
printf("\n");
|
||||
}else{
|
||||
if (flags & FLAG_LATEST_BASEBAND){
|
||||
info("user specified to use latest signed baseband (WARNING, THIS CAN CAUSE A NON-WORKING RESTORE)\n");
|
||||
client.loadLatestBaseband();
|
||||
}else{
|
||||
client.setBasebandPath(basebandPath);
|
||||
client.setBasebandManifestPath(basebandManifestPath);
|
||||
printf("Did set sep+baseband path and firmware\n");
|
||||
}
|
||||
|
||||
versVals.basebandMode = kBasebandModeOnlyBaseband;
|
||||
if (!(devVals.bbgcid = client.getBasebandGoldCertIDFromDevice())){
|
||||
printf("[WARNING] using tsschecker's fallback to get BasebandGoldCertID. This might result in invalid baseband signing status information\n");
|
||||
}
|
||||
if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), &devVals, &versVals))) {
|
||||
reterror(-3,"baseband firmware isn't signed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
client.putDeviceIntoRecovery();
|
||||
if (flags & FLAG_WAIT){
|
||||
client.waitForNonce();
|
||||
|
@ -248,7 +263,10 @@ int main(int argc, const char * argv[]) {
|
|||
}
|
||||
|
||||
try {
|
||||
res = client.doRestore(ipsw);
|
||||
if (bootargs)
|
||||
res = client.doJustBoot(ipsw,bootargs);
|
||||
else
|
||||
res = client.doRestore(ipsw);
|
||||
} catch (int error) {
|
||||
if (error == -20) error("maybe you forgot -w ?\n");
|
||||
err = error;
|
||||
|
|
Loading…
Reference in a new issue