├── .gitmodules ├── README.md ├── offsetfinder.xcodeproj └── project.pbxproj └── offsetfinder ├── machoman ├── machoman.c └── machoman.h ├── main.cpp ├── offsetfinder.c ├── offsetfinder.h └── patchfinder32 ├── patchfinder32.c └── patchfinder32.h /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/jssy"] 2 | path = external/jssy 3 | url = https://github.com/tihmstar/jssy 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # offsetfinder 2 | A simple tool to find offsets needed in 32bit jailbreaks. Feel free to contribute. 3 | 4 | ### How to use 5 | ``` 6 | ./offsetfinder [iOS BuildID] (device1 device2 device3 ...) 7 | ``` 8 | 9 | ### Notes 10 | Only works on 32bit kernelcaches (obviously). Didn't do a lot of testing, so stuff may happen. Also not sure all offsets needed are included. 11 | Pull requests are appreciated! 12 | 13 | *Important:* will not work on dumps/runtime kernel as it is, since it relies on symbols that get stripped at runtime. 14 | -------------------------------------------------------------------------------- /offsetfinder.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 872EDD281F6B3CEE00C153B3 /* offsetfinder.c in Sources */ = {isa = PBXBuildFile; fileRef = 87ECBF5E1F6A6F9F00D3E102 /* offsetfinder.c */; }; 11 | 872EDD2B1F6B3DC100C153B3 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 872EDD2A1F6B3DC100C153B3 /* main.cpp */; }; 12 | 873B54DA1F6A713D00E6EA7B /* patchfinder32.c in Sources */ = {isa = PBXBuildFile; fileRef = 873B54D81F6A713D00E6EA7B /* patchfinder32.c */; }; 13 | 873B54DE1F6A716600E6EA7B /* machoman.c in Sources */ = {isa = PBXBuildFile; fileRef = 873B54DC1F6A716600E6EA7B /* machoman.c */; }; 14 | 8791FEA41F6B454200D54D34 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8791FEA31F6B454200D54D34 /* libcurl.tbd */; }; 15 | 8791FEA61F6B497F00D54D34 /* libfragmentzip.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8791FEA51F6B497F00D54D34 /* libfragmentzip.0.dylib */; }; 16 | 8791FEA91F6B508200D54D34 /* libipatcher.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8791FEA71F6B4C9800D54D34 /* libipatcher.0.dylib */; }; 17 | 87B0A5D51F6B416A00F712A0 /* jssy.c in Sources */ = {isa = PBXBuildFile; fileRef = 87B0A5D31F6B416A00F712A0 /* jssy.c */; }; 18 | 87B0A5E61F6B443100F712A0 /* jssy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 87B0A5E31F6B443100F712A0 /* jssy.cpp */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXCopyFilesBuildPhase section */ 22 | 87ECBF591F6A6F9F00D3E102 /* CopyFiles */ = { 23 | isa = PBXCopyFilesBuildPhase; 24 | buildActionMask = 2147483647; 25 | dstPath = /usr/share/man/man1/; 26 | dstSubfolderSpec = 0; 27 | files = ( 28 | ); 29 | runOnlyForDeploymentPostprocessing = 1; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 872EDD261F6B3BF800C153B3 /* offsetfinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = offsetfinder.h; path = offsetfinder/offsetfinder.h; sourceTree = ""; }; 35 | 872EDD2A1F6B3DC100C153B3 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = offsetfinder/main.cpp; sourceTree = ""; }; 36 | 873B54D81F6A713D00E6EA7B /* patchfinder32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = patchfinder32.c; path = patchfinder32/patchfinder32.c; sourceTree = ""; }; 37 | 873B54D91F6A713D00E6EA7B /* patchfinder32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = patchfinder32.h; path = patchfinder32/patchfinder32.h; sourceTree = ""; }; 38 | 873B54DC1F6A716600E6EA7B /* machoman.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = machoman.c; path = machoman/machoman.c; sourceTree = ""; }; 39 | 873B54DD1F6A716600E6EA7B /* machoman.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = machoman.h; path = machoman/machoman.h; sourceTree = ""; }; 40 | 8791FEA31F6B454200D54D34 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; 41 | 8791FEA51F6B497F00D54D34 /* libfragmentzip.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libfragmentzip.0.dylib; path = ../../../../usr/local/lib/libfragmentzip.0.dylib; sourceTree = ""; }; 42 | 8791FEA71F6B4C9800D54D34 /* libipatcher.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libipatcher.0.dylib; path = ../../../../usr/local/lib/libipatcher.0.dylib; sourceTree = ""; }; 43 | 87B0A5D31F6B416A00F712A0 /* jssy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jssy.c; path = external/jssy/jssy/jssy.c; sourceTree = ""; }; 44 | 87B0A5D41F6B416A00F712A0 /* jssy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jssy.h; path = external/jssy/jssy/jssy.h; sourceTree = ""; }; 45 | 87B0A5E21F6B443100F712A0 /* helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = helper.h; path = external/jssy/jssy/helper.h; sourceTree = ""; }; 46 | 87B0A5E31F6B443100F712A0 /* jssy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = jssy.cpp; path = external/jssy/jssy/jssy.cpp; sourceTree = ""; }; 47 | 87B0A5E41F6B443100F712A0 /* jssy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = jssy.hpp; path = external/jssy/jssy/jssy.hpp; sourceTree = ""; }; 48 | 87B0A5E51F6B443100F712A0 /* ptr_smart.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ptr_smart.hpp; path = external/jssy/jssy/ptr_smart.hpp; sourceTree = ""; }; 49 | 87ECBF5B1F6A6F9F00D3E102 /* offsetfinder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = offsetfinder; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 87ECBF5E1F6A6F9F00D3E102 /* offsetfinder.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = offsetfinder.c; path = offsetfinder/offsetfinder.c; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 87ECBF581F6A6F9F00D3E102 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | 8791FEA91F6B508200D54D34 /* libipatcher.0.dylib in Frameworks */, 59 | 8791FEA61F6B497F00D54D34 /* libfragmentzip.0.dylib in Frameworks */, 60 | 8791FEA41F6B454200D54D34 /* libcurl.tbd in Frameworks */, 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 873B54D71F6A712D00E6EA7B /* patchfinder32 */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 873B54D91F6A713D00E6EA7B /* patchfinder32.h */, 71 | 873B54D81F6A713D00E6EA7B /* patchfinder32.c */, 72 | ); 73 | name = patchfinder32; 74 | sourceTree = ""; 75 | }; 76 | 873B54DB1F6A714700E6EA7B /* machoman */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 873B54DD1F6A716600E6EA7B /* machoman.h */, 80 | 873B54DC1F6A716600E6EA7B /* machoman.c */, 81 | ); 82 | name = machoman; 83 | sourceTree = ""; 84 | }; 85 | 8791FEA21F6B454200D54D34 /* Frameworks */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 8791FEA71F6B4C9800D54D34 /* libipatcher.0.dylib */, 89 | 8791FEA51F6B497F00D54D34 /* libfragmentzip.0.dylib */, 90 | 8791FEA31F6B454200D54D34 /* libcurl.tbd */, 91 | ); 92 | name = Frameworks; 93 | sourceTree = ""; 94 | }; 95 | 87B0A5D21F6B412100F712A0 /* jssy */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 87B0A5E21F6B443100F712A0 /* helper.h */, 99 | 87B0A5E31F6B443100F712A0 /* jssy.cpp */, 100 | 87B0A5E41F6B443100F712A0 /* jssy.hpp */, 101 | 87B0A5E51F6B443100F712A0 /* ptr_smart.hpp */, 102 | 87B0A5D31F6B416A00F712A0 /* jssy.c */, 103 | 87B0A5D41F6B416A00F712A0 /* jssy.h */, 104 | ); 105 | name = jssy; 106 | path = ..; 107 | sourceTree = ""; 108 | }; 109 | 87ECBF521F6A6F9F00D3E102 = { 110 | isa = PBXGroup; 111 | children = ( 112 | 87ECBF5D1F6A6F9F00D3E102 /* offsetfinder */, 113 | 872EDD261F6B3BF800C153B3 /* offsetfinder.h */, 114 | 87ECBF5E1F6A6F9F00D3E102 /* offsetfinder.c */, 115 | 872EDD2A1F6B3DC100C153B3 /* main.cpp */, 116 | 87ECBF5C1F6A6F9F00D3E102 /* Products */, 117 | 8791FEA21F6B454200D54D34 /* Frameworks */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | 87ECBF5C1F6A6F9F00D3E102 /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 87ECBF5B1F6A6F9F00D3E102 /* offsetfinder */, 125 | ); 126 | name = Products; 127 | sourceTree = ""; 128 | }; 129 | 87ECBF5D1F6A6F9F00D3E102 /* offsetfinder */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 873B54D71F6A712D00E6EA7B /* patchfinder32 */, 133 | 873B54DB1F6A714700E6EA7B /* machoman */, 134 | 87B0A5D21F6B412100F712A0 /* jssy */, 135 | ); 136 | path = offsetfinder; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 87ECBF5A1F6A6F9F00D3E102 /* offsetfinder */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 87ECBF621F6A6F9F00D3E102 /* Build configuration list for PBXNativeTarget "offsetfinder" */; 145 | buildPhases = ( 146 | 87ECBF571F6A6F9F00D3E102 /* Sources */, 147 | 87ECBF581F6A6F9F00D3E102 /* Frameworks */, 148 | 87ECBF591F6A6F9F00D3E102 /* CopyFiles */, 149 | ); 150 | buildRules = ( 151 | ); 152 | dependencies = ( 153 | ); 154 | name = offsetfinder; 155 | productName = offsetfinder; 156 | productReference = 87ECBF5B1F6A6F9F00D3E102 /* offsetfinder */; 157 | productType = "com.apple.product-type.tool"; 158 | }; 159 | /* End PBXNativeTarget section */ 160 | 161 | /* Begin PBXProject section */ 162 | 87ECBF531F6A6F9F00D3E102 /* Project object */ = { 163 | isa = PBXProject; 164 | attributes = { 165 | LastUpgradeCheck = 0830; 166 | ORGANIZATIONNAME = tihmstar; 167 | TargetAttributes = { 168 | 87ECBF5A1F6A6F9F00D3E102 = { 169 | CreatedOnToolsVersion = 8.3.3; 170 | ProvisioningStyle = Automatic; 171 | }; 172 | }; 173 | }; 174 | buildConfigurationList = 87ECBF561F6A6F9F00D3E102 /* Build configuration list for PBXProject "offsetfinder" */; 175 | compatibilityVersion = "Xcode 3.2"; 176 | developmentRegion = English; 177 | hasScannedForEncodings = 0; 178 | knownRegions = ( 179 | en, 180 | ); 181 | mainGroup = 87ECBF521F6A6F9F00D3E102; 182 | productRefGroup = 87ECBF5C1F6A6F9F00D3E102 /* Products */; 183 | projectDirPath = ""; 184 | projectRoot = ""; 185 | targets = ( 186 | 87ECBF5A1F6A6F9F00D3E102 /* offsetfinder */, 187 | ); 188 | }; 189 | /* End PBXProject section */ 190 | 191 | /* Begin PBXSourcesBuildPhase section */ 192 | 87ECBF571F6A6F9F00D3E102 /* Sources */ = { 193 | isa = PBXSourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 87B0A5D51F6B416A00F712A0 /* jssy.c in Sources */, 197 | 873B54DA1F6A713D00E6EA7B /* patchfinder32.c in Sources */, 198 | 87B0A5E61F6B443100F712A0 /* jssy.cpp in Sources */, 199 | 872EDD281F6B3CEE00C153B3 /* offsetfinder.c in Sources */, 200 | 872EDD2B1F6B3DC100C153B3 /* main.cpp in Sources */, 201 | 873B54DE1F6A716600E6EA7B /* machoman.c in Sources */, 202 | ); 203 | runOnlyForDeploymentPostprocessing = 0; 204 | }; 205 | /* End PBXSourcesBuildPhase section */ 206 | 207 | /* Begin XCBuildConfiguration section */ 208 | 87ECBF601F6A6F9F00D3E102 /* Debug */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | ALWAYS_SEARCH_USER_PATHS = NO; 212 | CLANG_ANALYZER_NONNULL = YES; 213 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 214 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 215 | CLANG_CXX_LIBRARY = "libc++"; 216 | CLANG_ENABLE_MODULES = YES; 217 | CLANG_ENABLE_OBJC_ARC = YES; 218 | CLANG_WARN_BOOL_CONVERSION = YES; 219 | CLANG_WARN_CONSTANT_CONVERSION = YES; 220 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 221 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 222 | CLANG_WARN_EMPTY_BODY = YES; 223 | CLANG_WARN_ENUM_CONVERSION = YES; 224 | CLANG_WARN_INFINITE_RECURSION = YES; 225 | CLANG_WARN_INT_CONVERSION = YES; 226 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 227 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 228 | CLANG_WARN_UNREACHABLE_CODE = YES; 229 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 230 | CODE_SIGN_IDENTITY = "-"; 231 | COPY_PHASE_STRIP = NO; 232 | DEBUG_INFORMATION_FORMAT = dwarf; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | ENABLE_TESTABILITY = YES; 235 | GCC_C_LANGUAGE_STANDARD = gnu99; 236 | GCC_DYNAMIC_NO_PIC = NO; 237 | GCC_NO_COMMON_BLOCKS = YES; 238 | GCC_OPTIMIZATION_LEVEL = 0; 239 | GCC_PREPROCESSOR_DEFINITIONS = ( 240 | "DEBUG=1", 241 | "$(inherited)", 242 | ); 243 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 245 | GCC_WARN_UNDECLARED_SELECTOR = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 247 | GCC_WARN_UNUSED_FUNCTION = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | MACOSX_DEPLOYMENT_TARGET = 10.12; 250 | MTL_ENABLE_DEBUG_INFO = YES; 251 | ONLY_ACTIVE_ARCH = YES; 252 | SDKROOT = macosx; 253 | }; 254 | name = Debug; 255 | }; 256 | 87ECBF611F6A6F9F00D3E102 /* Release */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | CLANG_ANALYZER_NONNULL = YES; 261 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_WARN_BOOL_CONVERSION = YES; 267 | CLANG_WARN_CONSTANT_CONVERSION = YES; 268 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 269 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 275 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | CODE_SIGN_IDENTITY = "-"; 279 | COPY_PHASE_STRIP = NO; 280 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 281 | ENABLE_NS_ASSERTIONS = NO; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu99; 284 | GCC_NO_COMMON_BLOCKS = YES; 285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 287 | GCC_WARN_UNDECLARED_SELECTOR = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 289 | GCC_WARN_UNUSED_FUNCTION = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | MACOSX_DEPLOYMENT_TARGET = 10.12; 292 | MTL_ENABLE_DEBUG_INFO = NO; 293 | SDKROOT = macosx; 294 | }; 295 | name = Release; 296 | }; 297 | 87ECBF631F6A6F9F00D3E102 /* Debug */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | ALWAYS_SEARCH_USER_PATHS = YES; 301 | LIBRARY_SEARCH_PATHS = /usr/local/lib; 302 | PRODUCT_NAME = "$(TARGET_NAME)"; 303 | USER_HEADER_SEARCH_PATHS = /usr/local/include; 304 | }; 305 | name = Debug; 306 | }; 307 | 87ECBF641F6A6F9F00D3E102 /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = YES; 311 | LIBRARY_SEARCH_PATHS = /usr/local/lib; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | USER_HEADER_SEARCH_PATHS = /usr/local/include; 314 | }; 315 | name = Release; 316 | }; 317 | /* End XCBuildConfiguration section */ 318 | 319 | /* Begin XCConfigurationList section */ 320 | 87ECBF561F6A6F9F00D3E102 /* Build configuration list for PBXProject "offsetfinder" */ = { 321 | isa = XCConfigurationList; 322 | buildConfigurations = ( 323 | 87ECBF601F6A6F9F00D3E102 /* Debug */, 324 | 87ECBF611F6A6F9F00D3E102 /* Release */, 325 | ); 326 | defaultConfigurationIsVisible = 0; 327 | defaultConfigurationName = Release; 328 | }; 329 | 87ECBF621F6A6F9F00D3E102 /* Build configuration list for PBXNativeTarget "offsetfinder" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 87ECBF631F6A6F9F00D3E102 /* Debug */, 333 | 87ECBF641F6A6F9F00D3E102 /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | /* End XCConfigurationList section */ 339 | }; 340 | rootObject = 87ECBF531F6A6F9F00D3E102 /* Project object */; 341 | } 342 | -------------------------------------------------------------------------------- /offsetfinder/machoman/machoman.c: -------------------------------------------------------------------------------- 1 | // 2 | // machoman.c 3 | // machoman 4 | // 5 | // Created by jndok on 14/05/16. 6 | // Copyright © 2016 jndok. All rights reserved. 7 | // 8 | 9 | #include "machoman.h" 10 | 11 | macho_map_t *map_macho_with_path(const char *path, int mode) 12 | { 13 | if (!path) return NULL; 14 | if (access(path, R_OK) == -1) return NULL; 15 | 16 | int32_t fd = open(path, mode); 17 | if (fd < 0) { 18 | return NULL; 19 | } 20 | 21 | struct stat st; 22 | if(fstat(fd, &st) != 0) 23 | goto fail; 24 | 25 | macho_map_t *map = (macho_map_t *)malloc(sizeof(macho_map_t)); 26 | if((map->map_data = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, (mode == O_RDONLY) ? MAP_PRIVATE : MAP_SHARED, fd, 0)) == MAP_FAILED) 27 | goto fail; 28 | map->map_magic = MACHO_MAP_MAGIC; 29 | map->map_size = (mach_vm_size_t)st.st_size; 30 | map->unique_id = (uint32_t)(((uint64_t)map << 32) >> 32); 31 | 32 | return map; 33 | 34 | fail: 35 | close(fd); 36 | 37 | return NULL; 38 | } 39 | 40 | void free_macho_map(macho_map_t *map) 41 | { 42 | if (!is_valid_macho_map(map)) { 43 | return; 44 | } 45 | 46 | munmap(map->map_data, map->map_size); 47 | free(map); 48 | } 49 | 50 | __attribute__((always_inline)) 51 | boolean_t is_valid_macho_file(const char *path) 52 | { 53 | if (!path) return FALSE; 54 | if (access(path, R_OK) == -1) return FALSE; 55 | 56 | int32_t fd = open(path, O_RDONLY); 57 | if (fd < 0) 58 | return FALSE; 59 | 60 | uint32_t magic = 0; 61 | if (read(fd, (void*)&magic, sizeof(uint32_t)) == -1) 62 | return FALSE; 63 | 64 | if ((magic == MH_MAGIC) || (magic == MH_MAGIC_64)) 65 | return TRUE; 66 | else 67 | return FALSE; 68 | } 69 | 70 | __attribute__((always_inline)) 71 | boolean_t is_valid_macho_map(macho_map_t *map) 72 | { 73 | if (!map) return FALSE; 74 | if (!map->map_data) FALSE; 75 | if (map->map_magic != MACHO_MAP_MAGIC) return FALSE; 76 | 77 | return TRUE; 78 | } 79 | 80 | __attribute__((always_inline)) 81 | struct mach_header *get_mach_header32(macho_map_t *map) 82 | { 83 | if (!is_valid_macho_map(map)) return NULL; 84 | 85 | return (struct mach_header*)(map->map_data); 86 | } 87 | 88 | __attribute__((always_inline)) 89 | struct load_command *find_load_command32(struct mach_header *mh, uint32_t lc) 90 | { 91 | struct load_command *lcmd = (struct load_command *)(mh + 1); 92 | for (uint32_t i=0; incmds; i++, lcmd = (void *)lcmd + lcmd->cmdsize) { 93 | if (lcmd->cmd == lc) 94 | return lcmd; 95 | } 96 | 97 | return NULL; 98 | } 99 | 100 | __attribute__((always_inline)) 101 | struct segment_command *find_segment_command32(struct mach_header *mh, const char *segname) 102 | { 103 | struct load_command *lcmd = (struct load_command *)(mh + 1); 104 | for (uint32_t i=0; incmds; i++, lcmd = (void *)lcmd + lcmd->cmdsize) { 105 | if (lcmd->cmd == LC_SEGMENT) { 106 | struct segment_command *seg = (struct segment_command*)(lcmd); 107 | if (strcmp(seg->segname, segname) == 0) 108 | return seg; 109 | } 110 | } 111 | 112 | return NULL; 113 | } 114 | 115 | __attribute__((always_inline)) 116 | struct section *find_section32(struct segment_command *seg, const char *sectname) 117 | { 118 | struct section *sect = (struct section *)(seg + 1); 119 | for (uint32_t i=0; insects; i++, sect++) { 120 | if (strcmp(sect->sectname, sectname) == 0) 121 | return sect; 122 | } 123 | 124 | return NULL; 125 | } 126 | 127 | __attribute__((always_inline)) 128 | struct symtab_command *find_symtab_command(struct mach_header *mh) 129 | { 130 | return (struct symtab_command *)find_load_command32(mh, LC_SYMTAB); 131 | } 132 | 133 | __attribute__((always_inline)) 134 | struct dysymtab_command *find_dysymtab_command(struct mach_header *mh) 135 | { 136 | return (struct dysymtab_command *)find_load_command32(mh, LC_DYSYMTAB); 137 | } 138 | -------------------------------------------------------------------------------- /offsetfinder/machoman/machoman.h: -------------------------------------------------------------------------------- 1 | /* 2 | * == libmachoman v0.1.0 == 3 | * 4 | * A simple library providing all you need 5 | * for generic Mach-O parsing. 6 | * I found myself rewriting this fucking code 7 | * in every project, so I finally decided to 8 | * do it right, once and for all! 9 | * 10 | */ 11 | 12 | // 13 | // machoman.h 14 | // machoman 15 | // 16 | // Created by jndok on 26/05/16. 17 | // Copyright © 2016 jndok. All rights reserved. 18 | // 19 | 20 | #ifndef machoman_h 21 | #define machoman_h 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define MACHO_MAP_MAGIC 0xDEADC0DE 37 | 38 | #define MACHO_MAP_SLIDE_OFFSET(map, off) ((uint64_t)(map->map_data) + (uint64_t)off) 39 | #define MACHO_MAP_UNSLIDE_OFFSET(map, off) ((uint64_t)off > (uint64_t)(map->map_data)) ? ((uint64_t)off - (uint64_t)(map->map_data)) : ((uint64_t)off) 40 | 41 | enum { 42 | MMRC_ErrGen = 1 43 | }; 44 | 45 | typedef struct macho_map { 46 | uint32_t map_magic; 47 | void *map_data; 48 | mach_vm_size_t map_size; 49 | uint32_t unique_id; 50 | } macho_map_t; 51 | 52 | macho_map_t *map_macho_with_path(const char *path, int mode); 53 | void free_macho_map(macho_map_t *map); 54 | 55 | __attribute__((always_inline)) boolean_t is_valid_macho_file(const char *path); /* before you map */ 56 | __attribute__((always_inline)) boolean_t is_valid_macho_map(macho_map_t *map); 57 | 58 | __attribute__((always_inline)) struct mach_header *get_mach_header32(macho_map_t *map); 59 | 60 | __attribute__((always_inline)) struct load_command *find_load_command32(struct mach_header *mh, uint32_t lc); 61 | __attribute__((always_inline)) struct segment_command *find_segment_command32(struct mach_header *mh, const char *segname); 62 | __attribute__((always_inline)) struct section *find_section32(struct segment_command *seg, const char *sectname); 63 | 64 | __attribute__((always_inline)) struct symtab_command *find_symtab_command(struct mach_header *mh); 65 | __attribute__((always_inline)) struct dysymtab_command *find_dysymtab_command(struct mach_header *mh); 66 | 67 | #endif /* machoman_h */ 68 | -------------------------------------------------------------------------------- /offsetfinder/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // offsetfinder 4 | // 5 | // Created by tihmstar on 15.09.17. 6 | // Copyright © 2017 tihmstar. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | extern "C"{ 13 | #include "offsetfinder.h" 14 | #include 15 | #include 16 | } 17 | #include 18 | #include "jssy.hpp" 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) { 26 | size_t written = fwrite(ptr, size, nmemb, stream); 27 | return written; 28 | } 29 | 30 | set found; 31 | 32 | int doprint(char *version){ 33 | string v{version}; 34 | 35 | if (found.find(v) != found.end()) 36 | return (fprintf(stderr, "not printing %s again\n",version),0); 37 | found.insert(v); 38 | return 1; 39 | } 40 | 41 | int main(int argc, const char * argv[]) { 42 | // if (argc < 2) { 43 | // printf("Usage: offsetfinder [buildID] (device1,device2...)\n"); 44 | // return 1; 45 | // } 46 | // CURL *curl; 47 | // FILE *fp; 48 | // CURLcode res; 49 | // char outfilename[FILENAME_MAX] = "/tmp/offsetfindertmp.json"; 50 | // curl = curl_easy_init(); 51 | // if (!curl) { 52 | // fprintf(stderr, "(!) Failed to creat firmwares.json\n"); 53 | // return 1; 54 | // } 55 | // fp = fopen(outfilename,"wb"); 56 | // curl_easy_setopt(curl, CURLOPT_URL, "https://api.ipsw.me/v2.1/firmwares.json"); 57 | // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 58 | // curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 59 | // fprintf(stderr, "(+) Downloading firmwares.json\n"); 60 | // res = curl_easy_perform(curl); 61 | // curl_easy_cleanup(curl); 62 | // fclose(fp); 63 | // 64 | // fprintf(stderr, "(+) Parsing firmwares.json\n"); 65 | // jssycpp::jssy firmwares(outfilename); 66 | // 67 | // vector> devlinks; 68 | // for (auto dev : firmwares["devices"]){ 69 | // for (int i=2; i< argc; i++){ 70 | // if (dev.stringValue().compare(argv[i]) == 0) goto okok; 71 | // } 72 | // continue; 73 | // okok: 74 | // for (auto devfw : dev.subval()["firmwares"]){ 75 | // if (devfw["buildid"].stringValue().compare(argv[1]) == 0){ 76 | // devlinks.push_back({dev.stringValue(),devfw["url"].stringValue()}); 77 | // } 78 | // } 79 | // } 80 | // int hasone = 0; 81 | // for (auto link:devlinks){ 82 | // fprintf(stderr, "(+) Opening Firmware for %s\n",link.first.c_str()); 83 | // fragmentzip_t * fz = fragmentzip_open(link.second.c_str()); 84 | // 85 | // assert(fz); 86 | // 87 | // fragmentzip_cd* cd = fz->cd; 88 | // for(int i = 0; i < fz->cd_end->cd_entries; i++) { 89 | // if (cd->len_filename > strlen("kernelcache") && !strncmp(cd->filename,"kernelcache",strlen("kernelcache"))){ 90 | // fprintf(stderr,"(+) Downloading %.*s\n",cd->len_filename,cd->filename); 91 | // char fname[cd->len_filename+1]; 92 | // strncpy(fname, cd->filename, cd->len_filename); 93 | // fname[cd->len_filename] = 0; 94 | // assert(!fragmentzip_download_file(fz, fname, "/tmp/offsetfinderkernel", NULL)); 95 | // goto okkk; 96 | // } 97 | // cd = fragmentzip_nextCD(cd); 98 | // } 99 | // fprintf(stderr, "(!) Failed to find kernel for %s!\n",link.first.c_str()); 100 | // return -2; 101 | // okkk: 102 | // fragmentzip_close(fz); 103 | // fprintf(stderr, "(+) Getting Firmware key\n"); 104 | // libipatcher::fw_key key; 105 | // key.iv[0] = key.key[0] = '0'; //indicate no encryption 106 | // 107 | // FILE *enckf = fopen("/tmp/offsetfinderkernel", "r"); 108 | // char *kbuf = NULL; 109 | // size_t ksize = 0; 110 | // 111 | // fseek(enckf, 0, SEEK_END); 112 | // ksize = ftell(enckf); 113 | // fseek(enckf, 0, SEEK_SET); 114 | // fclose(enckf); 115 | // 116 | // kbuf = (char*)malloc(ksize); 117 | // 118 | // std::pair deckernel; 119 | // 120 | // try{ 121 | // deckernel = libipatcher::extractKernel(kbuf, ksize, key); 122 | // }catch(std::exception &e){ 123 | // free(kbuf); 124 | // fprintf(stderr, "(!) Failed to get firmware key for %s!\n",link.first.c_str()); 125 | // printf("\n#ERROR failed_to_find_firmware_key_for_%s\n",link.first.c_str()); 126 | // continue; 127 | // } 128 | // free(kbuf); 129 | 130 | if (1){ 131 | std::pair deckernel; 132 | FILE *kk = fopen("/Users/tihmstar/Desktop/awatch/watch3_kernel.bin", "rb"); 133 | // FILE *kk = fopen("/Users/tihmstar/kernels/10.2/iPhone5,2/kernel.dec", "rb"); 134 | fseek(kk, 0, SEEK_END); 135 | deckernel.second = ftell(kk); 136 | fseek(kk, 0, SEEK_SET); 137 | deckernel.first = (char*)malloc(deckernel.second); 138 | fread(deckernel.first, 1, deckernel.second, kk); 139 | fclose(kk); 140 | 141 | macho_map_t *map = (macho_map_t *)malloc(sizeof(macho_map_t)); 142 | map->map_data = deckernel.first; 143 | map->map_magic = MACHO_MAP_MAGIC; 144 | map->map_size = (mach_vm_size_t)deckernel.second; 145 | map->unique_id = (uint32_t)(((uint64_t)map << 32) >> 32); 146 | 147 | // fprintf(stderr, "(+) Finding offsets\n"); 148 | // printf("\n// %s\n",link.first.c_str()); 149 | // if (hasone) printf("else "); 150 | if (printKernelConfig(map,doprint)) 151 | printf("if (0) {}\n"); 152 | // fprintf(stderr, "(+) Done %s\n",link.first.c_str()); 153 | // fflush(stdout); 154 | // 155 | // free(map); 156 | // hasone = 1; 157 | } 158 | 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /offsetfinder/offsetfinder.c: -------------------------------------------------------------------------------- 1 | // 2 | // of32.c 3 | // OF32 4 | // 5 | // Created by jndok on 23/08/2017. 6 | // Copyright © 2017 jndok. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "offsetfinder.h" 13 | #include "machoman/machoman.h" 14 | #include "patchfinder32/patchfinder32.h" 15 | 16 | 17 | enum { 18 | INSN_SEARCH_MODE_THUMB = 0, 19 | INSN_SEARCH_MODE_ARM32 20 | }; 21 | 22 | enum { 23 | INSN_SEARCH_DIRECTION_FWD = 0, 24 | INSN_SEARCH_DIRECTION_BWD 25 | }; 26 | 27 | #define OSSERIALIZER_SERIALIZE_SYMBOL_NAME "__ZNK12OSSerializer9serializeEP11OSSerialize" 28 | #define OSSYMBOL_GETMETACLASS_SYMBOL_NAME "__ZNK8OSSymbol12getMetaClassEv" 29 | #define BUFATTR_CPX_SYMBOL_NAME "_bufattr_cpx" 30 | #define COPYIN_SYMBOL_NAME "_copyin" 31 | #define KERNEL_PMAP_SYMBOL_NAME "_kernel_pmap" 32 | 33 | #define SLIDE(type, addr, slide) (type)((type)addr + (type)slide) 34 | #define UNSLIDE(type, addr, slide) (type)((type)addr - (type)slide) 35 | 36 | #define ADDR_KCACHE_TO_MAP(addr) ({ void *_tmp_addr = (void *)((addr) ? SLIDE(uint64_t, UNSLIDE(uint32_t, addr, kbase), base) : 0); _tmp_addr; }) 37 | 38 | uint8_t *base = NULL; 39 | uint32_t kbase = 0; 40 | uint32_t ksize = 0; 41 | 42 | uint32_t ADDR_MAP_TO_KCACHE(uint16_t* addr) { uint32_t _tmp_addr = ((addr) ? SLIDE(uint32_t, UNSLIDE(void*, addr, base), kbase) : 0); return _tmp_addr; } 43 | 44 | 45 | struct mach_header *mh = NULL; 46 | struct symtab_command *symtab = NULL; 47 | 48 | struct nlist *find_sym(const char *sym) 49 | { 50 | if (!sym || !base || !symtab) 51 | return NULL; 52 | 53 | void *psymtab = base + symtab->symoff; 54 | void *pstrtab = base + symtab->stroff; 55 | 56 | struct nlist *entry = (struct nlist *)psymtab; 57 | for (uint32_t i = 0; i < symtab->nsyms; i++, entry++) 58 | if (!strcmp(sym, (char *)(pstrtab + entry->n_un.n_strx))) 59 | return entry; 60 | 61 | return NULL; 62 | } 63 | 64 | uint32_t find_sig(uint8_t *sig, size_t size) 65 | { 66 | if (!mh || !sig) 67 | return -1; 68 | 69 | struct segment_command *text = find_segment_command32(mh, SEG_TEXT); 70 | if (!text) 71 | return -2; 72 | 73 | void *search_base = (base + text->fileoff); 74 | uint8_t *p = memmem(search_base, text->filesize, sig, size); 75 | if (!p) 76 | return -3; 77 | 78 | return (uint32_t)(p - base); 79 | } 80 | 81 | void *find_insn(void *start, size_t num, uint32_t insn, uint8_t direction, uint8_t mode) 82 | { 83 | if (!start || !num || !insn) 84 | return NULL; 85 | 86 | switch (mode) { 87 | case INSN_SEARCH_MODE_THUMB: { 88 | for (uint16_t *p = (uint16_t *)start; 89 | ((!direction) ? p < ((uint16_t *)start + num) : p > ((uint16_t *)start - num)); 90 | ((!direction) ? p++ : p--)) 91 | { 92 | if (*p == insn) 93 | return p; 94 | } 95 | break; 96 | } 97 | 98 | case INSN_SEARCH_MODE_ARM32: { 99 | for (uint32_t *p = (uint32_t *)start; 100 | ((!direction) ? p < ((uint32_t *)start + num) : p > ((uint32_t *)start - num)); 101 | ((!direction) ? p++ : p--)) 102 | { 103 | if (*p == insn) 104 | return p; 105 | } 106 | break; 107 | } 108 | 109 | default: 110 | break; 111 | } 112 | 113 | return NULL; 114 | } 115 | 116 | static int insn_cmp_imm_rn(uint16_t* i) 117 | { 118 | if((*i & 0xF800) == 0x2800) 119 | return (*i >> 8) & 7; 120 | else if((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) 121 | return *i & 0xF; 122 | else 123 | return 0; 124 | } 125 | 126 | static uint32_t bit_range(uint32_t x, int start, int end) 127 | { 128 | x = (x << (31 - start)) >> (31 - start); 129 | x = (x >> end); 130 | return x; 131 | } 132 | 133 | static uint32_t ror(uint32_t x, int places) 134 | { 135 | return (x >> places) | (x << (32 - places)); 136 | } 137 | 138 | static int thumb_expand_imm_c(uint16_t imm12) 139 | { 140 | if(bit_range(imm12, 11, 10) == 0) 141 | { 142 | switch(bit_range(imm12, 9, 8)) 143 | { 144 | case 0: 145 | return bit_range(imm12, 7, 0); 146 | case 1: 147 | return (bit_range(imm12, 7, 0) << 16) | bit_range(imm12, 7, 0); 148 | case 2: 149 | return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 8); 150 | case 3: 151 | return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 16) | (bit_range(imm12, 7, 0) << 8) | bit_range(imm12, 7, 0); 152 | default: 153 | return 0; 154 | } 155 | } else 156 | { 157 | uint32_t unrotated_value = 0x80 | bit_range(imm12, 6, 0); 158 | return ror(unrotated_value, bit_range(imm12, 11, 7)); 159 | } 160 | } 161 | 162 | static int insn_cmp_imm_imm(uint16_t* i) 163 | { 164 | if((*i & 0xF800) == 0x2800) 165 | return *i & 0xFF; 166 | else if((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) 167 | return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); 168 | else 169 | return 0; 170 | } 171 | 172 | static int insn_is_cmp_imm(uint16_t* i) 173 | { 174 | if((*i & 0xF800) == 0x2800) 175 | return 1; 176 | else if((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) 177 | return 1; 178 | else 179 | return 0; 180 | } 181 | 182 | static uint16_t* find_next_insn_matching(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* current_instruction, int (*match_func)(uint16_t*)){ 183 | while((uintptr_t)current_instruction < (uintptr_t)kdata+ksize) 184 | { 185 | if(insn_is_32bit(current_instruction) && !insn_is_32bit(current_instruction +1)) 186 | { 187 | current_instruction += 2; 188 | } else 189 | { 190 | ++current_instruction; 191 | } 192 | 193 | if(match_func(current_instruction)) 194 | { 195 | return current_instruction; 196 | } 197 | } 198 | 199 | return NULL; 200 | } 201 | 202 | /* offset finders */ 203 | 204 | uint32_t find_OSSerializer_serialize(void) 205 | { 206 | struct nlist *n = find_sym(OSSERIALIZER_SERIALIZE_SYMBOL_NAME); 207 | assert(n); 208 | 209 | return UNSLIDE(uint32_t, n->n_value+1, kbase); 210 | } 211 | 212 | uint32_t find_OSSymbol_getMetaClass(void) 213 | { 214 | struct nlist *n = find_sym(OSSYMBOL_GETMETACLASS_SYMBOL_NAME); 215 | assert(n); 216 | 217 | return UNSLIDE(uint32_t, n->n_value, kbase); 218 | } 219 | 220 | uint32_t find_calend_gettime(void) 221 | { 222 | struct nlist *n = find_sym("_clock_get_calendar_nanotime"); 223 | assert(n); 224 | 225 | struct segment_command *text = find_segment_command32(mh, SEG_TEXT); 226 | 227 | uint32_t xref = n->n_value; 228 | 229 | for (uint16_t *p = (uint16_t *)(base + text->fileoff); p < (uint16_t *)(base + text->filesize); p++) 230 | if (insn_is_32bit(p) && insn_is_bl(p)) { 231 | uint32_t ip = ADDR_MAP_TO_KCACHE(p); 232 | if ((ip + (int32_t)insn_bl_imm32(p) + 4) == xref) // XXX: assuming first xref is correct one, may not be (?) 233 | return UNSLIDE(uint32_t, 234 | ADDR_MAP_TO_KCACHE(find_insn(p, 10, 0xB590, INSN_SEARCH_DIRECTION_BWD, INSN_SEARCH_MODE_THUMB)), 235 | kbase); 236 | } 237 | 238 | return 0; 239 | } 240 | 241 | uint32_t find_bufattr_cpx(void) 242 | { 243 | struct nlist *n = find_sym(BUFATTR_CPX_SYMBOL_NAME); 244 | assert(n); 245 | 246 | return UNSLIDE(uint32_t, n->n_value, kbase); 247 | } 248 | 249 | uint32_t find_clock_ops(void) 250 | { 251 | struct nlist *n = find_sym("_clock_get_system_value"); 252 | assert(n); 253 | //0x3accdc 254 | uint32_t val = 0; 255 | uint32_t *addr = 0; 256 | 257 | uint32_t addr2 = 0; 258 | 259 | for (uint16_t *p = (uint16_t *)(ADDR_KCACHE_TO_MAP(n->n_value)); !insn_is_pop(p); p++) { 260 | if (insn_is_mov_imm(p) && insn_is_mov_imm(p) && !val) { 261 | val = insn_mov_imm_imm(p++); 262 | } else if (insn_is_movt(p) && val < (1<<16) ) { 263 | val |= (insn_movt_imm(p++) << 16); 264 | } else if (insn_is_add_reg(p) && (insn_add_reg_rm(p) == 0xF) && !addr) { 265 | uint32_t ip = ADDR_MAP_TO_KCACHE(p); 266 | addr = (uint32_t *)ADDR_KCACHE_TO_MAP(ip+val+4); 267 | } else if (insn_is_thumb2_ldr(p)){ 268 | addr2 = *(addr + ((*++p)& ((1<<12)-1))/4); 269 | } else if (insn_is_ldr_imm(p) && addr2){ 270 | addr2 += insn_ldr_imm_imm(p) + 4; 271 | return UNSLIDE(uint32_t, (addr2), kbase); 272 | } 273 | } 274 | return 0; 275 | } 276 | 277 | uint32_t find_copyin(void){ 278 | struct nlist *n = find_sym(COPYIN_SYMBOL_NAME); 279 | assert(n); 280 | 281 | return UNSLIDE(uint32_t, n->n_value, kbase); 282 | } 283 | 284 | uint32_t find_bx_lr(void) 285 | { 286 | return find_bufattr_cpx() + 0x2; 287 | } 288 | 289 | uint32_t find_write_gadget(void) 290 | { 291 | struct nlist *n = find_sym("_enable_kernel_vfp_context"); 292 | assert(n); 293 | 294 | uint16_t *p = find_insn(ADDR_KCACHE_TO_MAP(n->n_value), 50, 0x100C, INSN_SEARCH_DIRECTION_BWD, INSN_SEARCH_MODE_THUMB); 295 | assert(p); 296 | 297 | return UNSLIDE(uint32_t, ADDR_MAP_TO_KCACHE(p), kbase); 298 | } 299 | 300 | uint32_t find_vm_kernel_addrperm(void) 301 | { 302 | struct nlist *n = find_sym("_buf_kernel_addrperm_addr"); //THIS WAS TESTED ON 8.4.1 303 | assert(n); 304 | 305 | uint32_t val = 0; 306 | uint32_t *addr = 0; 307 | uint32_t addr2 = 0; 308 | 309 | for (uint16_t *p = (uint16_t *)(base + (n->n_value - kbase)); *p != 0xBF00; p++) { 310 | if (insn_is_mov_imm(p) && insn_is_mov_imm(p) && !val) { 311 | val = insn_mov_imm_imm(p++); 312 | } else if (insn_is_movt(p) && val < (1<<16) ) { 313 | val |= (insn_movt_imm(p++) << 16); 314 | } else if (insn_is_add_reg(p) && (insn_add_reg_rm(p) == 0xF) && !addr) { 315 | uint32_t ip = ADDR_MAP_TO_KCACHE(p); 316 | addr = (uint32_t *)ADDR_KCACHE_TO_MAP(ip+val+4); 317 | } else if (insn_is_thumb2_ldr(p)){ 318 | addr2 = (uint32_t)ADDR_MAP_TO_KCACHE(addr) + ((*++p)& ((1<<12)-1)); 319 | return UNSLIDE(uint32_t, (addr2-4), kbase); 320 | } 321 | } 322 | 323 | return 0; 324 | } 325 | 326 | uint32_t find_kernel_pmap(void) 327 | { 328 | struct nlist *n = find_sym(KERNEL_PMAP_SYMBOL_NAME); 329 | assert(n); 330 | 331 | return UNSLIDE(uint32_t, n->n_value, kbase); 332 | } 333 | 334 | uint32_t find_kernel_pmap_nosym(void){ 335 | uint8_t *str = memmem(base, ksize, "\"out of ptd entry", sizeof("\"out of ptd entry")-1); 336 | assert(str); 337 | 338 | uint16_t *ref = find_literal_ref(kbase, base, ksize, str-(uint8_t*)base); 339 | assert(ref); 340 | 341 | while (!insn_is_ldr_imm(ref)) ref ++; 342 | 343 | uint32_t *pmap = 0; 344 | for (uint16_t *p = ref; p>base; p--) { 345 | if (insn_is_bl(p)) { 346 | int32_t dst = (insn_bl_imm32(p) + 4); 347 | uint16_t *abs_dst = (uint16_t *)((uint8_t*)p+dst); 348 | if (abs_dst == ref){ 349 | pmap = p; 350 | break; 351 | } 352 | } 353 | } 354 | 355 | while (!insn_is_movt(pmap) || !insn_is_mov_imm(pmap-1)) pmap--; 356 | pmap--; 357 | uint32_t pmap_add_val = insn_mov_imm_imm(pmap++); 358 | pmap_add_val |= insn_movt_imm(pmap++) << 16; 359 | 360 | pmap = (uint8_t*)pmap + pmap_add_val + 4; 361 | 362 | return UNSLIDE(uint32_t, pmap, base); 363 | } 364 | 365 | uint32_t find_flush_dcache(void) 366 | { 367 | uint8_t sig[] = { 368 | 0x00, 0x00, 0xA0, 0xE3, 369 | 0x5E, 0x0F, 0x07, 0xEE 370 | }; 371 | 372 | return find_sig((void *)&sig, sizeof(sig)); 373 | } 374 | 375 | uint32_t find_invalidate_tlb(void) 376 | { 377 | uint8_t sig[] = { 378 | 0x00, 0x00, 0xA0, 0xE3, 379 | 0x17, 0x0F, 0x08, 0xEE, 380 | 0x4B, 0xF0, 0x7F, 0xF5, 381 | 0x6F, 0xF0, 0x7F, 0xF5, 382 | 0x1E, 0xFF, 0x2F, 0xE1 383 | }; 384 | 385 | return find_sig((void *)&sig, sizeof(sig)); 386 | } 387 | 388 | uint32_t find_allproc(void) 389 | { 390 | uint8_t *str = memmem(base, ksize, "\"pgrp_add : pgrp is dead adding process", sizeof("pgrp_add : pgrp is dead adding process")-1); 391 | assert(str); 392 | 393 | uint16_t *ref = find_literal_ref(kbase, base, ksize, str-(uint8_t*)base); 394 | assert(ref); 395 | 396 | while (!insn_is_thumb2_pop(ref++)) assert(refbase); 400 | uint16_t *top = ref; 401 | 402 | uint16_t *itttne = 0; 403 | for (uint16_t*i=bottom; i>base; i--) 404 | if (*i == 0xbf1e){ 405 | itttne = i; 406 | break; 407 | } 408 | assert(itttne); 409 | 410 | uint16_t *ittne = 0; 411 | for (uint16_t*i=itttne; iitttne; i--) { 422 | if (insn_is_thumb2_ldr(i)){ 423 | pos = i; 424 | offset = *(i+1) & ((1<<12)-1); 425 | rn = *i & ((1<<4)-1); 426 | break; 427 | } 428 | } 429 | assert(offset); 430 | 431 | uint32_t val = 0; 432 | for (uint16_t *p=pos; p>top; p--) { 433 | if (insn_add_reg_rm(p) == 15 && insn_add_reg_rd(p) == rn){ 434 | offset += (uint8_t*)p - (uint8_t*)base + kbase; 435 | }else if (insn_is_movt(p) && insn_movt_rd(p) == rn && !(val>>16)){ 436 | val |= insn_movt_imm(p) << 16; 437 | }else if (insn_is_mov_imm(p) && insn_mov_imm_rd(p) == rn && !(val & ((1<<16)-1))){ 438 | val |= insn_mov_imm_imm(p); 439 | } 440 | if (val >> 16 && (val & ((1<<16)-1))) 441 | break; 442 | } 443 | offset += val + 4; 444 | 445 | return UNSLIDE(uint32_t, offset, kbase); 446 | } 447 | 448 | uint32_t find_proc_ucred(void){ 449 | struct nlist *n = find_sym("_proc_ucred"); 450 | assert(n); 451 | 452 | uint32_t *addr = (uint32_t *)(ADDR_KCACHE_TO_MAP(n->n_value)); 453 | assert(addr && *addr); 454 | 455 | return ((*addr) >> 16); 456 | } 457 | 458 | uint32_t find_setreuid(void) 459 | { 460 | uint8_t sig[] = { 461 | 0xf0, 0xb5, 0x03, 0xaf, 462 | 0x2d, 0xe9, 0x00, 0x0d, 463 | 0x87, 0xb0, 0x04, 0x46, 464 | 0x02, 0x91, 0x03, 0x94, 465 | 0xd1, 0xf8, 0x00, 0xb0, 466 | 0x4d, 0x68, 0xdf, 0xf7 467 | }; 468 | 469 | return find_sig((void *)&sig, sizeof(sig)); 470 | } 471 | 472 | uint32_t find_task_for_pid(void) 473 | { 474 | uint8_t sig[] = { 475 | 0xf0, 0xb5, 0x03, 0xaf, 476 | 0x2d, 0xe9, 0x00, 0x0d, 477 | 0x84, 0xb0, 0x01, 0x46, 478 | 0x91, 0xe8, 0x41, 0x08, 479 | 0x00, 0x21, 0x03, 0x91 480 | }; 481 | 482 | return find_sig((void *)&sig, sizeof(sig)); 483 | } 484 | 485 | uint32_t find_zone_map(){ 486 | uint8_t *ptr=memmem(base, ksize, "zone_init", sizeof("zone_init")); 487 | uint16_t *ref = find_literal_ref(kbase, base, ksize, ptr-(uint8_t*)base); 488 | 489 | uint32_t val = 0; 490 | int rd = -1; 491 | while (!(val >> 16 && (val & ((1<<16)-1)))){ 492 | if (insn_is_mov_imm(ref)){ 493 | int trd = insn_movt_rd(ref); 494 | if (rd != trd && rd != -1){ 495 | ref++; 496 | continue; 497 | } 498 | else 499 | rd = trd; 500 | val |= insn_mov_imm_imm(ref++); 501 | }else if (insn_is_movt(ref)){ 502 | int trd = insn_movt_rd(ref); 503 | if (rd != trd && rd != -1){ 504 | ref++; 505 | continue; 506 | }else 507 | rd = trd; 508 | val |= insn_movt_imm(ref++) << 16; 509 | } 510 | ref++; 511 | } 512 | while (!insn_is_add_reg(ref)) 513 | ref++; 514 | 515 | if (insn_add_reg_rd(ref) != rd || insn_add_reg_rm(ref) != 15) 516 | return 0; 517 | 518 | return (uint32_t)UNSLIDE(uint32_t,((uint8_t*)ref+4+val),base); 519 | } 520 | 521 | uint32_t find_kernel_map(void){ 522 | struct nlist *n = find_sym("_kernel_map"); 523 | assert(n); 524 | return UNSLIDE(uint32_t, n->n_value, kbase); 525 | } 526 | 527 | uint32_t find_kernel_task(void){ 528 | struct nlist *n = find_sym("_kernel_task"); 529 | assert(n); 530 | return UNSLIDE(uint32_t, n->n_value, kbase); 531 | } 532 | 533 | uint32_t find_realhost(void){ 534 | struct nlist *n = find_sym("_KUNCExecute"); 535 | assert(n); 536 | uint16_t *ref = ADDR_KCACHE_TO_MAP(n->n_value); 537 | 538 | uint32_t val = 0; 539 | int rd = -1; 540 | while (!(val >> 16 && (val & ((1<<16)-1)))){ 541 | if (insn_is_mov_imm(ref)){ 542 | int trd = insn_movt_rd(ref); 543 | if (rd != trd && rd != -1){ 544 | ref++; 545 | continue; 546 | }else 547 | rd = trd; 548 | val |= insn_mov_imm_imm(ref++); 549 | }else if (insn_is_movt(ref)){ 550 | int trd = insn_movt_rd(ref); 551 | if (rd != trd && rd != -1){ 552 | ref++; 553 | continue; 554 | }else 555 | rd = trd; 556 | val |= insn_movt_imm(ref++) << 16; 557 | } 558 | ref++; 559 | } 560 | while (!insn_is_add_reg(ref)) 561 | ref++; 562 | 563 | if (insn_add_reg_rd(ref) != rd || insn_add_reg_rm(ref) != 15) 564 | return 0; 565 | 566 | return (uint32_t)UNSLIDE(uint32_t,((uint8_t*)ref+4+val),base); 567 | } 568 | 569 | uint32_t find_bzero(void){ 570 | struct nlist *n = find_sym("___bzero"); 571 | assert(n); 572 | return UNSLIDE(uint32_t, n->n_value, kbase); 573 | } 574 | 575 | uint32_t find_bcopy(void){ 576 | struct nlist *n = find_sym("_bcopy"); 577 | assert(n); 578 | return UNSLIDE(uint32_t, n->n_value+1, kbase); 579 | } 580 | 581 | uint32_t find_copyout(void){ 582 | struct nlist *n = find_sym("_copyout"); 583 | assert(n); 584 | return UNSLIDE(uint32_t, n->n_value, kbase); 585 | } 586 | 587 | uint32_t find_ipc_port_alloc_special(void){ 588 | struct nlist *n = find_sym("_KUNCGetNotificationID"); 589 | assert(n); 590 | uint16_t *ref = ADDR_KCACHE_TO_MAP(n->n_value); 591 | 592 | while (!insn_is_bl(ref)) 593 | ref++; 594 | ref++; 595 | while (!insn_is_bl(ref)) 596 | ref++; 597 | 598 | int32_t val = insn_bl_imm32(ref); 599 | 600 | return (uint32_t)UNSLIDE(uint32_t,((uint8_t*)ref+4+val+1),base); 601 | } 602 | 603 | uint32_t find_ipc_kobject_set(void){ 604 | struct nlist *n = find_sym("_KUNCGetNotificationID"); 605 | assert(n); 606 | uint16_t *ref = ADDR_KCACHE_TO_MAP(n->n_value); 607 | 608 | while (!insn_is_bl(ref)) 609 | ref++; 610 | ref++; 611 | while (!insn_is_bl(ref)) 612 | ref++; 613 | ref++; 614 | while (!insn_is_bl(ref)) 615 | ref++; 616 | 617 | int32_t val = insn_bl_imm32(ref); 618 | 619 | return (uint32_t)UNSLIDE(uint32_t,((uint8_t*)ref+4+val+1),base); 620 | } 621 | 622 | uint32_t find_ipc_port_make_send(void){ 623 | struct nlist *n = find_sym("_convert_task_to_port"); 624 | assert(n); 625 | uint16_t *ref = ADDR_KCACHE_TO_MAP(n->n_value); 626 | 627 | while (!insn_is_bl(ref)) 628 | ref++; 629 | ref++; 630 | while (!insn_is_bl(ref)) 631 | ref++; 632 | 633 | int32_t val = insn_bl_imm32(ref); 634 | 635 | return (uint32_t)UNSLIDE(uint32_t,((uint8_t*)ref+4+val+1),base); 636 | } 637 | 638 | uint32_t find_rop_ldr_r0_r0_0xc(){ 639 | uint8_t *p = memmem(base, ksize, "\xC0\x68\x70\x47", 4); 640 | if (!p) 641 | return 0; 642 | 643 | return (uint32_t)(p+1 - base); 644 | } 645 | 646 | uint32_t find_ipc_space_is_task(){ 647 | uint8_t *ptr=memmem(base, ksize, "\"ipc_task_init\"", sizeof("\"ipc_task_init\"")); 648 | uint16_t *ref = find_literal_ref(kbase, base, ksize, (uint32_t)(ptr-base)); 649 | 650 | int foundboth = 0; 651 | int rd = -1; 652 | do{ 653 | ref--; 654 | if (insn_is_mov_imm(ref)){ 655 | int trd = insn_movt_rd(ref); 656 | if (rd != trd && rd != -1){ 657 | ref++; 658 | continue; 659 | }else 660 | rd = trd; 661 | foundboth |=1; 662 | }else if (insn_is_movt(ref)){ 663 | int trd = insn_movt_rd(ref); 664 | if (rd != trd && rd != -1){ 665 | ref++; 666 | continue; 667 | }else 668 | rd = trd; 669 | foundboth |=2; 670 | } 671 | } while (foundboth!=3); 672 | 673 | uint16_t *beq = find_rel_branch_ref(ref, 0x1200, -1,insn_is_thumb2_branch,insn_thumb2_branch_imm); 674 | if (!beq) 675 | beq = find_rel_branch_ref(ref, 0x1200, -1,insn_is_thumb_branch,insn_thumb_branch_imm); 676 | assert(beq); 677 | 678 | uint16_t *strw = beq; 679 | while (!insn_is_thumb2_strw(--strw)); 680 | 681 | return insn_thumb2_strw_imm(strw); 682 | } 683 | 684 | 685 | typedef struct mig_subsystem_struct { 686 | uint32_t min; 687 | uint32_t max; 688 | char *names; 689 | } mig_subsys; 690 | 691 | mig_subsys task_subsys ={ 0xd48, 0xd7a , NULL}; 692 | uint32_t find_task_itk_self(){ 693 | uint32_t *task_subsystem=memmem(base, ksize, &task_subsys, 4); 694 | if (!task_subsystem) 695 | return 0; 696 | task_subsystem += 5; 697 | 698 | uint16_t *mach_ports_register = task_subsystem[3*6]; 699 | mach_ports_register = ADDR_KCACHE_TO_MAP(((uint64_t)mach_ports_register &~1)); 700 | 701 | 702 | struct nlist *n = find_sym("_lck_mtx_lock"); 703 | assert(n); 704 | uint16_t *lck_mtx_lock = ADDR_KCACHE_TO_MAP(n->n_value); 705 | 706 | uint16_t *thebl = 0; 707 | for (uint16_t *p = mach_ports_register; pn_value); 736 | 737 | uint16_t *thebl = 0; 738 | for (uint16_t *p = mach_ports_register; pn_value); 760 | vtab_IOUserClient += 2; 761 | 762 | struct nlist *nn = find_sym("__ZN12IOUserClient23getExternalTrapForIndexEm"); 763 | assert(nn); 764 | uint32_t getExternalTrapForIndex = nn->n_value+1; 765 | 766 | for (int i=0; i<0x200; i++) { 767 | if (vtab_IOUserClient[i]==getExternalTrapForIndex) 768 | return i; 769 | } 770 | 771 | return 0; 772 | } 773 | 774 | //IOUSERCLIENT_IPC 775 | mig_subsys host_priv_subsys = { 400, 426 } ; 776 | uint32_t find_iouserclient_ipc(){ 777 | uint16_t *iokit_user_client_trap = NULL; 778 | uint32_t *host_priv_subsystem=memmem(base, ksize, &host_priv_subsys, 8); 779 | if (!host_priv_subsystem) 780 | return 0; 781 | 782 | uint32_t *thetable = host_priv_subsystem; 783 | while (thetable>base){ 784 | struct _anon{ 785 | uint32_t ptr; 786 | uint32_t z0; 787 | uint32_t z1; 788 | } *obj = thetable; 789 | if (!obj->z0 && !obj->z1 && 790 | !memcmp(&obj[0], &obj[1], sizeof(struct _anon)) && 791 | !memcmp(&obj[0], &obj[2], sizeof(struct _anon)) && 792 | !memcmp(&obj[0], &obj[3], sizeof(struct _anon)) && 793 | !memcmp(&obj[0], &obj[4], sizeof(struct _anon)) && 794 | !obj[-1].ptr && obj[-1].z0 == 1 && !obj[-1].z1) { 795 | break; 796 | } 797 | thetable--; 798 | } 799 | 800 | if ((uint8_t*)thetable != base) { 801 | iokit_user_client_trap = ((uint32_t)UNSLIDE(uint32_t, (thetable[100*3] &~1), kbase) + base); 802 | 803 | }else{//iOS 11 kernel?? 804 | thetable = 0; 805 | while (host_priv_subsystem>base){ 806 | struct _anon2{ 807 | uint32_t ptr; 808 | uint32_t z0; 809 | uint32_t z1; 810 | uint32_t z2; 811 | } *obj = host_priv_subsystem; 812 | if (obj->ptr && !obj->z0 && !obj->z1 && !obj->z2 && 813 | !memcmp(&obj[0], &obj[1], sizeof(struct _anon2)) && 814 | !memcmp(&obj[0], &obj[2], sizeof(struct _anon2)) && 815 | !memcmp(&obj[0], &obj[3], sizeof(struct _anon2)) && 816 | !memcmp(&obj[0], &obj[4], sizeof(struct _anon2)) && 817 | !memcmp(&obj[0], &obj[5], sizeof(struct _anon2)) && 818 | !memcmp(&obj[0], &obj[6], sizeof(struct _anon2)) && 819 | !memcmp(&obj[0], &obj[7], sizeof(struct _anon2)) && 820 | !memcmp(&obj[0], &obj[8], sizeof(struct _anon2)) && 821 | !obj[-1].z2) { 822 | thetable = host_priv_subsystem; 823 | } 824 | host_priv_subsystem--; 825 | } 826 | iokit_user_client_trap = ((uint32_t)UNSLIDE(uint32_t, (thetable[100*4] &~1), kbase) + base); 827 | } 828 | assert(iokit_user_client_trap); 829 | 830 | uint16_t *bl_to_iokit_add_connect_reference = iokit_user_client_trap; 831 | 832 | while (!insn_is_bl(bl_to_iokit_add_connect_reference) || bl_to_iokit_add_connect_reference[-1] != 0x4620) //mov r0, r4 833 | bl_to_iokit_add_connect_reference++; 834 | 835 | int32_t dst = (insn_bl_imm32(bl_to_iokit_add_connect_reference) + 4); 836 | uint16_t *abs_dst = (uint16_t *)((uint8_t*)bl_to_iokit_add_connect_reference+dst); 837 | 838 | struct nlist *n = find_sym("_OSDecrementAtomic"); 839 | assert(n); 840 | uint16_t *OSDecrementAtomic = ADDR_KCACHE_TO_MAP(n->n_value); 841 | 842 | uint16_t *thebl = 0; 843 | for (uint16_t *p = abs_dst; pn_value+1, kbase); 874 | } 875 | 876 | uint32_t find_sizeof_task(){ 877 | uint8_t *ptr=memmem(base, ksize, "tasks", sizeof("tasks")); 878 | uint16_t *ref = find_literal_ref(kbase, base, ksize, (uint32_t)(ptr-base)); 879 | assert(ref); 880 | ref++; 881 | 882 | uint16_t *zinit = 0; 883 | 884 | struct nlist *n = find_sym("_zinit"); 885 | if (n) { 886 | zinit = ADDR_KCACHE_TO_MAP(n->n_value); 887 | }else if ((ptr=memmem(base, ksize, "zlog%d", sizeof("zlog%d")))){ 888 | uint16_t *ref2 = find_literal_ref(kbase, base, ksize, (uint32_t)(ptr-base)); 889 | if (ref2) { 890 | while (!insn_is_thumb2_push(--ref2)); 891 | while (!insn_is_push(--ref2)); 892 | zinit = ref2; 893 | } 894 | } 895 | 896 | uint16_t *bl = ref+2; 897 | while (!insn_is_bl(bl)) 898 | bl++; 899 | 900 | while (!insn_is_mov_imm(ref)) 901 | ref++; 902 | 903 | assert(insn_is_mov_imm(ref) && insn_is_bl(bl)); 904 | 905 | if (zinit) 906 | assert(insn_bl_imm32(bl)+4+(uint8_t*)bl == zinit); 907 | else{ 908 | fprintf(stderr, "WARNING: can't find zinit. Can't verify sizeof_task\n"); 909 | } 910 | 911 | return insn_mov_imm_imm(ref); 912 | } 913 | 914 | uint32_t find_task_bsd_info(void){ 915 | struct nlist *n = find_sym("_get_bsdtask_info"); 916 | assert(n); 917 | 918 | uint32_t *addr = (uint32_t *)(ADDR_KCACHE_TO_MAP(n->n_value)); 919 | assert(addr && *addr); 920 | 921 | return ((*addr) >> 16); 922 | } 923 | 924 | #define FIND_OFFSET(name) uint32_t off_##name = find_##name() 925 | #define PRINT_OFFSET(name,slide) fprintf(stdout, "pushOffset(0x%08x); //%s\n", off_##name + (slide ? kbase : 0), #name) 926 | 927 | #define FIND_AND_PRINT_OFFSET(name,slide) { FIND_OFFSET(name); /*assert(off_##name); */ PRINT_OFFSET(name,slide);} 928 | 929 | int printKernelConfig(macho_map_t *map, int (*doprint)(char*version)) { 930 | // macho_map_t *map = map_macho_with_path(kernelpath, O_RDONLY); 931 | assert(map); 932 | 933 | mh = get_mach_header32(map); 934 | 935 | if (mh->magic != MH_MAGIC) { 936 | printf("Error: Invalid kernelcache!\n"); 937 | return 2; 938 | } 939 | fprintf(stderr, "(+) Successfully mapped and validated kernelcache. Dumping offsets...\n\n"); 940 | 941 | base = map->map_data; 942 | ksize = (uint32_t)map->map_size; 943 | kbase = find_segment_command32(mh, SEG_TEXT)->vmaddr; 944 | 945 | symtab = find_symtab_command(mh); 946 | assert(symtab); 947 | char *version = ADDR_KCACHE_TO_MAP(find_sym("_version")->n_value); 948 | 949 | if (!doprint(version)) 950 | return 1; 951 | 952 | printf("if (!dstrcmp(uname, \"%s\")){\n", version); 953 | FIND_AND_PRINT_OFFSET(zone_map,1); 954 | FIND_AND_PRINT_OFFSET(kernel_map,1); 955 | FIND_AND_PRINT_OFFSET(kernel_task,1); 956 | FIND_AND_PRINT_OFFSET(realhost,1); 957 | FIND_AND_PRINT_OFFSET(bzero,1); 958 | FIND_AND_PRINT_OFFSET(bcopy,1); 959 | FIND_AND_PRINT_OFFSET(copyin,1); 960 | FIND_AND_PRINT_OFFSET(copyout,1); 961 | FIND_AND_PRINT_OFFSET(ipc_port_alloc_special,1); 962 | FIND_AND_PRINT_OFFSET(ipc_kobject_set,1); 963 | FIND_AND_PRINT_OFFSET(ipc_port_make_send,1); 964 | FIND_AND_PRINT_OFFSET(rop_ldr_r0_r0_0xc,1); 965 | FIND_AND_PRINT_OFFSET(chgproccnt,1); 966 | FIND_AND_PRINT_OFFSET(kauth_cred_ref,1); 967 | FIND_AND_PRINT_OFFSET(OSSerializer_serialize,1); 968 | 969 | // FIND_AND_PRINT_OFFSET(ipc_space_is_task,0); 970 | printf("pushOffset(0x00000018); //ipc_space_is_task\n"); 971 | FIND_AND_PRINT_OFFSET(task_itk_self,0); 972 | FIND_AND_PRINT_OFFSET(task_itk_registered,0); 973 | FIND_AND_PRINT_OFFSET(vtab_get_external_trap_for_index,0); 974 | FIND_AND_PRINT_OFFSET(iouserclient_ipc,0); 975 | FIND_AND_PRINT_OFFSET(proc_ucred,0); 976 | FIND_AND_PRINT_OFFSET(task_bsd_info,0); 977 | FIND_AND_PRINT_OFFSET(sizeof_task,0); 978 | 979 | 980 | 981 | printf("}"); 982 | fprintf(stderr, "\n"); 983 | 984 | 985 | return 0; 986 | } 987 | 988 | -------------------------------------------------------------------------------- /offsetfinder/offsetfinder.h: -------------------------------------------------------------------------------- 1 | // 2 | // offsetfinder.h 3 | // offsetfinder 4 | // 5 | // Created by tihmstar on 15.09.17. 6 | // Copyright © 2017 tihmstar. All rights reserved. 7 | // 8 | 9 | #ifndef offsetfinder_h 10 | #define offsetfinder_h 11 | 12 | #include "machoman.h" 13 | 14 | int printKernelConfig(macho_map_t *map, int (*doprint)(char*version)); 15 | 16 | 17 | #endif /* offsetfinder_h */ 18 | -------------------------------------------------------------------------------- /offsetfinder/patchfinder32/patchfinder32.c: -------------------------------------------------------------------------------- 1 | // 2 | // patchfinder32.c 3 | // HomeDepotOF 4 | // 5 | // Created by Nicolò Blasi on 24/08/2017. 6 | // Copyright © 2017 Nicolò Blasi. All rights reserved. 7 | // 8 | 9 | #include "patchfinder32.h" 10 | 11 | 12 | #define HAS_BITS(a,b) (((a) & (b)) == (b)) 13 | 14 | static uint32_t bit_range(uint32_t x, int start, int end) 15 | { 16 | x = (x << (31 - start)) >> (31 - start); 17 | x = (x >> end); 18 | return x; 19 | } 20 | 21 | static uint32_t ror(uint32_t x, int places) 22 | { 23 | return (x >> places) | (x << (32 - places)); 24 | } 25 | 26 | static int thumb_expand_imm_c(uint16_t imm12) 27 | { 28 | if(bit_range(imm12, 11, 10) == 0) 29 | { 30 | switch(bit_range(imm12, 9, 8)) 31 | { 32 | case 0: 33 | return bit_range(imm12, 7, 0); 34 | case 1: 35 | return (bit_range(imm12, 7, 0) << 16) | bit_range(imm12, 7, 0); 36 | case 2: 37 | return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 8); 38 | case 3: 39 | return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 16) | (bit_range(imm12, 7, 0) << 8) | bit_range(imm12, 7, 0); 40 | default: 41 | return 0; 42 | } 43 | } else 44 | { 45 | uint32_t unrotated_value = 0x80 | bit_range(imm12, 6, 0); 46 | return ror(unrotated_value, bit_range(imm12, 11, 7)); 47 | } 48 | } 49 | 50 | int insn_is_32bit(uint16_t* i) 51 | { 52 | return (*i & 0xe000) == 0xe000 && (*i & 0x1800) != 0x0; 53 | } 54 | 55 | 56 | int insn_is_add_reg(uint16_t* i) 57 | { 58 | if((*i & 0xFE00) == 0x1800) 59 | return 1; 60 | else if((*i & 0xFF00) == 0x4400) 61 | return 1; 62 | else if((*i & 0xFFE0) == 0xEB00) 63 | return 1; 64 | else 65 | return 0; 66 | } 67 | 68 | int insn_add_reg_rd(uint16_t* i) 69 | { 70 | if((*i & 0xFE00) == 0x1800) 71 | return (*i & 7); 72 | else if((*i & 0xFF00) == 0x4400) 73 | return (*i & 7) | ((*i & 0x80) >> 4) ; 74 | else if((*i & 0xFFE0) == 0xEB00) 75 | return (*(i + 1) >> 8) & 0xF; 76 | else 77 | return 0; 78 | } 79 | 80 | int insn_add_reg_rm(uint16_t* i) 81 | { 82 | if((*i & 0xFE00) == 0x1800) 83 | return (*i >> 6) & 7; 84 | else if((*i & 0xFF00) == 0x4400) 85 | return (*i >> 3) & 0xF; 86 | else if((*i & 0xFFE0) == 0xEB00) 87 | return *(i + 1) & 0xF; 88 | else 89 | return 0; 90 | } 91 | 92 | int insn_is_mov_imm(uint16_t* i) 93 | { 94 | if((*i & 0xF800) == 0x2000) 95 | return 1; 96 | else if((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) 97 | return 1; 98 | else if((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) 99 | return 1; 100 | else 101 | return 0; 102 | } 103 | 104 | int insn_mov_imm_rd(uint16_t* i) 105 | { 106 | if((*i & 0xF800) == 0x2000) 107 | return (*i >> 8) & 7; 108 | else if((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) 109 | return (*(i + 1) >> 8) & 0xF; 110 | else if((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) 111 | return (*(i + 1) >> 8) & 0xF; 112 | else 113 | return 0; 114 | } 115 | 116 | int insn_mov_imm_imm(uint16_t* i) 117 | { 118 | if((*i & 0xF800) == 0x2000) 119 | return *i & 0xF; 120 | else if((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) 121 | return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); 122 | else if((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) 123 | return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); 124 | else 125 | return 0; 126 | } 127 | 128 | int insn_is_movt(uint16_t* i) 129 | { 130 | return (*i & 0xFBF0) == 0xF2C0 && (*(i + 1) & 0x8000) == 0; 131 | } 132 | 133 | int insn_movt_rd(uint16_t* i) 134 | { 135 | return (*(i + 1) >> 8) & 0xF; 136 | } 137 | 138 | int insn_movt_imm(uint16_t* i) 139 | { 140 | return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); 141 | } 142 | 143 | int insn_is_ldr_imm(uint16_t* i) 144 | { 145 | uint8_t opA = bit_range(*i, 15, 12); 146 | uint8_t opB = bit_range(*i, 11, 9); 147 | 148 | return opA == 6 && (opB & 4) == 4; 149 | } 150 | 151 | int insn_is_ldr_literal(uint16_t *i){ 152 | return (*i >> 11) == 0b01001; 153 | } 154 | 155 | int insn_is_adr(uint16_t *i){ 156 | return HAS_BITS(*i, 0b10100 << 11); 157 | } 158 | 159 | 160 | int insn_is_pop(uint16_t *i){ 161 | return (*i >> 9) == 0b1011110; 162 | } 163 | 164 | int insn_is_push(uint16_t *i){ 165 | return HAS_BITS(*i, 0b1011010 << 9); 166 | } 167 | 168 | int insn_is_thumb2_pop(uint16_t *i){ 169 | return (*i == 0xe8bd); 170 | } 171 | 172 | int insn_is_thumb2_tst(uint16_t *i){ 173 | return !insn_is_bl(i) && (((*i >> 5) & ~(0b100000)) == 0b11110000000); 174 | } 175 | 176 | int insn_tst_imm(uint16_t *i){ 177 | return *(i+1) % (1<<8); 178 | } 179 | 180 | int insn_is_thumb2_push(uint16_t *i){ 181 | return (*i == 0xe92d); 182 | } 183 | 184 | int insn_is_thumb2_ldr(uint16_t *i){ 185 | return HAS_BITS(*i, 0b111110001101 << 4); 186 | } 187 | 188 | int insn_ldr_imm_rt(uint16_t* i) 189 | { 190 | return (*i & 7); 191 | } 192 | 193 | int insn_ldr_imm_imm(uint16_t* i) 194 | { 195 | return (((*i >> 6) & 0x1F) << 2); 196 | } 197 | 198 | int insn_thumb2_ldr_imm_imm(uint16_t* i){ 199 | return *(i+1) % (1<<12); 200 | } 201 | 202 | int insn_is_bl(uint16_t* i) 203 | { 204 | if((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd000) == 0xd000) 205 | return 1; 206 | else if((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd001) == 0xc000) 207 | return 1; 208 | else 209 | return 0; 210 | } 211 | 212 | int insn_is_thumb2_branch(uint16_t *i){ 213 | return (*i >>11 == 0b11110) && (*(i+1)>>15 == 0b1); 214 | } 215 | 216 | int insn_is_thumb_branch(uint16_t *i){ 217 | return ((*i >>11 == 0b11100) || (*i >>12 == 0b1101)); 218 | } 219 | 220 | int insn_is_thumb2_bne(uint16_t *i){ 221 | return HAS_BITS(*i >>6, 0b1111000001) && (*(i+1)>>15 == 0b1); 222 | } 223 | 224 | int insn_is_thumb2_orr(uint16_t *i){ 225 | return HAS_BITS((*i)>>5, 0b11110000010) && (*(i+1) >> 15 == 0); 226 | } 227 | 228 | int insn_is_thumb2_strw(uint16_t *i){ 229 | return (*i >> 4) == 0b111110001100; 230 | } 231 | 232 | int insn_is_thumb2_add(uint16_t *i){ 233 | return (((*i >> 5) & ~(1<<5)) == 0b11110001000 && (*(i+1) >> 15) == 0); 234 | } 235 | 236 | uint8_t insn_thumb2_orr_rn(uint16_t *i){ 237 | return *i % (1<<4); 238 | } 239 | 240 | uint8_t insn_ldr_literal_rt(uint16_t *i){ 241 | return (*i >> 8) % (1 << 3); 242 | } 243 | 244 | uint8_t insn_ldr_literal_imm(uint16_t *i){ 245 | return *i % (1 << 8); 246 | } 247 | 248 | uint8_t insn_adr_rd(uint16_t *i){ 249 | return (*i >> 8) % (1 << 3); 250 | } 251 | 252 | uint8_t insn_adr_imm(uint16_t *i){ 253 | return *i % (1 << 8); 254 | } 255 | 256 | uint8_t insn_thumb2_orr_rd(uint16_t *i){ 257 | return (*(i+1) >> 8) % (1 << 4); 258 | } 259 | 260 | uint8_t insn_thumb2_orr_imm(uint16_t *i){ 261 | return *(i+1) % (1<<8); 262 | } 263 | 264 | uint8_t insn_thumb2_strw_rn(uint16_t *i){ 265 | return *i % (1<<4); 266 | } 267 | 268 | uint8_t insn_thumb2_strw_rt(uint16_t *i){ 269 | return *(i+1) >> 12; 270 | } 271 | 272 | uint8_t insn_thumb2_strw_imm(uint16_t *i){ 273 | return *(i+1) % (1 << 12); 274 | } 275 | 276 | uint8_t insn_thumb2_add_rn(uint16_t *i){ 277 | return *i % (1 << 4); 278 | } 279 | 280 | uint8_t insn_thumb2_add_rd(uint16_t *i){ 281 | return (*(i+1) >> 8) % (1 << 4); 282 | } 283 | 284 | uint8_t insn_thumb2_add_imm(uint16_t *i){ 285 | return *(i+1) % (1 << 8); 286 | } 287 | 288 | uint32_t insn_thumb2_branch_imm(uint16_t *i){ 289 | uint32_t imm6 = (*i % (1<<6)); 290 | uint32_t imm11 = *(i+1) % (1<<11); 291 | return (imm6<<11) | imm11; 292 | } 293 | 294 | uint32_t insn_thumb_branch_imm(uint16_t *i){ 295 | if (*i >>11 == 0b11100) { 296 | return *i % (1<<11); 297 | }else{ 298 | return *i % (1<<8); 299 | } 300 | } 301 | 302 | 303 | 304 | uint32_t insn_bl_imm32(uint16_t* i) 305 | { 306 | uint16_t insn0 = *i; 307 | uint16_t insn1 = *(i + 1); 308 | uint32_t s = (insn0 >> 10) & 1; 309 | uint32_t j1 = (insn1 >> 13) & 1; 310 | uint32_t j2 = (insn1 >> 11) & 1; 311 | uint32_t i1 = ~(j1 ^ s) & 1; 312 | uint32_t i2 = ~(j2 ^ s) & 1; 313 | uint32_t imm10 = insn0 & 0x3ff; 314 | uint32_t imm11 = insn1 & 0x7ff; 315 | uint32_t imm32 = (imm11 << 1) | (imm10 << 12) | (i2 << 22) | (i1 << 23) | (s ? 0xff000000 : 0); 316 | return imm32; 317 | } 318 | 319 | uint16_t *find_rel_branch_ref(uint16_t* start, size_t len, int step, int (*branch_check_func)(uint16_t*), int32_t (*branch_imm_func)(uint16_t*)){ 320 | for (uint16_t *i = start; len>sizeof(uint16_t); len-=abs(step)*sizeof(uint16_t),i+=step) { 321 | if (branch_check_func(i)) { 322 | int32_t imm = (branch_imm_func(i)+2)*2; 323 | uint8_t *dst = imm + (uint8_t*)i; 324 | if (dst == start) { 325 | return i; 326 | } 327 | } 328 | } 329 | return 0; 330 | } 331 | 332 | uint16_t* find_literal_ref(uint32_t region, uint8_t* kdata, size_t ksize, uint32_t address){ 333 | 334 | for (uint16_t *p=kdata; pkdata; pp--) { 340 | 341 | if (insn_is_32bit(pp) && insn_is_movt(pp) && insn_movt_rd(pp) == rd && !(val>>16)){ 342 | val |= insn_movt_imm(pp) << 16; 343 | }else if (insn_is_32bit(pp) && insn_is_mov_imm(pp) && insn_mov_imm_rd(pp) == rd && !(val & ((1<<16)-1))){ 344 | val |= insn_mov_imm_imm(pp); 345 | } 346 | else if (insn_is_ldr_literal(pp) && insn_ldr_literal_rt(pp) == rd){ 347 | val = (insn_ldr_literal_imm(pp)*4+2); 348 | if (insn_is_32bit(pp)) 349 | val +=2; 350 | val = *(uint32_t*)((uint8_t*)p+val-2); 351 | break; 352 | } 353 | else if (insn_is_push(pp)){ 354 | val=0; 355 | break; 356 | } 357 | if (val >> 16 && (val & ((1<<16)-1))) 358 | break; 359 | } 360 | if (!val) 361 | continue; 362 | 363 | uint8_t* ref = pc + 4 + val; 364 | if (ref == address+region) 365 | return p; 366 | } 367 | } 368 | return 0; 369 | } 370 | 371 | 372 | /* patchfinder32 - END */ 373 | -------------------------------------------------------------------------------- /offsetfinder/patchfinder32/patchfinder32.h: -------------------------------------------------------------------------------- 1 | // 2 | // patchfinder32.h 3 | // HomeDepotOF 4 | // 5 | // Created by Nicolò Blasi on 24/08/2017. 6 | // Copyright © 2017 Nicolò Blasi. All rights reserved. 7 | // 8 | 9 | /* patchfinder32 - credits to planetbeing (https://github.com/planetbeing/ios-jailbreak-patchfinder) */ 10 | 11 | #ifndef patchfinder32_h 12 | #define patchfinder32_h 13 | 14 | #include 15 | #include 16 | 17 | int insn_is_32bit(uint16_t* i); 18 | 19 | int insn_is_add_reg(uint16_t* i); 20 | int insn_add_reg_rd(uint16_t* i); 21 | int insn_add_reg_rm(uint16_t* i); 22 | 23 | int insn_is_mov_imm(uint16_t* i); 24 | int insn_mov_imm_rd(uint16_t* i); 25 | int insn_mov_imm_imm(uint16_t* i); 26 | 27 | int insn_is_movt(uint16_t* i); 28 | int insn_movt_rd(uint16_t* i); 29 | int insn_movt_imm(uint16_t* i); 30 | 31 | int insn_is_ldr_imm(uint16_t* i); 32 | int insn_ldr_imm_rt(uint16_t* i); 33 | int insn_ldr_imm_imm(uint16_t* i); 34 | int insn_thumb2_ldr_imm_imm(uint16_t* i); 35 | 36 | 37 | int insn_is_bl(uint16_t* i); 38 | int insn_is_thumb2_branch(uint16_t *i); 39 | int insn_is_thumb_branch(uint16_t *i); 40 | int insn_is_thumb2_bne(uint16_t *i); 41 | int insn_is_thumb2_orr(uint16_t *i); 42 | int insn_is_thumb2_strw(uint16_t *i); 43 | int insn_is_thumb2_add(uint16_t *i); 44 | int insn_is_ldr_literal(uint16_t *i); 45 | 46 | int insn_is_adr(uint16_t *i); 47 | 48 | 49 | uint8_t insn_thumb2_orr_rn(uint16_t *i); 50 | uint8_t insn_thumb2_orr_rd(uint16_t *i); 51 | uint8_t insn_thumb2_orr_imm(uint16_t *i); 52 | uint8_t insn_thumb2_strw_rn(uint16_t *i); 53 | uint8_t insn_thumb2_strw_rt(uint16_t *i); 54 | uint8_t insn_thumb2_strw_imm(uint16_t *i); 55 | uint8_t insn_thumb2_add_rn(uint16_t *i); 56 | uint8_t insn_thumb2_add_rd(uint16_t *i); 57 | uint8_t insn_thumb2_add_imm(uint16_t *i); 58 | uint8_t insn_ldr_literal_rt(uint16_t *i); 59 | uint8_t insn_ldr_literal_imm(uint16_t *i); 60 | uint8_t insn_adr_rd(uint16_t *i); 61 | uint8_t insn_adr_imm(uint16_t *i); 62 | 63 | uint32_t insn_thumb2_branch_imm(uint16_t *i); 64 | uint32_t insn_thumb_branch_imm(uint16_t *i); 65 | 66 | 67 | uint32_t insn_bl_imm32(uint16_t* i); 68 | 69 | int insn_is_pop(uint16_t *i); 70 | int insn_is_push(uint16_t *i); 71 | int insn_is_thumb2_ldr(uint16_t *i); 72 | int insn_is_thumb2_pop(uint16_t *i); 73 | int insn_is_thumb2_push(uint16_t *i); 74 | int insn_is_thumb2_tst(uint16_t *i); 75 | int insn_tst_imm(uint16_t *i); 76 | 77 | 78 | 79 | 80 | uint16_t *find_rel_branch_ref(uint16_t* start, size_t len, int step, int (*branch_check_func)(uint16_t*), int32_t (*branch_imm_func)(uint16_t*)); 81 | uint16_t* find_literal_ref(uint32_t region, uint8_t* kdata, size_t ksize, uint32_t address); 82 | 83 | 84 | #endif /* patchfinder32_h */ 85 | --------------------------------------------------------------------------------