├── .gitignore ├── LICENSE.txt ├── README.md ├── resources ├── papers │ └── README.md └── scripts │ ├── Install Commonly Used Utilities │ ├── Hopper.py │ ├── Installer.sh │ ├── README.md │ ├── debugserver.py │ └── debugsrvEntitle.xml │ ├── Install XPwn │ └── build_xpwn.sh │ └── Install libimobiledevice │ └── libinstaller.sh └── wiki ├── Auditing-the-XNU-Kernel.md ├── BootROM-RE.md ├── Bypassing-AMFI.md ├── Disassemblers.md ├── Dumping-iBoot.md ├── Firmwares-and-Keys.md ├── History-of-iOS-Mitigations.md ├── IOKit-RE.md ├── Kernel-Patch-Protection-(KPP).md ├── Mach-O.md ├── Mach_and_BSD.md ├── Modern-Userland-Jailbreaking.md ├── README.md ├── Sandbox.md ├── Strategies-for-Sandbox-Escape.md ├── WebKit-Exploitation.md ├── XNU-Kernel-Exploitation.md ├── code └── ipc │ ├── client.c │ └── server.c ├── iBoot-Exploitation.md ├── iBoot-RE.md └── images └── mach_o_segments.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/osx,linux,windows 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | ### OSX ### 20 | *.DS_Store 21 | .AppleDouble 22 | .LSOverride 23 | 24 | # Icon must end with two \r 25 | Icon 26 | 27 | 28 | # Thumbnails 29 | ._* 30 | 31 | # Files that might appear in the root of a volume 32 | .DocumentRevisions-V100 33 | .fseventsd 34 | .Spotlight-V100 35 | .TemporaryItems 36 | .Trashes 37 | .VolumeIcon.icns 38 | .com.apple.timemachine.donotpresent 39 | 40 | # Directories potentially created on remote AFP share 41 | .AppleDB 42 | .AppleDesktop 43 | Network Trash Folder 44 | Temporary Items 45 | .apdisk 46 | 47 | ### Windows ### 48 | # Windows thumbnail cache files 49 | Thumbs.db 50 | ehthumbs.db 51 | ehthumbs_vista.db 52 | 53 | # Folder config file 54 | Desktop.ini 55 | 56 | # Recycle Bin used on file shares 57 | $RECYCLE.BIN/ 58 | 59 | # Windows Installer files 60 | *.cab 61 | *.msi 62 | *.msm 63 | *.msp 64 | 65 | # Windows shortcuts 66 | *.lnk 67 | 68 | # End of https://www.gitignore.io/api/osx,linux,windows 69 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The informations and code in this repository are licensed under the "Modified Anyone But Richard M Stallman" 2 | (MABRMS) license, described below. No other licenses may apply, unless the specific file specifies so. 3 | 4 | 5 | -------------------------------------------- 6 | The "Modified Anyone But Richard M Stallman" license 7 | -------------------------------------------- 8 | 9 | Do anything you want with these informations and code, with the exceptions listed 10 | below under "EXCEPTIONS". 11 | 12 | THIS STUFF IS PROVIDED "AS IS" WITH NO WARRANTY OF ANY KIND. 13 | 14 | In the event that you happen to make a zillion bucks off of 15 | this, then good for you; consider buying a homeless person a meal. 16 | 17 | 18 | EXCEPTIONS 19 | ---------- 20 | 21 | Richard M Stallman (the guy behind GNU, etc.) may not make use of or 22 | redistribute these informations and code or any of its derivatives. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOSRE 2 | 3 | [![Join the chat at freenode:iOSRE](https://img.shields.io/badge/irc-freenode:%20%23%23iOSRE-blue.svg)](http://webchat.freenode.net/?channels=%23%23iOSRE)
4 | iOS Reverse Engineering 5 | 6 | The aim of this project is to provide useful and updated tools and knowledge on iOS reverse engineering and exploitation. 7 | This is an ongoing effort, and still in a very new stage. 8 | 9 | You may contribute actual files by adding it to the "resources" folder. 10 | Please note that these files are mostly user-contributed and may be malicious, so do your own homework before running them. If you see something bad we haven't noticed, please open an issue. 11 | 12 | Thank you, and please join us at irc.freenode.net on `##iosre` for suggestions or plain idling 13 | -------------------------------------------------------------------------------- /resources/papers/README.md: -------------------------------------------------------------------------------- 1 | # OS X / iOS Technical Papers 2 | 3 | This list includes many technical papers about OS X and iOS exploitation/researching/reversing. 4 |
5 | The papers you see listed here have been published publicly and are free to redistribute. 6 | 7 | ### Contributing 8 | Instead of uploading a big chunk of PDFs to some hosting website or directly here on GitHub, I decided to link every entry directly. If a link is dead, and you have the original copy of the document, feel free to re-upload it and submit a pull request with the new URL. 9 |
10 | Similarly, if you want to add documents, please submit a pull request with your entry/entries, added to the correct section with working URL/URLs. 11 | 12 | # OS X 13 | 14 | ## Exploitation 15 | | *Document* | *Related Talk* | *Author* | *Year* | 16 | |----------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|------------------------------------|--------| 17 | | [Attacking the XNU Kernel in El Capitan](https://www.blackhat.com/docs/eu-15/materials/eu-15-Todesco-Attacking-The-XNU-Kernal-In-El-Capitain.pdf) | [Attacking The XNU Kernel In El Capitan](https://www.youtube.com/watch?v=k550C0V79ts) | Luca Todesco | 2015 | 18 | | [OS X Kernel is As Strong as its Weakest Part](https://papers.put.as/papers/macosx/2015/poc2015osxkernelisasstrongasitsweakestpartliangshuaitian.pdf) | N/A | Liang Chen, ShuaiTian Zhao | 2015 | 19 | | [Memory corruption is for wussies!](https://papers.put.as/papers/macosx/2016/SyScan360_SG_2016_-_Memory_Corruption_is_for_wussies.pdf) | N/A | fG! | 2016 | 20 | | [Don’t Trust Your Eye: Apple Graphics is Compromised!](https://papers.put.as/papers/macosx/2016/CanSecWest2016_Apple_Graphics_Compromised.pdf) | N/A | Liang Chen, Marco Grassi, Qidan He | 2016 | 21 | | [OS X El Capitan sinking the Ship](https://papers.put.as/papers/macosx/2016/syscan360stefanesserosxelcapitansinkingtheship.pdf) | N/A | Stefan Esser | 2016 | 22 | |[XNU:A Security Evaluation](https://papers.put.as/papers/macosx/2012/XNU_-a-security-evaluation-Daan_Keuper_2012-12-14-xnu.pdf)| N/A | Daan_Keuper | 2012 | 23 | 24 | ## Technical 25 | | *Document* | *Related Talk* | *Author* | *Year* | 26 | |-----------------------------------------------------------------------------------------------------------|----------------|----------------|--------| 27 | | [DYLIB HIJACKING ON OS X](https://papers.put.as/papers/macosx/2015/vb201503-dylib-hijacking.pdf) | N/A | Patrick Wardle | 2015 | 28 | | [Code Signing – Hashed Out](https://papers.put.as/papers/macosx/2015/CodeSigning-RSA.pdf) | N/A | Jonathan Levin | 2015 | 29 | | [The ARMs race to TrustZone](http://technologeeks.com/files/TZ.pdf) | N/A | Jonathan Levin | 2016 | 30 | # iOS 31 | 32 | ## Exploitation 33 | | *Document* | *Related Talk* | *Author* | *Year* | 34 | |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|--------| 35 | | [iOS Kernel Exploitation](https://papers.put.as/papers/ios/2011/BH_US_11_Esser_Exploiting_The_iOS_Kernel_Slides.pdf) | [BlackHat 2011 - iOS Kernel Exploitation](https://www.youtube.com/watch?v=fQHkA_s3d2o) | Stefan Esser | 2011 | 36 | | [iOS Kernel Exploitation -- IOKit Edition](https://papers.put.as/papers/ios/2011/SyScanTaipei2011_StefanEsser_iOS_Kernel_Exploitation_IOKit_Edition.pdf) | N/A | Stefan Esser | 2011 | 37 | | [iOS 5 An Exploitation Nightmare?](https://papers.put.as/papers/ios/2012/CSW2012_StefanEsser_iOS5_An_Exploitation_Nightmare_FINAL.pdf) | N/A | Stefan Esser | 2012 | 38 | | [iOS Kernel Heap Armageddon](https://papers.put.as/papers/ios/2012/SyScan2012_StefanEsser_iOS_Kernel_Heap_Armageddon.pdf) | N/A | Stefan Esser | 2012 | 39 | | [iOS 6 Kernel Security: A Hacker’s Guide](https://conference.hitb.org/hitbsecconf2012kul/materials/D1T2%20-%20Mark%20Dowd%20&%20Tarjei%20Mandt%20-%20iOS6%20Security.pdf) | [#HITB2012KUL D1T2 - Mark Dowd & Tarjei Mandt - iOS 6 Security](https://www.youtube.com/watch?v=O-WZinEoki4) | Mark Dowd, Tarjei Mandt | 2012 | 40 | | [Find Your Own iOS Kernel Bug](https://papers.put.as/papers/ios/2012/Xu-Hao-Xiabo-Chen-Find-Your-Own-iOS-Kernel-Bug.pdf) | N/A | Chen Xiaobo, Xu Hao | 2012 | 41 | | [Attacking the iOS Kernel: A Look at ‘evasi0n’](https://papers.put.as/papers/ios/2013/NISlecture201303.pdf) | N/A | Tarjei Mandt | 2013 | 42 | | [SWIPING THROUGH MODERN SECURITY FEATURES](https://papers.put.as/papers/ios/2013/D2T1-Pod2g-Planetbeing-Musclenerd-and-Pimskeks-aka-Evad3rs-Swiping-Through-Modern-Security-Features.pdf) | [#HITB2013AMS D2T1 Evad3rs - Swiping Through Modern Security Features](https://www.youtube.com/watch?v=brrIquvUR4M) | evad3rs | 2013 | 43 | | [Exploiting Unpatched iOS Vulnerabilities for Fun and Profit](https://papers.put.as/papers/ios/2014/iosjb_slide.pdf) | N/A | Yeongjin Jang, Tielei Wang, Byoungyoung Lee, Billy Lau | 2014 | 44 | | [iOS 6/7/8 Security - A Study in Fail](https://papers.put.as/papers/ios/2015/SyScan15_Stefan_Esser_-_iOS_678_Security_-_A_Study_in_Fail.pdf) | N/A | Stefan Esser | 2015 | 45 | | [OPTIMIZED FUZZING IOKIT IN iOS](https://papers.put.as/papers/ios/2015/us-15-Lei-Optimized-Fuzzing-IOKit-In-iOS-wp.pdf) | [Optimized Fuzzing IOKit In iOS](https://www.youtube.com/watch?v=XDT9Cn8GjJU) | Lei Long | 2015 | 46 | | [Review and Exploit Neglected Attack Surface in iOS 8](https://papers.put.as/papers/ios/2015/us-15-Wang-Review-And-Exploit-Neglected-Attack-Surface-In-iOS-8.pdf) | N/A | Pangu Team | 2015 | 47 | | [Hacking from iOS 8 to iOS 9](https://papers.put.as/papers/ios/2015/POC2015_RUXCON2015.pdf) | N/A | Pangu Team | 2015 | 48 | | [Dig Into The Attack Surface Of PDF And Gain 100 CVEs In 1 Year](https://www.blackhat.com/docs/asia-17/materials/asia-17-Liu-Dig-Into-The-Attack-Surface-Of-PDF-And-Gain-100-CVEs-In-1-Year.pdf)| N/A | Tencent XuanWu Lab | 2017 | 49 | |[Diving into the iOS Kernel: Breaking Entitlements](https://sparkes.zone/blog/jekyll/update/2018/04/06/diving-into-the-kernel-entitlements.html)| N/A | @iBSparkes | 2018| 50 | 51 | ## Technical 52 | | *Document* | *Related Talk* | *Author* | *Year* | 53 | |-----------------------------------------------------------------------------------------------------------|----------------|----------------|--------| 54 | | [Security Enclave](http://mista.nu/research/sep-paper.pdf) | [Demystifying the Secure Enclave Processor](https://www.youtube.com/watch?v=7UNeUT_sRos) | Tarjei Mandt, Mathew Solnik, and David Wang | 2016 | 55 | | [Build your own iOS kernel debugger](https://bugs.chromium.org/p/project-zero/issues/attachment?aid=346425&signed_aid=drSMyPfPWvCZgYKtiwI2iA==) | N/A | Ian Beer | 2018 | 56 | 57 | ## Exploit Write-ups 58 | | *CVEIDs* | *LINK* | 59 | |-------------|----------------| 60 | |CVE-2016-4655 CVE-2016-4656| | 61 | |CVE-2016-7644 CVE-2016-7637 CVE-2016-7661| | 62 | |CVE-2017-2370|| 63 | |CVE-2017-2416|| 64 | |CVE-2017-2533 CVE-2017-2535 CVE-2017-2534| | 65 | |CVE-2018-4087|https://blog.zimperium.com/cve-2018-4087-poc-escaping-sandbox-misleading-bluetoothd/| 66 | |CVE-2B-DETERMINED|http://bazad.github.io/2018/04/kernel-pointer-crash-log-ios/| 67 | ## External Links 68 | Here you can find external list of papers and documents, most of which are not listed here. 69 | 70 | * [@osxreverser](https://twitter.com/osxreverser)'s list: https://papers.put.as/ 71 | * [@snakeninny](https://twitter.com/snakeninny)'s iOSRE Book for beginners: https://github.com/iosre/iOSAppReverseEngineering 72 | -------------------------------------------------------------------------------- /resources/scripts/Install Commonly Used Utilities/Hopper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import urllib2 3 | import urllib 4 | import json 5 | headers = { 'User-Agent' : 'Mozilla/5.0' } 6 | req = urllib2.Request('http://hopperapp.com/include/files-api.php?request=releases',None,headers) 7 | print "Loading Hopper URL API" 8 | response = urllib2.urlopen(req) 9 | the_page = response.read() 10 | JSON=json.loads(the_page) 11 | OSXJSON=JSON["OS X"] 12 | url=OSXJSON["filename"] 13 | print "Downloading Hopper Latest With Size:",OSXJSON["file_length"] 14 | urllib.urlretrieve (url, "Hoppper-Latest.zip") -------------------------------------------------------------------------------- /resources/scripts/Install Commonly Used Utilities/Installer.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | echo "Installing Xcode Commandline Tools" 3 | xcode-select --install 4 | if ! type "brew" > /dev/null; then 5 | # install Homebrew 6 | echo "Installing Homebrew" 7 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 8 | else 9 | echo "Homebrew already installed" 10 | fi 11 | 12 | if ! type "dpkg" > /dev/null; then 13 | # install dpkg 14 | echo "Installing dpkg" 15 | brew install dpkg 16 | else 17 | echo "dpkg already installed" 18 | fi 19 | 20 | if ! type "ldid" > /dev/null; then 21 | # install ldid 22 | echo "Installing ldid" 23 | brew install ldid 24 | else 25 | echo "ldid already installed" 26 | fi 27 | 28 | export THEOS=/opt/theos 29 | if [ ! -d "$THEOS" ]; then 30 | # Theos isn't existe 31 | echo "Installing Theos" 32 | echo "export THEOS=/opt/theos" >>~/.bash_profile 33 | source ~/.bash_profile 34 | sudo git clone --recursive https://github.com/theos/theos.git $THEOS 35 | sudo git clone https://github.com/theos/headers.git $THEOS/Headers 36 | sudo cp -r $THEOS/Headers/ $THEOS/include 37 | sudo rm -rf $THEOS/Headers/ 38 | else 39 | # Theos existe 40 | echo "Theos already installed" 41 | fi 42 | 43 | if ! type "wget" > /dev/null; then 44 | # install wget 45 | echo "Installing wget" 46 | brew install wget 47 | else 48 | echo "wget already installed" 49 | fi 50 | 51 | if [ ! -d "/Applications/Reveal.app" ]; then 52 | # Reveal app isn't existe 53 | echo "Installing Reveal" 54 | wget http://download.revealapp.com/Reveal.app.zip 55 | unzip -XK ./Reveal.app.zip 56 | chmod +x ./Reveal.app/Contents/MacOS/Reveal 57 | mv ./Reveal.app /Applications/Reveal.app 58 | rm -rf ./Reveal.app 59 | rm -rf ./Reveal.app.zip 60 | else 61 | echo "Reveal app already installed" 62 | fi 63 | 64 | if [ ! -d "/Applications/Hopper Disassembler v3.app" ]; then 65 | # Hopper app isn't existe 66 | echo "Installing Hopper" 67 | sudo ./Hopper.py 68 | unzip -XK ./Hoppper-Latest.zip 69 | mv './Hopper Disassembler v3.app' '/Applications/Hopper Disassembler v3.app' 70 | else 71 | echo "Hopper app already installed" 72 | fi 73 | 74 | 75 | sudo ./debugserver.py 76 | git clone https://github.com/nygard/class-dump.git class-dump 77 | xcodebuild -project ./class-dump/class-dump.xcodeproj #Compile classdump 78 | mv ./class-dump/build/Release/class-dump /usr/local/bin 79 | rm -rf ./class-dump 80 | -------------------------------------------------------------------------------- /resources/scripts/Install Commonly Used Utilities/README.md: -------------------------------------------------------------------------------- 1 | # iOSRETools 2 | >>YOU MUST cd TO THIS FOLDER BEFORE DOING ANYTHING!!! 3 | >>Then Just ./Installer.sh 4 | A collection of commonly used iOSRE Tools 5 | 6 | Pull Requests Are Favoured 7 | 8 | >>Naville.Zhang -------------------------------------------------------------------------------- /resources/scripts/Install Commonly Used Utilities/debugserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import string 4 | import os 5 | Path = subprocess.check_output(['xcode-select', '-p']) 6 | Path = Path + "/Platforms/iPhoneOS.platform/DeviceSupport" 7 | Path = string.replace(Path, "\n", "") 8 | print "Developer Images Located At:", Path 9 | for Sub in os.listdir(Path): 10 | SubDire = os.path.join(Path, Sub) 11 | if (os.path.isdir(SubDire)): 12 | print "Loading Developer Disk Image At:\n",SubDire 13 | os.system("hdiutil mount "+"\""+SubDire+"\""+"/DeveloperDiskImage.dmg -mountpoint /Volumes/DeveloperDiskImage") 14 | DebugSrvPath=SubDire+"/debugserver" 15 | print DebugSrvPath 16 | print "Current DebugServer Copied To:\n"+DebugSrvPath 17 | os.system("cp /Volumes/DeveloperDiskImage/usr/bin/debugserver "+"\""+SubDire+"\"") 18 | os.system("codesign -s - --entitlements ./debugsrvEntitle.xml -f "+"\""+DebugSrvPath+"\"") 19 | Version=os.path.basename(os.path.normpath(SubDire))#Thanks http://stackoverflow.com/questions/3925096/how-to-get-only-the-last-part-of-a-path-in-python 20 | print "Version For Current DebugServer:\n"+Version 21 | os.system("cp "+"\""+DebugSrvPath+"\""+" ./DebugServer"+"\""+Version+"\"") 22 | 23 | 24 | print "Unloading Developer Disk Image At:\n",SubDire 25 | os.system("hdiutil unmount /Volumes/DeveloperDiskImage") 26 | os.remove(DebugSrvPath) 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/scripts/Install Commonly Used Utilities/debugsrvEntitle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.springboard.debugapplications 6 | 7 | run-unsigned-code 8 | 9 | get-task-allow 10 | 11 | task_for_pid-allow 12 | 13 | 14 | -------------------------------------------------------------------------------- /resources/scripts/Install XPwn/build_xpwn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ####################################################################### 3 | # 4 | # Project......: build_xpwn.sh 5 | # Creator......: matteyeux 6 | # Description..: Script to install XPwn tools 7 | # 8 | ###################################################################### 9 | # Language : 10 | # bash 11 | # Version : 0.3 12 | 13 | if [[ "$(whoami)" != "root" ]]; then 14 | echo "Please run this script as root" 15 | exit 1 16 | fi 17 | 18 | if [[ $(uname) != 'Linux' ]]; then 19 | echo "This script is only for Linux" 20 | exit 1 21 | fi 22 | 23 | apt-get -y install binutils 24 | apt-get -y install p7zip-full 25 | apt-get -y install git 26 | apt-get -y install build-essential 27 | apt-get -y install make 28 | apt-get -y install cmake 29 | apt-get -y install openssl 30 | apt-get -y install libcrypto++-dev:q 31 | apt-get -y install bsdiff 32 | apt-get -y install libbz2-dev 33 | apt-get -y install libpng3 34 | apt-get -y install libusb-1.0.0 35 | apt-get -y install libusb-1.0.0-dev 36 | apt-get -y install libssl-dev 37 | apt-get -y install libcurl3 38 | apt-get -y install python-pip 39 | cd ~ 40 | git clone https://github.com/xerub/xpwn.git 41 | mkdir ~/build 42 | cd ~/build 43 | cmake ~/xpwn 44 | make 45 | make package 46 | tar xvjf XPwn-0.5.8-Linux.tar.bz2 47 | 48 | cd XPwn-0.5.8-Linux 49 | cp dmg hdutil hfsplus ipsw ticket xpwntool validate /usr/local/bin/ 50 | 51 | echo "XPwn binaries installed to /usr/local/bin/" -------------------------------------------------------------------------------- /resources/scripts/Install libimobiledevice/libinstaller.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ####################################################################### 3 | # 4 | # Project......: libinstaller.sh 5 | # Creator......: matteyeux 6 | # Description..: Script to install libimobiledevice on OS X & Debian Distros 7 | # initials scripts: brew.sh & autobuild.sh by DarkMalloc 8 | # Type.........: Public 9 | # 10 | ###################################################################### 11 | # Language : 12 | # bash 13 | # Version : 0.2 14 | # 15 | # Change Log 16 | # ========== 17 | # 18 | # =============================================================== 19 | # Date | Who | What 20 | # --------------------------------------------------------------- 21 | # 27/12/15 | Mathieu Hautebas | Script creation 22 | # --------------------------------------------------------------- 23 | # 10/03/16 | HanSheng Zhang | Fix Stack overflow caused by naming issues 24 | # --------------------------------------------------------------- 25 | 26 | function apt-get(){ 27 | sudo apt-get install -y git 28 | sudo apt-get install -y build-essential 29 | sudo apt-get install -y make 30 | sudo apt-get install -y autoconf 31 | sudo apt-get install -y automake 32 | sudo apt-get install -y libtool 33 | sudo apt-get install -y openssl 34 | sudo apt-get install -y tar 35 | sudo apt-get install -y perl 36 | sudo apt-get install -y binutils 37 | sudo apt-get install -y gcc 38 | sudo apt-get install -y libstdc++6-dev 39 | sudo apt-get install -y libc6-dev 40 | sudo apt-get install -y libssl-dev 41 | sudo apt-get install -y libusb-1.0 42 | sudo apt-get install -y gcc4.2 43 | sudo apt-get install -y g++ 44 | sudo apt-get install -y libcurl4-gnutls-dev 45 | sudo apt-get install -y fuse 46 | sudo apt-get install -y libxml2-dev 47 | 48 | sudo apt-get install -y libgfortran1 49 | sudo apt-get install -y libgfortran2 50 | sudo apt-get install -y libgfortran 51 | sudo apt-get install -y libgcc1 52 | sudo apt-get install -y libreadline-dev 53 | sudo apt-get install -y libglib2.0-dev 54 | sudo apt-get install -y libzip-dev 55 | sudo apt-get install -y libclutter-1.0-dev 56 | sudo apt-get install -y libgtk2.0-dev 57 | sudo apt-get install -y libclutter-gtk-1.0-dev 58 | sudo apt-get install -y lib32bz2-dev 59 | sudo apt-get install -y libfuse-dev 60 | 61 | sudo apt-get install -y subversion 62 | sudo apt-get install -y cython 63 | sudo apt-get install -y python-2.7 64 | sudo apt-get install -y python2.7-numpy 65 | sudo apt-get install -y libncurses4 66 | sudo apt-get install -y libncurses5 67 | sudo apt-get install -y ncurses-base 68 | } 69 | 70 | function brewfunc(){ 71 | # Install Hombrew. 72 | if ! type "brew" > /dev/null; then 73 | echo "brew Doesn't Exist.Installing" 74 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 75 | 76 | else 77 | echo "Brew Exists. Using" 78 | fi 79 | 80 | 81 | # Install command-line tools using Homebrew. 82 | 83 | # Ask for the administrator password upfront. 84 | sudo -v 85 | 86 | # Keep-alive: update existing `sudo` time stamp until the script has finished. 87 | while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null & 88 | 89 | echo "Make sure we’re using the latest Homebrew." 90 | brew update 91 | 92 | echo "Upgrade any already-installed formulae." 93 | brew upgrade 94 | 95 | echo "Install GNU core utilities (those that come with OS X are outdated)". 96 | echo "Don’t forget to add `$(brew --prefix coreutils)/libexec/gnubin` to `$PATH`". 97 | brew install coreutils 98 | sudo ln -s /usr/local/bin/gsha256sum /usr/local/bin/sha256sum 99 | 100 | echo " Install some other useful utilities like `sponge`". 101 | brew install moreutils 102 | echo "Install GNU `find`, `locate`, `updatedb`, and `xargs`, `g`-prefixed". 103 | brew install findutils 104 | echo "Install GNU `sed`, overwriting the built-in `sed`". 105 | brew install gnu-sed --with-default-names 106 | 107 | echo "Install Development Packages"; 108 | brew install libxml2 109 | brew install libzip 110 | brew install libplist 111 | brew install openssl 112 | brew install clutter 113 | brew install cogl 114 | brew install usbmuxd 115 | 116 | 117 | # Install Software; 118 | brew install automake 119 | brew install cmake 120 | brew install colormake 121 | brew install autoconf 122 | brew install libtool 123 | brew install pkg-config 124 | brew install gcc 125 | brew install libusb 126 | brew install homebrew/fuse/ifuse 127 | brew install glib 128 | 129 | # Install Optional; 130 | brew install screenfetch 131 | brew install Caskroom/cask/osxfuse 132 | 133 | # Install extras; 134 | brew install bfg 135 | brew install binutils 136 | brew install binwalk 137 | brew install cifer 138 | brew install dex2jar 139 | brew install dns2tcp 140 | brew install fcrackzip 141 | brew install foremost 142 | brew install hashpump 143 | brew install hydra 144 | brew install john 145 | brew install knock 146 | brew install nmap 147 | brew install pngcheck 148 | brew install socat 149 | brew install sqlmap 150 | brew install tcpflow 151 | brew install tcpreplay 152 | brew install tcptrace 153 | brew install ucspi-tcp # `tcpserver` etc. 154 | brew install xz 155 | 156 | # Install other useful binaries. 157 | brew install ack 158 | #brew install exiv2 159 | brew install git 160 | #brew install imagemagick --with-webp 161 | brew install lua 162 | brew install lynx 163 | brew install p7zip 164 | brew install pigz 165 | 166 | # Install Node.js. Note: this installs `npm` too, using the recommended 167 | # installation method. 168 | brew install node 169 | 170 | # Remove outdated versions from the cellar. 171 | brew cleanup 172 | } 173 | 174 | function autobuild(){ 175 | successlibs=() 176 | failedlibs=() 177 | libs=( "libplist" "libusbmuxd" "libimobiledevice" "usbmuxd" "libirecovery" \ 178 | "ideviceinstaller" "libideviceactivation" "idevicerestore" "sbmanager" "ifuse" ) 179 | 180 | spinner() { 181 | # What On Earth Is This? 182 | local pid=$1 183 | local delay=0.75 184 | local spinstr='|/-\' 185 | echo "$pid" > "/tmp/.spinner.pid" 186 | while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do 187 | local temp=${spinstr#?} 188 | printf " [%c] " "$spinstr" 189 | local spinstr=$temp${spinstr%"$temp"} 190 | sleep $delay 191 | printf "\b\b\b\b\b\b" 192 | done 193 | printf " \b\b\b\b" 194 | } 195 | 196 | buildlibs() { 197 | for i in "${libs[@]}" 198 | do 199 | echo -e "\033[1;32mFetching $i..." 200 | git clone https://github.com/libimobiledevice/${i}.git 201 | cd $i 202 | echo -e "\033[1;32mConfiguring $i..." 203 | ./autogen.sh 204 | ./configure 205 | echo -e "\033[1;32mBuilding $i..." 206 | make && sudo make install 207 | echo -e "\033[1;32mInstalling $i..." 208 | cd .. 209 | done 210 | echo -e "\033[0m" 211 | } 212 | 213 | function buildr { 214 | buildlibs 215 | } 216 | echo -e "\033[1;37mLibimobiledevice library build script - Elrhk 2015" 217 | buildr 218 | } 219 | 220 | if [[ $(uname) == 'Linux' ]]; then 221 | apt-get 222 | autobuild 223 | exit 1 224 | elif [[ $(uname) == 'Darwin' ]]; then 225 | brewfunc 226 | autobuild 227 | fi -------------------------------------------------------------------------------- /wiki/Auditing-the-XNU-Kernel.md: -------------------------------------------------------------------------------- 1 | __TODO__ -------------------------------------------------------------------------------- /wiki/BootROM-RE.md: -------------------------------------------------------------------------------- 1 | # BootROM RE 2 | 3 | __TODO__ 4 | 5 | https://github.com/bat0s/BootROM 6 | -------------------------------------------------------------------------------- /wiki/Bypassing-AMFI.md: -------------------------------------------------------------------------------- 1 | ## Bypassing AMFI 2 | 3 | AppleMobileFileIntegrity is the kernel extension that handles codesign enforcement. 4 | It uses MAC Framework in order to hook into the Mach-O loading related functions in XNU, as well as hooking into mmap and several other functions. 5 | Code sign enforcement also happens at page fault time. 6 | 7 | When a mapping is added to an address space, it is not actually added to translation tables just yet. Instead, on the first access a page fault exception is generated and the kernel maps in the requested page. If a page is marked as executable, the kernel will also hash the page and compare it against the codesign blob for the vnode it's mapped from; if the hashes differ, the task is terminated. 8 | 9 | The main attack vector for AMFI has historically been dyld, the dynamic loader. Indeed, the dynamic loader is in charge for mapping Mach-Os such as dylibs into a given address space. Segments in a Mach-O describe a section of said address space; memory protection flags are also described by Mach-O segments and applied by dyld. 10 | 11 | Dyld also enforces code signatures by requiring Mach-O load commands to be in a segment marked as executable (in function sniffLoadCommands) to counter against @comex's incomplete codesign; however there is a chicken-and-egg issue here; Load commands are themselves part of a segment, however segments aren't mapped until load commands are parsed. This means dyld just copies load commands on the stack (which is rw- memory and thus not codesign enforced), parses load commands and checks wether the load commands were in an executable segment or not; on failure, dyld abort()s. 12 | 13 | Once segments are mapped in, dyld page faults into each of the segments's pages (in function crashIfInvalidSignature), which finally validates both the load commands and segments. 14 | 15 | The first attack against this was to mark a semgent as "textreloc", which would unprotect it to rw- after sniffLoadCommands checked load commands to be in a PROT_EXEC area, but before crashIfInvalidSignature could validate signatures. 16 | Following attacks involved overlapping segments so load commands would be detected to be in a executable segment, but after getting mmap()ed, a second non-executable mapping would map on top of them, effectively killing the crashIfInvalidCodeSignature check. 17 | -------------------------------------------------------------------------------- /wiki/Disassemblers.md: -------------------------------------------------------------------------------- 1 | [IDA](https://www.hex-rays.com/products/ida/) is one of the more powerful and useful disassemblers. However, it's not easy to get a copy with arm64 support at this time, and is also quite pricey. 2 | 3 | [Hopper](http://www.hopperapp.com) is a great disassembler, albeit missing some of the features which make IDA has. Quite affordable for the average person, and demo is very useful as well. 4 | 5 | [Capstone Engine](https://github.com/aquynh/capstone) is a open source disassembler. Hopper uses CE at its core. This one is totally free,with multiple bindings,can be integrated in your own projects,however, you might have to write your own binary loader for it 6 | 7 | Hopefully going to get [qira](https://github.com/BinaryAnalysisPlatform/qira) working on iOS. Would be incredibly useful for analysis. 8 | -------------------------------------------------------------------------------- /wiki/Dumping-iBoot.md: -------------------------------------------------------------------------------- 1 | This information only applies to iBoot64 on iOS 8 or lower. 2 | 3 | In order to dump iBoot, you need: 4 | 5 | 1. Kernel read/write (eg task_for_pid 0) 6 | 2. gPhysBase and gVirtBase 7 | 3. A pointer to the kernel pmap's level1 translation table entries. 8 | 9 | Once those are obtained, just add a mapping for gPhysBase to the level1 table (code for this is available upon request; drop me a pm on freenode), mapping 1GB of physical memory at a given virtual address. 10 | Additionally, make sure to clear the read only bit and set the EL0-accessible bit. 11 | 12 | At this point, it's simple matter of memmem to figure out where iBoot is hiding in phys. Given a gPhysBase map at 0xffffffc3c0000000, this code should do the trick. 13 | 14 | ``` 15 | int main(int argc, char **argv, char **envp) { 16 | char* base = (char*) 0xffffffc3c0000000; 17 | char* sig = (char*) "FFiBoot for "; 18 | char* iboot = (char*) memmem(base, (1<<30), sig+2, strlen(sig)-2); 19 | while (*(iboot-1) == 'F' && *(iboot-2) == 'F') { 20 | iboot ++; 21 | /* should fix size up here but too lazy lol */ 22 | iboot = (char*) memmem(iboot, (1<<30), sig+2, strlen(sig)-2); 23 | assert(iboot); 24 | } 25 | iboot = (char*) (((uintptr_t)iboot) & (~0xFFF)); 26 | printf("found iboot at %p\n", iboot); 27 | return 0; 28 | } 29 | ```` 30 | -------------------------------------------------------------------------------- /wiki/Firmwares-and-Keys.md: -------------------------------------------------------------------------------- 1 | # Firmwares and Keys 2 | 3 | Firmwares come as .ipsw files, which are .zip files in disguise. 4 | 5 | Here's what the folder structure looks like (example: iPhone5,4 on iOS 9.2.1): 6 | 7 | ``` 8 | iPhone5,4_9.2.1_13D15_Restore.ipsw/ 9 | ├── 058-32080-015.dmg 10 | ├── 058-32173-015.dmg 11 | ├── 058-32359-015.dmg 12 | ├── BuildManifest.plist 13 | ├── Firmware/ 14 | ├──── Mav7Mav8-6.01.00.Release.bbfw 15 | ├──── Mav7Mav8-6.01.00.Release.plist 16 | ├──── all_flash/ 17 | ├────── all_flash.n49ap.production/ 18 | ├────── DeviceTree.n49ap.img3 19 | ├────── LLB.n49.RELEASE.img3 20 | ├────── applelogo@2x~iphone.s5l8950x.img3 21 | ├────── batterycharging0@2x~iphone.s5l8950x.img3 22 | ├────── batterycharging1@2x~iphone.s5l8950x.img3 23 | ├────── batteryfull@2x~iphone.s5l8950x.img3 24 | ├────── batterylow0@2x~iphone.s5l8950x.img3 25 | ├────── batterylow1@2x~iphone.s5l8950x.img3 26 | ├────── glyphplugin@1136~iphone-lightning.s5l8950x.img3 27 | ├────── iBoot.n49.RELEASE.img3 28 | ├────── manifest 29 | ├────── recoverymode@1136~iphone-lightning.s5l8950x.img3 30 | ├──── dfu/ 31 | ├────── iBEC.n49.RELEASE.dfu 32 | ├────── iBSS.n49.RELEASE.dfu 33 | ├──── usr/ 34 | ├────── local/ 35 | ├────── standalone/ 36 | ├── Restore.plist 37 | └── kernelcache.release.n49 38 | ``` 39 | 40 | All of these files can be extracted using keys and xpwn. 41 | 42 | Firmware keys are posted on 43 | - https://theiphonewiki.com/wiki/Firmware_Keys 44 | - https://ipsw.me/keys 45 | - https://ipswcentral.com//keys 46 | 47 | For the kernelcache, run: 48 | 49 | `xpwntool path/to/cache /path/to/output -k KEY -iv IV -decrypt` 50 | 51 | The root filesystem is in the largest DMG file of the .ipsw. To extract it, download dmg ([OS X](http://www.ifans.com/forums/attachments/dmg-zip.68330/), [Windows](https://intdev.googlecode.com/files/dmg.exe)). Make sure dmg or dmg.exe is in your path and execute one of the following: 52 | 53 | `./dmg input.dmg output.dmg -k KEY` (OS X) 54 | 55 | `dmg.exe input.dmg output.dmg -k KEY` (Windows) 56 | -------------------------------------------------------------------------------- /wiki/History-of-iOS-Mitigations.md: -------------------------------------------------------------------------------- 1 | 2 | # Firmware Encryption 3 | 4 | Wasn't fully working until iOS 2.0. The 8900 format was used first, then img3 and now im4p. Common workarounds are low level exploits which allow to turn devices into key oracles. 5 | 6 | # Code Signing 7 | 8 | Introduced in iOS 2.0. Enforced by AppleMobileFileIntegrity, or AMFI. 9 | 10 | Common workarounds are unprotecting codesigned pages to rw- to avoid code sign enforcement, and neutering MISValidateSignature in amfid (these tricks are often combined in order to get dyld to load a fake dylib which interposes MISValidateSignature without triggering any code sign fault, which kills effectively codesigning system-wide, allowing arbitrary ad-hoc binaries to be loaded at will). 11 | 12 | For patching, amfi_get_out_of_my_way is a good technique. 13 | 14 | # LLB Validation 15 | 16 | On the S5L8900 no sigchecking was performed by the bootrom before jumping into the LLB- note that with a solid chain of trust this wouldn't be an issue since sigchecks are performed when flashing the image, but this allowed for easy persistance once a single injection vector was acquired. This changed with the introduction of the iPod Touch 2G, whose bootrom validated also the LLB image. 17 | 18 | Common workarounds are bootrom exploits or similar low level exploits, or an userland persistency vector (look for Code Signing workarounds). 19 | 20 | # dyld data-only dylib hardening 21 | # ASLR 22 | # Free List Hardening 23 | # Poisoning 24 | # Stack Guard 25 | # KASLR 26 | # Info Leak Mitigation Strategy 27 | # Proper kernel memory protection flags 28 | # Address Space Isolation 29 | # CS_RESTRICT 30 | # LwVM Write Locking 31 | # mmap hook TeamID validation 32 | # validateFirstFewPages 33 | # KPP 34 | # Modern AMFI 35 | # LaunchDaemons plists moved to xpcd_cache.dylib 36 | 1. First attempt (iOS x.y) just moved plists to code-signed xpcd_cache.dylib 37 | 2. Second attempt (iOS x.y) added a dummy function to xpcd_cache.dylib that launchd runs to make sure AMFI kicks in and checks integrety. 38 | 39 | Commond workarounds usually involve replacing daemons directly. A good target for this is softwareupdated, since stashing breaks OTA (and OTA is an unwanted feature, too). 40 | 41 | __TODO__ 42 | -------------------------------------------------------------------------------- /wiki/IOKit-RE.md: -------------------------------------------------------------------------------- 1 | # IOKit RE (may the 64 bits be with you) 2 | 3 | IOKit is a bunch of classes, a C++ framework for writing code and drivers in XNU kernel. 4 | It is implemented on top of the libkern library in a subset of C++. 5 | 6 | It is true that the generic parts of the IOKit are available in source. 7 | Here and there you might even find an outdated sources for some of the driver families kexts. 8 | However, most of the kexts present in the kernelcache on the iOS are binary and need to be REd. 9 | 10 | One of the challenges REing these kexts is the dynamic nature of the C++. 11 | Fortunately, libkern provides a sort of RTTI (Runtime Type Information) for safe dynamic casting and 12 | whatnot, which gives us information about the classes and the hierarchy. 13 | 14 | ## Meta 15 | > We only collect meta data ... 16 | 17 | Seriously though, there is a meta class for each and every class in libkern/IOKit. 18 | It provides the basis for runtime information about the classes and helps us a lot. 19 | 20 | ### Registration 21 | During the initialization of the kernel/kext, new classes are registered 22 | into the RTTI system by calling the OSMetaClass::OSMetaClass() function. 23 | This "register" function takes the following arguments: 24 | - pointer to instance of the meta class for the class we register 25 | - name of the class we register 26 | - pointer to instance of parent's meta class 27 | - size of an instance of the class we register 28 | 29 | These register calls are made from the init functions located in the __mod_init_func sections of the kernel and the kexts. 30 | Lets take the AMFI kext for example. It has 2 init functions in the mod_init_func section. 31 | Bellow is the content of the first one: 32 | ~~~ data 33 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C8C ADR X0, off_FFFFFF801FE3F228 34 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C90 NOP 35 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C94 ADR X1, aApplemobilefil ; "AppleMobileFileIntegrityUserClient" 36 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C98 NOP 37 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C9C NOP 38 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CA0 LDR X2, =off_FFFFFF801FD36DC8 39 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CA4 MOV W3, #0xE8 40 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CA8 BL sub_FFFFFF801FE1E270 41 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CAC ADRP X8, #off_FFFFFF801FE3F228@PAGE 42 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CB0 ADR X9, off_FFFFFF801FE3E8E0 43 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CB4 NOP 44 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CB8 ADD X9, X9, #0x10 45 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CBC STR X9, [X8,#off_FFFFFF801FE3F228@PAGEOFF] 46 | ~~~ 47 | Observe the following details (you will need your own kernelcache for this): 48 | - X0 is a pointer to a data structure residing in this kext's data section, specifically in the 49 | section named "__common" (on 64 bits). 50 | - X1 is a pointer to a string that looks like it could be a name of a class 51 | - X2 is another pointer to a "__common" data section, but this time not necessarily in the same kext. 52 | - W3 is a small immediate 53 | - BL is a stub function in the same kext. With the stub (through the symbol) leading to a function in the kernel. 54 | 55 | __Congratulations!__ You have found a meta class register call to OSMetaClass::OSMetaClass(). 56 | Just as you've guessed it: 57 | - X0 is the meta class 58 | - X1 is the name 59 | - X2 is the parent 60 | - W3 is the size 61 | - The function in the kernel is the OSMetaClass::OSMetaClass() function. 62 | 63 | There is a bit more though ... 64 | After the call to the register stub, it writes some pointer+0x10 into the mata class object. 65 | The first pointer in the object is usually the vtable. And indeed, this is the vtable for the meta 66 | class. 67 | 68 | #### Beautification 69 | Let's apply the knowledge we've gathered. Let's rename the objects and the vtable by the following 70 | patterns (python): 71 | ~~~python 72 | meta_object = "__ZN%d%s10gMetaClassE" % (len(class_name), class_name) 73 | meta_vtable = "__ZTVN%d%s9metaClassE" % (len(class_name), class_name) 74 | ~~~ 75 | 76 | Notes: 77 | * Parent meta class: 78 | The _parent_meta_object_ gets renamed when we find where the parent is registered and rename the 79 | _meta_object_ there. It is a pointer to the same place. 80 | * Renaming a stub: 81 | You can't really add the "stub" and be done with it, because you have such a stub in every kext. 82 | So, you need to be a bit creative here. 83 | 84 | ##### Results 85 | Now, IDA can demangle the names and will show us the following: 86 | ~~~ data 87 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C8C ADR X0, AppleMobileFileIntegrityUserClient::gMetaClass 88 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C90 NOP 89 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C94 ADR X1, aApplemobilefil ; "AppleMobileFileIntegrityUserClient" 90 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C98 NOP 91 | AppleMobileFileIntegrity:__text:FFFFFF801FE19C9C NOP 92 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CA0 LDR X2, =IOUserClient::gMetaClass 93 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CA4 MOV W3, #0xE8 94 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CA8 BL OSMetaClass::OSMetaClass::[stub_at_0xFFFFFF801FE1E270](char const*,OSMetaClass const*,uint) 95 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CAC ADRP X8, #AppleMobileFileIntegrityUserClient::gMetaClass@PAGE 96 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CB0 ADR X9, vtable for'AppleMobileFileIntegrityUserClient_::metaClass 97 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CB4 NOP 98 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CB8 ADD X9, X9, #0x10 99 | AppleMobileFileIntegrity:__text:FFFFFF801FE19CBC STR X9, [X8,#AppleMobileFileIntegrityUserClient::gMetaClass@PAGEOFF] 100 | ~~~ 101 | 102 | # TODO 103 | * __such wow!__ 104 | * __much to-do!__ 105 | * vtables (class and meta class) 106 | * structs 107 | * OSMetaClassBase vtable quirk 108 | * moar RE 109 | 110 | 111 | # Notes 112 | ## 64 vs 32 bits 113 | Sometimes the difference are minor, like R0 instead of X0. 114 | I believe the grand scheme is the same and it would be relatively easy to apply. 115 | And why would you be looking at 32 bits anyway, shoo, shoo! 116 | 117 | -------------------------------------------------------------------------------- /wiki/Kernel-Patch-Protection-(KPP).md: -------------------------------------------------------------------------------- 1 | As of iOS9, all arm64 devices have kernel patch protection implemented wherein something likely other than the kernel checks every so often for kernel integrity, otherwise panics. 2 | 3 | Checked ranges are __TEXT and __DATA.__const. 4 | It is speculated that checks are enforced by either the SEP or the Secure Monitor. 5 | 6 | Current attempts to bypass KPP actually avoid it entirely and were demonstrated in Pangu9. 7 | The general idea is not to patch __TEXT, but rather data structures. 8 | 9 | In particular, Pangu9 replaced hooks in AMFI's MAC policy to either disable or alter the checks. 10 | 11 | This technique has been mitigated in iOS 9.2 by moving MAC policies in __const. 12 | 13 | LwVM::_mapForIO patches on the other hand are applied by actually unprotecting the root partition in the partition structure rather than by patching the protection check out. This can be done by finding the LwVM manager, which contains an array of pointers to partition structures. To find the LwVM manager, take a look at a LightweightVolumeManagerUserClient object. 14 | 15 | 16 | ------------------------------- 17 | Found this by @xerub [Tick (FPU) Tock (IRQ)](https://xerub.github.io/ios/kpp/2017/04/13/tick-tock.html) 18 | -------------------------------------------------------------------------------- /wiki/Mach-O.md: -------------------------------------------------------------------------------- 1 | # The Mach-O Format 2 | 3 | The Mach-O file format is the executable format of choice for XNU and dyld. 4 | It serves a purpose analog to what ELF or PE do; to put it simply, it describes a portion of an address space. 5 | Support for multi-architecture executables is also provided thanks to the fat format, which allows you to join multiple different architecture Mach-OS letting the kernel pick which to load. Note that it is possible to influence this with posix_spawn APIs. 6 | 7 | # Working with Mach-Os 8 | 9 | 1. otool is provided out-of-the-box with the xcode cli utils. 10 | 2. jtool, by Jonathan Levin, author of MOXiI and MOXiI II, is an analog but more flexible and advanced tool. On the other hand, it lacks support for disassembling architectures other than arm64. 11 | 2. lipo is a tool for working with fat files 12 | 3. Apple headers, specifically ``/``. 13 | 14 | # General structure 15 | This image from Apple documentation illustrates pretty well how a Mach-O file is composed. 16 | 17 | ![Mach-O files structure](images/mach_o_segments.png) 18 | 19 | The **header** is the first thing you will encounter while parsing a Mach-O file. It is always located at the very beginning. 20 | 21 | Immediately following the header there are the **load commands**, these commands describe what the content of the file is. They give us an idea of how the file is structured. Particularly, each command describes its own **segment** a piece of data (located in the **data** part of the Mach-O file), specifying where it is located (offset) in the file, and its size. Each specific command may also contain other values, specific to its segment only. 22 | 23 | Finally, we have the **data**. This part of the file contains actual data. It also contains, as you are probably wondering, the executable code of the Mach-O. The structure of this part is described exactly by the load commands discussed above, the layout is really the same. Each segment may be divided into various **sections** which simply exist to sub-categorize the data in each segment. For example, the `__TEXT` segment contains various sections, among those the `__text` section, that contains the actual executable machine bytes. Another section is the `__cstring`, which only contains hardcoded C strings used in the program. 24 | 25 | # Universal Binaries (fat Mach-Os) structure 26 | 27 | Apple introduced universal binaries when the transition from PPC architecture to x86 architecture was made. Universal binaries consists of more Mach-O files chained together, preceded by a so-called _fat header_, which contains the fat magic number and the number of Mach-O objects included in the file. 28 | 29 | Here's the structure of a fat header (`struct fat_header`): 30 | 31 | ``` 32 | struct fat_header { 33 | uint32_t magic; /* FAT_MAGIC */ 34 | uint32_t nfat_arch; /* number of structs that follow */ 35 | }; 36 | ``` 37 | 38 | Immediately following the header, we find an `nfat_arch` number of `struct fat_arch`, each of those defines more in detail every Mach-O contained in the file. Here's the structure definition: 39 | 40 | ``` 41 | struct fat_arch { 42 | cpu_type_t cputype; /* cpu specifier (int) */ 43 | cpu_subtype_t cpusubtype; /* machine specifier (int) */ 44 | uint32_t offset; /* file offset to this object file */ 45 | uint32_t size; /* size of this object file */ 46 | uint32_t align; /* alignment as a power of 2 */ 47 | }; 48 | ``` 49 | 50 | The first two fields describe the architecture for the Mach-O this structure is referring to, so that _dyld_ knows which Mach-O to load for your specific CPU. 51 |
52 | The `offset` field indicates, from the beginning of the file, where the Mach-O this structure is referring to is located in the whole fat binary. The `size` field indicates the whole size of that same Mach-O. Finally, the `align` field indicates the address boundary where the Mach-O should be aligned (generally, this is a page boundary, `4096`). 53 | 54 | The `fat_header` and the various `fat_arch`s are stored at the beginning of the file, in the so-called _fat section_. The _fat section_ is 4096 bytes in size, and thus it can hypothetically contain up to 204 `fat_arch`s. The rest of the _fat section_, which doesn't contain either the header nor the archs, is filled with zeroes. 55 | 56 | On a final note, remember that every single value found in the _fat section_ (`fat_header` + `fat_arch`s) is big-endian encoded. This is because at the time universal binaries were designed PPC was still the most widely used architecture, and it was big-endian. So, when reading values from parsed structures in the _fat section_, flip them. 57 | 58 | Summarizing an universal binary structure with a visual representation: 59 | 60 | ``` 61 | +---------------------+ /* header (fat_header: 0x8) */ 62 | | | 63 | | FAT HEADER | 64 | | | 65 | +---------------------+ /* archs (fat_arch: 0x14) */ 66 | | FAT ARCH #1 | 67 | +---------------------+ 68 | | FAT ARCH #2 | 69 | +---------------------+ 70 | | ... | /* other eventual fat archs... */ 71 | +---------------------+ /* Mach-Os section (variable size) */ 72 | | | 73 | | | 74 | | | 75 | | | 76 | | MACH-O #1 | 77 | | | 78 | | | 79 | | | 80 | | | 81 | | | 82 | +---------------------+ 83 | | | 84 | | | 85 | | | 86 | | | 87 | | | 88 | | MACH-O #2 | 89 | | | 90 | | | 91 | | | 92 | | | 93 | +---------------------+ 94 | | ... | /* other eventual Mach-Os... */ 95 | +---------------------+ 96 | 97 | ``` 98 | 99 | # mach_header(_64) 100 | There are two structs (for both _x86_ and _x64_ architectures) for representing a Mach-O header: 101 | 102 | ``` 103 | struct mach_header; // 32-bit Mach-O format 104 | struct mach_header_64; // 64-bit Mach-O format 105 | ``` 106 | The differences are minimal, just a `reserved` field added to the 64-bit header. 107 | 108 | As per loader.h, the header file defining Mach-O constants and structures: 109 | ``` 110 | struct mach_header(_64) { 111 | uint32_t magic; /* mach magic number identifier */ 112 | cpu_type_t cputype; /* cpu specifier */ 113 | cpu_subtype_t cpusubtype; /* machine specifier */ 114 | uint32_t filetype; /* type of file */ 115 | uint32_t ncmds; /* number of load commands */ 116 | uint32_t sizeofcmds; /* the size of all the load commands */ 117 | uint32_t flags; /* flags */ 118 | uint32_t reserved; /* reserved; 64 bit only */ 119 | }; 120 | #define MH_MAGIC 0xfeedface /* the mach magic number */ 121 | #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ 122 | ``` 123 | ### Types of Mach-Os 124 | ``` 125 | // These shuld be representing userland Mach-Os 126 | #define MH_EXECUTE 0x2 /* demand paged executable file (executable) */ 127 | #define MH_FVMLIB 0x3 /* fixed VM shared library file (???) */ 128 | #define MH_DYLIB 0x6 /* dynamically bound shared library */ 129 | #define MH_DYLINKER 0x7 /* dynamic link editor */ 130 | #define MH_BUNDLE 0x8 /* dynamically bound bundle file */ 131 | 132 | // Compile-time Mach-Os, Generic address-space Mach-Os, ??? 133 | #define MH_OBJECT 0x1 /* relocatable object file (.o) */ 134 | #define MH_CORE 0x4 /* core file */ 135 | #define MH_PRELOAD 0x5 /* preloaded executable file */ 136 | #define MH_DYLIB_STUB 0x9 /* shared library stub for static */ 137 | /* linking only, no section contents */ 138 | #define MH_DSYM 0xa /* companion file with only debug */ 139 | /* sections */ 140 | 141 | // Kernel Mach-Os 142 | #define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */ 143 | ``` 144 | # Load Commands 145 | Load commands are located immediately after the Mach header. They describe the content of the file, and are necessary to correctly parse the Mach-O. 146 | 147 | They can be parsed using the `struct load_command`: 148 | 149 | ``` 150 | struct load_command { 151 | uint32_t cmd; /* type of load command */ 152 | uint32_t cmdsize; /* total size of command in bytes */ 153 | }; 154 | ``` 155 | For a comprehensive list and descriptions of load commands, look in `mach-o/loader.h`. 156 | 157 | The most important ones are the `LC_SEGMENT(_64)`s, which describe each segment in the file. For example, the segment's name, the virtual address, the virtual size, the file offset (i.e. where that segment data is located in the file), the file size, initial and maximum memory protections and the number of sections for that segment. 158 | 159 | # Segments 160 | Segments are portions of the Mach-O file that get mapped in the address space at runtime. They are composed of sections, which hold actual data. 161 |
162 | Whatever data they contain, it is needed by the process at runtime and so it gets mapped in the address space. 163 | 164 | # Sections 165 | As we have stated before, segments are made of sections, and those hold actual data. They can contain virtually anything, like executable code bytes, data, pointers, strings or even nothing at all (see `__PAGEZERO` segment). 166 | 167 | # nlist / nlist_64 168 | 169 | # Symbols 170 | Check [facebook/fishhook](https://github.com/facebook/fishhook) For Explanations 171 | 172 | # Lazy Linking 173 | Check [facebook/fishhook](https://github.com/facebook/fishhook) For Explanations 174 | 175 | # Position Independent Executables 176 | a.k.a. ASLR-Enabled Executables. 177 | 178 | PIE Flag is in the *thin* mach_header with value 0x200000 179 | 180 | Minus that from the original flag value will disable ASLR, and vice verse 181 | 182 | # Special Segments 183 | __PAGEZERO is a special segment with *ZERO* disk space and takes a page in VM. 184 | When code access NULL, it will land there 185 | Mach-O containing __RESTRICT/__restrict will be flagged by dyld and thus DYLD_INSERT_LIBRARIES EnvVar will be ignored.(This is added after iOS6) 186 | 187 | # Other common load commands 188 | 189 | # Malformed Mach-O 190 | By altering Mach-O headers. Different issues would happen within dyld. 191 | 192 | Sometimes it can protect the binary from being analyzed 193 | 194 | Sometimes it's a 0Day and can help bypass Code-Signature-Verification 195 | 196 | Examples: 197 | 198 | ~~[MachOProtector](https://github.com/Naville/MachOProtecter)~~ 199 | 200 | Won't Work After iOS 8.1 or OS X 10.11 201 | 202 | [yalu](https://github.com/kpwn/yalu) 203 | 204 | Maybe. Didn't Check SRC. 205 | 206 | [Pangu8](http://8.pangu.io) 207 | 208 | 209 | # Two Level Namespace 210 | 211 | # The Mach-O Address Space in xnu/dyld based OSes 212 | 213 | # Dyld Shared Cache 214 | Download the latest dyld source from [here](http://opensource.apple.com/source/dyld/). 215 | 216 | open `./launch-cache/dsc_extractor.cpp` and change `#if 0` to `#if 1`. 217 |
218 | Then just `clang++ -o dsc_extractor dsc_extractor.cpp dsc_iterator.cpp` 219 | and run `dsc_extractor` on the cache to extract. 220 | 221 | ##### Known Issues: 222 | Seems like segment VM Address is wrong. So the binary is not class-dump able (Just use runtime dump instead) 223 | not nm-able (solution: simply replace `LC_SEGMENT_SPLIT_INFO` to `LC_SOURCE_VERSION`) 224 | 225 | # References 226 | - [Apple OS X ABI Mach-O File Format Reference](https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/) 227 | - [loader.h (mach-o file format .h)](http://www.opensource.apple.com/source/xnu/xnu-3248.20.55/EXTERNAL_HEADERS/mach-o/loader.h) 228 | -------------------------------------------------------------------------------- /wiki/Mach_and_BSD.md: -------------------------------------------------------------------------------- 1 | # Mach & BSD 2 | 3 | The Mach microkernel and the BSD kernel are the two major components of XNU. 4 |
5 | Mach implements the absolute core of the operating system, while the BSD layer is built on top of Mach, and implements higher level concepts. 6 | 7 | _Note: As I'm writing this, I'm realizing that this whole writeup on Mach/BSD will be huge, so expect this article to be divided into several sub-articles soon._ 8 | 9 | ## Table of contents 10 | + [Mach](#mach) 11 | + [Introduction](#intro) 12 | + [Philosophy](#philosophy) 13 | + [Implementation](#implementation) 14 | + [Execution primitives](#execution_primitives) 15 | + [Threads](#threads) 16 | + [Tasks](#tasks) 17 | + [IPC primitives](#ipc_primitives) 18 | + [Messages](#messages) 19 | + [Introduction](#messages_intro) 20 | + [Utilizing messages](#utilizing_messages) 21 | + [Ports](#ports) 22 | + [Introduction](#ports_intro) 23 | + [Port rights](#port_rights) 24 | + [BSD](#bsd) 25 | + [Resources](#resources) 26 | 27 | ## Mach 28 | 29 | 30 | ### Introduction 31 | Mach is a microkernel, originally designed by CMU between the 80s and the 90s. Apple chose this microkernel as the base of their new operating system, and has substantially modified it from the original version. 32 | 33 | Mach is the absolute foundation of XNU, it deals with every crucial aspect needed for the correct functioning of the operating system. Mach does not bother with higher level concepts such as file systems or device drivers, for example. These concepts are left for other components to implement. 34 | 35 | 36 | ### Philosophy 37 | As stated before, Mach does not concern itself with higher level concepts, implementing just the bare-bones of the operating system. Mach is specifically designed to allow an entire operating system to be built upon it, which is exactly what Apple has done. 38 | 39 | The core idea behind Mach its minimalism. Being a microkernel, Mach implements only the fundamental abstractions (described more in detail later). 40 | 41 | Another key point in the Mach philosophy is how the various subsystems communicate, i.e. via a message passing facility. Interaction between components is completely implemented via IPC (inter-process communication) in Mach. This means that objects cannot directly call/invoke themselves, rather a message is sent from one object to another, that message is queued until the receiver handles it. 42 | This may seem unconventional, and it is. But, since Mach is a microkernel, all of the subsystems are separated from one another, thus message passing is needed for communication. 43 | 44 | Summarizing, remember that Mach is just the pure foundation of XNU, and everything else is built upon it. 45 | 46 | 47 | ### Implementation 48 | 49 | 50 | #### Execution primitives 51 | 52 | 53 | ##### Threads 54 | Mach is responsible for the basics abstractions of execution. 55 |
56 | The most basic unit of execution is indeed a _thread_. A thread provides basics scheduling statistics and machine registers, used for execution. Remember that a thread has no links to resources (such as virtual memory), as these are implemented in _tasks_. 57 |
58 | Also remember that exist a direct link between a Mach thread and a BSD thread. 59 | 60 | 61 | ##### Tasks 62 | A _task_ is basically a container object. It implements resources, such as virtual memory, and its only purpose it's to contain threads, since a task has no life by its own. 63 |
64 | It also exist a direct map between Mach tasks and BSD processes, as with threads. 65 |
66 | The threads in a task are kept in a singly linked list. 67 | 68 | 69 | #### IPC primitives 70 | 71 | 72 | ##### Messages 73 | 74 | 75 | ###### Introduction 76 | Mach messages are simply data exchanged between two endpoints, called ports. Mach messages constitutes the basic building block for IPC communication. 77 | 78 | A message has an header (`mach_msg_header_t`), a body (`mach_msg_body_t`), and optionally a trailer (`mach_msg_trailer_t`). 79 | 80 | The **header** contains all informations needed for the message to be sent and correctly received, such as: 81 | 82 | - `msgh_size`: The message size. 83 | - `msgh_remote_port`: The destination Mach port. 84 | - `msgh_local_port`: The local Mach port. 85 | - `msgh_id`: An unique ID. Used specifically with MIG. 86 | - `msgh_bits`: Optional bits. 87 | 88 | The standard **body** contains simply a `mach_msg_size_t`. The body is the actual data of the message and can contain virtually anything. 89 | 90 | The **trailer** contains a `mach_msg_trailer_type_t` (`unsigned int`), which specifies the trailer type, and a `mach_msg_trailer_size_t` for specifying the trailer size. 91 | 92 | 93 | ###### Utilizing messages 94 | Any user-land process is able to create Mach messages and use them for communication. 95 |
96 | Creating a simple message is straightforward. You are able to construct your message in any way you want, the only really needed piece is the `mach_msg_header_t`, which must **always** be located at the beginning of the message. 97 | 98 | Let's assume we are going to use the following structure for our message: 99 | ``` 100 | /* sending */ 101 | typedef struct simple_mach_message_send { 102 | mach_msg_header_t header; 103 | uint32_t x; 104 | } simple_mach_message_send_t; 105 | ``` 106 | This would be our message, at least for sending. The reason why we need two separate structures for sending and receiving is that the kernel implicitly adds a small trailer to our message while sending it, therefore the received message will be larger than the original, and would fail to receive. 107 |
108 | So, our structure for receiving: 109 | ``` 110 | /* receiving */ 111 | typedef struct simple_mach_message_recv { 112 | mach_msg_header_t header; 113 | uint32_t x; 114 | mach_msg_trailer_t trailer; // we could also use something like `uint32_t pad[8];` 115 | } simple_mach_message_recv_t; 116 | ``` 117 | This new structure is large enough and will contain the kernel-delivered message. Remember that your `send` struct instance's data will be sent to the receiver, while the `recv` struct instance will be created by the receiver and will receive the `send` structure data (imagine locally copying a structure's data to another structure). 118 | 119 | The message's header must be configured properly in order for the message to be sent/received. The absolutely necessary fields to set, for sending, are: 120 | - `msgh_bits`: Apart from indicating if the message is complex, this field specifies important message attributes, for example how to interpret the `msgh_remote_port` field and the `msgh_local_port` field. This can easily be filled with the use of the `MACH_MSGH_BITS(remote, local)` macro, where `remote` and `local` specify the interpretation of the two ports. 121 | - `msgh_remote_port`: Specifies the remote Mach port, i.e. where to send our message. 122 | - `msgh_size`: Specifies the message size. A `sizeof()` on your message structure will suffice. 123 | 124 | Additionally, you could specify other fields, such as `msgh_local_port` (a local Mach port, on which you hold receive rights) which could be interpreted by the receiver to send a reply message back. 125 | 126 | Receiving requires only one necessary field to be set: 127 | - `msgh_size`: The message size expected to be received. 128 | 129 | The (more common) API used to send/receive message is `mach_msg`. This API indeed gives you the ability to both send/receive messages, by passing specific parameters. Here's the definition: 130 | 131 | ``` 132 | extern mach_msg_return_t mach_msg( 133 | mach_msg_header_t *msg, 134 | mach_msg_option_t option, 135 | mach_msg_size_t send_size, 136 | mach_msg_size_t rcv_size, 137 | mach_port_name_t rcv_name, 138 | mach_msg_timeout_t timeout, 139 | mach_port_name_t notify); 140 | ``` 141 | 142 | - `mach_msg_header_t *msg`: Is the `mach_msg_header_t` of your structure instance (wether you are sending or receiving). 143 | - `mach_msg_option_t option`: The operation to perform. Send (`MACH_SEND_MSG`) or receive (`MACH_RCV_MSG`) are the most common. 144 | - `mach_msg_size_t send_size`: The size of the message you are sending. If you are receiving, pass `0` to this parameter. 145 | - `mach_msg_size_t rcv_size`: The size of the message you are receiving. If you are sending, this is optionally used to specify the size of the reply message. If you don't want it, pass `0` to this parameter. 146 | - `mach_port_name_t rcv_name`: The Mach port for receiving the message. If you are sending, this is used to specify an optional reply port. If you don't want it, pass `MACH_PORT_NULL`. 147 | - `mach_msg_timeout_t timeout`: Optionally specifies a timeout before giving up on sending/receiving. Pass `MACH_MSG_TIMEOUT_NONE` is you don't want a timeout. 148 | - `mach_port_name_t notify`: Optionally specifies a notification port, if you don't want it, pass `MACH_PORT_NULL`. 149 | 150 | For more example and code, see the `/wiki/code/ipc/` folder, I have made a sample client/server which interact by sending/receiving a message. 151 | 152 | Let's now discuss **complex messages**. A message is deemed _complex_ if the `MACH_MSGH_BITS_COMPLEX` flag is present in the `msgh_bits` field in its header. A complex message is structured differently: After the header, it follows a descriptor count field, followed by actual descriptors. 153 |
154 | There are various types of descriptors, they generally serve the purpose of including special "attachments" to the message. Indeed, descriptors are specifically intended to "give hints" about what kind of out-of-line data we include in the message. Out-of-line data is simply data not directly included within the message itself, but instead allocated and kept somewhere else in memory, and only referenced (via a pointer, for example) by the message. 155 | 156 | Here are the various descriptors defined in XNU: 157 | 158 | - `MACH_MSG_PORT_DESCRIPTOR`: Used to specify passing a port right along with the message. 159 | - `MACH_MSG_OOL_DESCRIPTOR`: Used to specify passing generic out-of-line data. 160 | - `MACH_MSG_OOL_PORTS_DESCRIPTOR`: Used to specify passing a port. 161 | - `MACH_MSG_OOL_VOLATILE_DESCRIPTOR`: Used to specify passing generic volatile (subject to frequent change) out-of-line data. 162 | 163 | A sample structure for a complex message would be: 164 | 165 | ``` 166 | struct complex_message { 167 | mach_msg_header_t header; 168 | mach_msg_body_t body; 169 | mach_msg_ool_descriptor_t desc; 170 | mach_msg_trailer_t trailer; /* optional, really */ 171 | }; 172 | ``` 173 | 174 | In this case, the `mach_msg_body_t` is required since it specifies the descriptor count. You should set the latter to the actual number of descriptors you intend to include in your message. In our case, the `body.msgh_descriptor_count` would be `1`. 175 | 176 | Now let's take a look to the specific fields of the `mach_msg_ool_descriptor_t`. I have chosen to use the `mach_msg_ool_descriptor_t` since it represents generic data, is the most used, and is a fundamental part of a known heap defragmentation technique (heap feng shui), used to increase the chances of a successful exploit. 177 | 178 | - `address`: The OOL data address. 179 | - `deallocate`: Should the data be deallocated after send? 180 | - `copy`: Copy options. 181 | - `type`: Descriptor type. 182 | - `size`: Data size. 183 | 184 | 185 | ##### Ports 186 | 187 | 188 | ###### Introduction 189 | Mach ports are endpoints for communication. From user-land perspective, a Mach port is nothing more than an integer, an opaque handle to a more complex object held in-kernel. 190 | 191 | Ports implement message queues to receive and enqueue messages. A message remains in a queue until a receiver dequeues it. Messages sent are guaranteed to be delivered. 192 | 193 | 194 | ###### Port rights 195 | Ports may be accessed only via port rights. Those are basically permissions held by threads and tasks, needed to interact with ports. Here's a list of all the port rights: 196 | 197 | - `MACH_PORT_RIGHT_SEND`: Whoever holds this right for a specific port, is allowed to send (enqueue) messages to that port. More than one entity at a time are allowed to retain this right. 198 | - `MACH_PORT_RIGHT_RECEIVE`: Whoever holds this right for a specific port, is allowed to receive (dequeue) messages from that port. Holding this right corresponds to having ownership over the port. Only one entity at a time is allowed to retain this right. 199 | - `MACH_PORT_RIGHT_SEND_ONCE`: Akin to `MACH_PORT_RIGHT_SEND`, but the right is revoked after one message has been sent. 200 | - `MACH_PORT_RIGHT_PORT_SET`: Receive rights for multiple ports (a port set). 201 | 202 | 203 | ## BSD 204 | BSD is primarily needed to implement what Mach leaves unimplemented. Things such as users, groups, files and others are obviously needed. BSD has also been heavily modified by Apple and differs significantly from other BSD implementations. 205 | 206 | Although Mach builds the foundations, XNU can still be considered mostly a BSD-like system, since the POSIX APIs exposed are more complete and effectively more used than Mach's. 207 | 208 | 209 | ### Resources 210 | A list of useful external resources. 211 | 212 | - [A deep-dive into the many flavors of IPC available on OS X](https://vimeo.com/127859750) : A talk by Ian Beer about IPC on OS X. 213 | -------------------------------------------------------------------------------- /wiki/Modern-Userland-Jailbreaking.md: -------------------------------------------------------------------------------- 1 | __TODO__ 2 | 3 | Cover 32 & 64 -------------------------------------------------------------------------------- /wiki/README.md: -------------------------------------------------------------------------------- 1 | Welcome to the iOSRE wiki! 2 | 3 | The aim of this wiki will be to provide detailed and updated information on reverse engineering iOS. 4 | Any sort of content related to iOS related reverse engineering is allowed, as well as exploitation techniques and discussions on mitigation bypasses. 5 | 6 | This is still very new, so at this point content may be incomplete or missing, but please join `##iOSRE` on Freenode if you have any suggestion or would like to see certain content. 7 | -------------------------------------------------------------------------------- /wiki/Sandbox.md: -------------------------------------------------------------------------------- 1 | __TODO__ -------------------------------------------------------------------------------- /wiki/Strategies-for-Sandbox-Escape.md: -------------------------------------------------------------------------------- 1 | __TODO__ -------------------------------------------------------------------------------- /wiki/WebKit-Exploitation.md: -------------------------------------------------------------------------------- 1 | The general WebKit/web browser stack is huge and has tons of room for error. This has been seen with the history of jailbreakme.com, and things like crashsafari.com 2 | 3 | Safari has run in a special sandbox for a while, and iOS now provides an API for a web view that runs in their own separate process like SFSafariViewController. 4 | 5 | It's still not all that difficult to mitigate this, considering many iOS apps do use web views that are in less restrictive sandboxes, like the App Store. However, you won't get JIT if you want to run in your own process. 6 | 7 | __Font Stacks__ 8 | 9 | TODO 10 | -------------------------------------------------------------------------------- /wiki/XNU-Kernel-Exploitation.md: -------------------------------------------------------------------------------- 1 | __TODO__ 2 | 3 | 4 | Would be nice to have several sub-pages here, e.g. "Exploitation of a demo kernel vulnerability", "Kernel Heap Vodooo", "IOKit", "libkern", "Mach", "Architecture details" -------------------------------------------------------------------------------- /wiki/code/ipc/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | /* our sending message structure */ 9 | struct message_send { 10 | mach_msg_header_t header; /* header; must always be at the beginning of the message */ 11 | uint32_t x; /* our data */ 12 | }; 13 | 14 | int main(void) { 15 | 16 | kern_return_t kr; 17 | mach_port_t send_port; /* this is the port exposed by our server, and where we will send our messages */ 18 | 19 | /* we obstain the service port via launchd */ 20 | kr = bootstrap_look_up(bootstrap_port, "test_service", &send_port); 21 | if (kr != KERN_SUCCESS) { 22 | printf("unable to find service.\n"); 23 | return -1; 24 | } 25 | 26 | struct message_send *msg = malloc(sizeof(struct message_send)); /* allocate our sending instance */ 27 | bzero(msg, sizeof(struct message_send)); /* remember to always zero out your message! junk data might corrupt it. */ 28 | 29 | /* how to interpret the remote/local ports passed to mach_msg. 30 | * The first arg of this macro specifies how we will use the remote port (MACH_MSG_TYPE_COPY_SEND). 31 | * The second arg of this macro specifies how we will use the local port. We pass 0 since we don't 32 | * use a local port, so behaviour is unspecified. 33 | */ 34 | msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, 0); 35 | msg->header.msgh_remote_port = send_port; /* where to send the message */ 36 | msg->header.msgh_size = sizeof(struct message_send); /* message size */ 37 | msg->x = 1000; /* our data */ 38 | 39 | kr = mach_msg( 40 | &(msg->header), /* our sending structure's header */ 41 | MACH_SEND_MSG, /* we want to send */ 42 | sizeof(struct message_send), /* send size */ 43 | 0, /* we are not receiving anything */ 44 | MACH_PORT_NULL, /* we are not receiving anything */ 45 | MACH_MSG_TIMEOUT_NONE, /* no timeout for send */ 46 | MACH_PORT_NULL /* no notification port */ 47 | ); 48 | 49 | if (kr != MACH_MSG_SUCCESS) { 50 | printf("failed to send: %s\n", mach_error_string(kr)); 51 | return -1; 52 | } else { 53 | printf("message sent!\n"); 54 | } 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /wiki/code/ipc/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | /* our receiving message structure */ 9 | struct message_recv { 10 | mach_msg_header_t header; /* header; must always be at the beginning of the message */ 11 | uint32_t x; /* our data */ 12 | mach_msg_trailer_t trailer; /* kernel-added trailer */ 13 | }; 14 | 15 | int main(void) { 16 | 17 | kern_return_t kr; 18 | mach_port_t receive_port; /* this is the port that we will be exposing to the system, and where we will receive messages */ 19 | 20 | /* we register a service via launchd, simply for exposing our port to other tasks */ 21 | kr = bootstrap_check_in(bootstrap_port, "test_service", &receive_port); 22 | if (kr != KERN_SUCCESS) { 23 | printf("failed to register service.\n"); 24 | return -1; 25 | } 26 | 27 | struct message_recv *msg = malloc(sizeof(struct message_recv)); /* allocate our receiving instance */ 28 | bzero(msg, sizeof(struct message_recv)); /* remember to always zero out your message! junk data might corrupt it. */ 29 | 30 | msg->header.msgh_size = sizeof(struct message_recv); /* expected message size, it shouldn't exceed our structure */ 31 | 32 | kr = mach_msg( 33 | &(msg->header), /* our receiving structure's header */ 34 | MACH_RCV_MSG, /* we want to receive */ 35 | 0, /* we are not sending anything */ 36 | sizeof(struct message_recv), /* size to receive */ 37 | receive_port, /* where to listen and receive messages */ 38 | MACH_MSG_TIMEOUT_NONE, /* we want to listen forever */ 39 | MACH_PORT_NULL /* no notification port */ 40 | ); 41 | 42 | if (kr != MACH_MSG_SUCCESS) { 43 | printf("failed to receive! %s\n", mach_error_string(kr)); 44 | return -1; 45 | } else { 46 | printf("received: %d\n", msg->x); /* let's print our received data */ 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /wiki/iBoot-Exploitation.md: -------------------------------------------------------------------------------- 1 | __TODO__ 2 | 3 | This is also a personal WIP, so I'll try to document as much as possible in here. --qwertyoruiop -------------------------------------------------------------------------------- /wiki/iBoot-RE.md: -------------------------------------------------------------------------------- 1 | # iBoot RE (64 bits) 2 | 3 | We focus on 64 bit iBoot cause we should:) 4 | 5 | ## In the beginning 6 | 7 | ### The Loading Address 8 | 9 | Bootloaders in general and iBoot in particular expect to run at a specific, predefined, addresses. 10 | Such an address called the __loading address__ (reset vector) of a bootloader. 11 | When loading the bootloader into IDA you need to supply the loading address, so IDA will be able to resolve data and code references properly. 12 | 13 | Most Apple bootloaders start with a relocation code which compares the loading address with the current address and moves the bootloader if needed. 14 | Looking at this relocation code we can extract the loading address of the particular bootloader. 15 | 16 | So, we start by using 0 as the loading address until we know better. 17 | 18 | Here is an iBoot 64 bit example loaded at 0: 19 | ~~~ data 20 | ROM:000 loc_0 21 | ROM:000 22 | ROM:000 ADRP X0, #loc_0@PAGE 23 | ROM:004 ADD X0, X0, #loc_0@PAGEOFF <=== X0 has the current page address 24 | ROM:008 LDR X1, =0x83D37B000 <=== this is the loading address 25 | ROM:00C BL sub_17634 26 | ROM:010 CMP X1, X0 <=== are we running at loading address 27 | ROM:014 B.EQ loc_44 <=== if yes: continue booting normally 28 | ROM:018 MOV X30, X1 <=== else: set LR to loading address 29 | ROM:01C LDR X2, =0x83D413440 30 | ROM:020 LDR X3, =0x83D37B000 31 | ROM:024 SUB X2, X2, X3 <=== calculate len 32 | ROM:028 33 | ROM:028 loc_28 <=== copy loop 34 | ROM:028 LDP X3, X4, [X0] 35 | ROM:02C STP X3, X4, [X1] 36 | ROM:030 ADD X0, X0, #0x10 37 | ROM:034 ADD X1, X1, #0x10 38 | ROM:038 SUBS X2, X2, #0x10 39 | ROM:03C B.NE loc_28 40 | ROM:040 RET <=== done copying -> return to loading address (LR) 41 | ROM:044 ; ------------------------------------------------------------- 42 | ROM:044 43 | ROM:044 loc_44 <=== rest of the iboot 44 | ROM:044 MSR #6, #0xF ; MSR DAIFSET, #0XF 45 | ROM:048 ADRP X30, #loc_AC8@PAGE 46 | ROM:04C ADD X30, X30, #loc_AC8@PAGEOFF 47 | ROM:050 ADRP X10, #loc_1F000@PAGE 48 | ROM:054 ADD X10, X10, #loc_1F000@PAGEOFF 49 | ROM:058 MSR #6, c12, c0, #0, X10 ; MSR VBAR_EL3, X10 50 | ~~~ 51 | 52 | So, the __loading address__ in this example is: __0x83D37B000__. 53 | With this knowledge we can load the iboot to IDA with a proper loading address. 54 | 55 | For 32 bits iboot the relocation code works the same, but it's not the first code. 56 | The iboot starts with an exception vector.The first vector (reset) branches to the relocation code and it's the same from there. 57 | 58 | Other bootloader: LLB, iBEC, IBSS have the same relocation code and hence the loading address available for grabbing. 59 | 60 | 61 | ### Beyond the loading address 62 | 63 | After relocation of the iBoot to the proper running place, the boot continues. 64 | Setting SP pointers, exception tables, etc. 65 | Below is the rest of the first function that runs on boot. 66 | Between the comments and the labels you should have no troubles following the code flow. 67 | 68 | 69 | ~~~ data 70 | ......... [ relocation code as shown above ] 71 | ROM:83D07B044 72 | ROM:83D07B044 ; mask exceptions 73 | ROM:83D07B044 MSR #6, #0xF ; MSR DAIFSET, #0XF 74 | ROM:83D07B048 ; set the next function to be executed on return 75 | ROM:83D07B048 ADRP X30, #_start@PAGE 76 | ROM:83D07B04C ADD X30, X30, #_start@PAGEOFF 77 | ROM:83D07B050 ; setup exceptions table base address 78 | ROM:83D07B050 ADRP X10, #exception_table@PAGE 79 | ROM:83D07B054 ADD X10, X10, #exception_table@PAGEOFF 80 | ROM:83D07B058 MSR #6, c12, c0, #0, X10 ; MSR VBAR_EL3, X10 81 | ROM:83D07B05C ; clear 512K of memory 82 | ROM:83D07B05C LDR X10, =base_addr_for_stack_and_stuff 83 | ROM:83D07B060 LDR X11, =0x80000 ; 512K 84 | ROM:83D07B064 ADD X11, X11, X10 85 | ROM:83D07B068 MOV X12, #0 86 | ROM:83D07B06C loop__clear_512K 87 | ROM:83D07B06C STP X12, X12, [X10] 88 | ROM:83D07B070 ADD X10, X10, #0x10 89 | ROM:83D07B074 CMP X10, X11 90 | ROM:83D07B078 B.NE loop__clear_512K 91 | ROM:83D07B07C ; set base address for stack and stuff 92 | ROM:83D07B07C LDR X10, =base_addr_for_stack_and_stuff 93 | ROM:83D07B080 ADD X10, X10, #1,LSL#12 ; (base + 4K) 94 | ROM:83D07B084 ; set EL3 SP to (base + 4K) 95 | ROM:83D07B084 MOV SP, X10 96 | ROM:83D07B088 MSR #5, #0 ; MSR SPSEL, #0 97 | ROM:83D07B08C ADD X10, X10, #2,LSL#12 ; ((base + 4K) + 8K) 98 | ROM:83D07B090 ; set EL0 SP to (base + 12K) 99 | ROM:83D07B090 MOV SP, X10 100 | ROM:83D07B094 ADD X20, X10, #2,LSL#12 ; (((base + 4K) + 8K) + 8K) 101 | ROM:83D07B098 ; zero additional space 102 | ROM:83D07B098 LDR X10, =_iboot_end ; from this addr 103 | ROM:83D07B09C LDR X11, =fb_mbe ; to this addr 104 | ROM:83D07B0A0 MOV X12, #0xF 105 | ROM:83D07B0A4 BIC X12, X11, X12 ; end addr aligned to 16 106 | ROM:83D07B0A8 MOV X13, #0 107 | ROM:83D07B0AC ; clear more space, aligned 16 108 | ROM:83D07B0AC loop__clear_more__aligned 109 | ROM:83D07B0AC STP X13, X13, [X10],#0x10 110 | ROM:83D07B0B0 CMP X10, X12 111 | ROM:83D07B0B4 B.NE loop__clear_more__aligned 112 | ROM:83D07B0B8 CMP X11, X12 113 | ROM:83D07B0BC B.EQ loc_83D07B0CC 114 | ROM:83D07B0C0 ; clear more space, the rest (unaligned) 115 | ROM:83D07B0C0 loop__clear_more__unaligned 116 | ROM:83D07B0C0 STR W13, [X10],#4 117 | ROM:83D07B0C4 CMP X10, X11 118 | ROM:83D07B0C8 B.NE loop__clear_more__unaligned 119 | ROM:83D07B0CC 120 | ROM:83D07B0CC loc_83D07B0CC 121 | ROM:83D07B0CC ; set Exception handlers SP to (base + 20K) 122 | ROM:83D07B0CC ADRP X11, #sp_for_exception_handlers@PAGE 123 | ROM:83D07B0D0 ADD X11, X11, #sp_for_exception_handlers@PAGEOFF 124 | ROM:83D07B0D4 STR X20, [X11] 125 | ROM:83D07B0D8 RET 126 | ~~~ 127 | 128 | 129 | Notes: 130 | - MSR DAIFSET, #0XF (mask all exceptions) 131 | This is very early stage and we don't want to be interrupted before we can handle exceptions properly. 132 | - _start 133 | We are running a kind of a 'reset vector' code now and this is the next 134 | function we execute by setting its address in the LR register and running with the RET instruction. 135 | - exception_table 136 | The address that goes into the VBAR_EL3 register is the beginning of the EL3 exception table. 137 | ARMv8 is very different from ARMv7 in how the exception table looks and works. 138 | Some of the differences are: 139 | - Instead of vector of dwords it has 0x80 bytes of code for each exception 140 | - There are multiple entries for the same exception depending on the circumstances of where the exception is taken from 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /wiki/images/mach_o_segments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kpwn/iOSRE/20aff7761b249cb2f76477ef39f8885bfcb404cf/wiki/images/mach_o_segments.png --------------------------------------------------------------------------------