mirror of
https://github.com/tihmstar/futurerestore.git
synced 2025-01-08 20: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
|
else
|
||||||
AC_MSG_CHECKING([for futurerestore libipatcher])
|
AC_MSG_CHECKING([for futurerestore libipatcher])
|
||||||
if test "$build_libipatcher" = "true"; then
|
if test "$build_libipatcher" = "true"; then
|
||||||
PKG_CHECK_MODULES(libipatcher, libipatcher >= 32)
|
PKG_CHECK_MODULES(libipatcher, libipatcher >= 38)
|
||||||
do_libipatcher=yes
|
do_libipatcher=yes
|
||||||
else
|
else
|
||||||
do_libipatcher=no
|
do_libipatcher=no
|
||||||
|
|
|
@ -125,9 +125,17 @@ int futurerestore::getDeviceMode(bool reRequest){
|
||||||
void futurerestore::putDeviceIntoRecovery(){
|
void futurerestore::putDeviceIntoRecovery(){
|
||||||
if (!_didInit) reterror(-1, "did not init\n");
|
if (!_didInit) reterror(-1, "did not init\n");
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBIPATCHER
|
||||||
|
_enterPwnRecoveryRequested = _isPwnDfu;
|
||||||
|
#endif
|
||||||
|
|
||||||
getDeviceMode(false);
|
getDeviceMode(false);
|
||||||
info("Found device in %s mode\n", _client->mode->string);
|
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");
|
info("Entering recovery mode...\n");
|
||||||
if (normal_enter_recovery(_client) < 0) {
|
if (normal_enter_recovery(_client) < 0) {
|
||||||
reterror(-2,"Unable to place device into recovery mode from %s mode\n", _client->mode->string);
|
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");
|
info("Device already in Recovery mode\n");
|
||||||
}else if (_client->mode->index == MODE_DFU && _isPwnDfu &&
|
}else if (_client->mode->index == MODE_DFU && _isPwnDfu &&
|
||||||
#ifdef HAVE_LIBIPATCHER
|
#ifdef HAVE_LIBIPATCHER
|
||||||
(_enterPwnRecoveryRequested = true)
|
true
|
||||||
#else
|
#else
|
||||||
false
|
false
|
||||||
#endif
|
#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
|
#ifndef HAVE_LIBIPATCHER
|
||||||
reterror(-404, "compiled without libipatcher");
|
reterror(-404, "compiled without libipatcher");
|
||||||
#else
|
#else
|
||||||
|
@ -430,15 +438,8 @@ void futurerestore::enterPwnRecovery(plist_t build_identity){
|
||||||
|
|
||||||
if (dfu_client_new(_client) < 0)
|
if (dfu_client_new(_client) < 0)
|
||||||
reterror(-91,"Unable to connect to DFU device\n");
|
reterror(-91,"Unable to connect to DFU device\n");
|
||||||
|
|
||||||
irecv_get_mode(_client->dfu->client, &mode);
|
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 {
|
try {
|
||||||
iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS");
|
iBSSKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBSS");
|
||||||
iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC");
|
iBECKeys = libipatcher::getFirmwareKey(_client->device->product_type, _client->build, "iBEC");
|
||||||
|
@ -453,15 +454,25 @@ void futurerestore::enterPwnRecovery(plist_t build_identity){
|
||||||
|
|
||||||
|
|
||||||
auto iBEC = getIPSWComponent(_client, build_identity, "iBEC");
|
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));
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
info("Sending %s (%lu bytes)...\n", "iBSS", iBSS.second);
|
||||||
// FIXME: Did I do this right????
|
// 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);
|
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) {
|
if (err != IRECV_E_SUCCESS) {
|
||||||
reterror(-92,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
reterror(-92,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_client->build_major > 8) {
|
if (_client->build_major > 8) {
|
||||||
/* reconnect */
|
/* reconnect */
|
||||||
|
@ -480,6 +491,8 @@ void futurerestore::enterPwnRecovery(plist_t build_identity){
|
||||||
if (err != IRECV_E_SUCCESS) {
|
if (err != IRECV_E_SUCCESS) {
|
||||||
reterror(-92,"ERROR: Unable to send %s component: %s\n", "iBSS", irecv_strerror(err));
|
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);
|
dfu_client_free(_client);
|
||||||
|
@ -922,6 +935,106 @@ error:
|
||||||
return result ? abs(result) : err;
|
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(){
|
futurerestore::~futurerestore(){
|
||||||
normal_client_free(_client);
|
normal_client_free(_client);
|
||||||
recovery_client_free(_client);
|
recovery_client_free(_client);
|
||||||
|
|
|
@ -62,7 +62,7 @@ class futurerestore {
|
||||||
bool _enterPwnRecoveryRequested = false;
|
bool _enterPwnRecoveryRequested = false;
|
||||||
bool _rerestoreiOS9 = false;
|
bool _rerestoreiOS9 = false;
|
||||||
//methods
|
//methods
|
||||||
void enterPwnRecovery(plist_t build_identity);
|
void enterPwnRecovery(plist_t build_identity, std::string bootargs = "");
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -105,6 +105,7 @@ public:
|
||||||
uint64_t getBasebandGoldCertIDFromDevice();
|
uint64_t getBasebandGoldCertIDFromDevice();
|
||||||
|
|
||||||
int doRestore(const char *ipsw);
|
int doRestore(const char *ipsw);
|
||||||
|
int doJustBoot(const char *ipsw, std::string bootargs = "");
|
||||||
|
|
||||||
~futurerestore();
|
~futurerestore();
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ static struct option longopts[] = {
|
||||||
{ "no-baseband", no_argument, NULL, '2' },
|
{ "no-baseband", no_argument, NULL, '2' },
|
||||||
#ifdef HAVE_LIBIPATCHER
|
#ifdef HAVE_LIBIPATCHER
|
||||||
{ "use-pwndfu", no_argument, NULL, '3' },
|
{ "use-pwndfu", no_argument, NULL, '3' },
|
||||||
|
{ "just-boot", optional_argument, NULL, '4' },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
@ -94,6 +95,7 @@ int main(int argc, const char * argv[]) {
|
||||||
const char *basebandManifestPath = NULL;
|
const char *basebandManifestPath = NULL;
|
||||||
const char *sepPath = NULL;
|
const char *sepPath = NULL;
|
||||||
const char *sepManifestPath = NULL;
|
const char *sepManifestPath = NULL;
|
||||||
|
const char *bootargs = NULL;
|
||||||
|
|
||||||
vector<const char*> apticketPaths;
|
vector<const char*> apticketPaths;
|
||||||
|
|
||||||
|
@ -142,6 +144,10 @@ int main(int argc, const char * argv[]) {
|
||||||
case '3': // long option: "no-baseband";
|
case '3': // long option: "no-baseband";
|
||||||
flags |= FLAG_IS_PWN_DFU;
|
flags |= FLAG_IS_PWN_DFU;
|
||||||
break;
|
break;
|
||||||
|
case '4': // long option: "just-boot";
|
||||||
|
bootargs = (optarg) ? optarg : "";
|
||||||
|
break;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'd': // long option: "debug"; can be called as short option
|
case 'd': // long option: "debug"; can be called as short option
|
||||||
idevicerestore_debug = 1;
|
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");
|
if (!client.init()) reterror(-3,"can't init, no device found\n");
|
||||||
|
|
||||||
printf("futurerestore init done\n");
|
printf("futurerestore init done\n");
|
||||||
|
if (bootargs && !(flags & FLAG_IS_PWN_DFU)) {
|
||||||
|
reterror(-2,"--just-boot required --use-pwndfu\n");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (apticketPaths.size()) client.loadAPTickets(apticketPaths);
|
if (apticketPaths.size()) client.loadAPTickets(apticketPaths);
|
||||||
|
|
||||||
if (!((apticketPaths.size() && ipsw)
|
if (!(
|
||||||
|
((apticketPaths.size() && ipsw)
|
||||||
&& ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND)))
|
&& ((basebandPath && basebandManifestPath) || ((flags & FLAG_LATEST_BASEBAND) || (flags & FLAG_NO_BASEBAND)))
|
||||||
&& ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit()) )) {
|
&& ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP) || client.is32bit())
|
||||||
|
) || (ipsw && bootargs && (flags & FLAG_IS_PWN_DFU))
|
||||||
|
)) {
|
||||||
|
|
||||||
if (!(flags & FLAG_WAIT) || ipsw){
|
if (!(flags & FLAG_WAIT) || ipsw){
|
||||||
error("missing argument\n");
|
error("missing argument\n");
|
||||||
cmd_help();
|
cmd_help();
|
||||||
|
@ -190,6 +203,9 @@ int main(int argc, const char * argv[]) {
|
||||||
}
|
}
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (bootargs){
|
||||||
|
|
||||||
|
}else{
|
||||||
devVals.deviceModel = (char*)client.getDeviceModelNoCopy();
|
devVals.deviceModel = (char*)client.getDeviceModelNoCopy();
|
||||||
devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy();
|
devVals.deviceBoard = (char*)client.getDeviceBoardNoCopy();
|
||||||
|
|
||||||
|
@ -235,8 +251,7 @@ int main(int argc, const char * argv[]) {
|
||||||
reterror(-3,"baseband firmware isn't signed\n");
|
reterror(-3,"baseband firmware isn't signed\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
client.putDeviceIntoRecovery();
|
client.putDeviceIntoRecovery();
|
||||||
if (flags & FLAG_WAIT){
|
if (flags & FLAG_WAIT){
|
||||||
client.waitForNonce();
|
client.waitForNonce();
|
||||||
|
@ -248,6 +263,9 @@ int main(int argc, const char * argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (bootargs)
|
||||||
|
res = client.doJustBoot(ipsw,bootargs);
|
||||||
|
else
|
||||||
res = client.doRestore(ipsw);
|
res = client.doRestore(ipsw);
|
||||||
} catch (int error) {
|
} catch (int error) {
|
||||||
if (error == -20) error("maybe you forgot -w ?\n");
|
if (error == -20) error("maybe you forgot -w ?\n");
|
||||||
|
|
Loading…
Reference in a new issue