├── .gitignore ├── .travis.yml ├── BH2012_MobileCertificatePinning.pdf ├── LICENSE ├── Makefile ├── README.md ├── SSLKillSwitch.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── SSLKillSwitch.xcscheme ├── SSLKillSwitch ├── Info.plist ├── SSLKillSwitch.h ├── SSLKillSwitch.m └── fishhook │ ├── LICENSE │ ├── README.md │ ├── fishhook.c │ └── fishhook.h ├── SSLKillSwitch2.plist ├── SSLKillSwitchTests ├── Info.plist └── SSLKillSwitchTests.m └── layout ├── DEBIAN └── control └── Library └── PreferenceLoader └── Preferences ├── SSLKillSwitch.png └── SSLKillSwitch_prefs.plist /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Appledoc 29 | html/ 30 | 31 | # Facebook Infer 32 | infer-out/ 33 | 34 | # Theos builds 35 | /theos 36 | /obj 37 | /_ 38 | *.deb 39 | .theos 40 | 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | script: xcodebuild -project SSLKillSwitch.xcodeproj -scheme SSLKillSwitch build test 3 | -------------------------------------------------------------------------------- /BH2012_MobileCertificatePinning.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samyk/ssl-kill-switch2/4f79d0f7fd3c81ed52f4cc2b55b4dbe3d9fec59f/BH2012_MobileCertificatePinning.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is the MIT license: http://www.opensource.org/licenses/mit-license.php 2 | 3 | Copyright 2015 Alban Diquet and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 | software and associated documentation files (the "Software"), to deal in the Software 7 | without restriction, including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 9 | to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 15 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 16 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 17 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCHS := armv7 arm64 2 | 3 | include theos/makefiles/common.mk 4 | 5 | TWEAK_NAME = SSLKillSwitch2 6 | SSLKillSwitch2_FILES = SSLKillSwitch/SSLKillSwitch.m 7 | 8 | SSLKillSwitch2_FRAMEWORKS = Security 9 | 10 | # Build as a Substrate Tweak 11 | SSLKillSwitch2_CFLAGS=-DSUBSTRATE_BUILD 12 | 13 | include $(THEOS_MAKE_PATH)/tweak.mk 14 | include $(THEOS_MAKE_PATH)/aggregate.mk 15 | 16 | 17 | after-install:: 18 | # Respring the device 19 | install.exec "killall -9 SpringBoard" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SSL Kill Switch 2 2 | ================= 3 | 4 | [![Build Status](https://travis-ci.org/nabla-c0d3/ssl-kill-switch2.svg?branch=master)](https://travis-ci.org/nabla-c0d3/ssl-kill-switch2) 5 | 6 | Blackbox tool to disable SSL certificate validation - including certificate 7 | pinning - within iOS and OS X Apps. Second iteration of 8 | https://github.com/iSECPartners/ios-ssl-kill-switch . 9 | 10 | Description 11 | ----------- 12 | 13 | Once loaded into an iOS or OS X App, SSL Kill Switch 2 patches specific 14 | low-level SSL functions within the Secure Transport API in order to override, 15 | and disable the system's default certificate validation as well as any kind 16 | of custom certificate validation (such as certificate pinning). 17 | 18 | It was successfully tested against various Apps implementing certificate 19 | pinning including the Apple App Store. The first version of SSL Kill Switch 20 | was initially released at Black Hat Vegas 2012. 21 | 22 | For more technical details on how it works, see 23 | http://nabla-c0d3.github.io/blog/2013/08/20/ios-ssl-kill-switch-v0-dot-5-released/ 24 | 25 | iOS Instructions 26 | ---------------- 27 | 28 | On iOS, SSL Kill Switch 2 can be installed as a Cydia Subtrate tweak on a 29 | jailbroken device. 30 | 31 | ### WARNING: THIS TWEAK WILL MAKE YOUR DEVICE INSECURE 32 | 33 | Installing SSL Kill Switch 2 allows anyone on the same network as the device to 34 | easily perform man-in-the-middle attacks against *any* SSL or HTTPS connection. 35 | This means that it is trivial to get access to emails, websites viewed in Safari 36 | and any other data downloaded by any App running on the device. 37 | 38 | ### Installation 39 | 40 | The following dependencies should be installed using Cydia: 41 | 42 | * Debian Packager 43 | * Cydia Substrate 44 | * PreferenceLoader 45 | 46 | Then, download the latest pre-compiled package available in the release tab of 47 | the SSL Kill Switch 2's GitHub page. Copy it to the device, install it and 48 | respring the device: 49 | 50 | dpkg -i .deb 51 | killall -HUP SpringBoard 52 | 53 | There should be a new menu in the device's Settings where you can 54 | enable the extension. Finally, kill and restart the App you want to test. 55 | 56 | The tweak can later be uninstalled using: 57 | 58 | dpkg -r com.nablac0d3.SSLKillSwitch2 59 | 60 | ### Intercepting the App Store's traffic 61 | 62 | Lots of people have asked about how to intercept the App Store's traffic using 63 | SSL Kill Switch 2. I wrote down some instructions here: 64 | http://nabla-c0d3.github.io/blog/2013/08/20/intercepting-the-app-stores-traffic-on-ios/ 65 | 66 | ### Build 67 | 68 | The build requires the Theos suite to be installed available at 69 | http://www.iphonedevwiki.net/index.php/Theos/Getting_Started . 70 | 71 | Then, within SSL Kill Switch 2's root foler, create a symlink to your theos 72 | installation: 73 | 74 | ln -s / theos 75 | 76 | Make sure dpkg is installed. If you have Homebrew, use: 77 | 78 | brew install dpkg 79 | 80 | Then, the SSL Kill Switch 2 Debian package can be built using: 81 | 82 | make package 83 | 84 | OS X Instructions 85 | ----------------- 86 | 87 | SSL Kill Switch 2 can be used in OS X Apps as a dynamic library to be injected into processes. 88 | 89 | ### Usage 90 | 91 | On OS X, the SSLKillSwitch library needs to be manually injected into the process where 92 | SSL pinning needs to be disabled. Once injected, it will automatically override and disable 93 | SSL validation. 94 | 95 | There are several ways to do this including: 96 | 97 | * Starting the process with LLDB or in Xcode Debug->Attach to process then pause, and load SSLKillSwitch using `dlopen()`: 98 | 99 | (lldb) expr (void*)dlopen("/path/to/build/SSLKillSwitch.framework/Versions/A/SSLKillSwitch", 1) 100 | 101 | Expected result is a non-zero pointer: 102 | 103 | (void *) $1 = 0x00007f92e74d10c0 104 | 105 | If you receive a zero pointer then you may need to enable code-signing and build for profiling then use the binary in the release folder, and even may have to copy the binary to the app's resources folder. In which case you would have seen a sandbox read violation output to console. To test a new version of the binary you need to kill the app and load it in again. 106 | 107 | * Using DYLD\_INSERT\_LIBRARIES to inject SSLKillSwitch and start the process. 108 | 109 | ### Restricted Apps 110 | 111 | TBD 112 | 113 | ### Build 114 | 115 | Use the Xcode project to build SSL Kill Switch 2 for OS X. The compiled library will then be 116 | available in _Products/SSLKillSwitch.framework/Versions/A/SSLKillSwitch_. This is the binary 117 | that you need to inject in the process where you want to disable SSL pinning. 118 | 119 | Changelog 120 | --------- 121 | 122 | * v0.12: Added support for iOS 11. 123 | * v0.11: Added support for iOS 10. 124 | * v0.10: Added support for proxy-ing [CocoaSPDY](https://github.com/twitter/CocoaSPDY) Apps (ie. Twitter iOS). 125 | * v0.9: Extended the MobileLoader filter to simplify the proxy-ing of the Apple App Store application. 126 | * V0.8: Added support for iOS 9. 127 | * v0.7: Renamed tool to SSL Kill Switch 2; added support for OS X Apps and TrustKit. 128 | * v0.6: Added support for iOS 7. 129 | * v0.5: Complete rewrite in order to add support for proxy-ing Apple's App Store application. 130 | * v0.4: Added hooks for SecTrustEvaluate(). 131 | * v0.3: Bug fixes and support for iOS 6. 132 | * v0.2: Initial release. 133 | 134 | License 135 | ------- 136 | 137 | MIT - See ./LICENSE. 138 | 139 | Author 140 | ------ 141 | 142 | Alban Diquet - @nabla_c0d3 143 | -------------------------------------------------------------------------------- /SSLKillSwitch.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8C2312151B50DB7B0057C459 /* SSLKillSwitch.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C2312141B50DB7B0057C459 /* SSLKillSwitch.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 8C23121B1B50DB7B0057C459 /* SSLKillSwitch.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C23120F1B50DB7B0057C459 /* SSLKillSwitch.framework */; }; 12 | 8C2312221B50DB7B0057C459 /* SSLKillSwitchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2312211B50DB7B0057C459 /* SSLKillSwitchTests.m */; }; 13 | 8C23122C1B50DC670057C459 /* SSLKillSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C23122B1B50DC670057C459 /* SSLKillSwitch.m */; }; 14 | 8C2312341B50EB030057C459 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 8C2312321B50EB030057C459 /* fishhook.c */; }; 15 | 8C2312351B50EB030057C459 /* fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C2312331B50EB030057C459 /* fishhook.h */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 8C23121C1B50DB7B0057C459 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 8C2312061B50DB7A0057C459 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 8C23120E1B50DB7B0057C459; 24 | remoteInfo = SSLKillSwitch; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 8C23120F1B50DB7B0057C459 /* SSLKillSwitch.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSLKillSwitch.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 8C2312131B50DB7B0057C459 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 8C2312141B50DB7B0057C459 /* SSLKillSwitch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSLKillSwitch.h; sourceTree = ""; }; 32 | 8C23121A1B50DB7B0057C459 /* SSLKillSwitchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSLKillSwitchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 8C2312201B50DB7B0057C459 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 8C2312211B50DB7B0057C459 /* SSLKillSwitchTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SSLKillSwitchTests.m; sourceTree = ""; }; 35 | 8C23122B1B50DC670057C459 /* SSLKillSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSLKillSwitch.m; sourceTree = ""; }; 36 | 8C2312321B50EB030057C459 /* fishhook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fishhook.c; path = fishhook/fishhook.c; sourceTree = ""; }; 37 | 8C2312331B50EB030057C459 /* fishhook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fishhook.h; path = fishhook/fishhook.h; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 8C23120B1B50DB7B0057C459 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | 8C2312171B50DB7B0057C459 /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | 8C23121B1B50DB7B0057C459 /* SSLKillSwitch.framework in Frameworks */, 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | 8C2312051B50DB7A0057C459 = { 60 | isa = PBXGroup; 61 | children = ( 62 | 8C2312111B50DB7B0057C459 /* SSLKillSwitch */, 63 | 8C23121E1B50DB7B0057C459 /* SSLKillSwitchTests */, 64 | 8C2312101B50DB7B0057C459 /* Products */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 8C2312101B50DB7B0057C459 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 8C23120F1B50DB7B0057C459 /* SSLKillSwitch.framework */, 72 | 8C23121A1B50DB7B0057C459 /* SSLKillSwitchTests.xctest */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 8C2312111B50DB7B0057C459 /* SSLKillSwitch */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 8C2312311B50EAEE0057C459 /* fishhook */, 81 | 8C2312141B50DB7B0057C459 /* SSLKillSwitch.h */, 82 | 8C2312121B50DB7B0057C459 /* Supporting Files */, 83 | 8C23122B1B50DC670057C459 /* SSLKillSwitch.m */, 84 | ); 85 | path = SSLKillSwitch; 86 | sourceTree = ""; 87 | }; 88 | 8C2312121B50DB7B0057C459 /* Supporting Files */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 8C2312131B50DB7B0057C459 /* Info.plist */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | 8C23121E1B50DB7B0057C459 /* SSLKillSwitchTests */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 8C2312211B50DB7B0057C459 /* SSLKillSwitchTests.m */, 100 | 8C23121F1B50DB7B0057C459 /* Supporting Files */, 101 | ); 102 | path = SSLKillSwitchTests; 103 | sourceTree = ""; 104 | }; 105 | 8C23121F1B50DB7B0057C459 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 8C2312201B50DB7B0057C459 /* Info.plist */, 109 | ); 110 | name = "Supporting Files"; 111 | sourceTree = ""; 112 | }; 113 | 8C2312311B50EAEE0057C459 /* fishhook */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 8C2312321B50EB030057C459 /* fishhook.c */, 117 | 8C2312331B50EB030057C459 /* fishhook.h */, 118 | ); 119 | name = fishhook; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXHeadersBuildPhase section */ 125 | 8C23120C1B50DB7B0057C459 /* Headers */ = { 126 | isa = PBXHeadersBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | 8C2312151B50DB7B0057C459 /* SSLKillSwitch.h in Headers */, 130 | 8C2312351B50EB030057C459 /* fishhook.h in Headers */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXHeadersBuildPhase section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | 8C23120E1B50DB7B0057C459 /* SSLKillSwitch */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = 8C2312251B50DB7B0057C459 /* Build configuration list for PBXNativeTarget "SSLKillSwitch" */; 140 | buildPhases = ( 141 | 8C23120A1B50DB7B0057C459 /* Sources */, 142 | 8C23120B1B50DB7B0057C459 /* Frameworks */, 143 | 8C23120C1B50DB7B0057C459 /* Headers */, 144 | 8C23120D1B50DB7B0057C459 /* Resources */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = SSLKillSwitch; 151 | productName = SSLKillSwitch; 152 | productReference = 8C23120F1B50DB7B0057C459 /* SSLKillSwitch.framework */; 153 | productType = "com.apple.product-type.framework"; 154 | }; 155 | 8C2312191B50DB7B0057C459 /* SSLKillSwitchTests */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 8C2312281B50DB7B0057C459 /* Build configuration list for PBXNativeTarget "SSLKillSwitchTests" */; 158 | buildPhases = ( 159 | 8C2312161B50DB7B0057C459 /* Sources */, 160 | 8C2312171B50DB7B0057C459 /* Frameworks */, 161 | 8C2312181B50DB7B0057C459 /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | 8C23121D1B50DB7B0057C459 /* PBXTargetDependency */, 167 | ); 168 | name = SSLKillSwitchTests; 169 | productName = SSLKillSwitchTests; 170 | productReference = 8C23121A1B50DB7B0057C459 /* SSLKillSwitchTests.xctest */; 171 | productType = "com.apple.product-type.bundle.unit-test"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | 8C2312061B50DB7A0057C459 /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | LastUpgradeCheck = 0930; 180 | ORGANIZATIONNAME = nablac0d3; 181 | TargetAttributes = { 182 | 8C23120E1B50DB7B0057C459 = { 183 | CreatedOnToolsVersion = 6.4; 184 | }; 185 | 8C2312191B50DB7B0057C459 = { 186 | CreatedOnToolsVersion = 6.4; 187 | }; 188 | }; 189 | }; 190 | buildConfigurationList = 8C2312091B50DB7A0057C459 /* Build configuration list for PBXProject "SSLKillSwitch" */; 191 | compatibilityVersion = "Xcode 3.2"; 192 | developmentRegion = English; 193 | hasScannedForEncodings = 0; 194 | knownRegions = ( 195 | en, 196 | ); 197 | mainGroup = 8C2312051B50DB7A0057C459; 198 | productRefGroup = 8C2312101B50DB7B0057C459 /* Products */; 199 | projectDirPath = ""; 200 | projectRoot = ""; 201 | targets = ( 202 | 8C23120E1B50DB7B0057C459 /* SSLKillSwitch */, 203 | 8C2312191B50DB7B0057C459 /* SSLKillSwitchTests */, 204 | ); 205 | }; 206 | /* End PBXProject section */ 207 | 208 | /* Begin PBXResourcesBuildPhase section */ 209 | 8C23120D1B50DB7B0057C459 /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | 8C2312181B50DB7B0057C459 /* Resources */ = { 217 | isa = PBXResourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXResourcesBuildPhase section */ 224 | 225 | /* Begin PBXSourcesBuildPhase section */ 226 | 8C23120A1B50DB7B0057C459 /* Sources */ = { 227 | isa = PBXSourcesBuildPhase; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | 8C2312341B50EB030057C459 /* fishhook.c in Sources */, 231 | 8C23122C1B50DC670057C459 /* SSLKillSwitch.m in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | 8C2312161B50DB7B0057C459 /* Sources */ = { 236 | isa = PBXSourcesBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | 8C2312221B50DB7B0057C459 /* SSLKillSwitchTests.m in Sources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | /* End PBXSourcesBuildPhase section */ 244 | 245 | /* Begin PBXTargetDependency section */ 246 | 8C23121D1B50DB7B0057C459 /* PBXTargetDependency */ = { 247 | isa = PBXTargetDependency; 248 | target = 8C23120E1B50DB7B0057C459 /* SSLKillSwitch */; 249 | targetProxy = 8C23121C1B50DB7B0057C459 /* PBXContainerItemProxy */; 250 | }; 251 | /* End PBXTargetDependency section */ 252 | 253 | /* Begin XCBuildConfiguration section */ 254 | 8C2312231B50DB7B0057C459 /* Debug */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | ALWAYS_SEARCH_USER_PATHS = NO; 258 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 259 | CLANG_CXX_LIBRARY = "libc++"; 260 | CLANG_ENABLE_MODULES = YES; 261 | CLANG_ENABLE_OBJC_ARC = YES; 262 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 263 | CLANG_WARN_BOOL_CONVERSION = YES; 264 | CLANG_WARN_COMMA = YES; 265 | CLANG_WARN_CONSTANT_CONVERSION = YES; 266 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 267 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 268 | CLANG_WARN_EMPTY_BODY = YES; 269 | CLANG_WARN_ENUM_CONVERSION = YES; 270 | CLANG_WARN_INFINITE_RECURSION = YES; 271 | CLANG_WARN_INT_CONVERSION = YES; 272 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 273 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 274 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 277 | CLANG_WARN_STRICT_PROTOTYPES = YES; 278 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 279 | CLANG_WARN_UNREACHABLE_CODE = YES; 280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 281 | COPY_PHASE_STRIP = NO; 282 | CURRENT_PROJECT_VERSION = 1; 283 | DEBUG_INFORMATION_FORMAT = dwarf; 284 | ENABLE_STRICT_OBJC_MSGSEND = YES; 285 | ENABLE_TESTABILITY = YES; 286 | GCC_C_LANGUAGE_STANDARD = gnu99; 287 | GCC_DYNAMIC_NO_PIC = NO; 288 | GCC_NO_COMMON_BLOCKS = YES; 289 | GCC_OPTIMIZATION_LEVEL = 0; 290 | GCC_PREPROCESSOR_DEFINITIONS = ( 291 | "DEBUG=1", 292 | "$(inherited)", 293 | ); 294 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 295 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 296 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 297 | GCC_WARN_UNDECLARED_SELECTOR = YES; 298 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 299 | GCC_WARN_UNUSED_FUNCTION = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | MACOSX_DEPLOYMENT_TARGET = 10.10; 302 | MTL_ENABLE_DEBUG_INFO = YES; 303 | ONLY_ACTIVE_ARCH = YES; 304 | SDKROOT = macosx; 305 | VERSIONING_SYSTEM = "apple-generic"; 306 | VERSION_INFO_PREFIX = ""; 307 | }; 308 | name = Debug; 309 | }; 310 | 8C2312241B50DB7B0057C459 /* 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_MODULES = YES; 317 | CLANG_ENABLE_OBJC_ARC = YES; 318 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 319 | CLANG_WARN_BOOL_CONVERSION = YES; 320 | CLANG_WARN_COMMA = YES; 321 | CLANG_WARN_CONSTANT_CONVERSION = YES; 322 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 323 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 324 | CLANG_WARN_EMPTY_BODY = YES; 325 | CLANG_WARN_ENUM_CONVERSION = YES; 326 | CLANG_WARN_INFINITE_RECURSION = YES; 327 | CLANG_WARN_INT_CONVERSION = YES; 328 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 330 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 333 | CLANG_WARN_STRICT_PROTOTYPES = YES; 334 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 335 | CLANG_WARN_UNREACHABLE_CODE = YES; 336 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 337 | COPY_PHASE_STRIP = NO; 338 | CURRENT_PROJECT_VERSION = 1; 339 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 340 | ENABLE_NS_ASSERTIONS = NO; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | GCC_C_LANGUAGE_STANDARD = gnu99; 343 | GCC_NO_COMMON_BLOCKS = YES; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | MACOSX_DEPLOYMENT_TARGET = 10.10; 351 | MTL_ENABLE_DEBUG_INFO = NO; 352 | SDKROOT = macosx; 353 | VERSIONING_SYSTEM = "apple-generic"; 354 | VERSION_INFO_PREFIX = ""; 355 | }; 356 | name = Release; 357 | }; 358 | 8C2312261B50DB7B0057C459 /* Debug */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | COMBINE_HIDPI_IMAGES = YES; 362 | DEFINES_MODULE = YES; 363 | DYLIB_COMPATIBILITY_VERSION = 1; 364 | DYLIB_CURRENT_VERSION = 1; 365 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 366 | FRAMEWORK_VERSION = A; 367 | INFOPLIST_FILE = SSLKillSwitch/Info.plist; 368 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 369 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 370 | PRODUCT_BUNDLE_IDENTIFIER = "com.nablac0d3.$(PRODUCT_NAME:rfc1034identifier)"; 371 | PRODUCT_NAME = "$(TARGET_NAME)"; 372 | SKIP_INSTALL = YES; 373 | }; 374 | name = Debug; 375 | }; 376 | 8C2312271B50DB7B0057C459 /* Release */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | COMBINE_HIDPI_IMAGES = YES; 380 | DEFINES_MODULE = YES; 381 | DYLIB_COMPATIBILITY_VERSION = 1; 382 | DYLIB_CURRENT_VERSION = 1; 383 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 384 | FRAMEWORK_VERSION = A; 385 | INFOPLIST_FILE = SSLKillSwitch/Info.plist; 386 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 387 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 388 | PRODUCT_BUNDLE_IDENTIFIER = "com.nablac0d3.$(PRODUCT_NAME:rfc1034identifier)"; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | SKIP_INSTALL = YES; 391 | }; 392 | name = Release; 393 | }; 394 | 8C2312291B50DB7B0057C459 /* Debug */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | COMBINE_HIDPI_IMAGES = YES; 398 | FRAMEWORK_SEARCH_PATHS = ( 399 | "$(DEVELOPER_FRAMEWORKS_DIR)", 400 | "$(inherited)", 401 | ); 402 | GCC_PREPROCESSOR_DEFINITIONS = ( 403 | "DEBUG=1", 404 | "$(inherited)", 405 | ); 406 | INFOPLIST_FILE = SSLKillSwitchTests/Info.plist; 407 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 408 | PRODUCT_BUNDLE_IDENTIFIER = "com.nablac0d3.$(PRODUCT_NAME:rfc1034identifier)"; 409 | PRODUCT_NAME = "$(TARGET_NAME)"; 410 | }; 411 | name = Debug; 412 | }; 413 | 8C23122A1B50DB7B0057C459 /* Release */ = { 414 | isa = XCBuildConfiguration; 415 | buildSettings = { 416 | COMBINE_HIDPI_IMAGES = YES; 417 | FRAMEWORK_SEARCH_PATHS = ( 418 | "$(DEVELOPER_FRAMEWORKS_DIR)", 419 | "$(inherited)", 420 | ); 421 | INFOPLIST_FILE = SSLKillSwitchTests/Info.plist; 422 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 423 | PRODUCT_BUNDLE_IDENTIFIER = "com.nablac0d3.$(PRODUCT_NAME:rfc1034identifier)"; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | }; 426 | name = Release; 427 | }; 428 | /* End XCBuildConfiguration section */ 429 | 430 | /* Begin XCConfigurationList section */ 431 | 8C2312091B50DB7A0057C459 /* Build configuration list for PBXProject "SSLKillSwitch" */ = { 432 | isa = XCConfigurationList; 433 | buildConfigurations = ( 434 | 8C2312231B50DB7B0057C459 /* Debug */, 435 | 8C2312241B50DB7B0057C459 /* Release */, 436 | ); 437 | defaultConfigurationIsVisible = 0; 438 | defaultConfigurationName = Release; 439 | }; 440 | 8C2312251B50DB7B0057C459 /* Build configuration list for PBXNativeTarget "SSLKillSwitch" */ = { 441 | isa = XCConfigurationList; 442 | buildConfigurations = ( 443 | 8C2312261B50DB7B0057C459 /* Debug */, 444 | 8C2312271B50DB7B0057C459 /* Release */, 445 | ); 446 | defaultConfigurationIsVisible = 0; 447 | defaultConfigurationName = Release; 448 | }; 449 | 8C2312281B50DB7B0057C459 /* Build configuration list for PBXNativeTarget "SSLKillSwitchTests" */ = { 450 | isa = XCConfigurationList; 451 | buildConfigurations = ( 452 | 8C2312291B50DB7B0057C459 /* Debug */, 453 | 8C23122A1B50DB7B0057C459 /* Release */, 454 | ); 455 | defaultConfigurationIsVisible = 0; 456 | defaultConfigurationName = Release; 457 | }; 458 | /* End XCConfigurationList section */ 459 | }; 460 | rootObject = 8C2312061B50DB7A0057C459 /* Project object */; 461 | } 462 | -------------------------------------------------------------------------------- /SSLKillSwitch.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SSLKillSwitch.xcodeproj/xcshareddata/xcschemes/SSLKillSwitch.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | 90 | 96 | 97 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /SSLKillSwitch/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 nablac0d3. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SSLKillSwitch/SSLKillSwitch.h: -------------------------------------------------------------------------------- 1 | // 2 | // SSLKillSwitch.h 3 | // SSLKillSwitch 4 | // 5 | // Created by Alban Diquet on 7/10/15. 6 | // Copyright (c) 2015 Alban Diquet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SSLKillSwitch. 12 | FOUNDATION_EXPORT double SSLKillSwitchVersionNumber; 13 | 14 | //! Project version string for SSLKillSwitch. 15 | FOUNDATION_EXPORT const unsigned char SSLKillSwitchVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SSLKillSwitch/SSLKillSwitch.m: -------------------------------------------------------------------------------- 1 | // 2 | // SSLKillSwitch.m 3 | // SSLKillSwitch 4 | // 5 | // Created by Alban Diquet on 7/10/15. 6 | // Copyright (c) 2015 Alban Diquet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #if SUBSTRATE_BUILD 13 | #import "substrate.h" 14 | 15 | #define PREFERENCE_FILE @"/private/var/mobile/Library/Preferences/com.nablac0d3.SSLKillSwitchSettings.plist" 16 | #define PREFERENCE_KEY @"shouldDisableCertificateValidation" 17 | 18 | #else 19 | 20 | #import "fishhook.h" 21 | #import 22 | 23 | #endif 24 | 25 | 26 | #pragma mark Utility Functions 27 | 28 | static void SSKLog(NSString *format, ...) 29 | { 30 | NSString *newFormat = [[NSString alloc] initWithFormat:@"=== SSL Kill Switch 2: %@", format]; 31 | va_list args; 32 | va_start(args, format); 33 | NSLogv(newFormat, args); 34 | va_end(args); 35 | } 36 | 37 | 38 | #if SUBSTRATE_BUILD 39 | // Utility function to read the Tweak's preferences 40 | static BOOL shouldHookFromPreference(NSString *preferenceSetting) 41 | { 42 | BOOL shouldHook = NO; 43 | NSMutableDictionary* plist = [[NSMutableDictionary alloc] initWithContentsOfFile:PREFERENCE_FILE]; 44 | 45 | if (!plist) 46 | { 47 | SSKLog(@"Preference file not found."); 48 | } 49 | else 50 | { 51 | shouldHook = [[plist objectForKey:preferenceSetting] boolValue]; 52 | SSKLog(@"Preference set to %d.", shouldHook); 53 | } 54 | return shouldHook; 55 | } 56 | #endif 57 | 58 | 59 | #pragma mark SecureTransport hooks - iOS 9 and below 60 | // Explanation here: https://nabla-c0d3.github.io/blog/2013/08/20/ios-ssl-kill-switch-v0-dot-5-released/ 61 | 62 | static OSStatus (*original_SSLSetSessionOption)(SSLContextRef context, 63 | SSLSessionOption option, 64 | Boolean value); 65 | 66 | static OSStatus replaced_SSLSetSessionOption(SSLContextRef context, 67 | SSLSessionOption option, 68 | Boolean value) 69 | { 70 | // Remove the ability to modify the value of the kSSLSessionOptionBreakOnServerAuth option 71 | if (option == kSSLSessionOptionBreakOnServerAuth) 72 | { 73 | return noErr; 74 | } 75 | return original_SSLSetSessionOption(context, option, value); 76 | } 77 | 78 | 79 | static SSLContextRef (*original_SSLCreateContext)(CFAllocatorRef alloc, 80 | SSLProtocolSide protocolSide, 81 | SSLConnectionType connectionType); 82 | 83 | static SSLContextRef replaced_SSLCreateContext(CFAllocatorRef alloc, 84 | SSLProtocolSide protocolSide, 85 | SSLConnectionType connectionType) 86 | { 87 | SSLContextRef sslContext = original_SSLCreateContext(alloc, protocolSide, connectionType); 88 | 89 | // Immediately set the kSSLSessionOptionBreakOnServerAuth option in order to disable cert validation 90 | original_SSLSetSessionOption(sslContext, kSSLSessionOptionBreakOnServerAuth, true); 91 | return sslContext; 92 | } 93 | 94 | 95 | static OSStatus (*original_SSLHandshake)(SSLContextRef context); 96 | 97 | static OSStatus replaced_SSLHandshake(SSLContextRef context) 98 | { 99 | 100 | OSStatus result = original_SSLHandshake(context); 101 | 102 | // Hijack the flow when breaking on server authentication 103 | if (result == errSSLServerAuthCompleted) 104 | { 105 | // Do not check the cert and call SSLHandshake() again 106 | return original_SSLHandshake(context); 107 | } 108 | 109 | return result; 110 | } 111 | 112 | 113 | #pragma mark libsystem_coretls.dylib hooks - iOS 10 114 | // Explanation here: https://nabla-c0d3.github.io/blog/2017/02/05/ios10-ssl-kill-switch/ 115 | 116 | static OSStatus (*original_tls_helper_create_peer_trust)(void *hdsk, bool server, SecTrustRef *trustRef); 117 | 118 | static OSStatus replaced_tls_helper_create_peer_trust(void *hdsk, bool server, SecTrustRef *trustRef) 119 | { 120 | // Do not actually set the trustRef 121 | return errSecSuccess; 122 | } 123 | 124 | 125 | #pragma mark CocoaSPDY hook 126 | #if SUBSTRATE_BUILD 127 | 128 | static void (*oldSetTLSTrustEvaluator)(id self, SEL _cmd, id evaluator); 129 | 130 | static void newSetTLSTrustEvaluator(id self, SEL _cmd, id evaluator) 131 | { 132 | // Set a nil evaluator to disable SSL validation 133 | oldSetTLSTrustEvaluator(self, _cmd, nil); 134 | } 135 | 136 | static void (*oldSetprotocolClasses)(id self, SEL _cmd, NSArray *protocolClasses); 137 | 138 | static void newSetprotocolClasses(id self, SEL _cmd, NSArray *protocolClasses) 139 | { 140 | // Do not register protocol classes which is how CocoaSPDY works 141 | // This should force the App to downgrade from SPDY to HTTPS 142 | } 143 | 144 | static void (*oldRegisterOrigin)(id self, SEL _cmd, NSString *origin); 145 | 146 | static void newRegisterOrigin(id self, SEL _cmd, NSString *origin) 147 | { 148 | // Do not register protocol classes which is how CocoaSPDY works 149 | // This should force the App to downgrade from SPDY to HTTPS 150 | } 151 | #endif 152 | 153 | 154 | 155 | #pragma mark Dylib Constructor 156 | 157 | __attribute__((constructor)) static void init(int argc, const char **argv) 158 | { 159 | #if SUBSTRATE_BUILD 160 | // Should we enable the hook ? 161 | if (shouldHookFromPreference(PREFERENCE_KEY)) 162 | { 163 | // Substrate-based hooking; only hook if the preference file says so 164 | SSKLog(@"Substrate hook enabled."); 165 | 166 | // SecureTransport hooks - works up to iOS 9 167 | MSHookFunction((void *) SSLHandshake,(void *) replaced_SSLHandshake, (void **) &original_SSLHandshake); 168 | MSHookFunction((void *) SSLSetSessionOption,(void *) replaced_SSLSetSessionOption, (void **) &original_SSLSetSessionOption); 169 | MSHookFunction((void *) SSLCreateContext,(void *) replaced_SSLCreateContext, (void **) &original_SSLCreateContext); 170 | 171 | // libsystem_coretls.dylib hook - works on iOS 10 172 | // TODO: Enable this hook for the fishhook-based hooking so it works on OS X too 173 | NSProcessInfo *processInfo = [NSProcessInfo processInfo]; 174 | if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){11, 0, 0}]) 175 | { 176 | // Support for iOS 11 177 | void* handle = dlopen("/usr/lib/libnetwork.dylib", RTLD_NOW); 178 | void *tls_helper_create_peer_trust = dlsym(handle, "nw_tls_create_peer_trust"); 179 | if (tls_helper_create_peer_trust) 180 | { 181 | MSHookFunction((void *) tls_helper_create_peer_trust, (void *) replaced_tls_helper_create_peer_trust, (void **) &original_tls_helper_create_peer_trust); 182 | } 183 | } 184 | else if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 0, 0}]) 185 | { 186 | // Support for iOS 10 187 | void *tls_helper_create_peer_trust = dlsym(RTLD_DEFAULT, "tls_helper_create_peer_trust"); 188 | MSHookFunction((void *) tls_helper_create_peer_trust, (void *) replaced_tls_helper_create_peer_trust, (void **) &original_tls_helper_create_peer_trust); 189 | } 190 | 191 | 192 | // CocoaSPDY hooks - https://github.com/twitter/CocoaSPDY 193 | // TODO: Enable these hooks for the fishhook-based hooking so it works on OS X too 194 | Class spdyProtocolClass = NSClassFromString(@"SPDYProtocol"); 195 | if (spdyProtocolClass) 196 | { 197 | // Disable trust evaluation 198 | MSHookMessageEx(object_getClass(spdyProtocolClass), NSSelectorFromString(@"setTLSTrustEvaluator:"), (IMP) &newSetTLSTrustEvaluator, (IMP *)&oldSetTLSTrustEvaluator); 199 | 200 | // CocoaSPDY works by getting registered as a NSURLProtocol; block that so the Apps switches back to HTTP as SPDY is tricky to proxy 201 | Class spdyUrlConnectionProtocolClass = NSClassFromString(@"SPDYURLConnectionProtocol"); 202 | MSHookMessageEx(object_getClass(spdyUrlConnectionProtocolClass), NSSelectorFromString(@"registerOrigin:"), (IMP) &newRegisterOrigin, (IMP *)&oldRegisterOrigin); 203 | 204 | MSHookMessageEx(NSClassFromString(@"NSURLSessionConfiguration"), NSSelectorFromString(@"setprotocolClasses:"), (IMP) &newSetprotocolClasses, (IMP *)&oldSetprotocolClasses); 205 | } 206 | } 207 | else 208 | { 209 | SSKLog(@"Substrate hook disabled."); 210 | } 211 | 212 | #else 213 | // Fishhook-based hooking, for OS X builds; always hook 214 | SSKLog(@"Fishhook hook enabled."); 215 | original_SSLHandshake = dlsym(RTLD_DEFAULT, "SSLHandshake"); 216 | if ((rebind_symbols((struct rebinding[1]){{(char *)"SSLHandshake", (void *)replaced_SSLHandshake}}, 1) < 0)) 217 | { 218 | SSKLog(@"Hooking failed."); 219 | } 220 | 221 | original_SSLSetSessionOption = dlsym(RTLD_DEFAULT, "SSLSetSessionOption"); 222 | if ((rebind_symbols((struct rebinding[1]){{(char *)"SSLSetSessionOption", (void *)replaced_SSLSetSessionOption}}, 1) < 0)) 223 | { 224 | SSKLog(@"Hooking failed."); 225 | } 226 | 227 | original_SSLCreateContext = dlsym(RTLD_DEFAULT, "SSLCreateContext"); 228 | if ((rebind_symbols((struct rebinding[1]){{(char *)"SSLCreateContext", (void *)replaced_SSLCreateContext}}, 1) < 0)) 229 | { 230 | SSKLog(@"Hooking failed."); 231 | } 232 | 233 | original_tls_helper_create_peer_trust = dlsym(RTLD_DEFAULT, "tls_helper_create_peer_trust"); 234 | if ((rebind_symbols((struct rebinding[1]){{(char *)"tls_helper_create_peer_trust", (void *)replaced_tls_helper_create_peer_trust}}, 1) < 0)) 235 | { 236 | SSKLog(@"Hooking failed."); 237 | } 238 | #endif 239 | } 240 | 241 | -------------------------------------------------------------------------------- /SSLKillSwitch/fishhook/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /SSLKillSwitch/fishhook/README.md: -------------------------------------------------------------------------------- 1 | # fishhook 2 | 3 | __fishhook__ is a very simple library that enables dynamically rebinding symbols in Mach-O binaries running on iOS in the simulator and on device. This provides functionality that is similar to using [`DYLD_INTERPOSE`][interpose] on OS X. At Facebook, we've found it useful as a way to hook calls in libSystem for debugging/tracing purposes (for example, auditing for double-close issues with file descriptors). 4 | 5 | [interpose]: http://opensource.apple.com/source/dyld/dyld-210.2.3/include/mach-o/dyld-interposing.h "" 6 | 7 | ## Usage 8 | 9 | Once you add `fishhook.h`/`fishhook.c` to your project, you can rebind symbols as follows: 10 | ```Objective-C 11 | #import 12 | 13 | #import 14 | 15 | #import "AppDelegate.h" 16 | #import "fishhook.h" 17 | 18 | static int (*orig_close)(int); 19 | static int (*orig_open)(const char *, int, ...); 20 | 21 | int my_close(int fd) { 22 | printf("Calling real close(%d)\n", fd); 23 | return orig_close(fd); 24 | } 25 | 26 | int my_open(const char *path, int oflag, ...) { 27 | va_list ap = {0}; 28 | mode_t mode = 0; 29 | 30 | if ((oflag & O_CREAT) != 0) { 31 | // mode only applies to O_CREAT 32 | va_start(ap, oflag); 33 | mode = va_arg(ap, int); 34 | va_end(ap); 35 | printf("Calling real open('%s', %d, %d)\n", path, oflag, mode); 36 | return orig_open(path, oflag, mode); 37 | } else { 38 | printf("Calling real open('%s', %d)\n", path, oflag); 39 | return orig_open(path, oflag, mode); 40 | } 41 | } 42 | 43 | int main(int argc, char * argv[]) 44 | { 45 | @autoreleasepool { 46 | rebind_symbols((struct rebinding[2]){{"close", my_close, (void *)&orig_close}, {"open", my_open, (void *)&orig_open}}, 2); 47 | 48 | // Open our own binary and print out first 4 bytes (which is the same 49 | // for all Mach-O binaries on a given architecture) 50 | int fd = open(argv[0], O_RDONLY); 51 | uint32_t magic_number = 0; 52 | read(fd, &magic_number, 4); 53 | printf("Mach-O Magic Number: %x \n", magic_number); 54 | close(fd); 55 | 56 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 57 | } 58 | } 59 | ``` 60 | ### Sample output 61 | ``` 62 | Calling real open('/var/mobile/Applications/161DA598-5B83-41F5-8A44-675491AF6A2C/Test.app/Test', 0) 63 | Mach-O Magic Number: feedface 64 | Calling real close(3) 65 | ... 66 | ``` 67 | 68 | ## How it works 69 | 70 | `dyld` binds lazy and non-lazy symbols by updating pointers in particular sections of the `__DATA` segment of a Mach-O binary. __fishhook__ re-binds these symbols by determining the locations to update for each of the symbol names passed to `rebind_symbols` and then writing out the corresponding replacements. 71 | 72 | For a given image, the `__DATA` segment may contain two sections that are relevant for dynamic symbol bindings: `__nl_symbol_ptr` and `__la_symbol_ptr`. `__nl_symbol_ptr` is an array of pointers to non-lazily bound data (these are bound at the time a library is loaded) and `__la_symbol_ptr` is an array of pointers to imported functions that is generally filled by a routine called `dyld_stub_binder` during the first call to that symbol (it's also possible to tell `dyld` to bind these at launch). In order to find the name of the symbol that corresponds to a particular location in one of these sections, we have to jump through several layers of indirection. For the two relevant sections, the section headers (`struct section`s from ``) provide an offset (in the `reserved1` field) into what is known as the indirect symbol table. The indirect symbol table, which is located in the `__LINKEDIT` segment of the binary, is just an array of indexes into the symbol table (also in `__LINKEDIT`) whose order is identical to that of the pointers in the non-lazy and lazy symbol sections. So, given `struct section nl_symbol_ptr`, the corresponding index in the symbol table of the first address in that section is `indirect_symbol_table[nl_symbol_ptr->reserved1]`. The symbol table itself is an array of `struct nlist`s (see ``), and each `nlist` contains an index into the string table in `__LINKEDIT` which where the actual symbol names are stored. So, for each pointer `__nl_symbol_ptr` and `__la_symbol_ptr`, we are able to find the corresponding symbol and then the corresponding string to compare against the requested symbol names, and if there is a match, we replace the pointer in the section with the replacement. 73 | 74 | The process of looking up the name of a given entry in the lazy or non-lazy pointer tables looks like this: 75 | ![Visual explanation](http://i.imgur.com/HVXqHCz.png) -------------------------------------------------------------------------------- /SSLKillSwitch/fishhook/fishhook.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #import "fishhook.h" 25 | 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | 34 | #ifdef __LP64__ 35 | typedef struct mach_header_64 mach_header_t; 36 | typedef struct segment_command_64 segment_command_t; 37 | typedef struct section_64 section_t; 38 | typedef struct nlist_64 nlist_t; 39 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 40 | #else 41 | typedef struct mach_header mach_header_t; 42 | typedef struct segment_command segment_command_t; 43 | typedef struct section section_t; 44 | typedef struct nlist nlist_t; 45 | #define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT 46 | #endif 47 | 48 | #ifndef SEG_DATA_CONST 49 | #define SEG_DATA_CONST "__DATA_CONST" 50 | #endif 51 | 52 | struct rebindings_entry { 53 | struct rebinding *rebindings; 54 | size_t rebindings_nel; 55 | struct rebindings_entry *next; 56 | }; 57 | 58 | static struct rebindings_entry *_rebindings_head; 59 | 60 | static int prepend_rebindings(struct rebindings_entry **rebindings_head, 61 | struct rebinding rebindings[], 62 | size_t nel) { 63 | struct rebindings_entry *new_entry = malloc(sizeof(struct rebindings_entry)); 64 | if (!new_entry) { 65 | return -1; 66 | } 67 | new_entry->rebindings = malloc(sizeof(struct rebinding) * nel); 68 | if (!new_entry->rebindings) { 69 | free(new_entry); 70 | return -1; 71 | } 72 | memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); 73 | new_entry->rebindings_nel = nel; 74 | new_entry->next = *rebindings_head; 75 | *rebindings_head = new_entry; 76 | return 0; 77 | } 78 | 79 | static void perform_rebinding_with_section(struct rebindings_entry *rebindings, 80 | section_t *section, 81 | intptr_t slide, 82 | nlist_t *symtab, 83 | char *strtab, 84 | uint32_t *indirect_symtab) { 85 | uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; 86 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); 87 | for (uint i = 0; i < section->size / sizeof(void *); i++) { 88 | uint32_t symtab_index = indirect_symbol_indices[i]; 89 | if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || 90 | symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { 91 | continue; 92 | } 93 | uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; 94 | char *symbol_name = strtab + strtab_offset; 95 | struct rebindings_entry *cur = rebindings; 96 | while (cur) { 97 | for (uint j = 0; j < cur->rebindings_nel; j++) { 98 | if (strlen(symbol_name) > 1 && 99 | strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { 100 | if (cur->rebindings[j].replaced != NULL && 101 | indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { 102 | *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; 103 | } 104 | indirect_symbol_bindings[i] = cur->rebindings[j].replacement; 105 | goto symbol_loop; 106 | } 107 | } 108 | cur = cur->next; 109 | } 110 | symbol_loop:; 111 | } 112 | } 113 | 114 | static void rebind_symbols_for_image(struct rebindings_entry *rebindings, 115 | const struct mach_header *header, 116 | intptr_t slide) { 117 | Dl_info info; 118 | if (dladdr(header, &info) == 0) { 119 | return; 120 | } 121 | 122 | segment_command_t *cur_seg_cmd; 123 | segment_command_t *linkedit_segment = NULL; 124 | struct symtab_command* symtab_cmd = NULL; 125 | struct dysymtab_command* dysymtab_cmd = NULL; 126 | 127 | uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); 128 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 129 | cur_seg_cmd = (segment_command_t *)cur; 130 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 131 | if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { 132 | linkedit_segment = cur_seg_cmd; 133 | } 134 | } else if (cur_seg_cmd->cmd == LC_SYMTAB) { 135 | symtab_cmd = (struct symtab_command*)cur_seg_cmd; 136 | } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { 137 | dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; 138 | } 139 | } 140 | 141 | if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || 142 | !dysymtab_cmd->nindirectsyms) { 143 | return; 144 | } 145 | 146 | // Find base symbol/string table addresses 147 | uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; 148 | nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); 149 | char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); 150 | 151 | // Get indirect symbol table (array of uint32_t indices into symbol table) 152 | uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); 153 | 154 | cur = (uintptr_t)header + sizeof(mach_header_t); 155 | for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { 156 | cur_seg_cmd = (segment_command_t *)cur; 157 | if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { 158 | if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && 159 | strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { 160 | continue; 161 | } 162 | for (uint j = 0; j < cur_seg_cmd->nsects; j++) { 163 | section_t *sect = 164 | (section_t *)(cur + sizeof(segment_command_t)) + j; 165 | if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { 166 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 167 | } 168 | if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { 169 | perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); 170 | } 171 | } 172 | } 173 | } 174 | } 175 | 176 | static void _rebind_symbols_for_image(const struct mach_header *header, 177 | intptr_t slide) { 178 | rebind_symbols_for_image(_rebindings_head, header, slide); 179 | } 180 | 181 | int rebind_symbols_image(void *header, 182 | intptr_t slide, 183 | struct rebinding rebindings[], 184 | size_t rebindings_nel) { 185 | struct rebindings_entry *rebindings_head = NULL; 186 | int retval = prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); 187 | rebind_symbols_for_image(rebindings_head, header, slide); 188 | free(rebindings_head); 189 | return retval; 190 | } 191 | 192 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { 193 | int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); 194 | if (retval < 0) { 195 | return retval; 196 | } 197 | // If this was the first call, register callback for image additions (which is also invoked for 198 | // existing images, otherwise, just run on existing images 199 | if (!_rebindings_head->next) { 200 | _dyld_register_func_for_add_image(_rebind_symbols_for_image); 201 | } else { 202 | uint32_t c = _dyld_image_count(); 203 | for (uint32_t i = 0; i < c; i++) { 204 | _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); 205 | } 206 | } 207 | return retval; 208 | } 209 | -------------------------------------------------------------------------------- /SSLKillSwitch/fishhook/fishhook.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. 2 | // All rights reserved. 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // * Redistributions of source code must retain the above copyright notice, 6 | // this list of conditions and the following disclaimer. 7 | // * Redistributions in binary form must reproduce the above copyright notice, 8 | // this list of conditions and the following disclaimer in the documentation 9 | // and/or other materials provided with the distribution. 10 | // * Neither the name Facebook nor the names of its contributors may be used to 11 | // endorse or promote products derived from this software without specific 12 | // prior written permission. 13 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #ifndef fishhook_h 25 | #define fishhook_h 26 | 27 | #include 28 | #include 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif //__cplusplus 33 | 34 | /* 35 | * A structure representing a particular intended rebinding from a symbol 36 | * name to its replacement 37 | */ 38 | struct rebinding { 39 | const char *name; 40 | void *replacement; 41 | void **replaced; 42 | }; 43 | 44 | /* 45 | * For each rebinding in rebindings, rebinds references to external, indirect 46 | * symbols with the specified name to instead point at replacement for each 47 | * image in the calling process as well as for all future images that are loaded 48 | * by the process. If rebind_functions is called more than once, the symbols to 49 | * rebind are added to the existing list of rebindings, and if a given symbol 50 | * is rebound more than once, the later rebinding will take precedence. 51 | */ 52 | int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); 53 | 54 | /* 55 | * Rebinds as above, but only in the specified image. The header should point 56 | * to the mach-o header, the slide should be the slide offset. Others as above. 57 | */ 58 | int rebind_symbols_image(void *header, 59 | intptr_t slide, 60 | struct rebinding rebindings[], 61 | size_t rebindings_nel); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif //__cplusplus 66 | 67 | #endif //fishhook_h 68 | 69 | -------------------------------------------------------------------------------- /SSLKillSwitch2.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.apple.AuthKit", 5 | "com.apple.UIKit", 6 | "com.apple.itunesstored", 7 | ); 8 | }; 9 | } -------------------------------------------------------------------------------- /SSLKillSwitchTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SSLKillSwitchTests/SSLKillSwitchTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SSLKillSwitchTests.m 3 | // SSLKillSwitchTests 4 | // 5 | // Created by Alban Diquet on 7/10/15. 6 | // Copyright (c) 2015 Alban Diquet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SSLKillSwitchTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SSLKillSwitchTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /layout/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: com.nablac0d3.sslkillswitch2 2 | Name: SSL Kill Switch 2 3 | Depends: mobilesubstrate, preferenceloader 4 | Version: 0.12 5 | Architecture: iphoneos-arm 6 | Description: Blackbox tool to disable SSL certificate validation - including certificate pinning - within iOS and OS X Apps. 7 | Maintainer: Alban Diquet 8 | Author: Alban Diquet 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /layout/Library/PreferenceLoader/Preferences/SSLKillSwitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samyk/ssl-kill-switch2/4f79d0f7fd3c81ed52f4cc2b55b4dbe3d9fec59f/layout/Library/PreferenceLoader/Preferences/SSLKillSwitch.png -------------------------------------------------------------------------------- /layout/Library/PreferenceLoader/Preferences/SSLKillSwitch_prefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | cell 8 | PSLinkCell 9 | icon 10 | SSLKillSwitch.png 11 | label 12 | SSL Kill Switch 2 13 | 14 | items 15 | 16 | 17 | cell 18 | PSGroupCell 19 | label 20 | 21 | footerText 22 | SSL Kill Switch 2 23 | 24 | 25 | cell 26 | PSSwitchCell 27 | default 28 | 29 | defaults 30 | com.nablac0d3.SSLKillSwitchSettings 31 | key 32 | shouldDisableCertificateValidation 33 | label 34 | Disable Certificate Validation 35 | 36 | 37 | title 38 | SSL Kill Switch 2 39 | 40 | 41 | --------------------------------------------------------------------------------