forked from writeups/iOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
723fe9a
commit 47d21cf
Showing
56 changed files
with
1,494 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__TODO__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# BootROM RE | ||
|
||
__TODO__ | ||
|
||
https://github.com/bat0s/BootROM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
## Bypassing AMFI | ||
|
||
AppleMobileFileIntegrity is the kernel extension that handles codesign enforcement. | ||
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. | ||
Code sign enforcement also happens at page fault time. | ||
|
||
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. | ||
|
||
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. | ||
|
||
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. | ||
|
||
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. | ||
|
||
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. | ||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[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. | ||
|
||
[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. | ||
|
||
[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 | ||
|
||
Hopefully going to get [qira](https://github.com/BinaryAnalysisPlatform/qira) working on iOS. Would be incredibly useful for analysis. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
This information only applies to iBoot64 on iOS 8 or lower. | ||
|
||
In order to dump iBoot, you need: | ||
|
||
1. Kernel read/write (eg task_for_pid 0) | ||
2. gPhysBase and gVirtBase | ||
3. A pointer to the kernel pmap's level1 translation table entries. | ||
|
||
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. | ||
Additionally, make sure to clear the read only bit and set the EL0-accessible bit. | ||
|
||
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. | ||
|
||
``` | ||
int main(int argc, char **argv, char **envp) { | ||
char* base = (char*) 0xffffffc3c0000000; | ||
char* sig = (char*) "FFiBoot for "; | ||
char* iboot = (char*) memmem(base, (1<<30), sig+2, strlen(sig)-2); | ||
while (*(iboot-1) == 'F' && *(iboot-2) == 'F') { | ||
iboot ++; | ||
/* should fix size up here but too lazy lol */ | ||
iboot = (char*) memmem(iboot, (1<<30), sig+2, strlen(sig)-2); | ||
assert(iboot); | ||
} | ||
iboot = (char*) (((uintptr_t)iboot) & (~0xFFF)); | ||
printf("found iboot at %p\n", iboot); | ||
return 0; | ||
} | ||
```` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Firmwares and Keys | ||
|
||
Firmwares come as .ipsw files, which are .zip files in disguise. | ||
|
||
Here's what the folder structure looks like (example: iPhone5,4 on iOS 9.2.1): | ||
|
||
``` | ||
iPhone5,4_9.2.1_13D15_Restore.ipsw/ | ||
├── 058-32080-015.dmg | ||
├── 058-32173-015.dmg | ||
├── 058-32359-015.dmg | ||
├── BuildManifest.plist | ||
├── Firmware/ | ||
├──── Mav7Mav8-6.01.00.Release.bbfw | ||
├──── Mav7Mav8-6.01.00.Release.plist | ||
├──── all_flash/ | ||
├────── all_flash.n49ap.production/ | ||
├────── DeviceTree.n49ap.img3 | ||
├────── LLB.n49.RELEASE.img3 | ||
├────── applelogo@2x~iphone.s5l8950x.img3 | ||
├────── batterycharging0@2x~iphone.s5l8950x.img3 | ||
├────── batterycharging1@2x~iphone.s5l8950x.img3 | ||
├────── batteryfull@2x~iphone.s5l8950x.img3 | ||
├────── batterylow0@2x~iphone.s5l8950x.img3 | ||
├────── batterylow1@2x~iphone.s5l8950x.img3 | ||
├────── glyphplugin@1136~iphone-lightning.s5l8950x.img3 | ||
├────── iBoot.n49.RELEASE.img3 | ||
├────── manifest | ||
├────── recoverymode@1136~iphone-lightning.s5l8950x.img3 | ||
├──── dfu/ | ||
├────── iBEC.n49.RELEASE.dfu | ||
├────── iBSS.n49.RELEASE.dfu | ||
├──── usr/ | ||
├────── local/ | ||
├────── standalone/ | ||
├── Restore.plist | ||
└── kernelcache.release.n49 | ||
``` | ||
|
||
All of these files can be extracted using keys and xpwn. | ||
|
||
Firmware keys are posted on | ||
- https://theiphonewiki.com/wiki/Firmware_Keys | ||
- https://ipsw.me/keys | ||
- https://ipswcentral.com//keys | ||
|
||
For the kernelcache, run: | ||
|
||
`xpwntool path/to/cache /path/to/output -k KEY -iv IV -decrypt` | ||
|
||
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: | ||
|
||
`./dmg input.dmg output.dmg -k KEY` (OS X) | ||
|
||
`dmg.exe input.dmg output.dmg -k KEY` (Windows) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
|
||
# Firmware Encryption | ||
|
||
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. | ||
|
||
# Code Signing | ||
|
||
Introduced in iOS 2.0. Enforced by AppleMobileFileIntegrity, or AMFI. | ||
|
||
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). | ||
|
||
For patching, amfi_get_out_of_my_way is a good technique. | ||
|
||
# LLB Validation | ||
|
||
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. | ||
|
||
Common workarounds are bootrom exploits or similar low level exploits, or an userland persistency vector (look for Code Signing workarounds). | ||
|
||
# dyld data-only dylib hardening | ||
# ASLR | ||
# Free List Hardening | ||
# Poisoning | ||
# Stack Guard | ||
# KASLR | ||
# Info Leak Mitigation Strategy | ||
# Proper kernel memory protection flags | ||
# Address Space Isolation | ||
# CS_RESTRICT | ||
# LwVM Write Locking | ||
# mmap hook TeamID validation | ||
# validateFirstFewPages | ||
# KPP | ||
# Modern AMFI | ||
# LaunchDaemons plists moved to xpcd_cache.dylib | ||
1. First attempt (iOS x.y) just moved plists to code-signed xpcd_cache.dylib | ||
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. | ||
|
||
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). | ||
|
||
__TODO__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# IOKit RE (may the 64 bits be with you) | ||
|
||
IOKit is a bunch of classes, a C++ framework for writing code and drivers in XNU kernel. | ||
It is implemented on top of the libkern library in a subset of C++. | ||
|
||
It is true that the generic parts of the IOKit are available in source. | ||
Here and there you might even find an outdated sources for some of the driver families kexts. | ||
However, most of the kexts present in the kernelcache on the iOS are binary and need to be REd. | ||
|
||
One of the challenges REing these kexts is the dynamic nature of the C++. | ||
Fortunately, libkern provides a sort of RTTI (Runtime Type Information) for safe dynamic casting and | ||
whatnot, which gives us information about the classes and the hierarchy. | ||
|
||
## Meta | ||
> We only collect meta data ... | ||
Seriously though, there is a meta class for each and every class in libkern/IOKit. | ||
It provides the basis for runtime information about the classes and helps us a lot. | ||
|
||
### Registration | ||
During the initialization of the kernel/kext, new classes are registered | ||
into the RTTI system by calling the OSMetaClass::OSMetaClass() function. | ||
This "register" function takes the following arguments: | ||
- pointer to instance of the meta class for the class we register | ||
- name of the class we register | ||
- pointer to instance of parent's meta class | ||
- size of an instance of the class we register | ||
|
||
These register calls are made from the init functions located in the __mod_init_func sections of the kernel and the kexts. | ||
Lets take the AMFI kext for example. It has 2 init functions in the mod_init_func section. | ||
Bellow is the content of the first one: | ||
~~~ data | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C8C ADR X0, off_FFFFFF801FE3F228 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C90 NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C94 ADR X1, aApplemobilefil ; "AppleMobileFileIntegrityUserClient" | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C98 NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C9C NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CA0 LDR X2, =off_FFFFFF801FD36DC8 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CA4 MOV W3, #0xE8 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CA8 BL sub_FFFFFF801FE1E270 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CAC ADRP X8, #off_FFFFFF801FE3F228@PAGE | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CB0 ADR X9, off_FFFFFF801FE3E8E0 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CB4 NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CB8 ADD X9, X9, #0x10 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CBC STR X9, [X8,#off_FFFFFF801FE3F228@PAGEOFF] | ||
~~~ | ||
Observe the following details (you will need your own kernelcache for this): | ||
- X0 is a pointer to a data structure residing in this kext's data section, specifically in the | ||
section named "__common" (on 64 bits). | ||
- X1 is a pointer to a string that looks like it could be a name of a class | ||
- X2 is another pointer to a "__common" data section, but this time not necessarily in the same kext. | ||
- W3 is a small immediate | ||
- BL is a stub function in the same kext. With the stub (through the symbol) leading to a function in the kernel. | ||
|
||
__Congratulations!__ You have found a meta class register call to OSMetaClass::OSMetaClass(). | ||
Just as you've guessed it: | ||
- X0 is the meta class | ||
- X1 is the name | ||
- X2 is the parent | ||
- W3 is the size | ||
- The function in the kernel is the OSMetaClass::OSMetaClass() function. | ||
|
||
There is a bit more though ... | ||
After the call to the register stub, it writes some pointer+0x10 into the mata class object. | ||
The first pointer in the object is usually the vtable. And indeed, this is the vtable for the meta | ||
class. | ||
|
||
#### Beautification | ||
Let's apply the knowledge we've gathered. Let's rename the objects and the vtable by the following | ||
patterns (python): | ||
~~~python | ||
meta_object = "__ZN%d%s10gMetaClassE" % (len(class_name), class_name) | ||
meta_vtable = "__ZTVN%d%s9metaClassE" % (len(class_name), class_name) | ||
~~~ | ||
|
||
Notes: | ||
* Parent meta class: | ||
The _parent_meta_object_ gets renamed when we find where the parent is registered and rename the | ||
_meta_object_ there. It is a pointer to the same place. | ||
* Renaming a stub: | ||
You can't really add the "stub" and be done with it, because you have such a stub in every kext. | ||
So, you need to be a bit creative here. | ||
|
||
##### Results | ||
Now, IDA can demangle the names and will show us the following: | ||
~~~ data | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C8C ADR X0, AppleMobileFileIntegrityUserClient::gMetaClass | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C90 NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C94 ADR X1, aApplemobilefil ; "AppleMobileFileIntegrityUserClient" | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C98 NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19C9C NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CA0 LDR X2, =IOUserClient::gMetaClass | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CA4 MOV W3, #0xE8 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CA8 BL OSMetaClass::OSMetaClass::[stub_at_0xFFFFFF801FE1E270](char const*,OSMetaClass const*,uint) | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CAC ADRP X8, #AppleMobileFileIntegrityUserClient::gMetaClass@PAGE | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CB0 ADR X9, vtable for'AppleMobileFileIntegrityUserClient_::metaClass | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CB4 NOP | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CB8 ADD X9, X9, #0x10 | ||
AppleMobileFileIntegrity:__text:FFFFFF801FE19CBC STR X9, [X8,#AppleMobileFileIntegrityUserClient::gMetaClass@PAGEOFF] | ||
~~~ | ||
|
||
# TODO | ||
* __such wow!__ | ||
* __much to-do!__ | ||
* vtables (class and meta class) | ||
* structs | ||
* OSMetaClassBase vtable quirk | ||
* moar RE | ||
|
||
|
||
# Notes | ||
## 64 vs 32 bits | ||
Sometimes the difference are minor, like R0 instead of X0. | ||
I believe the grand scheme is the same and it would be relatively easy to apply. | ||
And why would you be looking at 32 bits anyway, shoo, shoo! | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
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. | ||
|
||
Checked ranges are __TEXT and __DATA.__const. | ||
It is speculated that checks are enforced by either the SEP or the Secure Monitor. | ||
|
||
Current attempts to bypass KPP actually avoid it entirely and were demonstrated in Pangu9. | ||
The general idea is not to patch __TEXT, but rather data structures. | ||
|
||
In particular, Pangu9 replaced hooks in AMFI's MAC policy to either disable or alter the checks. | ||
|
||
This technique has been mitigated in iOS 9.2 by moving MAC policies in __const. | ||
|
||
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. | ||
|
||
|
||
------------------------------- | ||
Found this by @xerub [Tick (FPU) Tock (IRQ)](https://xerub.github.io/ios/kpp/2017/04/13/tick-tock.html) |
Oops, something went wrong.