Skip to content

Commit

Permalink
Added Writeups
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephShenton committed Jun 11, 2018
1 parent 723fe9a commit 47d21cf
Show file tree
Hide file tree
Showing 56 changed files with 1,494 additions and 0 deletions.
1 change: 1 addition & 0 deletions About iOS/Auditing-the-XNU-Kernel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__TODO__
5 changes: 5 additions & 0 deletions About iOS/BootROM-RE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# BootROM RE

__TODO__

https://github.com/bat0s/BootROM
16 changes: 16 additions & 0 deletions About iOS/Bypassing-AMFI.md
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.
7 changes: 7 additions & 0 deletions About iOS/Disassemblers.md
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.
29 changes: 29 additions & 0 deletions About iOS/Dumping-iBoot.md
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;
}
````
55 changes: 55 additions & 0 deletions About iOS/Firmwares-and-Keys.md
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)
41 changes: 41 additions & 0 deletions About iOS/History-of-iOS-Mitigations.md
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__
116 changes: 116 additions & 0 deletions About iOS/IOKit-RE.md
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!

17 changes: 17 additions & 0 deletions About iOS/Kernel-Patch-Protection-(KPP).md
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)
Loading

0 comments on commit 47d21cf

Please sign in to comment.