├── README.markdown ├── libevil.xcodeproj └── project.pbxproj ├── libevil ├── libevil-Prefix.pch ├── libevil.h └── libevil.m └── testEvil ├── AppDelegate.h ├── AppDelegate.m ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── en.lproj └── InfoPlist.strings ├── main.m ├── testEvil-Info.plist └── testEvil-Prefix.pch /README.markdown: -------------------------------------------------------------------------------- 1 | libevil 2 | ----------- 3 | 4 | You should not use this code. Seriously. 5 | 6 | libevil uses VM memory protection and remapping tricks to allow for patching arbitrary functions on iOS/ARM. This is similar in function to mach\_override, except that libevil has to work without the ability to write to executable pages. 7 | 8 | This is achieved as follows: 9 | 10 | * All mapped segments of the executable to be patched are remapped to a new address for preservation. 11 | * The target page containing the function to be patched is set to PROT\_NONE, triggering a crash if one attempts to execute anything in that page. 12 | * A custom signal handler interprets the crash: 13 | * If the IP of the crashed thread points at a patched function, thread state is rewritten to point at the new user-supplied function. 14 | * If the IP of the crash thread points at some other address in the patched page, it is rewritten to execute from the 15 | mirrored copy of the binary. 16 | * If the si\_addr of the crash is within the patched page, all registers containing that address are rewritten to point 17 | at the mirrored copy of the binary. 18 | 19 | The entire binary is remapped as to 'correctly' handle PC-relative addressing that would otherwise fail. There are still 20 | innumerable ways that this code can explode in your face. Remember how I said not to use it? 21 | 22 | A fancier implementation would involve performing instruction interpretation from the crashed page, rather than 23 | letting the CPU execute from remapped pages. This would involve actually implementing an ARM emulator, which seems 24 | like drastic overkill for a massive hack. 25 | 26 | The implementation only supports ARM, so you can only test it out on your iOS device. 27 | 28 | Example Usage 29 | ----------- 30 | 31 | Here's an example of how you might patch the NSLog() function. This patch will affect both your own usage, and any system 32 | or library code that calls NSLog(). 33 | 34 | First, define your replacement function, as well as a function pointer to hold a reference 35 | that may be used to call the original NSLog() implementation: 36 | 37 | void (*orig_NSLog)(NSString *fmt, ...) = NULL; 38 | 39 | void my_NSLog (NSString *fmt, ...) { 40 | orig_NSLog(@"I'm in your computers, patching your strings ..."); 41 | 42 | NSString *newFmt = [NSString stringWithFormat: @"[PATCHED]: %@", fmt]; 43 | 44 | va_list ap; 45 | va_start(ap, fmt); 46 | NSLogv(newFmt, ap); 47 | va_end(ap); 48 | } 49 | 50 | To actually apply the patch: 51 | 52 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 53 | evil_init(); 54 | evil_override_ptr(NSLog, my_NSLog, (void **) &orig_NSLog); 55 | NSLog(@"Print a string"); 56 | } 57 | 58 | If you run this code, you should see something like the following. Note that the OS usage of NSLog() has been patched, too: 59 | 60 | Jan 20 10:09:02 Spyglass testEvil[309] : I'm in your computers, patching your strings ... 61 | Jan 20 10:09:02 Spyglass testEvil[309] : [PATCHED]: Print a string 62 | Jan 20 10:09:02 Spyglass testEvil[309] : I'm in your computers, patching your strings ... 63 | Jan 20 10:09:02 Spyglass testEvil[309] : [PATCHED]: Application windows are expected to have a root view controller at the end of application launch 64 | 65 | This works by catching and 'correcting' the crash, so don't try to run the code under the debugger using Xcode. It will just helpfully note that you crashed trying to execute NSLog(). 66 | -------------------------------------------------------------------------------- /libevil.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 054A290516AB71D400C2B9B6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 054A290416AB71D400C2B9B6 /* Foundation.framework */; }; 11 | 054A290A16AB71D400C2B9B6 /* libevil.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 054A290916AB71D400C2B9B6 /* libevil.h */; }; 12 | 054A290C16AB71D400C2B9B6 /* libevil.m in Sources */ = {isa = PBXBuildFile; fileRef = 054A290B16AB71D400C2B9B6 /* libevil.m */; }; 13 | 054A293416AB85D100C2B9B6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 054A291516AB71D400C2B9B6 /* UIKit.framework */; }; 14 | 054A293516AB85D100C2B9B6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 054A290416AB71D400C2B9B6 /* Foundation.framework */; }; 15 | 054A293716AB85D100C2B9B6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 054A293616AB85D100C2B9B6 /* CoreGraphics.framework */; }; 16 | 054A293D16AB85D100C2B9B6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 054A293B16AB85D100C2B9B6 /* InfoPlist.strings */; }; 17 | 054A293F16AB85D100C2B9B6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 054A293E16AB85D100C2B9B6 /* main.m */; }; 18 | 054A294316AB85D100C2B9B6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 054A294216AB85D100C2B9B6 /* AppDelegate.m */; }; 19 | 054A294516AB85D100C2B9B6 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 054A294416AB85D100C2B9B6 /* Default.png */; }; 20 | 054A294716AB85D100C2B9B6 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 054A294616AB85D100C2B9B6 /* Default@2x.png */; }; 21 | 054A294916AB85D100C2B9B6 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 054A294816AB85D100C2B9B6 /* Default-568h@2x.png */; }; 22 | 054A294F16AB862A00C2B9B6 /* liblibevil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 054A290116AB71D400C2B9B6 /* liblibevil.a */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 054A294D16AB862500C2B9B6 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 054A28F816AB71D400C2B9B6 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 054A290016AB71D400C2B9B6; 31 | remoteInfo = libevil; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXCopyFilesBuildPhase section */ 36 | 054A28FF16AB71D400C2B9B6 /* CopyFiles */ = { 37 | isa = PBXCopyFilesBuildPhase; 38 | buildActionMask = 2147483647; 39 | dstPath = "include/${PRODUCT_NAME}"; 40 | dstSubfolderSpec = 16; 41 | files = ( 42 | 054A290A16AB71D400C2B9B6 /* libevil.h in CopyFiles */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXCopyFilesBuildPhase section */ 47 | 48 | /* Begin PBXFileReference section */ 49 | 054A290116AB71D400C2B9B6 /* liblibevil.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblibevil.a; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 054A290416AB71D400C2B9B6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 51 | 054A290816AB71D400C2B9B6 /* libevil-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "libevil-Prefix.pch"; sourceTree = ""; }; 52 | 054A290916AB71D400C2B9B6 /* libevil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libevil.h; sourceTree = ""; }; 53 | 054A290B16AB71D400C2B9B6 /* libevil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = libevil.m; sourceTree = ""; }; 54 | 054A291316AB71D400C2B9B6 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 55 | 054A291516AB71D400C2B9B6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 56 | 054A293216AB85D100C2B9B6 /* testEvil.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testEvil.app; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 054A293616AB85D100C2B9B6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 58 | 054A293A16AB85D100C2B9B6 /* testEvil-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "testEvil-Info.plist"; sourceTree = ""; }; 59 | 054A293C16AB85D100C2B9B6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 60 | 054A293E16AB85D100C2B9B6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 61 | 054A294016AB85D100C2B9B6 /* testEvil-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "testEvil-Prefix.pch"; sourceTree = ""; }; 62 | 054A294116AB85D100C2B9B6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 63 | 054A294216AB85D100C2B9B6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 64 | 054A294416AB85D100C2B9B6 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 65 | 054A294616AB85D100C2B9B6 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 66 | 054A294816AB85D100C2B9B6 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | 054A28FE16AB71D400C2B9B6 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | 054A290516AB71D400C2B9B6 /* Foundation.framework in Frameworks */, 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | 054A292F16AB85D100C2B9B6 /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | 054A293416AB85D100C2B9B6 /* UIKit.framework in Frameworks */, 83 | 054A293516AB85D100C2B9B6 /* Foundation.framework in Frameworks */, 84 | 054A293716AB85D100C2B9B6 /* CoreGraphics.framework in Frameworks */, 85 | 054A294F16AB862A00C2B9B6 /* liblibevil.a in Frameworks */, 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | /* End PBXFrameworksBuildPhase section */ 90 | 91 | /* Begin PBXGroup section */ 92 | 054A28F616AB71D400C2B9B6 = { 93 | isa = PBXGroup; 94 | children = ( 95 | 054A290616AB71D400C2B9B6 /* libevil */, 96 | 054A293816AB85D100C2B9B6 /* testEvil */, 97 | 054A290316AB71D400C2B9B6 /* Frameworks */, 98 | 054A290216AB71D400C2B9B6 /* Products */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 054A290216AB71D400C2B9B6 /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 054A290116AB71D400C2B9B6 /* liblibevil.a */, 106 | 054A293216AB85D100C2B9B6 /* testEvil.app */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | 054A290316AB71D400C2B9B6 /* Frameworks */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 054A290416AB71D400C2B9B6 /* Foundation.framework */, 115 | 054A291316AB71D400C2B9B6 /* SenTestingKit.framework */, 116 | 054A291516AB71D400C2B9B6 /* UIKit.framework */, 117 | 054A293616AB85D100C2B9B6 /* CoreGraphics.framework */, 118 | ); 119 | name = Frameworks; 120 | sourceTree = ""; 121 | }; 122 | 054A290616AB71D400C2B9B6 /* libevil */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 054A290916AB71D400C2B9B6 /* libevil.h */, 126 | 054A290B16AB71D400C2B9B6 /* libevil.m */, 127 | 054A290716AB71D400C2B9B6 /* Supporting Files */, 128 | ); 129 | path = libevil; 130 | sourceTree = ""; 131 | }; 132 | 054A290716AB71D400C2B9B6 /* Supporting Files */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 054A290816AB71D400C2B9B6 /* libevil-Prefix.pch */, 136 | ); 137 | name = "Supporting Files"; 138 | sourceTree = ""; 139 | }; 140 | 054A293816AB85D100C2B9B6 /* testEvil */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 054A294116AB85D100C2B9B6 /* AppDelegate.h */, 144 | 054A294216AB85D100C2B9B6 /* AppDelegate.m */, 145 | 054A293916AB85D100C2B9B6 /* Supporting Files */, 146 | ); 147 | path = testEvil; 148 | sourceTree = ""; 149 | }; 150 | 054A293916AB85D100C2B9B6 /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 054A293A16AB85D100C2B9B6 /* testEvil-Info.plist */, 154 | 054A293B16AB85D100C2B9B6 /* InfoPlist.strings */, 155 | 054A293E16AB85D100C2B9B6 /* main.m */, 156 | 054A294016AB85D100C2B9B6 /* testEvil-Prefix.pch */, 157 | 054A294416AB85D100C2B9B6 /* Default.png */, 158 | 054A294616AB85D100C2B9B6 /* Default@2x.png */, 159 | 054A294816AB85D100C2B9B6 /* Default-568h@2x.png */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | 054A290016AB71D400C2B9B6 /* libevil */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 054A292616AB71D400C2B9B6 /* Build configuration list for PBXNativeTarget "libevil" */; 170 | buildPhases = ( 171 | 054A28FD16AB71D400C2B9B6 /* Sources */, 172 | 054A28FE16AB71D400C2B9B6 /* Frameworks */, 173 | 054A28FF16AB71D400C2B9B6 /* CopyFiles */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = libevil; 180 | productName = libevil; 181 | productReference = 054A290116AB71D400C2B9B6 /* liblibevil.a */; 182 | productType = "com.apple.product-type.library.static"; 183 | }; 184 | 054A293116AB85D100C2B9B6 /* testEvil */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 054A294A16AB85D100C2B9B6 /* Build configuration list for PBXNativeTarget "testEvil" */; 187 | buildPhases = ( 188 | 054A292E16AB85D100C2B9B6 /* Sources */, 189 | 054A292F16AB85D100C2B9B6 /* Frameworks */, 190 | 054A293016AB85D100C2B9B6 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | 054A294E16AB862500C2B9B6 /* PBXTargetDependency */, 196 | ); 197 | name = testEvil; 198 | productName = testEvil; 199 | productReference = 054A293216AB85D100C2B9B6 /* testEvil.app */; 200 | productType = "com.apple.product-type.application"; 201 | }; 202 | /* End PBXNativeTarget section */ 203 | 204 | /* Begin PBXProject section */ 205 | 054A28F816AB71D400C2B9B6 /* Project object */ = { 206 | isa = PBXProject; 207 | attributes = { 208 | LastUpgradeCheck = 0450; 209 | ORGANIZATIONNAME = "Landon Fuller"; 210 | }; 211 | buildConfigurationList = 054A28FB16AB71D400C2B9B6 /* Build configuration list for PBXProject "libevil" */; 212 | compatibilityVersion = "Xcode 3.2"; 213 | developmentRegion = English; 214 | hasScannedForEncodings = 0; 215 | knownRegions = ( 216 | en, 217 | ); 218 | mainGroup = 054A28F616AB71D400C2B9B6; 219 | productRefGroup = 054A290216AB71D400C2B9B6 /* Products */; 220 | projectDirPath = ""; 221 | projectRoot = ""; 222 | targets = ( 223 | 054A290016AB71D400C2B9B6 /* libevil */, 224 | 054A293116AB85D100C2B9B6 /* testEvil */, 225 | ); 226 | }; 227 | /* End PBXProject section */ 228 | 229 | /* Begin PBXResourcesBuildPhase section */ 230 | 054A293016AB85D100C2B9B6 /* Resources */ = { 231 | isa = PBXResourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | 054A293D16AB85D100C2B9B6 /* InfoPlist.strings in Resources */, 235 | 054A294516AB85D100C2B9B6 /* Default.png in Resources */, 236 | 054A294716AB85D100C2B9B6 /* Default@2x.png in Resources */, 237 | 054A294916AB85D100C2B9B6 /* Default-568h@2x.png in Resources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | /* End PBXResourcesBuildPhase section */ 242 | 243 | /* Begin PBXSourcesBuildPhase section */ 244 | 054A28FD16AB71D400C2B9B6 /* Sources */ = { 245 | isa = PBXSourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | 054A290C16AB71D400C2B9B6 /* libevil.m in Sources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | 054A292E16AB85D100C2B9B6 /* Sources */ = { 253 | isa = PBXSourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | 054A293F16AB85D100C2B9B6 /* main.m in Sources */, 257 | 054A294316AB85D100C2B9B6 /* AppDelegate.m in Sources */, 258 | ); 259 | runOnlyForDeploymentPostprocessing = 0; 260 | }; 261 | /* End PBXSourcesBuildPhase section */ 262 | 263 | /* Begin PBXTargetDependency section */ 264 | 054A294E16AB862500C2B9B6 /* PBXTargetDependency */ = { 265 | isa = PBXTargetDependency; 266 | target = 054A290016AB71D400C2B9B6 /* libevil */; 267 | targetProxy = 054A294D16AB862500C2B9B6 /* PBXContainerItemProxy */; 268 | }; 269 | /* End PBXTargetDependency section */ 270 | 271 | /* Begin PBXVariantGroup section */ 272 | 054A293B16AB85D100C2B9B6 /* InfoPlist.strings */ = { 273 | isa = PBXVariantGroup; 274 | children = ( 275 | 054A293C16AB85D100C2B9B6 /* en */, 276 | ); 277 | name = InfoPlist.strings; 278 | sourceTree = ""; 279 | }; 280 | /* End PBXVariantGroup section */ 281 | 282 | /* Begin XCBuildConfiguration section */ 283 | 054A292416AB71D400C2B9B6 /* Debug */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ALWAYS_SEARCH_USER_PATHS = NO; 287 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 288 | CLANG_CXX_LIBRARY = "libc++"; 289 | CLANG_ENABLE_OBJC_ARC = YES; 290 | CLANG_WARN_EMPTY_BODY = YES; 291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 292 | COPY_PHASE_STRIP = NO; 293 | GCC_C_LANGUAGE_STANDARD = gnu99; 294 | GCC_DYNAMIC_NO_PIC = NO; 295 | GCC_OPTIMIZATION_LEVEL = 0; 296 | GCC_PREPROCESSOR_DEFINITIONS = ( 297 | "DEBUG=1", 298 | "$(inherited)", 299 | ); 300 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 301 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 302 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 303 | GCC_WARN_UNUSED_VARIABLE = YES; 304 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 305 | ONLY_ACTIVE_ARCH = YES; 306 | SDKROOT = iphoneos; 307 | }; 308 | name = Debug; 309 | }; 310 | 054A292516AB71D400C2B9B6 /* Release */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 315 | CLANG_CXX_LIBRARY = "libc++"; 316 | CLANG_ENABLE_OBJC_ARC = YES; 317 | CLANG_WARN_EMPTY_BODY = YES; 318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 319 | COPY_PHASE_STRIP = YES; 320 | GCC_C_LANGUAGE_STANDARD = gnu99; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 322 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 323 | GCC_WARN_UNUSED_VARIABLE = YES; 324 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 325 | SDKROOT = iphoneos; 326 | VALIDATE_PRODUCT = YES; 327 | }; 328 | name = Release; 329 | }; 330 | 054A292716AB71D400C2B9B6 /* Debug */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | DSTROOT = /tmp/libevil.dst; 334 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 335 | GCC_PREFIX_HEADER = "libevil/libevil-Prefix.pch"; 336 | OTHER_LDFLAGS = "-ObjC"; 337 | PRODUCT_NAME = "$(TARGET_NAME)"; 338 | SKIP_INSTALL = YES; 339 | }; 340 | name = Debug; 341 | }; 342 | 054A292816AB71D400C2B9B6 /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | DSTROOT = /tmp/libevil.dst; 346 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 347 | GCC_PREFIX_HEADER = "libevil/libevil-Prefix.pch"; 348 | OTHER_LDFLAGS = "-ObjC"; 349 | PRODUCT_NAME = "$(TARGET_NAME)"; 350 | SKIP_INSTALL = YES; 351 | }; 352 | name = Release; 353 | }; 354 | 054A294B16AB85D100C2B9B6 /* Debug */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 358 | FRAMEWORK_SEARCH_PATHS = ( 359 | "$(inherited)", 360 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 361 | ); 362 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 363 | GCC_PREFIX_HEADER = "testEvil/testEvil-Prefix.pch"; 364 | INFOPLIST_FILE = "testEvil/testEvil-Info.plist"; 365 | PRODUCT_NAME = "$(TARGET_NAME)"; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | WRAPPER_EXTENSION = app; 368 | }; 369 | name = Debug; 370 | }; 371 | 054A294C16AB85D100C2B9B6 /* Release */ = { 372 | isa = XCBuildConfiguration; 373 | buildSettings = { 374 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 375 | FRAMEWORK_SEARCH_PATHS = ( 376 | "$(inherited)", 377 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 378 | ); 379 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 380 | GCC_PREFIX_HEADER = "testEvil/testEvil-Prefix.pch"; 381 | INFOPLIST_FILE = "testEvil/testEvil-Info.plist"; 382 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 383 | PRODUCT_NAME = "$(TARGET_NAME)"; 384 | TARGETED_DEVICE_FAMILY = "1,2"; 385 | WRAPPER_EXTENSION = app; 386 | }; 387 | name = Release; 388 | }; 389 | /* End XCBuildConfiguration section */ 390 | 391 | /* Begin XCConfigurationList section */ 392 | 054A28FB16AB71D400C2B9B6 /* Build configuration list for PBXProject "libevil" */ = { 393 | isa = XCConfigurationList; 394 | buildConfigurations = ( 395 | 054A292416AB71D400C2B9B6 /* Debug */, 396 | 054A292516AB71D400C2B9B6 /* Release */, 397 | ); 398 | defaultConfigurationIsVisible = 0; 399 | defaultConfigurationName = Release; 400 | }; 401 | 054A292616AB71D400C2B9B6 /* Build configuration list for PBXNativeTarget "libevil" */ = { 402 | isa = XCConfigurationList; 403 | buildConfigurations = ( 404 | 054A292716AB71D400C2B9B6 /* Debug */, 405 | 054A292816AB71D400C2B9B6 /* Release */, 406 | ); 407 | defaultConfigurationIsVisible = 0; 408 | defaultConfigurationName = Release; 409 | }; 410 | 054A294A16AB85D100C2B9B6 /* Build configuration list for PBXNativeTarget "testEvil" */ = { 411 | isa = XCConfigurationList; 412 | buildConfigurations = ( 413 | 054A294B16AB85D100C2B9B6 /* Debug */, 414 | 054A294C16AB85D100C2B9B6 /* Release */, 415 | ); 416 | defaultConfigurationIsVisible = 0; 417 | defaultConfigurationName = Release; 418 | }; 419 | /* End XCConfigurationList section */ 420 | }; 421 | rootObject = 054A28F816AB71D400C2B9B6 /* Project object */; 422 | } 423 | -------------------------------------------------------------------------------- /libevil/libevil-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'libevil' target in the 'libevil' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /libevil/libevil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Plausible Labs Cooperative, Inc. 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | void evil_init (void); 30 | kern_return_t evil_override_ptr (void *function, const void *newFunction, void **originalRentry); -------------------------------------------------------------------------------- /libevil/libevil.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Landon Fuller . 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | // 30 | // Don't ever use this code. 31 | // It's not thread-safe, async-safe, or child-safe. It will 32 | // destroy the universe and all things in it. It's also a terrible 33 | // idea, and I intentionally avoided worrying about effeciency or 34 | // correctness. 35 | // 36 | // There are ways to make this vaguely reliable, but I'm not telling. 37 | // Don't use this code unless you know how to fix it yourself, 38 | // and probably not even then. I mean it. 39 | // 40 | // You've been warned. 41 | // 42 | 43 | #import 44 | #import 45 | #import 46 | 47 | #import 48 | 49 | #import 50 | 51 | #import 52 | #import 53 | 54 | 55 | struct patch { 56 | vm_address_t orig_addr; 57 | vm_address_t new_addr; 58 | 59 | vm_size_t mapped_size; 60 | 61 | vm_address_t orig_fptr; 62 | vm_address_t orig_fptr_nthumb; // low-order bit masked 63 | vm_address_t new_fptr; 64 | }; 65 | 66 | static struct patch patches[128]; 67 | static size_t patch_count = 0; 68 | 69 | static void page_mapper (int signo, siginfo_t *info, void *uapVoid) { 70 | ucontext_t *uap = uapVoid; 71 | uintptr_t pc = uap->uc_mcontext->__ss.__pc; 72 | 73 | #if 0 74 | NSLog(@"Freak out with address: %p", info->si_addr); 75 | 76 | for (int i = 0; i < 15; i++) { 77 | uintptr_t rv = uap->uc_mcontext->__ss.__r[i]; 78 | NSLog(@"r%d = %p", i, (void *) rv); 79 | } 80 | #endif 81 | 82 | if (pc == (uintptr_t) info->si_addr) { 83 | for (int i = 0; i < patch_count; i++) { 84 | if (patches[i].orig_fptr_nthumb == pc) { 85 | uap->uc_mcontext->__ss.__pc = (uintptr_t) patches[i].new_fptr; 86 | return; 87 | } 88 | } 89 | 90 | for (int i = 0; i < patch_count; i++) { 91 | struct patch *p = &patches[i]; 92 | if (pc >= p->orig_addr && pc < (p->orig_addr + p->mapped_size)) { 93 | uap->uc_mcontext->__ss.__pc = p->new_addr + (pc - p->orig_addr); 94 | return; 95 | } 96 | } 97 | } 98 | 99 | // This is six kinds of wrong; we're just rewriting any registers that match the si_addr, and 100 | // are pointed into now-dead pages. The danger here ought to be obvious. 101 | for (int i = 0; i < patch_count; i++) { 102 | struct patch *p = &patches[i]; 103 | 104 | if ((uintptr_t) info->si_addr < p->orig_addr) 105 | continue; 106 | 107 | if ((uintptr_t) info->si_addr >= p->orig_addr + p->mapped_size) 108 | continue; 109 | 110 | // XXX we abuse the r[] array here. 111 | for (int i = 0; i < 15; i++) { 112 | uintptr_t rv = uap->uc_mcontext->__ss.__r[i]; 113 | if (rv == (uintptr_t) info->si_addr) { 114 | if (p->new_addr > p->orig_addr) 115 | uap->uc_mcontext->__ss.__r[i] -= p->new_addr - p->orig_addr; 116 | else 117 | uap->uc_mcontext->__ss.__r[i] += p->orig_addr - p->new_addr; 118 | #if 0 119 | NSLog(@"Rewrite: %p -> %p", info->si_addr, (void *) uap->uc_mcontext->__ss.__r[i]); 120 | #endif 121 | } 122 | } 123 | 124 | uintptr_t rv = uap->uc_mcontext->__ss.__lr; 125 | if (rv == (uintptr_t) info->si_addr) { 126 | uap->uc_mcontext->__ss.__lr += p->new_addr - p->orig_addr; 127 | if (p->new_addr > p->orig_addr) 128 | uap->uc_mcontext->__ss.__lr -= p->new_addr - p->orig_addr; 129 | else 130 | uap->uc_mcontext->__ss.__lr += p->orig_addr - p->new_addr; 131 | } 132 | } 133 | 134 | return; 135 | } 136 | 137 | void evil_init (void) { 138 | struct sigaction act; 139 | memset(&act, 0, sizeof(act)); 140 | act.sa_sigaction = page_mapper; 141 | act.sa_flags = SA_SIGINFO; 142 | 143 | if (sigaction(SIGSEGV, &act, NULL) < 0) { 144 | perror("sigaction"); 145 | } 146 | 147 | if (sigaction(SIGBUS, &act, NULL) < 0) { 148 | perror("sigaction"); 149 | } 150 | } 151 | 152 | 153 | static BOOL macho_iterate_segments (const void *header, void (^block)(const char segname[16], vm_address_t vmaddr, vm_size_t vmsize, BOOL *cont)) { 154 | const struct mach_header *header32 = (const struct mach_header *) header; 155 | const struct mach_header_64 *header64 = (const struct mach_header_64 *) header; 156 | struct load_command *cmd; 157 | uint32_t ncmds; 158 | 159 | /* Check for 32-bit/64-bit header and extract required values */ 160 | switch (header32->magic) { 161 | /* 32-bit */ 162 | case MH_MAGIC: 163 | case MH_CIGAM: 164 | ncmds = header32->ncmds; 165 | cmd = (struct load_command *) (header32 + 1); 166 | break; 167 | 168 | /* 64-bit */ 169 | case MH_MAGIC_64: 170 | case MH_CIGAM_64: 171 | ncmds = header64->ncmds; 172 | cmd = (struct load_command *) (header64 + 1); 173 | break; 174 | 175 | default: 176 | NSLog(@"Invalid Mach-O header magic value: %x", header32->magic); 177 | return false; 178 | } 179 | 180 | for (uint32_t i = 0; cmd != NULL && i < ncmds; i++) { 181 | BOOL cont = true; 182 | 183 | /* 32-bit text segment */ 184 | if (cmd->cmd == LC_SEGMENT) { 185 | struct segment_command *segment = (struct segment_command *) cmd; 186 | block(segment->segname, segment->vmaddr, segment->vmsize, &cont); 187 | } 188 | 189 | /* 64-bit text segment */ 190 | else if (cmd->cmd == LC_SEGMENT_64) { 191 | struct segment_command_64 *segment = (struct segment_command_64 *) cmd; 192 | block(segment->segname, segment->vmaddr, segment->vmsize, &cont); 193 | } 194 | 195 | cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize); 196 | 197 | if (!cont) 198 | break; 199 | } 200 | 201 | return true; 202 | } 203 | 204 | extern void *_sigtramp; 205 | 206 | // Replace 'function' with 'newImp', and return an address at 'originalRentry' that 207 | // may be used to call the original function. 208 | kern_return_t evil_override_ptr (void *function, const void *newFunction, void **originalRentry) { 209 | __block kern_return_t kt; 210 | 211 | vm_address_t page = trunc_page((vm_address_t) function); 212 | assert(page != trunc_page((vm_address_t) _sigtramp)); 213 | 214 | /* Determine the Mach-O image and size. */ 215 | Dl_info dlinfo; 216 | if (dladdr(function, &dlinfo) == 0) { 217 | NSLog(@"dladdr() failed: %s", dlerror()); 218 | return KERN_FAILURE; 219 | } 220 | 221 | vm_address_t image_addr = (vm_address_t) dlinfo.dli_fbase; 222 | __block vm_address_t image_end = image_addr; 223 | __block intptr_t image_slide = 0x0; 224 | bool ret = macho_iterate_segments(dlinfo.dli_fbase, ^(const char segname[16], vm_address_t vmaddr, vm_size_t vmsize, BOOL *cont) { 225 | if (vmaddr + vmsize > image_end) 226 | image_end = vmaddr + vmsize; 227 | 228 | // compute the slide. we could also get this iterating the images via dyld, but whatever. 229 | if (strcmp(segname, SEG_TEXT) == 0) { 230 | if (vmaddr < image_addr) 231 | image_slide = image_addr - vmaddr; 232 | else 233 | image_slide = vmaddr - image_addr; 234 | } 235 | 236 | }); 237 | vm_address_t image_size = image_end - image_addr; 238 | 239 | if (!ret) { 240 | NSLog(@"Failed parsing Mach-O header"); 241 | return KERN_FAILURE; 242 | } 243 | 244 | /* Allocate a single contigious block large enough for our purposes */ 245 | vm_address_t target = 0x0; 246 | kt = vm_allocate(mach_task_self(), &target, image_size, VM_FLAGS_ANYWHERE); 247 | if (kt != KERN_SUCCESS) { 248 | NSLog(@"Failed reserving sufficient space"); 249 | return KERN_FAILURE; 250 | } 251 | 252 | /* Remap the segments into place */ 253 | macho_iterate_segments(dlinfo.dli_fbase, ^(const char segname[16], vm_address_t vmaddr, vm_size_t vmsize, BOOL *cont) { 254 | if (vmsize == 0) 255 | return; 256 | 257 | vm_address_t seg_source = vmaddr + image_slide; 258 | vm_address_t seg_target = target + (seg_source - image_addr); 259 | 260 | vm_prot_t cprot, mprot; 261 | kt = vm_remap(mach_task_self(), 262 | &seg_target, 263 | vmsize, 264 | 0x0, 265 | VM_FLAGS_FIXED|VM_FLAGS_OVERWRITE, 266 | mach_task_self(), 267 | seg_source, 268 | false, 269 | &cprot, 270 | &mprot, 271 | VM_INHERIT_SHARE); 272 | if (kt != KERN_SUCCESS) { 273 | *cont = false; 274 | return; 275 | } 276 | }); 277 | 278 | if (kt != KERN_SUCCESS) { 279 | NSLog(@"Failed to remap pages: %x", kt); 280 | return kt; 281 | } 282 | 283 | struct patch *p = &patches[patch_count]; 284 | p->orig_addr = image_addr; 285 | p->new_addr = target; 286 | p->mapped_size = image_size; 287 | 288 | p->orig_fptr = (uintptr_t) function; 289 | p->orig_fptr_nthumb = ((uintptr_t) function) & ~1; 290 | p->new_fptr = (vm_address_t) newFunction; 291 | 292 | patch_count++; 293 | 294 | // For whatever reason we can't just remove PROT_WRITE with mprotect. It 295 | // succeeds, but then doesn't do anything. So instead, we overwrite the 296 | // target with a dead page. 297 | // There's a race condition between the vm_allocate and vm_protect. One could 298 | // probably fix that by allocating elsewhere, setting permissions, and remapping in, 299 | // or by mapping in the NULL page. 300 | #if 1 301 | // vm_deallocate(mach_task_self(), page, PAGE_SIZE); 302 | 303 | kt = vm_allocate(mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_FIXED|VM_FLAGS_OVERWRITE); 304 | if (kt != KERN_SUCCESS) { 305 | NSLog(@"Failed reserving sufficient space"); 306 | return KERN_FAILURE; 307 | } 308 | vm_protect(mach_task_self(), page, PAGE_SIZE, true, VM_PROT_NONE); 309 | 310 | #else 311 | if (mprotect(page, PAGE_SIZE, PROT_NONE) != 0) { 312 | perror("mprotect"); 313 | return KERN_FAILURE; 314 | } 315 | #endif 316 | 317 | if (originalRentry) 318 | *originalRentry = (void *) (p->new_addr + (p->orig_fptr - p->orig_addr)); 319 | 320 | return KERN_SUCCESS; 321 | } -------------------------------------------------------------------------------- /testEvil/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // testEvil 4 | // 5 | // Created by Landon Fuller on 1/19/13. 6 | // Copyright (c) 2013 Landon Fuller. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /testEvil/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Landon Fuller . 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #import "AppDelegate.h" 30 | #import "libevil.h" 31 | 32 | void (*orig_NSLog)(NSString *fmt, ...) = NULL; 33 | 34 | void my_NSLog (NSString *fmt, ...) { 35 | orig_NSLog(@"I'm in your computers, patching your strings ..."); 36 | 37 | NSString *newFmt = [NSString stringWithFormat: @"[PATCHED]: %@", fmt]; 38 | 39 | va_list ap; 40 | va_start(ap, fmt); 41 | NSLogv(newFmt, ap); 42 | va_end(ap); 43 | } 44 | 45 | @implementation AppDelegate 46 | 47 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 48 | evil_init(); 49 | 50 | evil_override_ptr(NSLog, my_NSLog, (void **) &orig_NSLog); 51 | NSLog(@"Please print this sir"); 52 | 53 | 54 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 55 | // Override point for customization after application launch. 56 | self.window.backgroundColor = [UIColor whiteColor]; 57 | [self.window makeKeyAndVisible]; 58 | return YES; 59 | } 60 | 61 | - (void)applicationWillResignActive:(UIApplication *)application { 62 | } 63 | 64 | - (void)applicationDidEnterBackground:(UIApplication *)application { 65 | } 66 | 67 | - (void)applicationWillEnterForeground:(UIApplication *)application { 68 | } 69 | 70 | - (void)applicationDidBecomeActive:(UIApplication *)application { 71 | } 72 | 73 | - (void)applicationWillTerminate:(UIApplication *)application { 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /testEvil/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/libevil_patch/2894868def2e8db7da7abc81b138960da79a20d6/testEvil/Default-568h@2x.png -------------------------------------------------------------------------------- /testEvil/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/libevil_patch/2894868def2e8db7da7abc81b138960da79a20d6/testEvil/Default.png -------------------------------------------------------------------------------- /testEvil/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/landonf/libevil_patch/2894868def2e8db7da7abc81b138960da79a20d6/testEvil/Default@2x.png -------------------------------------------------------------------------------- /testEvil/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /testEvil/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Landon Fuller 3 | * 4 | * Copyright (c) 2013 Landon Fuller . 5 | * All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | 30 | #import 31 | #import "AppDelegate.h" 32 | 33 | int main(int argc, char *argv[]) { 34 | @autoreleasepool { 35 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /testEvil/testEvil-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.bikemonkey.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /testEvil/testEvil-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'testEvil' target in the 'testEvil' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | --------------------------------------------------------------------------------