├── .gitignore ├── README.md ├── dumpdecrypted.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── monkey.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── monkey.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── dumpdecrypted ├── Package ├── DEBIAN │ └── control └── Library │ └── MobileSubstrate │ └── DynamicLibraries │ ├── dumpdecrypted.dylib │ └── dumpdecrypted.plist ├── dumpdecrypted-Prefix.pch └── dumpdecrypted.m /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | It is recommended to use [frida-ios-dump](https://github.com/AloneMonkey/frida-ios-dump) instead! 2 | 3 | Dumps decrypted mach-o files from encrypted `applications`、`framework` or `app extensions`. 4 | 5 | ### You should install [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev) first 6 | 7 | 8 | # Usage 9 | 10 | 1) open `dumpdecrypted.xcodeproj` edit `dumpdecrypted.plist` 11 | 12 | ``` 13 | { 14 | Filter = { 15 | Bundles = ("target.bundle.id"); 16 | }; 17 | } 18 | ``` 19 | 20 | 2) Set Build Settings 21 | 22 | * MonkeyDevDeviceIP 23 | * MonkeyDevDevicePort 24 | 25 | 3) launch application or app extension 26 | 27 | ``` 28 | mach-o decryption dumper 29 | DISCLAIMER: This tool is only meant for security research purposes, not for application crackers. 30 | [+] detected 32bit ARM binary in memory. 31 | [+] offset to cryptid found: @0x1ba08(from 0x1b000) = a08 32 | [+] Found encrypted data at address 00004000 of length 573440 bytes - type 1. 33 | [+] Opening /private/var/mobile/Containers/Bundle/Application/A9622900-FC0A-4D64-AC2E-AC9B69773A22/xxx.app/PlugIns/xxx.appex/xxx for reading. 34 | [+] Reading header 35 | [+] Detecting header type 36 | [+] Executable is a FAT image - searching for right architecture 37 | [+] Correct arch is at offset 16384 in the file 38 | [+] Opening /var/mobile/Containers/Data/PluginKitPlugin/D5C1CB12-DB5B-4C53-9191-B23142841035/Documents/xxx.decrypted for writing. 39 | [+] Copying the not encrypted start of the file 40 | [+] Dumping the decrypted data into the file 41 | [+] Copying the not encrypted remainder of the file 42 | [+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset 4a08 43 | [+] Closing original file 44 | [+] Closing dump file 45 | ``` 46 | 47 | # Check And Thin 48 | $ otool -l xxx.decrypted | grep crypt 49 | 50 | ``` 51 | xxx.decrypted (architecture armv7): 52 | cryptoff 16384 53 | cryptsize 10960896 54 | cryptid 0 55 | xxx.decrypted (architecture arm64): 56 | cryptoff 16384 57 | cryptsize 12124160 58 | cryptid 1 59 | ``` 60 | 61 | Thin: 62 | 63 | ``` 64 | $ lipo -thin armv7 xxx.decrypted -output xxx_armv7.decrypted 65 | $ lipo -thin armv64 xxx.decrypted -output xxx_arm64.decrypted 66 | ``` 67 | 68 | 69 | # Author 70 | 71 | [Dumpdecrypted](https://github.com/stefanesser/dumpdecrypted) was orignally developed by [stefanesser](https://github.com/stefanesser). 72 | Learn from [conradev](https://github.com/conradev/dumpdecrypted) 73 | -------------------------------------------------------------------------------- /dumpdecrypted.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8C0441D11FE54F3100DD366C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C0441D01FE54F3100DD366C /* Foundation.framework */; }; 11 | 8C0441D91FE54F3100DD366C /* dumpdecrypted.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C0441D81FE54F3100DD366C /* dumpdecrypted.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 8C0441CD1FE54F3100DD366C /* dumpdecrypted.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = dumpdecrypted.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 16 | 8C0441D01FE54F3100DD366C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 17 | 8C0441D51FE54F3100DD366C /* control */ = {isa = PBXFileReference; lastKnownFileType = text; name = control; path = Package/DEBIAN/control; sourceTree = ""; }; 18 | 8C0441D71FE54F3100DD366C /* dumpdecrypted-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "dumpdecrypted-Prefix.pch"; sourceTree = ""; }; 19 | 8C0441D81FE54F3100DD366C /* dumpdecrypted.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = dumpdecrypted.m; sourceTree = ""; }; 20 | 8C0441DD1FE54F3100DD366C /* dumpdecrypted.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = dumpdecrypted.plist; path = Package/Library/MobileSubstrate/DynamicLibraries/dumpdecrypted.plist; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 8C0441C91FE54F3100DD366C /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | 8C0441D11FE54F3100DD366C /* Foundation.framework in Frameworks */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | 8C0441C31FE54F3100DD366C = { 36 | isa = PBXGroup; 37 | children = ( 38 | 8C0441D21FE54F3100DD366C /* dumpdecrypted */, 39 | 8C0441CF1FE54F3100DD366C /* Frameworks */, 40 | 8C0441CE1FE54F3100DD366C /* Products */, 41 | ); 42 | sourceTree = ""; 43 | }; 44 | 8C0441CE1FE54F3100DD366C /* Products */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 8C0441CD1FE54F3100DD366C /* dumpdecrypted.dylib */, 48 | ); 49 | name = Products; 50 | sourceTree = ""; 51 | }; 52 | 8C0441CF1FE54F3100DD366C /* Frameworks */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 8C0441D01FE54F3100DD366C /* Foundation.framework */, 56 | ); 57 | name = Frameworks; 58 | sourceTree = ""; 59 | }; 60 | 8C0441D21FE54F3100DD366C /* dumpdecrypted */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 8C0441D81FE54F3100DD366C /* dumpdecrypted.m */, 64 | 8C0441D31FE54F3100DD366C /* Package */, 65 | 8C0441D61FE54F3100DD366C /* Supporting Files */, 66 | ); 67 | path = dumpdecrypted; 68 | sourceTree = ""; 69 | }; 70 | 8C0441D31FE54F3100DD366C /* Package */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 8C0441D41FE54F3100DD366C /* DEBIAN */, 74 | 8C0441DA1FE54F3100DD366C /* Library */, 75 | ); 76 | name = Package; 77 | sourceTree = ""; 78 | }; 79 | 8C0441D41FE54F3100DD366C /* DEBIAN */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 8C0441D51FE54F3100DD366C /* control */, 83 | ); 84 | name = DEBIAN; 85 | sourceTree = ""; 86 | }; 87 | 8C0441D61FE54F3100DD366C /* Supporting Files */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 8C0441D71FE54F3100DD366C /* dumpdecrypted-Prefix.pch */, 91 | ); 92 | name = "Supporting Files"; 93 | sourceTree = ""; 94 | }; 95 | 8C0441DA1FE54F3100DD366C /* Library */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 8C0441DB1FE54F3100DD366C /* MobileSubstrate */, 99 | ); 100 | name = Library; 101 | sourceTree = ""; 102 | }; 103 | 8C0441DB1FE54F3100DD366C /* MobileSubstrate */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 8C0441DC1FE54F3100DD366C /* DynamicLibraries */, 107 | ); 108 | name = MobileSubstrate; 109 | sourceTree = ""; 110 | }; 111 | 8C0441DC1FE54F3100DD366C /* DynamicLibraries */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 8C0441DD1FE54F3100DD366C /* dumpdecrypted.plist */, 115 | ); 116 | name = DynamicLibraries; 117 | sourceTree = ""; 118 | }; 119 | /* End PBXGroup section */ 120 | 121 | /* Begin PBXHeadersBuildPhase section */ 122 | 8C0441CA1FE54F3100DD366C /* Headers */ = { 123 | isa = PBXHeadersBuildPhase; 124 | buildActionMask = 2147483647; 125 | files = ( 126 | ); 127 | runOnlyForDeploymentPostprocessing = 0; 128 | }; 129 | /* End PBXHeadersBuildPhase section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | 8C0441CC1FE54F3100DD366C /* dumpdecrypted */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 8C0441E01FE54F3100DD366C /* Build configuration list for PBXNativeTarget "dumpdecrypted" */; 135 | buildPhases = ( 136 | 8C0441C81FE54F3100DD366C /* Sources */, 137 | 8C0441C91FE54F3100DD366C /* Frameworks */, 138 | 8C0441CA1FE54F3100DD366C /* Headers */, 139 | 8C0441CB1FE54F3100DD366C /* ShellScript */, 140 | ); 141 | buildRules = ( 142 | ); 143 | dependencies = ( 144 | ); 145 | name = dumpdecrypted; 146 | productName = dumpdecrypted; 147 | productReference = 8C0441CD1FE54F3100DD366C /* dumpdecrypted.dylib */; 148 | productType = "com.apple.product-type.library.dynamic"; 149 | }; 150 | /* End PBXNativeTarget section */ 151 | 152 | /* Begin PBXProject section */ 153 | 8C0441C41FE54F3100DD366C /* Project object */ = { 154 | isa = PBXProject; 155 | attributes = { 156 | LastUpgradeCheck = 0900; 157 | TargetAttributes = { 158 | 8C0441CC1FE54F3100DD366C = { 159 | CreatedOnToolsVersion = 9.0; 160 | ProvisioningStyle = Automatic; 161 | }; 162 | }; 163 | }; 164 | buildConfigurationList = 8C0441C71FE54F3100DD366C /* Build configuration list for PBXProject "dumpdecrypted" */; 165 | compatibilityVersion = "Xcode 8.0"; 166 | developmentRegion = en; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = 8C0441C31FE54F3100DD366C; 172 | productRefGroup = 8C0441CE1FE54F3100DD366C /* Products */; 173 | projectDirPath = ""; 174 | projectRoot = ""; 175 | targets = ( 176 | 8C0441CC1FE54F3100DD366C /* dumpdecrypted */, 177 | ); 178 | }; 179 | /* End PBXProject section */ 180 | 181 | /* Begin PBXShellScriptBuildPhase section */ 182 | 8C0441CB1FE54F3100DD366C /* ShellScript */ = { 183 | isa = PBXShellScriptBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | ); 187 | inputPaths = ( 188 | ); 189 | outputPaths = ( 190 | ); 191 | runOnlyForDeploymentPostprocessing = 0; 192 | shellPath = /bin/sh; 193 | shellScript = "/opt/MonkeyDev/bin/md --xcbp"; 194 | }; 195 | /* End PBXShellScriptBuildPhase section */ 196 | 197 | /* Begin PBXSourcesBuildPhase section */ 198 | 8C0441C81FE54F3100DD366C /* Sources */ = { 199 | isa = PBXSourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 8C0441D91FE54F3100DD366C /* dumpdecrypted.m in Sources */, 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | }; 206 | /* End PBXSourcesBuildPhase section */ 207 | 208 | /* Begin XCBuildConfiguration section */ 209 | 8C0441DE1FE54F3100DD366C /* Release */ = { 210 | isa = XCBuildConfiguration; 211 | buildSettings = { 212 | CODE_SIGN_IDENTITY = "iPhone Developer"; 213 | COPY_PHASE_STRIP = YES; 214 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; 215 | FRAMEWORK_SEARCH_PATHS = ( 216 | "$(MonkeyDevPath)/frameworks/**", 217 | "$(MonkeyDevTheosPath)/vendor/lib", 218 | ); 219 | GCC_C_LANGUAGE_STANDARD = gnu99; 220 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 222 | GCC_WARN_UNUSED_VARIABLE = YES; 223 | HEADER_SEARCH_PATHS = "$(MonkeyDevTheosPath)/vendor/include/**"; 224 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 225 | LIBRARY_SEARCH_PATHS = "$(MonkeyDevTheosPath)/vendor/lib/**"; 226 | MonkeyDevPath = /opt/MonkeyDev; 227 | MonkeyDevTheosPath = /opt/theos; 228 | OTHER_CFLAGS = "-DTHEOS_INSTANCE_NAME=\"\\\"dumpdecrypted\\\"\""; 229 | SDKROOT = iphoneos; 230 | TARGETED_DEVICE_FAMILY = "1,2"; 231 | VALIDATE_PRODUCT = YES; 232 | }; 233 | name = Release; 234 | }; 235 | 8C0441DF1FE54F3100DD366C /* Debug */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | CODE_SIGN_IDENTITY = "iPhone Developer"; 239 | COPY_PHASE_STRIP = NO; 240 | EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.gch (*) .DS_Store CVS .svn .git .hg *.xcodeproj *.xcode *.pbproj *.pbxproj"; 241 | FRAMEWORK_SEARCH_PATHS = ( 242 | "$(MonkeyDevPath)/frameworks/**", 243 | "$(MonkeyDevTheosPath)/vendor/lib", 244 | ); 245 | GCC_C_LANGUAGE_STANDARD = gnu99; 246 | GCC_DYNAMIC_NO_PIC = NO; 247 | GCC_OPTIMIZATION_LEVEL = 0; 248 | GCC_PREPROCESSOR_DEFINITIONS = ( 249 | "DEBUG=1", 250 | "$(inherited)", 251 | ); 252 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 253 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 254 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | HEADER_SEARCH_PATHS = "$(MonkeyDevTheosPath)/vendor/include/**"; 257 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 258 | LIBRARY_SEARCH_PATHS = "$(MonkeyDevTheosPath)/vendor/lib/**"; 259 | MonkeyDevPath = /opt/MonkeyDev; 260 | MonkeyDevTheosPath = /opt/theos; 261 | OTHER_CFLAGS = "-DTHEOS_INSTANCE_NAME=\"\\\"dumpdecrypted\\\"\""; 262 | SDKROOT = iphoneos; 263 | TARGETED_DEVICE_FAMILY = "1,2"; 264 | VALIDATE_PRODUCT = NO; 265 | }; 266 | name = Debug; 267 | }; 268 | 8C0441E11FE54F3100DD366C /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | CODE_SIGN_IDENTITY = ""; 272 | CODE_SIGN_STYLE = Automatic; 273 | DEVELOPMENT_TEAM = 9XQEPG2J2J; 274 | DYLIB_COMPATIBILITY_VERSION = 1; 275 | DYLIB_CURRENT_VERSION = 1; 276 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 277 | GCC_PREFIX_HEADER = "dumpdecrypted/dumpdecrypted-Prefix.pch"; 278 | HEADER_SEARCH_PATHS = ( 279 | "$(MonkeyDevPath)/include", 280 | "$(MonkeyDevTheosPath)/vendor/include/**", 281 | ); 282 | INSTALL_PATH = /Library/MobileSubstrate/DynamicLibraries; 283 | MonkeyDevBuildPackageOnAnyBuild = NO; 284 | MonkeyDevClearUiCacheOnInstall = NO; 285 | MonkeyDevCopyOnBuild = NO; 286 | MonkeyDevDeviceIP = ""; 287 | MonkeyDevDevicePassword = ""; 288 | MonkeyDevDevicePort = ""; 289 | MonkeyDevInstallOnAnyBuild = YES; 290 | MonkeyDevInstallOnProfiling = YES; 291 | MonkeyDevkillProcessOnInstall = SpringBoard; 292 | PRODUCT_NAME = "$(TARGET_NAME)"; 293 | TARGETED_DEVICE_FAMILY = "1,2"; 294 | }; 295 | name = Release; 296 | }; 297 | 8C0441E21FE54F3100DD366C /* Debug */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | CODE_SIGN_IDENTITY = ""; 301 | CODE_SIGN_STYLE = Automatic; 302 | DEVELOPMENT_TEAM = 9XQEPG2J2J; 303 | DYLIB_COMPATIBILITY_VERSION = 1; 304 | DYLIB_CURRENT_VERSION = 1; 305 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 306 | GCC_PREFIX_HEADER = "dumpdecrypted/dumpdecrypted-Prefix.pch"; 307 | HEADER_SEARCH_PATHS = ( 308 | "$(MonkeyDevPath)/include", 309 | "$(MonkeyDevTheosPath)/vendor/include/**", 310 | ); 311 | INSTALL_PATH = /Library/MobileSubstrate/DynamicLibraries; 312 | MonkeyDevBuildPackageOnAnyBuild = NO; 313 | MonkeyDevClearUiCacheOnInstall = NO; 314 | MonkeyDevCopyOnBuild = NO; 315 | MonkeyDevDeviceIP = ""; 316 | MonkeyDevDevicePassword = ""; 317 | MonkeyDevDevicePort = ""; 318 | MonkeyDevInstallOnAnyBuild = YES; 319 | MonkeyDevInstallOnProfiling = YES; 320 | MonkeyDevkillProcessOnInstall = SpringBoard; 321 | PRODUCT_NAME = "$(TARGET_NAME)"; 322 | TARGETED_DEVICE_FAMILY = "1,2"; 323 | }; 324 | name = Debug; 325 | }; 326 | /* End XCBuildConfiguration section */ 327 | 328 | /* Begin XCConfigurationList section */ 329 | 8C0441C71FE54F3100DD366C /* Build configuration list for PBXProject "dumpdecrypted" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 8C0441DE1FE54F3100DD366C /* Release */, 333 | 8C0441DF1FE54F3100DD366C /* Debug */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | 8C0441E01FE54F3100DD366C /* Build configuration list for PBXNativeTarget "dumpdecrypted" */ = { 339 | isa = XCConfigurationList; 340 | buildConfigurations = ( 341 | 8C0441E11FE54F3100DD366C /* Release */, 342 | 8C0441E21FE54F3100DD366C /* Debug */, 343 | ); 344 | defaultConfigurationIsVisible = 0; 345 | defaultConfigurationName = Release; 346 | }; 347 | /* End XCConfigurationList section */ 348 | }; 349 | rootObject = 8C0441C41FE54F3100DD366C /* Project object */; 350 | } 351 | -------------------------------------------------------------------------------- /dumpdecrypted.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dumpdecrypted.xcodeproj/project.xcworkspace/xcuserdata/monkey.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AloneMonkey/dumpdecrypted/d52213786597a50c36eac0b8114cddbbb05c0129/dumpdecrypted.xcodeproj/project.xcworkspace/xcuserdata/monkey.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /dumpdecrypted.xcodeproj/xcuserdata/monkey.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | dumpdecrypted.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /dumpdecrypted/Package/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: com.alonemonkey.dumpdecrypted 2 | Name: dumpdecrypted 3 | Version: 0.1-1 4 | Description: 5 | Section: Tweaks 6 | Depends: firmware (>= 5.0), mobilesubstrate 7 | Conflicts: 8 | Replaces: 9 | Priority: optional 10 | Architecture: iphoneos-arm 11 | Author: monkey 12 | dev: 13 | Homepage: 14 | Depiction: 15 | Maintainer: 16 | Icon: 17 | 18 | -------------------------------------------------------------------------------- /dumpdecrypted/Package/Library/MobileSubstrate/DynamicLibraries/dumpdecrypted.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AloneMonkey/dumpdecrypted/d52213786597a50c36eac0b8114cddbbb05c0129/dumpdecrypted/Package/Library/MobileSubstrate/DynamicLibraries/dumpdecrypted.dylib -------------------------------------------------------------------------------- /dumpdecrypted/Package/Library/MobileSubstrate/DynamicLibraries/dumpdecrypted.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.target.bundleid 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dumpdecrypted/dumpdecrypted-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'dumpdecrypted' target in the 'dumpdecrypted' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /dumpdecrypted/dumpdecrypted.m: -------------------------------------------------------------------------------- 1 | #if TARGET_OS_SIMULATOR 2 | #error Do not support the simulator, please use the real iPhone Device. 3 | #endif 4 | 5 | /* 6 | 7 | Dumps decrypted iPhone Applications to a file - better solution than those GDB scripts for non working GDB versions 8 | (C) Copyright 2011-2014 Stefan Esser 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define swap32(value) (((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24) ) 22 | 23 | void dumptofile(const char *path, const struct mach_header *mh){ 24 | struct load_command *lc; 25 | struct encryption_info_command *eic; 26 | struct fat_header *fh; 27 | struct fat_arch *arch; 28 | char buffer[1024]; 29 | char rpath[4096],npath[4096]; /* should be big enough for PATH_MAX */ 30 | unsigned int fileoffs = 0, off_cryptid = 0, restsize; 31 | int i,fd,outfd,r,n,toread; 32 | char *tmp; 33 | 34 | if (realpath(path, rpath) == NULL) { 35 | strlcpy(rpath, path, sizeof(rpath)); 36 | } 37 | 38 | /* extract basename */ 39 | tmp = strrchr(rpath, '/'); 40 | printf("\n\n"); 41 | if (tmp == NULL) { 42 | printf("[-] Unexpected error with filename.\n"); 43 | _exit(1); 44 | } else { 45 | printf("[+] Dumping %s\n", tmp+1); 46 | } 47 | 48 | /* detect if this is a arm64 binary */ 49 | if (mh->magic == MH_MAGIC_64) { 50 | lc = (struct load_command *)((unsigned char *)mh + sizeof(struct mach_header_64)); 51 | NSLog(@"[+] detected 64bit ARM binary in memory.\n"); 52 | } else { /* we might want to check for other errors here, too */ 53 | lc = (struct load_command *)((unsigned char *)mh + sizeof(struct mach_header)); 54 | NSLog(@"[+] detected 32bit ARM binary in memory.\n"); 55 | } 56 | 57 | /* searching all load commands for an LC_ENCRYPTION_INFO load command */ 58 | for (i=0; incmds; i++) { 59 | /*printf("Load Command (%d): %08x\n", i, lc->cmd);*/ 60 | 61 | if (lc->cmd == LC_ENCRYPTION_INFO || lc->cmd == LC_ENCRYPTION_INFO_64) { 62 | eic = (struct encryption_info_command *)lc; 63 | 64 | /* If this load command is present, but data is not crypted then exit */ 65 | if (eic->cryptid == 0) { 66 | break; 67 | } 68 | off_cryptid=(off_t)((void*)&eic->cryptid - (void*)mh); 69 | 70 | NSLog(@"[+] offset to cryptid found: @%p(from %p) = %x\n", &eic->cryptid, mh, off_cryptid); 71 | 72 | NSLog(@"[+] Found encrypted data at address %08x of length %u bytes - type %u.\n", eic->cryptoff, eic->cryptsize, eic->cryptid); 73 | 74 | NSLog(@"[+] Opening %s for reading.\n", rpath); 75 | fd = open(rpath, O_RDONLY); 76 | if (fd == -1) { 77 | NSLog(@"[-] Failed opening.\n"); 78 | return; 79 | } 80 | 81 | NSLog(@"[+] Reading header\n"); 82 | n = read(fd, (void *)buffer, sizeof(buffer)); 83 | if (n != sizeof(buffer)) { 84 | NSLog(@"[W] Warning read only %d bytes\n", n); 85 | } 86 | 87 | NSLog(@"[+] Detecting header type\n"); 88 | fh = (struct fat_header *)buffer; 89 | 90 | /* Is this a FAT file - we assume the right endianess */ 91 | if (fh->magic == FAT_CIGAM) { 92 | NSLog(@"[+] Executable is a FAT image - searching for right architecture\n"); 93 | arch = (struct fat_arch *)&fh[1]; 94 | for (i=0; infat_arch); i++) { 95 | if ((mh->cputype == swap32(arch->cputype)) && (mh->cpusubtype == swap32(arch->cpusubtype))) { 96 | fileoffs = swap32(arch->offset); 97 | NSLog(@"[+] Correct arch is at offset %u in the file\n", fileoffs); 98 | break; 99 | } 100 | arch++; 101 | } 102 | if (fileoffs == 0) { 103 | NSLog(@"[-] Could not find correct arch in FAT image\n"); 104 | _exit(1); 105 | } 106 | } else if (fh->magic == MH_MAGIC || fh->magic == MH_MAGIC_64) { 107 | NSLog(@"[+] Executable is a plain MACH-O image\n"); 108 | } else { 109 | NSLog(@"[-] Executable is of unknown type\n"); 110 | return; 111 | } 112 | 113 | //获取程序Document目录路径 114 | NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 115 | 116 | strlcpy(npath, docPath.UTF8String, sizeof(npath)); 117 | strlcat(npath, tmp, sizeof(npath)); 118 | strlcat(npath, ".decrypted", sizeof(npath)); 119 | strlcpy(buffer, npath, sizeof(buffer)); 120 | 121 | NSLog(@"[+] Opening %s for writing.\n", npath); 122 | outfd = open(npath, O_RDWR|O_CREAT|O_TRUNC, 0644); 123 | if (outfd == -1) { 124 | if (strncmp("/private/var/mobile/Applications/", rpath, 33) == 0) { 125 | NSLog(@"[-] Failed opening. Most probably a sandbox issue. Trying something different.\n"); 126 | 127 | /* create new name */ 128 | strlcpy(npath, "/private/var/mobile/Applications/", sizeof(npath)); 129 | tmp = strchr(rpath+33, '/'); 130 | if (tmp == NULL) { 131 | NSLog(@"[-] Unexpected error with filename.\n"); 132 | return; 133 | } 134 | tmp++; 135 | *tmp++ = 0; 136 | strlcat(npath, rpath+33, sizeof(npath)); 137 | strlcat(npath, "tmp/", sizeof(npath)); 138 | strlcat(npath, buffer, sizeof(npath)); 139 | NSLog(@"[+] Opening %s for writing.\n", npath); 140 | outfd = open(npath, O_RDWR|O_CREAT|O_TRUNC, 0644); 141 | } 142 | if (outfd == -1) { 143 | NSLog(@"[-] Failed opening\n"); 144 | return; 145 | } 146 | } 147 | 148 | /* calculate address of beginning of crypted data */ 149 | n = fileoffs + eic->cryptoff; 150 | 151 | restsize = lseek(fd, 0, SEEK_END) - n - eic->cryptsize; 152 | lseek(fd, 0, SEEK_SET); 153 | 154 | NSLog(@"[+] Copying the not encrypted start of the file\n"); 155 | /* first copy all the data before the encrypted data */ 156 | while (n > 0) { 157 | toread = (n > sizeof(buffer)) ? sizeof(buffer) : n; 158 | r = read(fd, buffer, toread); 159 | if (r != toread) { 160 | NSLog(@"[-] Error reading file\n"); 161 | return; 162 | } 163 | n -= r; 164 | 165 | r = write(outfd, buffer, toread); 166 | if (r != toread) { 167 | NSLog(@"[-] Error writing file\n"); 168 | return; 169 | } 170 | } 171 | 172 | /* now write the previously encrypted data */ 173 | NSLog(@"[+] Dumping the decrypted data into the file\n"); 174 | r = write(outfd, (unsigned char *)mh + eic->cryptoff, eic->cryptsize); 175 | if (r != eic->cryptsize) { 176 | NSLog(@"[-] Error writing file\n"); 177 | return; 178 | } 179 | 180 | /* and finish with the remainder of the file */ 181 | n = restsize; 182 | lseek(fd, eic->cryptsize, SEEK_CUR); 183 | NSLog(@"[+] Copying the not encrypted remainder of the file\n"); 184 | while (n > 0) { 185 | toread = (n > sizeof(buffer)) ? sizeof(buffer) : n; 186 | r = read(fd, buffer, toread); 187 | if (r != toread) { 188 | NSLog(@"[-] Error reading file\n"); 189 | return; 190 | } 191 | n -= r; 192 | 193 | r = write(outfd, buffer, toread); 194 | if (r != toread) { 195 | NSLog(@"[-] Error writing file\n"); 196 | return; 197 | } 198 | } 199 | 200 | if (off_cryptid) { 201 | uint32_t zero=0; 202 | off_cryptid+=fileoffs; 203 | NSLog(@"[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset %x\n", off_cryptid); 204 | if (lseek(outfd, off_cryptid, SEEK_SET) != off_cryptid || write(outfd, &zero, 4) != 4) { 205 | NSLog(@"[-] Error writing cryptid value\n"); 206 | } 207 | } 208 | 209 | NSLog(@"[+] Closing original file\n"); 210 | close(fd); 211 | NSLog(@"[+] Closing dump file\n"); 212 | close(outfd); 213 | 214 | return; 215 | } 216 | 217 | lc = (struct load_command *)((unsigned char *)lc+lc->cmdsize); 218 | } 219 | NSLog(@"[-] This mach-o file is not encrypted. Nothing was decrypted.\n"); 220 | return; 221 | } 222 | 223 | static void image_added(const struct mach_header *mh, intptr_t slide) { 224 | Dl_info image_info; 225 | int result = dladdr(mh, &image_info); 226 | dumptofile(image_info.dli_fname, mh); 227 | } 228 | 229 | __attribute__((constructor)) 230 | static void dumpexecutable() { 231 | printf("mach-o decryption dumper\n\n"); 232 | printf("DISCLAIMER: This tool is only meant for security research purposes, not for application crackers."); 233 | _dyld_register_func_for_add_image(&image_added); 234 | } 235 | 236 | 237 | --------------------------------------------------------------------------------