mirror of
https://github.com/tihmstar/futurerestore.git
synced 2025-04-20 14:31:41 +00:00
Add -h, -g, and -i, fix some linux issues
This commit is contained in:
parent
7d93f437ba
commit
6b18838674
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -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) |
|
||||
|
|
2
external/idevicerestore
vendored
2
external/idevicerestore
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 6910da2f8d7c4667e89afdacc700006e89c589bd
|
||||
Subproject commit 44c13e418806e8cb5b666486bb0de6052e5cfb3d
|
2
external/tsschecker
vendored
2
external/tsschecker
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 7446832da266b3dbd04e7850bf336cf2d4b1c641
|
||||
Subproject commit 13745170f46651b87a2215dbc4d70a2676d4c8af
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue