From 56aab40cf24816579b260600d1c2a034b781b5bd Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 15 Sep 2016 14:22:49 +0200 Subject: [PATCH] . --- .gitmodules | 9 + futurerestore.xcodeproj/project.pbxproj | 240 +++++++++++ futurerestore/config.h | 22 + futurerestore/futurerestore.cpp | 538 ++++++++++++++++++++++++ futurerestore/futurerestore.hpp | 62 +++ futurerestore/main.cpp | 164 +++++++- 6 files changed, 1030 insertions(+), 5 deletions(-) create mode 100644 .gitmodules create mode 100644 futurerestore/config.h create mode 100644 futurerestore/futurerestore.cpp create mode 100644 futurerestore/futurerestore.hpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..d48f1351 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "external/img4tool"] + path = external/img4tool + url = ssh://git@tihmstar.net:23/img4tool.git +[submodule "external/tsschecker"] + path = external/tsschecker + url = git@github.com:tihmstar/tsschecker.git +[submodule "external/idevicerestore"] + path = external/idevicerestore + url = git@github.com:tihmstar/idevicerestore.git diff --git a/futurerestore.xcodeproj/project.pbxproj b/futurerestore.xcodeproj/project.pbxproj index 74188430..abd179cf 100644 --- a/futurerestore.xcodeproj/project.pbxproj +++ b/futurerestore.xcodeproj/project.pbxproj @@ -8,6 +8,39 @@ /* Begin PBXBuildFile section */ 878587471D89CFDC008689F0 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 878587461D89CFDC008689F0 /* main.cpp */; }; + 878587A71D89D56E008689F0 /* libplist.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587A61D89D56E008689F0 /* libplist.3.dylib */; }; + 878587AB1D89D590008689F0 /* libimobiledevice.6.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587AA1D89D590008689F0 /* libimobiledevice.6.dylib */; }; + 878587AD1D89D59E008689F0 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587AC1D89D59E008689F0 /* libz.tbd */; }; + 878587AF1D89D5A5008689F0 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587AE1D89D5A5008689F0 /* libcurl.tbd */; }; + 878587B11D89D5B0008689F0 /* libcrypto.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587B01D89D5B0008689F0 /* libcrypto.tbd */; }; + 878587B31D89D5D5008689F0 /* libzip.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587B21D89D5D5008689F0 /* libzip.4.dylib */; }; + 878587B51D89D5E6008689F0 /* libpartialzip-1.0.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587B41D89D5E6008689F0 /* libpartialzip-1.0.0.dylib */; }; + 878587B71D89D637008689F0 /* libirecovery.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 878587B61D89D637008689F0 /* libirecovery.2.dylib */; }; + 8799B0B21D89D99D002F4D5F /* futurerestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8799B0B01D89D99D002F4D5F /* futurerestore.cpp */; }; + 8799B0B31D89DAE7002F4D5F /* idevicerestore.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785875C1D89D1C1008689F0 /* idevicerestore.c */; settings = {COMPILER_FLAGS = "-D HAVE_CONFIG_H=1 "; }; }; + 8799B0B41D89DAF6002F4D5F /* tss.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587761D89D1C1008689F0 /* tss.c */; }; + 8799B0B51D89DAFF002F4D5F /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587511D89D1C1008689F0 /* common.c */; }; + 8799B0B61D89DAFF002F4D5F /* dfu.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587531D89D1C1008689F0 /* dfu.c */; }; + 8799B0B71D89DAFF002F4D5F /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876C1D89D1C1008689F0 /* normal.c */; }; + 8799B0B81D89DAFF002F4D5F /* recovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876E1D89D1C1008689F0 /* recovery.c */; }; + 8799B0B91D89DB0D002F4D5F /* img3.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785875E1D89D1C1008689F0 /* img3.c */; }; + 8799B0BB1D89DB12002F4D5F /* download.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587551D89D1C1008689F0 /* download.c */; }; + 8799B0BC1D89DB27002F4D5F /* ipsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587621D89D1C1008689F0 /* ipsw.c */; }; + 8799B0BD1D89DB27002F4D5F /* limera1n.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587641D89D1C1008689F0 /* limera1n.c */; }; + 8799B0BE1D89DB27002F4D5F /* restore.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587701D89D1C1008689F0 /* restore.c */; }; + 8799B0BF1D89DB38002F4D5F /* asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785874F1D89D1C1008689F0 /* asr.c */; }; + 8799B0C01D89DB38002F4D5F /* fdr.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587581D89D1C1008689F0 /* fdr.c */; }; + 8799B0C11D89DB38002F4D5F /* fls.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785875A1D89D1C1008689F0 /* fls.c */; }; + 8799B0C21D89DB46002F4D5F /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587741D89D1C1008689F0 /* thread.c */; }; + 8799B0C31D89DB4B002F4D5F /* socket.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587721D89D1C1008689F0 /* socket.c */; }; + 8799B0C41D89DB55002F4D5F /* mbn.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785876A1D89D1C1008689F0 /* mbn.c */; }; + 8799B0C51D89DB67002F4D5F /* locking.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587671D89D1C1008689F0 /* locking.c */; }; + 8799B0C81D89E2BD002F4D5F /* img4tool.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587901D89D1ED008689F0 /* img4tool.c */; }; + 8799B0C91D89E2C3002F4D5F /* img4.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785878E1D89D1ED008689F0 /* img4.c */; }; + 8799B0CA1D89E371002F4D5F /* img4.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587601D89D1C1008689F0 /* img4.c */; }; + 8799B0CB1D89F796002F4D5F /* tsschecker.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785879F1D89D2BA008689F0 /* tsschecker.c */; }; + 8799B0CC1D89F7B9002F4D5F /* download.c in Sources */ = {isa = PBXBuildFile; fileRef = 878587981D89D2BA008689F0 /* download.c */; }; + 8799B0CD1D89F7B9002F4D5F /* jsmn.c in Sources */ = {isa = PBXBuildFile; fileRef = 8785879A1D89D2BA008689F0 /* jsmn.c */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -25,6 +58,70 @@ /* Begin PBXFileReference section */ 878587431D89CFDC008689F0 /* futurerestore */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = futurerestore; sourceTree = BUILT_PRODUCTS_DIR; }; 878587461D89CFDC008689F0 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 8785874F1D89D1C1008689F0 /* asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asr.c; sourceTree = ""; }; + 878587501D89D1C1008689F0 /* asr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asr.h; sourceTree = ""; }; + 878587511D89D1C1008689F0 /* common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = common.c; sourceTree = ""; }; + 878587521D89D1C1008689F0 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; + 878587531D89D1C1008689F0 /* dfu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfu.c; sourceTree = ""; }; + 878587541D89D1C1008689F0 /* dfu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfu.h; sourceTree = ""; }; + 878587551D89D1C1008689F0 /* download.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = download.c; sourceTree = ""; }; + 878587561D89D1C1008689F0 /* download.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = download.h; sourceTree = ""; }; + 878587571D89D1C1008689F0 /* endianness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = endianness.h; sourceTree = ""; }; + 878587581D89D1C1008689F0 /* fdr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fdr.c; sourceTree = ""; }; + 878587591D89D1C1008689F0 /* fdr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fdr.h; sourceTree = ""; }; + 8785875A1D89D1C1008689F0 /* fls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fls.c; sourceTree = ""; }; + 8785875B1D89D1C1008689F0 /* fls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fls.h; sourceTree = ""; }; + 8785875C1D89D1C1008689F0 /* idevicerestore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = idevicerestore.c; sourceTree = ""; }; + 8785875D1D89D1C1008689F0 /* idevicerestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = idevicerestore.h; sourceTree = ""; }; + 8785875E1D89D1C1008689F0 /* img3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = img3.c; sourceTree = ""; }; + 8785875F1D89D1C1008689F0 /* img3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = img3.h; sourceTree = ""; }; + 878587601D89D1C1008689F0 /* img4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = img4.c; sourceTree = ""; }; + 878587611D89D1C1008689F0 /* img4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = img4.h; sourceTree = ""; }; + 878587621D89D1C1008689F0 /* ipsw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ipsw.c; sourceTree = ""; }; + 878587631D89D1C1008689F0 /* ipsw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipsw.h; sourceTree = ""; }; + 878587641D89D1C1008689F0 /* limera1n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = limera1n.c; sourceTree = ""; }; + 878587651D89D1C1008689F0 /* limera1n.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = limera1n.h; sourceTree = ""; }; + 878587661D89D1C1008689F0 /* limera1n_payload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = limera1n_payload.h; sourceTree = ""; }; + 878587671D89D1C1008689F0 /* locking.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locking.c; sourceTree = ""; }; + 878587681D89D1C1008689F0 /* locking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = locking.h; sourceTree = ""; }; + 8785876A1D89D1C1008689F0 /* mbn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mbn.c; sourceTree = ""; }; + 8785876B1D89D1C1008689F0 /* mbn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mbn.h; sourceTree = ""; }; + 8785876C1D89D1C1008689F0 /* normal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = normal.c; sourceTree = ""; }; + 8785876D1D89D1C1008689F0 /* normal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = normal.h; sourceTree = ""; }; + 8785876E1D89D1C1008689F0 /* recovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = recovery.c; sourceTree = ""; }; + 8785876F1D89D1C1008689F0 /* recovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recovery.h; sourceTree = ""; }; + 878587701D89D1C1008689F0 /* restore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = restore.c; sourceTree = ""; }; + 878587711D89D1C1008689F0 /* restore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = restore.h; sourceTree = ""; }; + 878587721D89D1C1008689F0 /* socket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = socket.c; sourceTree = ""; }; + 878587731D89D1C1008689F0 /* socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = socket.h; sourceTree = ""; }; + 878587741D89D1C1008689F0 /* thread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thread.c; sourceTree = ""; }; + 878587751D89D1C1008689F0 /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread.h; sourceTree = ""; }; + 878587761D89D1C1008689F0 /* tss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tss.c; sourceTree = ""; }; + 878587771D89D1C1008689F0 /* tss.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tss.h; sourceTree = ""; }; + 8785878C1D89D1ED008689F0 /* all_img4tool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = all_img4tool.h; sourceTree = ""; }; + 8785878E1D89D1ED008689F0 /* img4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = img4.c; sourceTree = ""; }; + 8785878F1D89D1ED008689F0 /* img4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = img4.h; sourceTree = ""; }; + 878587901D89D1ED008689F0 /* img4tool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = img4tool.c; sourceTree = ""; }; + 878587941D89D243008689F0 /* img4tool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = img4tool.h; sourceTree = ""; }; + 878587951D89D290008689F0 /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + 878587971D89D2BA008689F0 /* all_tsschecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = all_tsschecker.h; sourceTree = ""; }; + 878587981D89D2BA008689F0 /* download.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = download.c; sourceTree = ""; }; + 878587991D89D2BA008689F0 /* download.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = download.h; sourceTree = ""; }; + 8785879A1D89D2BA008689F0 /* jsmn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jsmn.c; sourceTree = ""; }; + 8785879B1D89D2BA008689F0 /* jsmn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsmn.h; sourceTree = ""; }; + 8785879F1D89D2BA008689F0 /* tsschecker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsschecker.c; sourceTree = ""; }; + 878587A01D89D2BA008689F0 /* tsschecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsschecker.h; sourceTree = ""; }; + 878587A61D89D56E008689F0 /* libplist.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libplist.3.dylib; path = ../../../../usr/local/lib/libplist.3.dylib; sourceTree = ""; }; + 878587A81D89D578008689F0 /* libirecovery.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libirecovery.1.dylib; path = ../../../../usr/local/lib/libirecovery.1.dylib; sourceTree = ""; }; + 878587AA1D89D590008689F0 /* libimobiledevice.6.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libimobiledevice.6.dylib; path = ../../../../usr/local/lib/libimobiledevice.6.dylib; sourceTree = ""; }; + 878587AC1D89D59E008689F0 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 878587AE1D89D5A5008689F0 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; + 878587B01D89D5B0008689F0 /* libcrypto.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcrypto.tbd; path = usr/lib/libcrypto.tbd; sourceTree = SDKROOT; }; + 878587B21D89D5D5008689F0 /* libzip.4.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libzip.4.dylib; path = ../../../../usr/local/lib/libzip.4.dylib; sourceTree = ""; }; + 878587B41D89D5E6008689F0 /* libpartialzip-1.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libpartialzip-1.0.0.dylib"; path = "../../../../usr/local/lib/libpartialzip-1.0.0.dylib"; sourceTree = ""; }; + 878587B61D89D637008689F0 /* libirecovery.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libirecovery.2.dylib; path = ../../../../usr/local/lib/libirecovery.2.dylib; sourceTree = ""; }; + 8799B0B01D89D99D002F4D5F /* futurerestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = futurerestore.cpp; sourceTree = ""; }; + 8799B0B11D89D99D002F4D5F /* futurerestore.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = futurerestore.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -32,6 +129,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 878587B71D89D637008689F0 /* libirecovery.2.dylib in Frameworks */, + 878587B51D89D5E6008689F0 /* libpartialzip-1.0.0.dylib in Frameworks */, + 878587B31D89D5D5008689F0 /* libzip.4.dylib in Frameworks */, + 878587B11D89D5B0008689F0 /* libcrypto.tbd in Frameworks */, + 878587AF1D89D5A5008689F0 /* libcurl.tbd in Frameworks */, + 878587AD1D89D59E008689F0 /* libz.tbd in Frameworks */, + 878587AB1D89D590008689F0 /* libimobiledevice.6.dylib in Frameworks */, + 878587A71D89D56E008689F0 /* libplist.3.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -41,6 +146,15 @@ 8785873A1D89CFDC008689F0 = { isa = PBXGroup; children = ( + 878587B61D89D637008689F0 /* libirecovery.2.dylib */, + 878587B41D89D5E6008689F0 /* libpartialzip-1.0.0.dylib */, + 878587B21D89D5D5008689F0 /* libzip.4.dylib */, + 878587B01D89D5B0008689F0 /* libcrypto.tbd */, + 878587AE1D89D5A5008689F0 /* libcurl.tbd */, + 878587AC1D89D59E008689F0 /* libz.tbd */, + 878587AA1D89D590008689F0 /* libimobiledevice.6.dylib */, + 878587A81D89D578008689F0 /* libirecovery.1.dylib */, + 878587A61D89D56E008689F0 /* libplist.3.dylib */, 878587451D89CFDC008689F0 /* futurerestore */, 878587441D89CFDC008689F0 /* Products */, ); @@ -57,11 +171,101 @@ 878587451D89CFDC008689F0 /* futurerestore */ = { isa = PBXGroup; children = ( + 878587951D89D290008689F0 /* config.h */, + 8785874D1D89D1A4008689F0 /* external */, + 8799B0B11D89D99D002F4D5F /* futurerestore.hpp */, + 8799B0B01D89D99D002F4D5F /* futurerestore.cpp */, 878587461D89CFDC008689F0 /* main.cpp */, ); path = futurerestore; sourceTree = ""; }; + 8785874D1D89D1A4008689F0 /* external */ = { + isa = PBXGroup; + children = ( + 878587961D89D2BA008689F0 /* tsschecker */, + 8785878B1D89D1ED008689F0 /* img4tool */, + 8785874E1D89D1C1008689F0 /* idevicerestore */, + ); + name = external; + sourceTree = ""; + }; + 8785874E1D89D1C1008689F0 /* idevicerestore */ = { + isa = PBXGroup; + children = ( + 8785874F1D89D1C1008689F0 /* asr.c */, + 878587501D89D1C1008689F0 /* asr.h */, + 878587511D89D1C1008689F0 /* common.c */, + 878587521D89D1C1008689F0 /* common.h */, + 878587531D89D1C1008689F0 /* dfu.c */, + 878587541D89D1C1008689F0 /* dfu.h */, + 878587551D89D1C1008689F0 /* download.c */, + 878587561D89D1C1008689F0 /* download.h */, + 878587571D89D1C1008689F0 /* endianness.h */, + 878587581D89D1C1008689F0 /* fdr.c */, + 878587591D89D1C1008689F0 /* fdr.h */, + 8785875A1D89D1C1008689F0 /* fls.c */, + 8785875B1D89D1C1008689F0 /* fls.h */, + 8785875C1D89D1C1008689F0 /* idevicerestore.c */, + 8785875D1D89D1C1008689F0 /* idevicerestore.h */, + 8785875E1D89D1C1008689F0 /* img3.c */, + 8785875F1D89D1C1008689F0 /* img3.h */, + 878587601D89D1C1008689F0 /* img4.c */, + 878587611D89D1C1008689F0 /* img4.h */, + 878587621D89D1C1008689F0 /* ipsw.c */, + 878587631D89D1C1008689F0 /* ipsw.h */, + 878587641D89D1C1008689F0 /* limera1n.c */, + 878587651D89D1C1008689F0 /* limera1n.h */, + 878587661D89D1C1008689F0 /* limera1n_payload.h */, + 878587671D89D1C1008689F0 /* locking.c */, + 878587681D89D1C1008689F0 /* locking.h */, + 8785876A1D89D1C1008689F0 /* mbn.c */, + 8785876B1D89D1C1008689F0 /* mbn.h */, + 8785876C1D89D1C1008689F0 /* normal.c */, + 8785876D1D89D1C1008689F0 /* normal.h */, + 8785876E1D89D1C1008689F0 /* recovery.c */, + 8785876F1D89D1C1008689F0 /* recovery.h */, + 878587701D89D1C1008689F0 /* restore.c */, + 878587711D89D1C1008689F0 /* restore.h */, + 878587721D89D1C1008689F0 /* socket.c */, + 878587731D89D1C1008689F0 /* socket.h */, + 878587741D89D1C1008689F0 /* thread.c */, + 878587751D89D1C1008689F0 /* thread.h */, + 878587761D89D1C1008689F0 /* tss.c */, + 878587771D89D1C1008689F0 /* tss.h */, + ); + name = idevicerestore; + path = external/idevicerestore/src; + sourceTree = SOURCE_ROOT; + }; + 8785878B1D89D1ED008689F0 /* img4tool */ = { + isa = PBXGroup; + children = ( + 8785878C1D89D1ED008689F0 /* all_img4tool.h */, + 8785878F1D89D1ED008689F0 /* img4.h */, + 8785878E1D89D1ED008689F0 /* img4.c */, + 878587941D89D243008689F0 /* img4tool.h */, + 878587901D89D1ED008689F0 /* img4tool.c */, + ); + name = img4tool; + path = external/img4tool/img4tool; + sourceTree = SOURCE_ROOT; + }; + 878587961D89D2BA008689F0 /* tsschecker */ = { + isa = PBXGroup; + children = ( + 878587971D89D2BA008689F0 /* all_tsschecker.h */, + 878587991D89D2BA008689F0 /* download.h */, + 878587981D89D2BA008689F0 /* download.c */, + 8785879B1D89D2BA008689F0 /* jsmn.h */, + 8785879A1D89D2BA008689F0 /* jsmn.c */, + 878587A01D89D2BA008689F0 /* tsschecker.h */, + 8785879F1D89D2BA008689F0 /* tsschecker.c */, + ); + name = tsschecker; + path = external/tsschecker/tsschecker; + sourceTree = SOURCE_ROOT; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -118,7 +322,32 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8799B0C11D89DB38002F4D5F /* fls.c in Sources */, + 8799B0B41D89DAF6002F4D5F /* tss.c in Sources */, + 8799B0C01D89DB38002F4D5F /* fdr.c in Sources */, + 8799B0BC1D89DB27002F4D5F /* ipsw.c in Sources */, + 8799B0CC1D89F7B9002F4D5F /* download.c in Sources */, + 8799B0B91D89DB0D002F4D5F /* img3.c in Sources */, + 8799B0B51D89DAFF002F4D5F /* common.c in Sources */, + 8799B0C41D89DB55002F4D5F /* mbn.c in Sources */, + 8799B0B81D89DAFF002F4D5F /* recovery.c in Sources */, + 8799B0B31D89DAE7002F4D5F /* idevicerestore.c in Sources */, + 8799B0C81D89E2BD002F4D5F /* img4tool.c in Sources */, + 8799B0BB1D89DB12002F4D5F /* download.c in Sources */, + 8799B0B71D89DAFF002F4D5F /* normal.c in Sources */, + 8799B0CD1D89F7B9002F4D5F /* jsmn.c in Sources */, + 8799B0C31D89DB4B002F4D5F /* socket.c in Sources */, + 8799B0C21D89DB46002F4D5F /* thread.c in Sources */, + 8799B0B61D89DAFF002F4D5F /* dfu.c in Sources */, + 8799B0BD1D89DB27002F4D5F /* limera1n.c in Sources */, + 8799B0C51D89DB67002F4D5F /* locking.c in Sources */, 878587471D89CFDC008689F0 /* main.cpp in Sources */, + 8799B0BF1D89DB38002F4D5F /* asr.c in Sources */, + 8799B0BE1D89DB27002F4D5F /* restore.c in Sources */, + 8799B0CB1D89F796002F4D5F /* tsschecker.c in Sources */, + 8799B0C91D89E2C3002F4D5F /* img4.c in Sources */, + 8799B0CA1D89E371002F4D5F /* img4.c in Sources */, + 8799B0B21D89D99D002F4D5F /* futurerestore.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -209,14 +438,24 @@ 8785874B1D89CFDC008689F0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + HEADER_SEARCH_PATHS = ""; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + OTHER_CFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "/usr/local/include /opt/local/include"; }; name = Debug; }; 8785874C1D89CFDC008689F0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + HEADER_SEARCH_PATHS = ""; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + OTHER_CFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "/usr/local/include /opt/local/include"; }; name = Release; }; @@ -239,6 +478,7 @@ 8785874C1D89CFDC008689F0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/futurerestore/config.h b/futurerestore/config.h new file mode 100644 index 00000000..35ee0b4d --- /dev/null +++ b/futurerestore/config.h @@ -0,0 +1,22 @@ +// +// config.h +// futurerestore +// +// Created by tihmstar on 04.09.16. +// Copyright © 2016 tihmstar. All rights reserved. +// + +#ifndef config_h +#define config_h + +#define IMG4TOOL_NOMAIN + + +//idevicerestore config +#define IDEVICERESTORE_NOMAIN +#define PACKAGE_URL "http://libimobiledevice.org" + + + + +#endif /* config_h */ diff --git a/futurerestore/futurerestore.cpp b/futurerestore/futurerestore.cpp new file mode 100644 index 00000000..bd79efc2 --- /dev/null +++ b/futurerestore/futurerestore.cpp @@ -0,0 +1,538 @@ +// +// futurerestore.cpp +// futurerestore +// +// Created by tihmstar on 14.09.16. +// Copyright © 2016 tihmstar. All rights reserved. +// + +#include +#include +#include +#include +#include +#include "futurerestore.hpp" +#include "common.h" +#include "all_tsschecker.h" +#include "../external/img4tool/img4tool/img4.h" +#include "img4tool.h" +#include "normal.h" +#include "recovery.h" +#include "ipsw.h" +#include "locking.h" +#include "restore.h" + +#define NONCESIZE 20 +#define USEC_PER_SEC 1000000 + +#define reterror(code,msg ...) error(msg),throw int(code) +#define safeFree(buf) if (buf) free(buf), buf = NULL +#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL + +futurerestore::futurerestore(){ + _client = idevicerestore_client_new(); + if (_client == NULL) throw std::string("could not create idevicerestore client\n"); + _didInit = false; + _apticket = NULL; + _im4m = NULL; +} + +bool futurerestore::init(){ + if (_didInit) return _didInit; + return _didInit = (check_mode(_client) != MODE_UNKNOWN); +} + +uint64_t futurerestore::getDeviceEcid(){ + if (!_didInit) reterror(-1, "did not init"); + uint64_t ecid; + + get_ecid(_client, &ecid); + + return ecid; +} + +int futurerestore::getDeviceMode(bool reRequest){ + if (!_didInit) reterror(-1, "did not init"); + if (!reRequest && _client->mode->index != MODE_UNKNOWN) { + return _client->mode->index; + }else{ + normal_client_free(_client); + recovery_client_free(_client); + return check_mode(_client); + } +} + +void futurerestore::putDeviceIntoRecovery(){ + if (!_didInit) reterror(-1, "did not init"); + + getDeviceMode(false); + info("Found device in %s mode\n", _client->mode->string); + if (_client->mode->index == MODE_NORMAL) { + 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); + } + }else if (_client->mode->index == MODE_RECOVERY){ + info("Device already in Recovery mode\n"); + }else{ + reterror(-3, "unsupported devicemode, please put device in recovery mode or normal mode\n"); + } + + free(_client->udid); + _client->udid = NULL; + normal_client_free(_client); + recovery_client_free(_client); +} + +void futurerestore::setAutoboot(bool val){ + if (!_didInit) reterror(-1, "did not init"); + + if (getDeviceMode(false) != MODE_RECOVERY){ + reterror(-2, "can't set autoboot, when device isn't in recovery mode\n"); + } + + if (_client->recovery || recovery_client_new(_client) == 0) { + if (recovery_set_autoboot(_client, val)){ + reterror(-3,"Setting auto-boot failed?!\n"); + } + } else { + reterror(-4,"Could not connect to device in recovery mode.\n"); + } +} + +bool futurerestore::nonceMatchesApTicket(){ + if (!_didInit) reterror(-1, "did not init"); + if (getDeviceMode(true) != MODE_RECOVERY) reterror(-10, "Device not in recovery mode, can't check apnonce\n"); + + unsigned char* realnonce; + int realNonceSize = 0; + recovery_get_ap_nonce(_client, &realnonce, &realNonceSize); + + return memcmp(realnonce, (unsigned const char*)getNonceFromIM4M(_im4m), realNonceSize) == 0; +} + +void futurerestore::waitForNonce(const char *nonce){ + if (!_didInit) reterror(-1, "did not init"); + setAutoboot(false); + + unsigned char* realnonce; + int realNonceSize = 0; + + info("waiting for nonce: "); + int i = 0; + for (i = 0; i < NONCESIZE; i++) { + info("%02x ", ((unsigned char *)nonce)[i]); + } + info("\n"); + + do { + if (realNonceSize){ + recovery_send_reset(_client); + recovery_client_free(_client); + usleep(1*USEC_PER_SEC); + } + while (getDeviceMode(true) != MODE_RECOVERY) usleep(USEC_PER_SEC*0.5); + if (recovery_client_new(_client)) reterror(-4,"Could not connect to device in recovery mode.\n"); + + recovery_get_ap_nonce(_client, &realnonce, &realNonceSize); + info("Got ApNonce from device: "); + int i = 0; + for (i = 0; i < realNonceSize; i++) { + info("%02x ", realnonce[i]); + } + info("\n"); + } while (memcmp(realnonce, (unsigned const char*)nonce, realNonceSize) != 0); + info("Device has requested ApNonce now\n"); + + setAutoboot(true); +} +void futurerestore::waitForNonce(){ + if (!_im4m) reterror(-1, "No IM4M loaded\n"); + waitForNonce(getNonceFromIM4M(_im4m)); +} + + +void futurerestore::loadAPTicket(const char *apticketPath){ + if (_apticket) plist_free(_apticket), _apticket = NULL; + FILE *f = fopen(apticketPath,"rb"); + fseek(f, 0, SEEK_END); + + size_t fSize = ftell(f); + fseek(f, 0, SEEK_SET); + char *buf = (char*)malloc(fSize); + fread(buf, fSize, 1, f); + fclose(f); + + if (memcmp(buf, "bplist00", 8) == 0) + plist_from_bin(buf, (uint32_t)fSize, &_apticket); + else + plist_from_xml(buf, (uint32_t)fSize, &_apticket); + + if (_im4m) free(_im4m); + + plist_t ticket = plist_dict_get_item(_apticket, "ApImg4Ticket"); + uint64_t im4msize=0; + plist_get_data_val(ticket, &_im4m, &im4msize); +} + +void futurerestore::loadAPTicket(string apticketPath){ + loadAPTicket(apticketPath.c_str()); +} + +int futurerestore::doRestore(const char *ipsw, bool noerase){ + int err = 0; + + struct idevicerestore_client_t* client = _client; + int unused; + int result = 0; + int delete_fs = 0; + char* filesystem = NULL; + plist_t buildmanifest = NULL; + plist_t sepbuildmanifest = NULL; + plist_t basebandbuildmanifest = NULL; + plist_t build_identity = NULL; + plist_t sep_build_identity = NULL; + plist_t bb_build_identity = NULL; + + client->ipsw = strdup(ipsw); + if (!noerase) client->flags |= FLAG_ERASE; + + getDeviceMode(true); + info("Found device in %s mode\n", client->mode->string); + if (client->mode->index != MODE_RECOVERY) reterror(-6, "device not in 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); + + if (!nonceMatchesApTicket()) reterror(-20, "Devicenonce does not match APTicket nonce\n"); + + + // 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"); + + client->tss = _apticket; + plist_dict_remove_item(client->tss, "BBTicket"); + plist_dict_remove_item(client->tss, "BasebandFirmware"); + + if (noerase) { + build_identity = build_manifest_get_build_identity_for_model_with_restore_behavior(buildmanifest, client->device->hardware_model, "Update"); + if (!build_identity) { + build_identity = build_manifest_get_build_identity_for_model(buildmanifest, client->device->hardware_model); + } + }else{ + build_identity = build_manifest_get_build_identity_for_model_with_restore_behavior(buildmanifest, client->device->hardware_model, "Erase"); + if (build_identity == NULL) { + reterror(-5,"ERROR: Unable to find any build identities\n"); + } + } + + sepbuildmanifest = loadPlistFromFile(_sepManifestPath); + sep_build_identity = build_manifest_get_build_identity_for_model_with_restore_behavior(sepbuildmanifest, client->device->hardware_model, "Erase"); + if (sep_build_identity == NULL) { + reterror(-5,"ERROR: Unable to find any build identities for sep\n"); + } + + basebandbuildmanifest = loadPlistFromFile(_basebandManifestPath); + bb_build_identity = build_manifest_get_build_identity_for_model_with_restore_behavior(basebandbuildmanifest, client->device->hardware_model, "Erase"); + if (bb_build_identity == NULL) { + reterror(-5,"ERROR: Unable to find any build identities for baseband\n"); + } + + + plist_t bb_manifest = plist_dict_get_item(bb_build_identity, "Manifest"); + + plist_t bb_baseband = plist_copy(plist_dict_get_item(bb_manifest, "BasebandFirmware")); + + plist_t info = plist_dict_get_item(build_identity, "Info"); + plist_t manifest = plist_dict_get_item(info, "Manifest"); + + plist_dict_set_item(manifest, "BasebandFirmware", bb_baseband); + + client->bbfwtmp = (char*)_basebandPath; + + + /* print information about current build identity */ + build_identity_print_information(build_identity); + + // Get filesystem name from build identity + char* fsname = NULL; + if (build_identity_get_component_path(build_identity, "OS", &fsname) < 0) { + error("ERROR: Unable get path for filesystem component\n"); + return -1; + } + + // check if we already have an extracted filesystem + struct stat st; + memset(&st, '\0', sizeof(struct stat)); + char tmpf[1024]; + if (client->cache_dir) { + if (stat(client->cache_dir, &st) < 0) { + mkdir_with_parents(client->cache_dir, 0755); + } + strcpy(tmpf, client->cache_dir); + strcat(tmpf, "/"); + char *ipswtmp = strdup(client->ipsw); + strcat(tmpf, basename(ipswtmp)); + free(ipswtmp); + } else { + strcpy(tmpf, client->ipsw); + } + char* p = strrchr((const char*)tmpf, '.'); + if (p) { + *p = '\0'; + } + + if (stat(tmpf, &st) < 0) { + __mkdir(tmpf, 0755); + } + strcat(tmpf, "/"); + strcat(tmpf, fsname); + + memset(&st, '\0', sizeof(struct stat)); + if (stat(tmpf, &st) == 0) { + off_t fssize = 0; + ipsw_get_file_size(client->ipsw, fsname, &fssize); + if ((fssize > 0) && (st.st_size == fssize)) { + info("Using cached filesystem from '%s'\n", tmpf); + filesystem = strdup(tmpf); + } + } + + if (!filesystem) { + char extfn[1024]; + strcpy(extfn, tmpf); + strcat(extfn, ".extract"); + char lockfn[1024]; + strcpy(lockfn, tmpf); + strcat(lockfn, ".lock"); + lock_info_t li; + + lock_file(lockfn, &li); + FILE* extf = NULL; + if (access(extfn, F_OK) != 0) { + extf = fopen(extfn, "w"); + } + unlock_file(&li); + if (!extf) { + // use temp filename + filesystem = tempnam(NULL, "ipsw_"); + if (!filesystem) { + error("WARNING: Could not get temporary filename, using '%s' in current directory\n", fsname); + filesystem = strdup(fsname); + } + delete_fs = 1; + } else { + // use .extract as filename + filesystem = strdup(extfn); + fclose(extf); + } + remove(lockfn); + + // Extract filesystem from IPSW + info("Extracting filesystem from IPSW\n"); + if (ipsw_extract_to_file_with_progress(client->ipsw, fsname, filesystem, 1) < 0) { + reterror(-7,"ERROR: Unable to extract filesystem from IPSW\n"); + } + + if (strstr(filesystem, ".extract")) { + // rename .extract to + remove(tmpf); + rename(filesystem, tmpf); + free(filesystem); + filesystem = strdup(tmpf); + } + } + + if ((client->build_major > 8)) { + if (!client->image4supported) { + /* send ApTicket */ + if (recovery_send_ticket(client) < 0) { + error("WARNING: Unable to send APTicket\n"); + } + } + } + + /* now we load the iBEC */ + if (recovery_send_ibec(client, build_identity) < 0) { + reterror(-8,"ERROR: Unable to send iBEC\n"); + } + recovery_client_free(client); + + /* this must be long enough to allow the device to run the iBEC */ + /* FIXME: Probably better to detect if the device is back then */ + sleep(7); + + check_mode(client); + + //do magic + get_sep_nonce(client, &client->sepnonce, &client->sepnonce_size); + get_ap_nonce(client, &client->nonce, &client->nonce_size); + get_ecid(client, &client->ecid); + if (client->mode->index == MODE_RECOVERY) { + if (client->srnm == NULL) { + reterror(-9,"ERROR: could not retrieve device serial number. Can't continue.\n"); + } + if (recovery_enter_restore(client, build_identity) < 0) { + reterror(-10,"ERROR: Unable to place device into restore mode\n"); + } + recovery_client_free(client); + } + + + if (get_tss_response(client, sep_build_identity, &client->septss) < 0) { + reterror(-11,"ERROR: Unable to get SHSH blobs for SEP\n"); + } + + FILE *fsep = fopen(_sepPath, "r"); + fseek(fsep, 0, SEEK_END); + client->sepfwdatasize = ftell(fsep); + fseek(fsep, 0, SEEK_SET); + client->sepfwdata = (char*)malloc(client->sepfwdatasize); + fread(client->sepfwdata, 1, client->sepfwdatasize, fsep); + fclose(fsep); + + + if (client->mode->index == MODE_RESTORE) { + info("About to restore device... \n"); + result = restore_device(client, build_identity, filesystem); + if (result < 0) { + reterror(-11,"ERROR: Unable to restore device\n"); + } + } + + info("Cleaning up...\n"); + + +error: + safeFree(client->sepfwdata); + safePlistFree(buildmanifest); + safePlistFree(sepbuildmanifest); + safePlistFree(basebandbuildmanifest); + safePlistFree(build_identity); + safePlistFree(sep_build_identity); + safePlistFree(bb_build_identity); + if (delete_fs && filesystem) unlink(filesystem); + if (!result && !err) info("DONE\n"); + return result ? abs(result) : err; +} + + +futurerestore::~futurerestore(){ + idevicerestore_client_free(_client); + safeFree(_im4m); + safePlistFree(_apticket); +} + +#pragma mark static methods + +char *futurerestore::getNonceFromIM4M(const char* im4m){ + char *ret = NULL; + t_asn1Tag *mainSet = NULL; + t_asn1Tag *manbSet = NULL; + t_asn1Tag *manpSet = NULL; + char *nonceOctet = NULL; + char *bnch = NULL; + char *manb = NULL; + char *manp = NULL; + + if (!im4m) reterror(-15, "Got empty IM4M\n"); + + if (asn1ElementsInObject(im4m)< 3){ + error("unexpected number of Elements in IM4M sequence\n"); + goto error; + } + mainSet = asn1ElementAtIndex(im4m, 2); + + manb = getValueForTagInSet((char*)mainSet, 0x4d414e42); //MANB priv Tag + if (asn1ElementsInObject(manb)< 2){ + error("unexpected number of Elements in MANB sequence\n"); + goto error; + } + manbSet = asn1ElementAtIndex(manb, 1); + + manp = getValueForTagInSet((char*)manbSet, 0x4d414e50); //MANP priv Tag + if (asn1ElementsInObject(manp)< 2){ + error("unexpected number of Elements in MANP sequence\n"); + goto error; + } + manpSet = asn1ElementAtIndex(manp, 1); + + bnch = getValueForTagInSet((char*)manpSet, 0x424e4348); //BNCH priv Tag + if (asn1ElementsInObject(bnch)< 2){ + error("unexpected number of Elements in BNCH sequence\n"); + goto error; + } + nonceOctet = (char*)asn1ElementAtIndex(bnch, 1); + + ret = (char*)malloc(NONCESIZE); + if (ret){ + nonceOctet++; + memcpy(ret, nonceOctet + asn1Len(nonceOctet).sizeBytes, NONCESIZE); + } + + +error: + return ret; + +} + +char *futurerestore::getNonceFromAPTicket(const char* apticketPath){ + char *ret = NULL; + if (char *im4m = im4mFormShshFile(apticketPath)){ + ret = getNonceFromIM4M(im4m); + free(im4m); + } + return ret; +} + +plist_t futurerestore::loadPlistFromFile(const char *path){ + plist_t ret = NULL; + + FILE *f = fopen(path,"rb"); + if (!f){ + error("could not open file %s\n",path); + return NULL; + } + fseek(f, 0, SEEK_END); + size_t bufSize = ftell(f); + fseek(f, 0, SEEK_SET); + + char *buf = (char*)malloc(bufSize); + if (!buf){ + error("failed to alloc memory\n"); + return NULL; + } + + fread(buf, 1, bufSize, f); + fclose(f); + + if (memcmp(buf, "bplist00", 8) == 0) + plist_from_bin(buf, (uint32_t)bufSize, &ret); + else + plist_from_xml(buf, (uint32_t)bufSize, &ret); + free(buf); + + return ret; +} + diff --git a/futurerestore/futurerestore.hpp b/futurerestore/futurerestore.hpp new file mode 100644 index 00000000..d89a678b --- /dev/null +++ b/futurerestore/futurerestore.hpp @@ -0,0 +1,62 @@ +// +// futurerestore.hpp +// futurerestore +// +// Created by tihmstar on 14.09.16. +// Copyright © 2016 tihmstar. All rights reserved. +// + +#ifndef futurerestore_hpp +#define futurerestore_hpp + +#include "config.h" +#include +#include "idevicerestore.h" + +using namespace std; + +class futurerestore { + struct idevicerestore_client_t* _client; + bool _didInit; + plist_t _apticket; + char *_im4m; + + const char *_sepManifestPath; + const char *_basebandManifestPath; + const char *_sepPath; + const char *_basebandPath; + +public: + futurerestore(); + bool init(); + int getDeviceMode(bool reRequest); + uint64_t getDeviceEcid(); + void putDeviceIntoRecovery(); + void setAutoboot(bool val); + void waitForNonce(); + void waitForNonce(const char *nonce); + void loadAPTicket(const char *apticketPath); + void loadAPTicket(string apticketPath); + + bool nonceMatchesApTicket(); + + + void setSepManifestPath(const char *sepManifestPath){_sepManifestPath = sepManifestPath;}; + void setBasebandManifestPath(const char *basebandManifestPath){_basebandManifestPath = basebandManifestPath;}; + void setSepPath(const char *sepPath){_sepPath = sepPath;}; + void setBasebandPath(const char *basebandPath){_basebandPath = basebandPath;}; + + int doRestore(const char *ipsw, bool noerase); + + ~futurerestore(); + + static char *getNonceFromIM4M(const char* im4m); + static char *getNonceFromAPTicket(const char* apticketPath); + static plist_t loadPlistFromFile(const char *path); + +}; + + + + +#endif /* futurerestore_hpp */ diff --git a/futurerestore/main.cpp b/futurerestore/main.cpp index d748042d..4159b4f2 100644 --- a/futurerestore/main.cpp +++ b/futurerestore/main.cpp @@ -1,4 +1,4 @@ -// + // main.cpp // futurerestore // @@ -7,9 +7,163 @@ // #include +#include +#include "futurerestore.hpp" +#include "all_tsschecker.h" +#include "tsschecker.h" -int main(int argc, const char * argv[]) { - // insert code here... - std::cout << "Hello, World!\n"; - return 0; +#define safeFree(buf) if (buf) free(buf), buf = NULL +#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL + +static struct option longopts[] = { + { "apticket", required_argument, NULL, 't' }, + { "baseband", required_argument, NULL, 'b' }, + { "baseband-plist", required_argument, NULL, 'p' }, + { "sep", required_argument, NULL, 's' }, + { "sep-manifest", required_argument, NULL, 'm' }, + { "wait", no_argument, NULL, 'w' }, + { "update", no_argument, NULL, 'u' }, + { "debug", no_argument, NULL, 'd' }, + { NULL, 0, NULL, 0 } +}; + +#define FLAG_WAIT 1 << 0 +#define FLAG_UPDATE 1 << 1 + +void cmd_help(){ + printf("Usage: futurerestore [OPTIONS] IPSW\n"); + printf("Allows restoring nonmatching iOS/Sep/Baseband\n\n"); + + printf(" -t, --apticket PATH\t\tApticket used for restoring\n"); + printf(" -b, --baseband PATH\t\tBaseband to be flashed\n"); + printf(" -p, --baseband-manifest PATH\t\tBuildmanifest for requesting baseband ticket\n"); + printf(" -s, --sep PATH\t\tSep to be flashed\n"); + printf(" -m, --sep-manifest PATH\t\tBuildmanifest for requesting sep ticket\n"); + printf(" -w, --wait\t\tkeep rebooting until nonce matches APTicket\n"); + printf(" -u, --update\t\tupdate instead of erase install\n"); + printf("\n"); +} + +using namespace std; +int main(int argc, const char * argv[]) { +#define reterror(code,a ...) do {error(a); err = code; goto error;} while (0) + int err=0; + int res = 0; + + int optindex = 0; + int opt = 0; + long flags = 0; + + int isSepManifestSigned = 0; + int isBasebandSigned = 0; + + const char *ipsw = NULL; + const char *apticketPath = NULL; + const char *basebandPath = NULL; + const char *basebandManifestPath = NULL; + const char *sepPath = NULL; + const char *sepManifestPath = NULL; + + + t_devicevals devVals; + t_iosVersion versVals; + memset(&devVals, 0, sizeof(devVals)); + memset(&versVals, 0, sizeof(versVals)); + + if (argc == 1){ + cmd_help(); + return -1; + } + + while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wud", longopts, &optindex)) > 0) { + switch (opt) { + case 't': // long option: "apticket"; can be called as short option + apticketPath = optarg; + break; + case 'b': // long option: "baseband"; can be called as short option + basebandPath = optarg; + break; + case 'p': // long option: "baseband-plist"; can be called as short option + basebandManifestPath = optarg; + break; + case 's': // long option: "sep"; can be called as short option + sepPath = optarg; + break; + case 'm': // long option: "sep-manifest"; can be called as short option + sepManifestPath = optarg; + break; + case 'w': // long option: "wait"; can be called as short option + flags |= FLAG_WAIT; + break; + case 'u': // long option: "update"; can be called as short option + flags |= FLAG_UPDATE; + break; + case 'd': // long option: "debug"; can be called as short option + idevicerestore_debug = 1; + break; + default: + cmd_help(); + return -1; + } + } + if (argc-optind == 1) { + argc -= optind; + argv += optind; + + ipsw = argv[0]; + } + + futurerestore client; + client.init(); + + if (apticketPath) client.loadAPTicket(apticketPath); + + if (flags & FLAG_WAIT){ + client.putDeviceIntoRecovery(); + client.waitForNonce(); + } + if (!(apticketPath && basebandPath && basebandManifestPath && sepPath && sepManifestPath && ipsw)) { + if (!(flags & FLAG_WAIT) || ipsw){ + error("missing argument\n"); + cmd_help(); + err = -2; + }else{ + info("done\n"); + } + goto error; + } + + + versVals.basebandMode = kBasebandModeWithoutBaseband; + if (!(isSepManifestSigned = isManifestSignedForDevice(sepManifestPath, NULL, devVals, versVals))){ + reterror(-3,"sep firmware isn't signed\n"); + } + + versVals.basebandMode = kBasebandModeOnlyBaseband; + if (!(isBasebandSigned = isManifestSignedForDevice(basebandManifestPath, NULL, devVals, versVals))){ + reterror(-3,"baseband firmware isn't signed\n"); + } + + client.setSepPath(sepPath); + client.setSepManifestPath(sepManifestPath); + client.setBasebandPath(basebandPath); + client.setBasebandManifestPath(basebandManifestPath); + + + client.putDeviceIntoRecovery(); + + try { + res = client.doRestore(ipsw, flags & FLAG_UPDATE); + } catch (int error) { + if (error == -20) error("maybe you forgot -w ?\n"); + err = error; + } + + cout << "Done: restoring "<< (res ? "succeeded" : "failed"); + if (!res) cout << ". Errorcode="<