├── README.md ├── otachecker.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── tihmstar.xcuserdatad │ └── xcschemes │ ├── otachecker.xcscheme │ └── xcschememanagement.plist └── otachecker └── main.m /README.md: -------------------------------------------------------------------------------- 1 | quick and dirty tool to check what ota blobs are currently being signed by apple 2 | 3 | run "otachecker" to get a list of signed iOS versions/devices 4 | or run "otachecker -h" for help 5 | 6 | "otachecker -u -d iPhone4,1 -i 6.1.3" prints you a link where to get otazip for iPhone4,1 6.1.3 7 | -------------------------------------------------------------------------------- /otachecker.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8730E5D01BD810FD00D4B62A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8730E5CF1BD810FD00D4B62A /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 8730E5CA1BD810FD00D4B62A /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 8730E5CC1BD810FD00D4B62A /* otachecker */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = otachecker; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 8730E5CF1BD810FD00D4B62A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 8730E5C91BD810FD00D4B62A /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 8730E5C31BD810FD00D4B62A = { 42 | isa = PBXGroup; 43 | children = ( 44 | 8730E5CE1BD810FD00D4B62A /* otachecker */, 45 | 8730E5CD1BD810FD00D4B62A /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 8730E5CD1BD810FD00D4B62A /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 8730E5CC1BD810FD00D4B62A /* otachecker */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 8730E5CE1BD810FD00D4B62A /* otachecker */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 8730E5CF1BD810FD00D4B62A /* main.m */, 61 | ); 62 | path = otachecker; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 8730E5CB1BD810FD00D4B62A /* otachecker */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 8730E5D31BD810FD00D4B62A /* Build configuration list for PBXNativeTarget "otachecker" */; 71 | buildPhases = ( 72 | 8730E5C81BD810FD00D4B62A /* Sources */, 73 | 8730E5C91BD810FD00D4B62A /* Frameworks */, 74 | 8730E5CA1BD810FD00D4B62A /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = otachecker; 81 | productName = otachecker; 82 | productReference = 8730E5CC1BD810FD00D4B62A /* otachecker */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 8730E5C41BD810FD00D4B62A /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0700; 92 | ORGANIZATIONNAME = tihmstar; 93 | TargetAttributes = { 94 | 8730E5CB1BD810FD00D4B62A = { 95 | CreatedOnToolsVersion = 7.0; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = 8730E5C71BD810FD00D4B62A /* Build configuration list for PBXProject "otachecker" */; 100 | compatibilityVersion = "Xcode 3.2"; 101 | developmentRegion = English; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | ); 106 | mainGroup = 8730E5C31BD810FD00D4B62A; 107 | productRefGroup = 8730E5CD1BD810FD00D4B62A /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 8730E5CB1BD810FD00D4B62A /* otachecker */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 8730E5C81BD810FD00D4B62A /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 8730E5D01BD810FD00D4B62A /* main.m in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 8730E5D11BD810FD00D4B62A /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 133 | CLANG_CXX_LIBRARY = "libc++"; 134 | CLANG_ENABLE_MODULES = YES; 135 | CLANG_ENABLE_OBJC_ARC = YES; 136 | CLANG_WARN_BOOL_CONVERSION = YES; 137 | CLANG_WARN_CONSTANT_CONVERSION = YES; 138 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 139 | CLANG_WARN_EMPTY_BODY = YES; 140 | CLANG_WARN_ENUM_CONVERSION = YES; 141 | CLANG_WARN_INT_CONVERSION = YES; 142 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 143 | CLANG_WARN_UNREACHABLE_CODE = YES; 144 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 145 | COPY_PHASE_STRIP = NO; 146 | DEBUG_INFORMATION_FORMAT = dwarf; 147 | ENABLE_STRICT_OBJC_MSGSEND = YES; 148 | ENABLE_TESTABILITY = YES; 149 | GCC_C_LANGUAGE_STANDARD = gnu99; 150 | GCC_DYNAMIC_NO_PIC = NO; 151 | GCC_NO_COMMON_BLOCKS = YES; 152 | GCC_OPTIMIZATION_LEVEL = 0; 153 | GCC_PREPROCESSOR_DEFINITIONS = ( 154 | "DEBUG=1", 155 | "$(inherited)", 156 | ); 157 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 158 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 159 | GCC_WARN_UNDECLARED_SELECTOR = YES; 160 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 161 | GCC_WARN_UNUSED_FUNCTION = YES; 162 | GCC_WARN_UNUSED_VARIABLE = YES; 163 | MACOSX_DEPLOYMENT_TARGET = 10.10; 164 | MTL_ENABLE_DEBUG_INFO = YES; 165 | ONLY_ACTIVE_ARCH = YES; 166 | SDKROOT = macosx; 167 | }; 168 | name = Debug; 169 | }; 170 | 8730E5D21BD810FD00D4B62A /* Release */ = { 171 | isa = XCBuildConfiguration; 172 | buildSettings = { 173 | ALWAYS_SEARCH_USER_PATHS = NO; 174 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 175 | CLANG_CXX_LIBRARY = "libc++"; 176 | CLANG_ENABLE_MODULES = YES; 177 | CLANG_ENABLE_OBJC_ARC = YES; 178 | CLANG_WARN_BOOL_CONVERSION = YES; 179 | CLANG_WARN_CONSTANT_CONVERSION = YES; 180 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 181 | CLANG_WARN_EMPTY_BODY = YES; 182 | CLANG_WARN_ENUM_CONVERSION = YES; 183 | CLANG_WARN_INT_CONVERSION = YES; 184 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 185 | CLANG_WARN_UNREACHABLE_CODE = YES; 186 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 187 | COPY_PHASE_STRIP = NO; 188 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 189 | ENABLE_NS_ASSERTIONS = NO; 190 | ENABLE_STRICT_OBJC_MSGSEND = YES; 191 | GCC_C_LANGUAGE_STANDARD = gnu99; 192 | GCC_NO_COMMON_BLOCKS = YES; 193 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 194 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 195 | GCC_WARN_UNDECLARED_SELECTOR = YES; 196 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 197 | GCC_WARN_UNUSED_FUNCTION = YES; 198 | GCC_WARN_UNUSED_VARIABLE = YES; 199 | MACOSX_DEPLOYMENT_TARGET = 10.10; 200 | MTL_ENABLE_DEBUG_INFO = NO; 201 | SDKROOT = macosx; 202 | }; 203 | name = Release; 204 | }; 205 | 8730E5D41BD810FD00D4B62A /* Debug */ = { 206 | isa = XCBuildConfiguration; 207 | buildSettings = { 208 | PRODUCT_NAME = "$(TARGET_NAME)"; 209 | }; 210 | name = Debug; 211 | }; 212 | 8730E5D51BD810FD00D4B62A /* Release */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | PRODUCT_NAME = "$(TARGET_NAME)"; 216 | }; 217 | name = Release; 218 | }; 219 | /* End XCBuildConfiguration section */ 220 | 221 | /* Begin XCConfigurationList section */ 222 | 8730E5C71BD810FD00D4B62A /* Build configuration list for PBXProject "otachecker" */ = { 223 | isa = XCConfigurationList; 224 | buildConfigurations = ( 225 | 8730E5D11BD810FD00D4B62A /* Debug */, 226 | 8730E5D21BD810FD00D4B62A /* Release */, 227 | ); 228 | defaultConfigurationIsVisible = 0; 229 | defaultConfigurationName = Release; 230 | }; 231 | 8730E5D31BD810FD00D4B62A /* Build configuration list for PBXNativeTarget "otachecker" */ = { 232 | isa = XCConfigurationList; 233 | buildConfigurations = ( 234 | 8730E5D41BD810FD00D4B62A /* Debug */, 235 | 8730E5D51BD810FD00D4B62A /* Release */, 236 | ); 237 | defaultConfigurationIsVisible = 0; 238 | }; 239 | /* End XCConfigurationList section */ 240 | }; 241 | rootObject = 8730E5C41BD810FD00D4B62A /* Project object */; 242 | } 243 | -------------------------------------------------------------------------------- /otachecker.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /otachecker.xcodeproj/xcuserdata/tihmstar.xcuserdatad/xcschemes/otachecker.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /otachecker.xcodeproj/xcuserdata/tihmstar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | otachecker.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8730E5CB1BD810FD00D4B62A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /otachecker/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // otachecker 4 | // 5 | // Created by tihmstar on 21.10.15. 6 | // Copyright © 2015 tihmstar. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | void printOtas(NSDictionary *softwareupdates){ 12 | NSMutableDictionary *res = [NSMutableDictionary new]; 13 | printf("checking what ota versions are being signed\n"); 14 | NSArray *otas = [softwareupdates valueForKey:@"Assets"]; 15 | 16 | for (NSDictionary *obj in otas) { 17 | id allowableOTA; 18 | if ((allowableOTA = [obj valueForKey:@"AllowableOTA"]) && [allowableOTA boolValue] == FALSE) continue; 19 | 20 | NSString *version = [obj valueForKey:@"OSVersion"]; 21 | NSArray *devices = [obj valueForKey:@"SupportedDevices"]; 22 | 23 | NSMutableArray *resdevs = [res valueForKey:version]; 24 | if (!resdevs) resdevs = [NSMutableArray new]; 25 | 26 | for (NSString *dev in devices) if (![resdevs containsObject:dev]) [resdevs addObject:dev]; 27 | 28 | [res setValue:resdevs forKey:version]; 29 | } 30 | 31 | printf("Apple currently signs following ota firmwares:\n"); 32 | for (NSString *key in [[res allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]) { 33 | NSArray *devs = [res valueForKey:key]; 34 | printf("[iOS %s]:\n",[key UTF8String]); 35 | 36 | char currentDevice[0x100]; 37 | memset(currentDevice, 0, 0x100); 38 | 39 | for (NSString *device in [devs sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]) { 40 | const char *c_device = [device UTF8String]; 41 | if (*currentDevice != '\0' && strncmp(currentDevice, c_device, strlen(currentDevice)) != 0){ 42 | memset(currentDevice, 0, 0x100); 43 | printf("\n"); 44 | } 45 | 46 | if (*currentDevice == '\0') { 47 | int i = 0; 48 | while (isalpha(c_device[(i = (int)strlen(currentDevice))])) currentDevice[i] = c_device[i]; 49 | } 50 | 51 | printf("%s ",c_device); 52 | } 53 | printf("\n\n"); 54 | } 55 | printf("\n"); 56 | } 57 | 58 | void printhelp(){ 59 | printf("otachecker:\n"); 60 | printf("default (no args): shows what ota firmware is signed for which devices\n"); 61 | printf(" -h\t\tshows this help\n"); 62 | printf(" -d\t\tset devices (for -u)\n"); 63 | printf(" -i\t\tset ios version (for -u)\n"); 64 | printf(" -u\t\tprints url of ota zip (requires -i and -d)\n"); 65 | printf("\n\n"); 66 | } 67 | 68 | void printURL(NSString *device, NSString *ios, NSDictionary *softwareupdates){ 69 | NSArray *otas = [softwareupdates valueForKey:@"Assets"]; 70 | 71 | printf("checking ota url for %s %s\n",[device UTF8String],[ios UTF8String]); 72 | 73 | for (NSDictionary *obj in otas) { 74 | NSString *version = [obj valueForKey:@"OSVersion"]; 75 | NSArray *devices = [obj valueForKey:@"SupportedDevices"]; 76 | 77 | if ([version isEqualToString:ios]) { 78 | if ([devices containsObject:device]) { 79 | NSString *url = [[obj valueForKey:@"__BaseURL"] stringByAppendingString:[obj valueForKey:@"__RelativePath"]]; 80 | printf("ota url for %s %s: %s",[device UTF8String],[ios UTF8String],[url UTF8String]); 81 | exit(0); 82 | } 83 | } 84 | } 85 | printf("ota for %s %s is not signed\n",[device UTF8String],[ios UTF8String]); 86 | } 87 | 88 | int main(int argc, const char * argv[]) { 89 | @autoreleasepool { 90 | printf("downloading com_apple_MobileAsset_SoftwareUpdate.xml\n"); 91 | NSDictionary *softwareupdates = [[NSDictionary alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://mesu.apple.com/assets/com_apple_MobileAsset_SoftwareUpdate/com_apple_MobileAsset_SoftwareUpdate.xml"]]; 92 | 93 | BOOL wantsURL = false; 94 | NSString *device; 95 | NSString *ios; 96 | 97 | char c; 98 | if (argc == 1) { 99 | printOtas(softwareupdates); 100 | exit(0); 101 | } 102 | 103 | while ((c = getopt (argc, argv, "hui:d:")) != -1){ 104 | switch (c){ 105 | case 'h': 106 | printhelp(); 107 | break; 108 | 109 | case 'd': 110 | device = [[NSString alloc] initWithCString:optarg encoding:NSUTF8StringEncoding]; 111 | break; 112 | 113 | case 'i': 114 | ios = [[NSString alloc] initWithCString:optarg encoding:NSUTF8StringEncoding]; 115 | break; 116 | 117 | case 'u': 118 | wantsURL = TRUE; 119 | break; 120 | 121 | case '?': 122 | if (optopt == 'd' || optopt == 'i'){ 123 | printf("Error: %c requires argument\n",optopt); 124 | 125 | } 126 | exit(1); 127 | break; 128 | 129 | default: 130 | printOtas(softwareupdates); 131 | exit(0); 132 | } 133 | } 134 | 135 | if (wantsURL){ 136 | if (!device || !ios) { 137 | printf("Error: -d and -i required for -u\n"); 138 | exit(1); 139 | } 140 | printURL(device,ios,softwareupdates); 141 | } 142 | 143 | } 144 | return 0; 145 | } 146 | 147 | 148 | 149 | 150 | 151 | --------------------------------------------------------------------------------