Add -h, -g, and -i, fix some linux issues

This commit is contained in:
Cryptiiiic 2022-03-21 15:04:13 -07:00
parent 7d93f437ba
commit 6b18838674
No known key found for this signature in database
GPG key ID: 6027B509EFE3A76B
7 changed files with 249 additions and 128 deletions

3
.gitmodules vendored
View file

@ -1,7 +1,8 @@
[submodule "external/idevicerestore"]
path = external/idevicerestore
url = https://github.com/futurerestore/idevicerestore.git
branch = test
branch = main
[submodule "external/tsschecker"]
path = external/tsschecker
url = https://github.com/1Conan/tsschecker.git
branch = master

View file

@ -69,6 +69,8 @@ Usage: `futurerestore [OPTIONS] iPSW`
| ` -d ` | ` --debug ` | Show all code, use to save a log for debug testing |
| ` -e ` | ` --exit-recovery ` | Exit recovery mode and quit |
| ` -c ` | ` --custom-latest VERSION ` | Specify custom latest version to use for SEP, Baseband and other FirmwareUpdater components |
| ` -g ` | ` --custom-latest-buildid BUILDID ` | Specify custom latest buildid to use for SEP, Baseband and other FirmwareUpdater components |
| ` -i ` | ` --custom-latest-beta ` | Get custom url from list of beta firmwares |
| | ` --use-pwndfu ` | Restoring devices with Odysseus method. Device needs to be in pwned DFU mode already |
| | ` --no-ibss ` | Restoring devices with Odysseus method. For checkm8/iPwnder32 specifically, bootrom needs to be patched already with unless iPwnder. |
| | ` --rdsk PATH ` | Set custom restore ramdisk for entering restoremode(requires use-pwndfu) |

@ -1 +1 @@
Subproject commit 6910da2f8d7c4667e89afdacc700006e89c589bd
Subproject commit 44c13e418806e8cb5b666486bb0de6052e5cfb3d

2
external/tsschecker vendored

@ -1 +1 @@
Subproject commit 7446832da266b3dbd04e7850bf336cf2d4b1c641
Subproject commit 13745170f46651b87a2215dbc4d70a2676d4c8af

View file

@ -38,33 +38,57 @@ extern "C" {
#include <windows.h>
#define safe_mkdir(path, mode) mkdir(path)
#else
#include <sys/stat.h>
void safe_mkdir(const char *path, int mode) {
int newID = 1000;
#ifdef __APPLE__
#define NEW_ID 501
newID = 501;
#else
#define NEW_ID 1000
std::ifstream osReleaseStream(std::string("/etc/os-release"));
std::string osRelease;
if(osReleaseStream.good()) {
osReleaseStream.seekg(std::ifstream::end);
osRelease.reserve(osReleaseStream.tellg());
osReleaseStream.seekg(std::ifstream::beg);
osRelease.assign((std::istreambuf_iterator<char>(osReleaseStream)), std::istreambuf_iterator<char>());
if ((osReleaseStream.rdstate() & std::ifstream::goodbit) == 0) {
int pos = osRelease.find(std::string("\nID="));
if(pos != std::string::npos) {
osRelease.erase(0, pos + 4);
pos = osRelease.find('\n');
osRelease.erase(pos, osRelease.length());
if(std::equal(osRelease.begin(), osRelease.end(), std::string("ubuntu").end())) {
if (getuid() == 999) {
newID = 999;
}
}
}
}
}
#endif
#define safe_mkdir(path, mode) \
do { \
int id = getuid(); \
setuid(NEW_ID); \
setgid(NEW_ID); \
seteuid(NEW_ID); \
setegid(NEW_ID); \
mkdir(path, mode); \
setuid(id); \
setgid(id); \
seteuid(id); \
setegid(id); \
} while(false)
int id = (int)getuid();
int id1 = (int)getgid();
int id2 = (int)geteuid();
int id3 = (int)getegid();
if(newID > -1) {
setuid(newID);
setgid(newID);
seteuid(newID);
setegid(newID);
}
mkdir(path, mode);
if(newID > -1) {
setuid(id);
setgid(id1);
seteuid(id2);
setegid(id3);
}
}
#endif
#define USEC_PER_SEC 1000000
#ifdef WIN32
std::string futurerestoreTempPath(download");
std::string futurerestoreTempPath("download");
#else
std::string tempPath("/tmp");
std::string futurerestoreTempPath(tempPath + "/futurerestore");
@ -115,7 +139,10 @@ futurerestore::futurerestore(bool isUpdateInstall, bool isPwnDfu, bool noIBSS, b
nocache = 1; //tsschecker nocache
_foundnonce = -1;
_useCustomLatest = false;
_useCustomLatestBuildID = false;
_useCustomLatestBeta = false;
_customLatest = std::string("");
_customLatestBuildID = std::string("");
}
bool futurerestore::init() {
@ -376,7 +403,8 @@ void futurerestore::loadAPTickets(const vector<const char *> &apticketPaths) {
int blen = 0;
int readsize = 16384; //0x4000
int bufsize = readsize;
char *bin = (char *) malloc(bufsize);
std::allocator<uint8_t> alloc;
char *bin = (char *)alloc.allocate(bufsize);
char *p = bin;
do {
int bytes_read = gzread(zf, p, readsize);
@ -521,13 +549,14 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg
ibss_name.append(img3_end);
ibec_name.append(img3_end);
}
std::allocator<uint8_t> alloc;
if (!_noCache) {
ibss = fopen(ibss_name.c_str(), "rb");
if (ibss) {
fseek(ibss, 0, SEEK_END);
iBSS.second = ftell(ibss);
fseek(ibss, 0, SEEK_SET);
retassure(iBSS.first = (char *) malloc(iBSS.second), "failed to calloc memory for Rose\n");
retassure(iBSS.first = (char *)alloc.allocate(iBSS.second), "failed to allocate memory for Rose\n");
size_t freadRet = 0;
retassure((freadRet = fread((char *) iBSS.first, 1, iBSS.second, ibss)) == iBSS.second,
"failed to load iBSS. size=%zu but fread returned %zu\n", iBSS.second, freadRet);
@ -539,7 +568,7 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg
fseek(ibec, 0, SEEK_END);
iBEC.second = ftell(ibec);
fseek(ibec, 0, SEEK_SET);
retassure(iBEC.first = (char *) malloc(iBEC.second), "failed to calloc memory for Rose\n");
retassure(iBEC.first = (char *)alloc.allocate(iBEC.second), "failed to allocate memory for Rose\n");
size_t freadRet = 0;
retassure((freadRet = fread((char *) iBEC.first, 1, iBEC.second, ibec)) == iBEC.second,
"failed to load iBEC. size=%zu but fread returned %zu\n", iBEC.second, freadRet);
@ -795,7 +824,7 @@ void futurerestore::enterPwnRecovery(plist_t build_identity, std::string bootarg
"failed to write generator to nvram");
retassure(!irecv_saveenv(_client->recovery->client), "failed to save nvram");
uint64_t gen = std::stoul(generator, nullptr, 16);
auto *nonce = (uint8_t *) calloc(_client->nonce_size, sizeof(uint8_t));
auto *nonce = (uint8_t *)alloc.allocate(_client->nonce_size);
if (_client->nonce_size == 20) {
SHA1((unsigned char *) &gen, 8, nonce);
} else if (_client->nonce_size == 32) {
@ -1378,6 +1407,12 @@ void futurerestore::loadFirmwareTokens() {
long cnt = parseTokens(_firmwareJson, &_firmwareTokens);
retassure(cnt > 0, "[TSSC] parsing %s.json failed\n", (0) ? "ota" : "firmware");
}
if(!_betaFirmwareTokens) {
if (!_betaFirmwareJson) _betaFirmwareJson = getBetaFirmwareJson(getDeviceModelNoCopy());
retassure(_betaFirmwareJson, "[TSSC] could not get betas json\n");
long cnt = parseTokens(_betaFirmwareJson, &_betaFirmwareTokens);
retassure(cnt > 0, "[TSSC] parsing %s.json failed\n", (0) ? "ota" : "firmware");
}
}
const char *futurerestore::getDeviceModelNoCopy() {
@ -1441,7 +1476,12 @@ char *futurerestore::getLatestManifest() {
int versionCnt = 0;
int i = 0;
char **versions = getListOfiOSForDevice(_firmwareTokens, device, 0, &versionCnt);
char **versions = nullptr;
if(_useCustomLatestBuildID) {
versions = getListOfiOSForDevice2(_firmwareTokens, device, 0, &versionCnt, 1);
} else {
versions = getListOfiOSForDevice(_firmwareTokens, device, 0, &versionCnt);
}
retassure(versionCnt, "[TSSC] failed finding latest firmware version\n");
char *bpos = nullptr;
while ((bpos = strstr((char *) (versVals.version = strdup(versions[i++])), "[B]")) != nullptr) {
@ -1464,18 +1504,50 @@ char *futurerestore::getLatestManifest() {
if(i != -1) {
reterror("[TSSC] failed to find custom version for device!\n");
}
} else if(!_useCustomLatestBeta && _useCustomLatestBuildID) {
i = 0;
while (i < versionCnt) {
versVals.buildID = strdup(versions[i++]);
std::string version(versVals.buildID);
if (!std::equal(_customLatestBuildID.begin(), _customLatestBuildID.end(), version.begin())) {
free((char *) versVals.buildID);
} else {
i = -1;
break;
}
}
if(i != -1) {
reterror("[TSSC] failed to find custom buildid for device!\n");
}
}
if(!_useCustomLatestBeta) {
if(_useCustomLatestBuildID) {
info("[TSSC] selecting latest firmware version: %s\n", versVals.buildID);
} else {
info("[TSSC] selecting latest firmware version: %s\n", versVals.version);
}
}
info("[TSSC] selecting latest firmware version: %s\n", versVals.version);
if (bpos) *bpos = '\0';
if (versions) free(versions[versionCnt - 1]), free(versions);
ptr_smart<const char *> autofree(
versVals.version); //make sure it gets freed after function finishes execution by either reaching end or throwing exception
ptr_smart<const char *> autofree2(
versVals.buildID); //make sure it gets freed after function finishes execution by either reaching end or throwing exception
_latestFirmwareUrl = getFirmwareUrl(device, &versVals, _firmwareTokens);
if(_useCustomLatestBeta) {
info("[TSSC] selecting latest firmware version: %s\n", _customLatestBuildID.c_str());
_latestFirmwareUrl = getBetaURLForDevice(_betaFirmwareTokens, _customLatestBuildID.c_str());
_latestManifest = getBuildManifest(_latestFirmwareUrl, device, nullptr, _customLatestBuildID.c_str(), 0);
} else {
_latestFirmwareUrl = getFirmwareUrl(device, &versVals, _firmwareTokens);
if(_useCustomLatestBuildID) {
_latestManifest = getBuildManifest(_latestFirmwareUrl, device, nullptr, versVals.buildID, 0);
} else {
_latestManifest = getBuildManifest(_latestFirmwareUrl, device, versVals.version, versVals.buildID, 0);
}
}
retassure(_latestFirmwareUrl, "could not find url of latest firmware version\n");
_latestManifest = getBuildManifest(_latestFirmwareUrl, device, versVals.version, versVals.buildID, 0);
retassure(_latestManifest, "could not get buildmanifest of latest firmware version\n");
}
@ -1626,7 +1698,7 @@ void futurerestore::downloadLatestBaseband() {
info("downloading Baseband\n\n");
retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathStr, basebandTempPath.c_str()),
"could not download baseband\n");
saveStringToFile(manifeststr, basebandManifestTempPath.c_str());
saveStringToFile(manifeststr, basebandManifestTempPath);
setBasebandPath(basebandTempPath);
setBasebandManifestPath(basebandManifestTempPath);
loadBaseband(this->_basebandPath);
@ -1634,11 +1706,11 @@ void futurerestore::downloadLatestBaseband() {
}
void futurerestore::downloadLatestSep() {
char *manifeststr = getLatestManifest();
char *pathStr = getPathOfElementInManifest("SEP", manifeststr, getDeviceBoardNoCopy(), 0);
std::string manifestString = getLatestManifest();
std::string pathString = getPathOfElementInManifest("SEP", manifestString.c_str(), getDeviceBoardNoCopy(), 0);
info("downloading SEP\n\n");
retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathStr, sepTempPath.c_str()), "could not download SEP\n");
saveStringToFile(manifeststr, sepManifestTempPath.c_str());
retassure(!downloadPartialzip(getLatestFirmwareUrl(), pathString.c_str(), sepTempPath.c_str()), "could not download SEP\n");
saveStringToFile(manifestString, sepManifestTempPath);
setSepPath(sepTempPath);
setSepManifestPath(sepManifestTempPath);
loadSep(this->_sepPath);
@ -1663,8 +1735,9 @@ void futurerestore::loadRose(std::string rosePath) {
roseFileStream.seekg(0, std::ios_base::end);
_client->rosefwdatasize = roseFileStream.tellg();
roseFileStream.seekg(0, std::ios_base::beg);
retassure(_client->rosefwdata = (char *) calloc(_client->rosefwdatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, rosePath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->rosefwdata = (char *)alloc.allocate(_client->rosefwdatasize),
"%s: failed to allocate memory for %s\n", __func__, rosePath.c_str());
roseFileStream.read((char *) _client->rosefwdata,
(std::streamsize) _client->rosefwdatasize);
retassure(*(uint64_t *) (_client->rosefwdata) != 0,
@ -1678,8 +1751,9 @@ void futurerestore::loadSE(std::string sePath) {
seFileStream.seekg(0, std::ios_base::end);
_client->sefwdatasize = seFileStream.tellg();
seFileStream.seekg(0, std::ios_base::beg);
retassure(_client->sefwdata = (char *) calloc(_client->sefwdatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, sePath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->sefwdata = (char *)alloc.allocate(_client->sefwdatasize),
"%s: failed to allocate memory for %s\n", __func__, sePath.c_str());
seFileStream.read((char *) _client->sefwdata,
(std::streamsize) _client->sefwdatasize);
retassure(*(uint64_t *) (_client->sefwdata) != 0,
@ -1695,8 +1769,9 @@ void futurerestore::loadSavage(std::array<std::string, 6> savagePaths) {
savageFileStream.seekg(0, std::ios_base::end);
_client->savagefwdatasize[index] = savageFileStream.tellg();
savageFileStream.seekg(0, std::ios_base::beg);
retassure(_client->savagefwdata[index] = (char *) calloc(_client->savagefwdatasize[index], 1),
"%s: failed to calloc memory for %s\n", __func__, savagePath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->savagefwdata[index] = (char *)alloc.allocate(_client->savagefwdatasize[index]),
"%s: failed to allocate memory for %s\n", __func__, savagePath.c_str());
savageFileStream.read((char *) _client->savagefwdata[index],
(std::streamsize) _client->savagefwdatasize[index]);
retassure(*(uint64_t *) (_client->savagefwdata[index]) != 0,
@ -1715,8 +1790,9 @@ void futurerestore::loadVeridian(std::string veridianDGMPath, std::string veridi
veridianDGMFileStream.seekg(0, std::ios_base::end);
_client->veridiandgmfwdatasize = veridianDGMFileStream.tellg();
veridianDGMFileStream.seekg(0, std::ios_base::beg);
retassure(_client->veridiandgmfwdata = (char *) calloc(_client->veridiandgmfwdatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, veridianDGMPath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->veridiandgmfwdata = (char *)alloc.allocate(_client->veridiandgmfwdatasize),
"%s: failed to allocate memory for %s\n", __func__, veridianDGMPath.c_str());
veridianDGMFileStream.read((char *) _client->veridiandgmfwdata,
(std::streamsize) _client->veridiandgmfwdatasize);
retassure(*(uint64_t *) (_client->veridiandgmfwdata) != 0,
@ -1725,8 +1801,8 @@ void futurerestore::loadVeridian(std::string veridianDGMPath, std::string veridi
veridianFWMFileStream.seekg(0, std::ios_base::end);
_client->veridianfwmfwdatasize = veridianFWMFileStream.tellg();
veridianFWMFileStream.seekg(0, std::ios_base::beg);
retassure(_client->veridianfwmfwdata = (char *) calloc(_client->veridianfwmfwdatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, veridianFWMPath.c_str());
retassure(_client->veridianfwmfwdata = (char *)alloc.allocate(_client->veridianfwmfwdatasize),
"%s: failed to allocate memory for %s\n", __func__, veridianFWMPath.c_str());
veridianFWMFileStream.read((char *) _client->veridianfwmfwdata,
(std::streamsize) _client->veridianfwmfwdatasize);
retassure(*(uint64_t *) (_client->veridianfwmfwdata) != 0,
@ -1740,8 +1816,9 @@ void futurerestore::loadRamdisk(std::string ramdiskPath) {
ramdiskFileStream.seekg(0, std::ios_base::end);
_client->ramdiskdatasize = ramdiskFileStream.tellg();
ramdiskFileStream.seekg(0, std::ios_base::beg);
retassure(_client->ramdiskdata = (char *) calloc(_client->ramdiskdatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, ramdiskPath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->ramdiskdata = (char *)alloc.allocate(_client->ramdiskdatasize),
"%s: failed to allocate memory for %s\n", __func__, ramdiskPath.c_str());
ramdiskFileStream.read((char *) _client->ramdiskdata,
(std::streamsize) _client->ramdiskdatasize);
retassure(*(uint64_t *) (_client->ramdiskdata) != 0,
@ -1755,8 +1832,9 @@ void futurerestore::loadKernel(std::string kernelPath) {
kernelFileStream.seekg(0, std::ios_base::end);
_client->kerneldatasize = kernelFileStream.tellg();
kernelFileStream.seekg(0, std::ios_base::beg);
retassure(_client->kerneldata = (char *) calloc(_client->kerneldatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, kernelPath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->kerneldata = (char *)alloc.allocate(_client->kerneldatasize),
"%s: failed to allocate memory for %s\n", __func__, kernelPath.c_str());
kernelFileStream.read((char *) _client->kerneldata,
(std::streamsize) _client->kerneldatasize);
retassure(*(uint64_t *) (_client->kerneldata) != 0,
@ -1770,8 +1848,9 @@ void futurerestore::loadSep(std::string sepPath) {
sepFileStream.seekg(0, std::ios_base::end);
_client->sepfwdatasize = sepFileStream.tellg();
sepFileStream.seekg(0, std::ios_base::beg);
retassure(_client->sepfwdata = (char *) calloc(_client->sepfwdatasize, 1),
"%s: failed to calloc memory for %s\n", __func__, sepPath.c_str());
std::allocator<uint8_t> alloc;
retassure(_client->sepfwdata = (char *)alloc.allocate(_client->sepfwdatasize),
"%s: failed to allocate memory for %s\n", __func__, sepPath.c_str());
sepFileStream.read((char *) _client->sepfwdata,
(std::streamsize) _client->sepfwdatasize);
retassure(*(uint64_t *) (_client->sepfwdata) != 0,
@ -1784,8 +1863,9 @@ void futurerestore::loadBaseband(std::string basebandPath) {
retassure(basebandFileStream.good(), "%s: failed init file stream for %s!\n", __func__, basebandPath.c_str());
basebandFileStream.seekg(0, std::ios_base::beg);
uint64_t *basebandFront = nullptr;
retassure(basebandFront = (uint64_t *) calloc(1, sizeof(uint64_t)),
"%s: failed to calloc memory for %s\n", __func__, basebandPath.c_str());
std::allocator<uint8_t> alloc;
retassure(basebandFront = (uint64_t *)alloc.allocate(sizeof(uint64_t)),
"%s: failed to allocate memory for %s\n", __func__, basebandPath.c_str());
basebandFileStream.read((char *)basebandFront, (std::streamsize)sizeof(uint64_t));
retassure(*(uint64_t *) (basebandFront) != 0, "%s: failed to load Baseband for %s!\n",
__func__, basebandPath.c_str());
@ -1793,13 +1873,15 @@ void futurerestore::loadBaseband(std::string basebandPath) {
#pragma mark static methods
inline void futurerestore::saveStringToFile(const char *str, const char *path) {
FILE *f = nullptr;
retassure(f = fopen(path, "w"), "can't save file at %s\n", path);
size_t len = strlen(str);
size_t wlen = fwrite(str, 1, len, f);
fclose(f);
retassure(len == wlen, "saving file failed, wrote=%zu actual=%zu\n", wlen, len);
inline void futurerestore::saveStringToFile(std::string str, std::string path) {
if(str.empty() || path.empty()) {
info("%s: No data to save!", __func__);
return;
}
std::ofstream fileStream(path);
retassure(fileStream.good(), "%s: failed init file stream for %s!\n", __func__, path.c_str());
fileStream.write(str.data(), str.length());
retassure((fileStream.rdstate() & std::ofstream::goodbit) == 0, "Can't save file at %s\n", path.c_str());
}
std::pair<const char *, size_t> futurerestore::getNonceFromSCAB(const char *scab, size_t scabSize) {

View file

@ -65,11 +65,16 @@ class futurerestore {
bool _noRestore = false;
char *_firmwareJson = nullptr;
char *_betaFirmwareJson = nullptr;
jssytok_t *_firmwareTokens = nullptr;;
jssytok_t *_betaFirmwareTokens = nullptr;
char *_latestManifest = nullptr;
char *_latestFirmwareUrl = nullptr;
bool _useCustomLatest = false;
bool _useCustomLatestBuildID = false;
bool _useCustomLatestBeta = false;
std::string _customLatest;
std::string _customLatestBuildID;
plist_t _sepbuildmanifest = nullptr;
plist_t _basebandbuildmanifest = nullptr;
@ -135,6 +140,7 @@ public:
void loadBaseband(std::string basebandPath);
void setCustomLatest(std::string version){_customLatest = version; _useCustomLatest = true;}
void setCustomLatestBuildID(std::string version, bool beta){_customLatestBuildID = version; _useCustomLatest = false; _useCustomLatestBuildID = true; _useCustomLatestBeta = beta;}
void setSepPath(std::string sepPath) {_sepPath = sepPath;}
void setSepManifestPath(std::string sepManifestPath) {_sepManifestPath = sepManifestPath;}
void setRamdiskPath(std::string ramdiskPath) {_ramdiskPath = ramdiskPath;}
@ -158,7 +164,7 @@ public:
static std::pair<const char *,size_t> getNonceFromSCAB(const char* scab, size_t scabSize);
static uint64_t getEcidFromSCAB(const char* scab, size_t scabSize);
static plist_t loadPlistFromFile(const char *path);
static void saveStringToFile(const char *str, const char *path);
static void saveStringToFile(std::string str, std::string path);
static char *getPathOfElementInManifest(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall);
static bool elemExists(const char *element, const char *manifeststr, const char *boardConfig, int isUpdateInstall);
static std::string getGeneratorFromSHSH2(plist_t shsh2);

View file

@ -30,87 +30,97 @@ extern "C"{
#endif
static struct option longopts[] = {
{ "apticket", required_argument, nullptr, 't' },
{ "baseband", required_argument, nullptr, 'b' },
{ "baseband-manifest", required_argument, nullptr, 'p' },
{ "sep", required_argument, nullptr, 's' },
{ "sep-manifest", required_argument, nullptr, 'm' },
{ "wait", no_argument, nullptr, 'w' },
{ "update", no_argument, nullptr, 'u' },
{ "debug", no_argument, nullptr, 'd' },
{ "exit-recovery", no_argument, nullptr, 'e' },
{ "custom-latest", required_argument, nullptr, 'c' },
{ "latest-sep", no_argument, nullptr, '0' },
{ "no-restore", no_argument, nullptr, 'z' },
{ "latest-baseband", no_argument, nullptr, '1' },
{ "no-baseband", no_argument, nullptr, '2' },
{ "apticket", required_argument, nullptr, 't' },
{ "baseband", required_argument, nullptr, 'b' },
{ "baseband-manifest", required_argument, nullptr, 'p' },
{ "sep", required_argument, nullptr, 's' },
{ "sep-manifest", required_argument, nullptr, 'm' },
{ "wait", no_argument, nullptr, 'w' },
{ "update", no_argument, nullptr, 'u' },
{ "debug", no_argument, nullptr, 'd' },
{ "exit-recovery", no_argument, nullptr, 'e' },
{ "custom-latest", required_argument, nullptr, 'c' },
{ "custom-latest-buildid", required_argument, nullptr, 'g' },
{ "help", no_argument, nullptr, 'h' },
{ "custom-latest-beta", no_argument, nullptr, 'i' },
{ "latest-sep", no_argument, nullptr, '0' },
{ "no-restore", no_argument, nullptr, 'z' },
{ "latest-baseband", no_argument, nullptr, '1' },
{ "no-baseband", no_argument, nullptr, '2' },
#ifdef HAVE_LIBIPATCHER
{ "use-pwndfu", no_argument, nullptr, '3' },
{ "no-ibss", no_argument, nullptr, '4' },
{ "rdsk", required_argument, nullptr, '5' },
{ "rkrn", required_argument, nullptr, '6' },
{ "set-nonce", optional_argument, nullptr, '7' },
{ "serial", no_argument, nullptr, '8' },
{ "boot-args", required_argument, nullptr, '9' },
{ "no-cache", no_argument, nullptr, 'a' },
{ "skip-blob", no_argument, nullptr, 'f' },
{ "use-pwndfu", no_argument, nullptr, '3' },
{ "no-ibss", no_argument, nullptr, '4' },
{ "rdsk", required_argument, nullptr, '5' },
{ "rkrn", required_argument, nullptr, '6' },
{ "set-nonce", optional_argument, nullptr, '7' },
{ "serial", no_argument, nullptr, '8' },
{ "boot-args", required_argument, nullptr, '9' },
{ "no-cache", no_argument, nullptr, 'a' },
{ "skip-blob", no_argument, nullptr, 'f' },
#endif
{ nullptr, 0, nullptr, 0 }
};
#define FLAG_WAIT 1 << 0
#define FLAG_UPDATE 1 << 1
#define FLAG_LATEST_SEP 1 << 2
#define FLAG_LATEST_BASEBAND 1 << 3
#define FLAG_NO_BASEBAND 1 << 4
#define FLAG_IS_PWN_DFU 1 << 5
#define FLAG_NO_IBSS 1 << 6
#define FLAG_RESTORE_RAMDISK 1 << 7
#define FLAG_RESTORE_KERNEL 1 << 8
#define FLAG_SET_NONCE 1 << 9
#define FLAG_SERIAL 1 << 10
#define FLAG_BOOT_ARGS 1 << 11
#define FLAG_NO_CACHE 1 << 12
#define FLAG_SKIP_BLOB 1 << 13
#define FLAG_NO_RESTORE_FR 1 << 14
#define FLAG_WAIT 1 << 0
#define FLAG_UPDATE 1 << 1
#define FLAG_LATEST_SEP 1 << 2
#define FLAG_LATEST_BASEBAND 1 << 3
#define FLAG_NO_BASEBAND 1 << 4
#define FLAG_IS_PWN_DFU 1 << 5
#define FLAG_NO_IBSS 1 << 6
#define FLAG_RESTORE_RAMDISK 1 << 7
#define FLAG_RESTORE_KERNEL 1 << 8
#define FLAG_SET_NONCE 1 << 9
#define FLAG_SERIAL 1 << 10
#define FLAG_BOOT_ARGS 1 << 11
#define FLAG_NO_CACHE 1 << 12
#define FLAG_SKIP_BLOB 1 << 13
#define FLAG_NO_RESTORE_FR 1 << 14
#define FLAG_CUSTOM_LATEST 1 << 15
#define FLAG_CUSTOM_LATEST_BUILDID 1 << 16
#define FLAG_CUSTOM_LATEST_BETA 1 << 17
void cmd_help(){
printf("Usage: futurerestore [OPTIONS] iPSW\n");
printf("Allows restoring to non-matching firmware with custom SEP+baseband\n");
printf("\nGeneral options:\n");
printf(" -t, --apticket PATH\t\tSigning tickets used for restoring\n");
printf(" -u, --update\t\t\tUpdate instead of erase install (requires appropriate APTicket)\n");
printf(" \t\t\tDO NOT use this parameter, if you update from jailbroken firmware!\n");
printf(" -w, --wait\t\t\tKeep rebooting until ApNonce matches APTicket (ApNonce collision, unreliable)\n");
printf(" -d, --debug\t\t\tShow all code, use to save a log for debug testing\n");
printf(" -e, --exit-recovery\t\tExit recovery mode and quit\n");
printf(" -z, --no-restore\t\tDo not restore and end right before NOR data is sent\n");
printf(" -c, --custom-latest VERSION\tSpecify custom latest version to use for SEP, Baseband and other FirmwareUpdater components\n");
printf(" -h, --help\t\t\t\tShows this usage message\n");
printf(" -t, --apticket PATH\t\t\tSigning tickets used for restoring\n");
printf(" -u, --update\t\t\t\tUpdate instead of erase install (requires appropriate APTicket)\n");
printf(" \t\t\t\tDO NOT use this parameter, if you update from jailbroken firmware!\n");
printf(" -w, --wait\t\t\t\tKeep rebooting until ApNonce matches APTicket (ApNonce collision, unreliable)\n");
printf(" -d, --debug\t\t\t\tShow all code, use to save a log for debug testing\n");
printf(" -e, --exit-recovery\t\t\tExit recovery mode and quit\n");
printf(" -z, --no-restore\t\t\tDo not restore and end right before NOR data is sent\n");
printf(" -c, --custom-latest VERSION\t\tSpecify custom latest version to use for SEP, Baseband and other FirmwareUpdater components\n");
printf(" -g, --custom-latest-buildid BUILDID\tSpecify custom latest buildid to use for SEP, Baseband and other FirmwareUpdater components\n");
printf(" -i, --custom-latest-beta\t\tGet custom url from list of beta firmwares");
#ifdef HAVE_LIBIPATCHER
printf("\nOptions for downgrading with Odysseus:\n");
printf(" --use-pwndfu\t\tRestoring devices with Odysseus method. Device needs to be in pwned DFU mode already\n");
printf(" --no-ibss\t\t\tRestoring devices with Odysseus method. For checkm8/iPwnder32 specifically, bootrom needs to be patched already with unless iPwnder.\n");
printf(" --rdsk PATH\t\tSet custom restore ramdisk for entering restoremode(requires use-pwndfu)\n");
printf(" --rkrn PATH\t\tSet custom restore kernelcache for entering restoremode(requires use-pwndfu)\n");
printf(" --set-nonce\t\tSet custom nonce from your blob then exit recovery(requires use-pwndfu)\n");
printf(" --set-nonce=0xNONCE\tSet custom nonce then exit recovery(requires use-pwndfu)\n");
printf(" --serial\t\t\tEnable serial during boot(requires serial cable and use-pwndfu)\n");
printf(" --boot-args\t\tSet custom restore boot-args(PROCEED WITH CAUTION)(requires use-pwndfu)\n");
printf(" --no-cache\t\tDisable cached patched iBSS/iBEC(requires use-pwndfu)\n");
printf(" --skip-blob\t\tSkip SHSH blob validation(PROCEED WITH CAUTION)(requires use-pwndfu)\n");
printf(" --use-pwndfu\t\t\tRestoring devices with Odysseus method. Device needs to be in pwned DFU mode already\n");
printf(" --no-ibss\t\t\t\tRestoring devices with Odysseus method. For checkm8/iPwnder32 specifically, bootrom needs to be patched already with unless iPwnder.\n");
printf(" --rdsk PATH\t\t\tSet custom restore ramdisk for entering restoremode(requires use-pwndfu)\n");
printf(" --rkrn PATH\t\t\tSet custom restore kernelcache for entering restoremode(requires use-pwndfu)\n");
printf(" --set-nonce\t\t\tSet custom nonce from your blob then exit recovery(requires use-pwndfu)\n");
printf(" --set-nonce=0xNONCE\t\tSet custom nonce then exit recovery(requires use-pwndfu)\n");
printf(" --serial\t\t\t\tEnable serial during boot(requires serial cable and use-pwndfu)\n");
printf(" --boot-args\t\t\tSet custom restore boot-args(PROCEED WITH CAUTION)(requires use-pwndfu)\n");
printf(" --no-cache\t\t\tDisable cached patched iBSS/iBEC(requires use-pwndfu)\n");
printf(" --skip-blob\t\t\tSkip SHSH blob validation(PROCEED WITH CAUTION)(requires use-pwndfu)\n");
#endif
printf("\nOptions for SEP:\n");
printf(" --latest-sep\t\tUse latest signed SEP instead of manually specifying one\n");
printf(" -s, --sep PATH\t\tSEP to be flashed\n");
printf(" -m, --sep-manifest PATH\tBuildManifest for requesting SEP ticket\n");
printf(" --latest-sep\t\t\tUse latest signed SEP instead of manually specifying one\n");
printf(" -s, --sep PATH\t\t\tSEP to be flashed\n");
printf(" -m, --sep-manifest PATH\t\tBuildManifest for requesting SEP ticket\n");
printf("\nOptions for baseband:\n");
printf(" --latest-baseband\t\tUse latest signed baseband instead of manually specifying one\n");
printf(" -b, --baseband PATH\t\tBaseband to be flashed\n");
printf(" -p, --baseband-manifest PATH\tBuildManifest for requesting baseband ticket\n");
printf(" --no-baseband\t\tSkip checks and don't flash baseband\n");
printf(" \t\tOnly use this for device without a baseband (eg. iPod touch or some Wi-Fi only iPads)\n\n");
printf(" --latest-baseband\t\t\tUse latest signed baseband instead of manually specifying one\n");
printf(" -b, --baseband PATH\t\t\tBaseband to be flashed\n");
printf(" -p, --baseband-manifest PATH\t\tBuildManifest for requesting baseband ticket\n");
printf(" --no-baseband\t\t\tSkip checks and don't flash baseband\n");
printf(" \t\t\tOnly use this for device without a baseband (eg. iPod touch or some Wi-Fi only iPads)\n\n");
}
using namespace std;
@ -145,6 +155,7 @@ int main_r(int argc, const char * argv[]) {
const char *sepManifestPath = nullptr;
const char *bootargs = nullptr;
std::string customLatest;
std::string customLatestBuildID;
const char *ramdiskPath = nullptr;
const char *kernelPath = nullptr;
const char *custom_nonce = nullptr;
@ -159,8 +170,12 @@ int main_r(int argc, const char * argv[]) {
return -1;
}
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:c:wude0z123456789af", longopts, &optindex)) > 0) {
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:c:g:hiwude0z123456789af", longopts, &optindex)) > 0) {
switch (opt) {
case 'h': // long option: "help"; can be called as short option
cmd_help();
return 0;
break;
case 't': // long option: "apticket"; can be called as short option
apticketPaths.push_back(optarg);
break;
@ -182,8 +197,16 @@ int main_r(int argc, const char * argv[]) {
case 'u': // long option: "update"; can be called as short option
flags |= FLAG_UPDATE;
break;
case 'c': // long option: "custom-latest";
case 'c': // long option: "custom-latest"; can be called as short option
customLatest = (optarg) ? std::string(optarg) : std::string("");
flags |= FLAG_CUSTOM_LATEST;
break;
case 'g': // long option: "custom-latest-buildid"; can be called as short option
customLatestBuildID = (optarg) ? std::string(optarg) : std::string("");
flags |= FLAG_CUSTOM_LATEST_BUILDID;
break;
case 'i': // long option: "custom-latest-beta"; can be called as short option
flags |= FLAG_CUSTOM_LATEST_BETA;
break;
case '0': // long option: "latest-sep";
flags |= FLAG_LATEST_SEP;
@ -292,6 +315,10 @@ int main_r(int argc, const char * argv[]) {
retassure((flags & FLAG_IS_PWN_DFU),"--no-cache requires --use-pwndfu\n");
if(flags & FLAG_SKIP_BLOB)
retassure((flags & FLAG_IS_PWN_DFU),"--skip-blob requires --use-pwndfu\n");
if(flags & FLAG_CUSTOM_LATEST_BETA)
retassure((flags & FLAG_CUSTOM_LATEST_BUILDID),"-i, --custom-latest-beta requires -g, --custom-latest-buildid\n");
if(flags & FLAG_CUSTOM_LATEST_BUILDID)
retassure((flags & FLAG_CUSTOM_LATEST) == 0,"-g, --custom-latest-buildid is not compatible with -c, --custom-latest\n");
if (exitRecovery) {
client.exitRecovery();
@ -307,6 +334,9 @@ int main_r(int argc, const char * argv[]) {
if(!customLatest.empty()) {
client.setCustomLatest(customLatest);
}
if(!customLatestBuildID.empty()) {
client.setCustomLatestBuildID(customLatestBuildID, (flags & FLAG_CUSTOM_LATEST_BETA) != 0);
}
if (!(
((!apticketPaths.empty() && ipsw)