Added Writeups

This commit is contained in:
Joseph Shenton 2018-06-11 17:42:03 +10:00
parent 723fe9a514
commit 47d21cf4da
56 changed files with 30474 additions and 0 deletions

View File

@ -0,0 +1 @@
__TODO__

5
About iOS/BootROM-RE.md Executable file
View File

@ -0,0 +1,5 @@
# BootROM RE
__TODO__
https://github.com/bat0s/BootROM

16
About iOS/Bypassing-AMFI.md Executable file
View File

@ -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
About iOS/Disassemblers.md Executable file
View File

@ -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
About iOS/Dumping-iBoot.md Executable file
View File

@ -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
About iOS/Firmwares-and-Keys.md Executable file
View File

@ -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)

View File

@ -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
About iOS/IOKit-RE.md Executable file
View File

@ -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!

View File

@ -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)

227
About iOS/Mach-O.md Executable file
View File

@ -0,0 +1,227 @@
# The Mach-O Format
The Mach-O file format is the executable format of choice for XNU and dyld.
It serves a purpose analog to what ELF or PE do; to put it simply, it describes a portion of an address space.
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.
# Working with Mach-Os
1. otool is provided out-of-the-box with the xcode cli utils.
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.
2. lipo is a tool for working with fat files
3. Apple headers, specifically `<mach-o/loader.h>`/`<mach-o/fat.h>`.
# General structure
This image from Apple documentation illustrates pretty well how a Mach-O file is composed.
![Mach-O files structure](images/mach_o_segments.png)
The **header** is the first thing you will encounter while parsing a Mach-O file. It is always located at the very beginning.
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.
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.
# Universal Binaries (fat Mach-Os) structure
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.
Here's the structure of a fat header (`struct fat_header`):
```
struct fat_header {
uint32_t magic; /* FAT_MAGIC */
uint32_t nfat_arch; /* number of structs that follow */
};
```
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:
```
struct fat_arch {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint32_t offset; /* file offset to this object file */
uint32_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
};
```
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.
<br>
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`).
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.
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.
Summarizing an universal binary structure with a visual representation:
```
+---------------------+ /* header (fat_header: 0x8) */
| |
| FAT HEADER |
| |
+---------------------+ /* archs (fat_arch: 0x14) */
| FAT ARCH #1 |
+---------------------+
| FAT ARCH #2 |
+---------------------+
| ... | /* other eventual fat archs... */
+---------------------+ /* Mach-Os section (variable size) */
| |
| |
| |
| |
| MACH-O #1 |
| |
| |
| |
| |
| |
+---------------------+
| |
| |
| |
| |
| |
| MACH-O #2 |
| |
| |
| |
| |
+---------------------+
| ... | /* other eventual Mach-Os... */
+---------------------+
```
# mach_header(_64)
There are two structs (for both _x86_ and _x64_ architectures) for representing a Mach-O header:
```
struct mach_header; // 32-bit Mach-O format
struct mach_header_64; // 64-bit Mach-O format
```
The differences are minimal, just a `reserved` field added to the 64-bit header.
As per loader.h, the header file defining Mach-O constants and structures:
```
struct mach_header(_64) {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved; 64 bit only */
};
#define MH_MAGIC 0xfeedface /* the mach magic number */
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
```
### Types of Mach-Os
```
// These shuld be representing userland Mach-Os
#define MH_EXECUTE 0x2 /* demand paged executable file (executable) */
#define MH_FVMLIB 0x3 /* fixed VM shared library file (???) */
#define MH_DYLIB 0x6 /* dynamically bound shared library */
#define MH_DYLINKER 0x7 /* dynamic link editor */
#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
// Compile-time Mach-Os, Generic address-space Mach-Os, ???
#define MH_OBJECT 0x1 /* relocatable object file (.o) */
#define MH_CORE 0x4 /* core file */
#define MH_PRELOAD 0x5 /* preloaded executable file */
#define MH_DYLIB_STUB 0x9 /* shared library stub for static */
/* linking only, no section contents */
#define MH_DSYM 0xa /* companion file with only debug */
/* sections */
// Kernel Mach-Os
#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
```
# Load Commands
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.
They can be parsed using the `struct load_command`:
```
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
```
For a comprehensive list and descriptions of load commands, look in `mach-o/loader.h`.
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.
# Segments
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.
<br>
Whatever data they contain, it is needed by the process at runtime and so it gets mapped in the address space.
# Sections
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).
# nlist / nlist_64
# Symbols
Check [facebook/fishhook](https://github.com/facebook/fishhook) For Explanations
# Lazy Linking
Check [facebook/fishhook](https://github.com/facebook/fishhook) For Explanations
# Position Independent Executables
a.k.a. ASLR-Enabled Executables.
PIE Flag is in the *thin* mach_header with value 0x200000
Minus that from the original flag value will disable ASLR, and vice verse
# Special Segments
__PAGEZERO is a special segment with *ZERO* disk space and takes a page in VM.
When code access NULL, it will land there
Mach-O containing __RESTRICT/__restrict will be flagged by dyld and thus DYLD_INSERT_LIBRARIES EnvVar will be ignored.(This is added after iOS6)
# Other common load commands
# Malformed Mach-O
By altering Mach-O headers. Different issues would happen within dyld.
Sometimes it can protect the binary from being analyzed
Sometimes it's a 0Day and can help bypass Code-Signature-Verification
Examples:
~~[MachOProtector](https://github.com/Naville/MachOProtecter)~~
Won't Work After iOS 8.1 or OS X 10.11
[yalu](https://github.com/kpwn/yalu)
Maybe. Didn't Check SRC.
[Pangu8](http://8.pangu.io)
# Two Level Namespace
# The Mach-O Address Space in xnu/dyld based OSes
# Dyld Shared Cache
Download the latest dyld source from [here](http://opensource.apple.com/source/dyld/).
open `./launch-cache/dsc_extractor.cpp` and change `#if 0` to `#if 1`.
<br>
Then just `clang++ -o dsc_extractor dsc_extractor.cpp dsc_iterator.cpp`
and run `dsc_extractor` on the cache to extract.
##### Known Issues:
Seems like segment VM Address is wrong. So the binary is not class-dump able (Just use runtime dump instead)
not nm-able (solution: simply replace `LC_SEGMENT_SPLIT_INFO` to `LC_SOURCE_VERSION`)
# References
- [Apple OS X ABI Mach-O File Format Reference](https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/)
- [loader.h (mach-o file format .h)](http://www.opensource.apple.com/source/xnu/xnu-3248.20.55/EXTERNAL_HEADERS/mach-o/loader.h)

212
About iOS/Mach_and_BSD.md Executable file
View File

@ -0,0 +1,212 @@
# Mach & BSD
The Mach microkernel and the BSD kernel are the two major components of XNU.
<br>
Mach implements the absolute core of the operating system, while the BSD layer is built on top of Mach, and implements higher level concepts.
_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._
## Table of contents
+ [Mach](#mach)
+ [Introduction](#intro)
+ [Philosophy](#philosophy)
+ [Implementation](#implementation)
+ [Execution primitives](#execution_primitives)
+ [Threads](#threads)
+ [Tasks](#tasks)
+ [IPC primitives](#ipc_primitives)
+ [Messages](#messages)
+ [Introduction](#messages_intro)
+ [Utilizing messages](#utilizing_messages)
+ [Ports](#ports)
+ [Introduction](#ports_intro)
+ [Port rights](#port_rights)
+ [BSD](#bsd)
+ [Resources](#resources)
## Mach
<a name="intro"></a>
### Introduction
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.
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.
<a name="philosophy"></a>
### Philosophy
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.
The core idea behind Mach its minimalism. Being a microkernel, Mach implements only the fundamental abstractions (described more in detail later).
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.
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.
Summarizing, remember that Mach is just the pure foundation of XNU, and everything else is built upon it.
<a name="implementation"></a>
### Implementation
<a name="execution_primitives"></a>
#### Execution primitives
<a name="threads"></a>
##### Threads
Mach is responsible for the basics abstractions of execution.
<br>
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_.
<br>
Also remember that exist a direct link between a Mach thread and a BSD thread.
<a name="tasks"></a>
##### Tasks
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.
<br>
It also exist a direct map between Mach tasks and BSD processes, as with threads.
<br>
The threads in a task are kept in a singly linked list.
<a name="ipc_primitives"></a>
#### IPC primitives
<a name="messages"></a>
##### Messages
<a name="messages_intro"></a>
###### Introduction
Mach messages are simply data exchanged between two endpoints, called ports. Mach messages constitutes the basic building block for IPC communication.
A message has an header (`mach_msg_header_t`), a body (`mach_msg_body_t`), and optionally a trailer (`mach_msg_trailer_t`).
The **header** contains all informations needed for the message to be sent and correctly received, such as:
- `msgh_size`: The message size.
- `msgh_remote_port`: The destination Mach port.
- `msgh_local_port`: The local Mach port.
- `msgh_id`: An unique ID. Used specifically with MIG.
- `msgh_bits`: Optional bits.
The standard **body** contains simply a `mach_msg_size_t`. The body is the actual data of the message and can contain virtually anything.
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.
<a name="utilizing_messages"></a>
###### Utilizing messages
Any user-land process is able to create Mach messages and use them for communication.
<br>
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.
Let's assume we are going to use the following structure for our message:
```
/* sending */
typedef struct simple_mach_message_send {
mach_msg_header_t header;
uint32_t x;
} simple_mach_message_send_t;
```
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.
<br>
So, our structure for receiving:
```
/* receiving */
typedef struct simple_mach_message_recv {
mach_msg_header_t header;
uint32_t x;
mach_msg_trailer_t trailer; // we could also use something like `uint32_t pad[8];`
} simple_mach_message_recv_t;
```
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).
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:
- `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.
- `msgh_remote_port`: Specifies the remote Mach port, i.e. where to send our message.
- `msgh_size`: Specifies the message size. A `sizeof()` on your message structure will suffice.
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.
Receiving requires only one necessary field to be set:
- `msgh_size`: The message size expected to be received.
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:
```
extern mach_msg_return_t mach_msg(
mach_msg_header_t *msg,
mach_msg_option_t option,
mach_msg_size_t send_size,
mach_msg_size_t rcv_size,
mach_port_name_t rcv_name,
mach_msg_timeout_t timeout,
mach_port_name_t notify);
```
- `mach_msg_header_t *msg`: Is the `mach_msg_header_t` of your structure instance (wether you are sending or receiving).
- `mach_msg_option_t option`: The operation to perform. Send (`MACH_SEND_MSG`) or receive (`MACH_RCV_MSG`) are the most common.
- `mach_msg_size_t send_size`: The size of the message you are sending. If you are receiving, pass `0` to this parameter.
- `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.
- `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`.
- `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.
- `mach_port_name_t notify`: Optionally specifies a notification port, if you don't want it, pass `MACH_PORT_NULL`.
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.
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.
<br>
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.
Here are the various descriptors defined in XNU:
- `MACH_MSG_PORT_DESCRIPTOR`: Used to specify passing a port right along with the message.
- `MACH_MSG_OOL_DESCRIPTOR`: Used to specify passing generic out-of-line data.
- `MACH_MSG_OOL_PORTS_DESCRIPTOR`: Used to specify passing a port.
- `MACH_MSG_OOL_VOLATILE_DESCRIPTOR`: Used to specify passing generic volatile (subject to frequent change) out-of-line data.
A sample structure for a complex message would be:
```
struct complex_message {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_ool_descriptor_t desc;
mach_msg_trailer_t trailer; /* optional, really */
};
```
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`.
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.
- `address`: The OOL data address.
- `deallocate`: Should the data be deallocated after send?
- `copy`: Copy options.
- `type`: Descriptor type.
- `size`: Data size.
<a name="ports"></a>
##### Ports
<a name="ports_intro"></a>
###### Introduction
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.
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.
<a name="port_rights"></a>
###### Port rights
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:
- `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.
- `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.
- `MACH_PORT_RIGHT_SEND_ONCE`: Akin to `MACH_PORT_RIGHT_SEND`, but the right is revoked after one message has been sent.
- `MACH_PORT_RIGHT_PORT_SET`: Receive rights for multiple ports (a port set).
<a name="bsd"></a>
## BSD
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.
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.
<a name="resources"></a>
### Resources
A list of useful external resources.
- [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.

View File

@ -0,0 +1,3 @@
__TODO__
Cover 32 & 64

6
About iOS/README.md Executable file
View File

@ -0,0 +1,6 @@
Welcome to the iOSRE wiki!
The aim of this wiki will be to provide detailed and updated information on reverse engineering iOS.
Any sort of content related to iOS related reverse engineering is allowed, as well as exploitation techniques and discussions on mitigation bypasses.
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.

1
About iOS/Sandbox.md Executable file
View File

@ -0,0 +1 @@
__TODO__

View File

@ -0,0 +1 @@
__TODO__

View File

@ -0,0 +1,9 @@
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
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.
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.
__Font Stacks__
TODO

View File

@ -0,0 +1,4 @@
__TODO__
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"

57
About iOS/code/ipc/client.c Executable file
View File

@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>
#include <mach/mach.h>
#include <servers/bootstrap.h>
/* our sending message structure */
struct message_send {
mach_msg_header_t header; /* header; must always be at the beginning of the message */
uint32_t x; /* our data */
};
int main(void) {
kern_return_t kr;
mach_port_t send_port; /* this is the port exposed by our server, and where we will send our messages */
/* we obstain the service port via launchd */
kr = bootstrap_look_up(bootstrap_port, "test_service", &send_port);
if (kr != KERN_SUCCESS) {
printf("unable to find service.\n");
return -1;
}
struct message_send *msg = malloc(sizeof(struct message_send)); /* allocate our sending instance */
bzero(msg, sizeof(struct message_send)); /* remember to always zero out your message! junk data might corrupt it. */
/* how to interpret the remote/local ports passed to mach_msg.
* The first arg of this macro specifies how we will use the remote port (MACH_MSG_TYPE_COPY_SEND).
* The second arg of this macro specifies how we will use the local port. We pass 0 since we don't
* use a local port, so behaviour is unspecified.
*/
msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, 0);
msg->header.msgh_remote_port = send_port; /* where to send the message */
msg->header.msgh_size = sizeof(struct message_send); /* message size */
msg->x = 1000; /* our data */
kr = mach_msg(
&(msg->header), /* our sending structure's header */
MACH_SEND_MSG, /* we want to send */
sizeof(struct message_send), /* send size */
0, /* we are not receiving anything */
MACH_PORT_NULL, /* we are not receiving anything */
MACH_MSG_TIMEOUT_NONE, /* no timeout for send */
MACH_PORT_NULL /* no notification port */
);
if (kr != MACH_MSG_SUCCESS) {
printf("failed to send: %s\n", mach_error_string(kr));
return -1;
} else {
printf("message sent!\n");
}
return 0;
}

50
About iOS/code/ipc/server.c Executable file
View File

@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include <mach/mach.h>
#include <servers/bootstrap.h>
/* our receiving message structure */
struct message_recv {
mach_msg_header_t header; /* header; must always be at the beginning of the message */
uint32_t x; /* our data */
mach_msg_trailer_t trailer; /* kernel-added trailer */
};
int main(void) {
kern_return_t kr;
mach_port_t receive_port; /* this is the port that we will be exposing to the system, and where we will receive messages */
/* we register a service via launchd, simply for exposing our port to other tasks */
kr = bootstrap_check_in(bootstrap_port, "test_service", &receive_port);
if (kr != KERN_SUCCESS) {
printf("failed to register service.\n");
return -1;
}
struct message_recv *msg = malloc(sizeof(struct message_recv)); /* allocate our receiving instance */
bzero(msg, sizeof(struct message_recv)); /* remember to always zero out your message! junk data might corrupt it. */
msg->header.msgh_size = sizeof(struct message_recv); /* expected message size, it shouldn't exceed our structure */
kr = mach_msg(
&(msg->header), /* our receiving structure's header */
MACH_RCV_MSG, /* we want to receive */
0, /* we are not sending anything */
sizeof(struct message_recv), /* size to receive */
receive_port, /* where to listen and receive messages */
MACH_MSG_TIMEOUT_NONE, /* we want to listen forever */
MACH_PORT_NULL /* no notification port */
);
if (kr != MACH_MSG_SUCCESS) {
printf("failed to receive! %s\n", mach_error_string(kr));
return -1;
} else {
printf("received: %d\n", msg->x); /* let's print our received data */
}
return 0;
}

View File

@ -0,0 +1,3 @@
__TODO__
This is also a personal WIP, so I'll try to document as much as possible in here. --qwertyoruiop

143
About iOS/iBoot-RE.md Executable file
View File

@ -0,0 +1,143 @@
# iBoot RE (64 bits)
We focus on 64 bit iBoot cause we should:)
## In the beginning
### The Loading Address
Bootloaders in general and iBoot in particular expect to run at a specific, predefined, addresses.
Such an address called the __loading address__ (reset vector) of a bootloader.
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.
Most Apple bootloaders start with a relocation code which compares the loading address with the current address and moves the bootloader if needed.
Looking at this relocation code we can extract the loading address of the particular bootloader.
So, we start by using 0 as the loading address until we know better.
Here is an iBoot 64 bit example loaded at 0:
~~~ data
ROM:000 loc_0
ROM:000
ROM:000 ADRP X0, #loc_0@PAGE
ROM:004 ADD X0, X0, #loc_0@PAGEOFF <=== X0 has the current page address
ROM:008 LDR X1, =0x83D37B000 <=== this is the loading address
ROM:00C BL sub_17634
ROM:010 CMP X1, X0 <=== are we running at loading address
ROM:014 B.EQ loc_44 <=== if yes: continue booting normally
ROM:018 MOV X30, X1 <=== else: set LR to loading address
ROM:01C LDR X2, =0x83D413440
ROM:020 LDR X3, =0x83D37B000
ROM:024 SUB X2, X2, X3 <=== calculate len
ROM:028
ROM:028 loc_28 <=== copy loop
ROM:028 LDP X3, X4, [X0]
ROM:02C STP X3, X4, [X1]
ROM:030 ADD X0, X0, #0x10
ROM:034 ADD X1, X1, #0x10
ROM:038 SUBS X2, X2, #0x10
ROM:03C B.NE loc_28
ROM:040 RET <=== done copying -> return to loading address (LR)
ROM:044 ; -------------------------------------------------------------
ROM:044
ROM:044 loc_44 <=== rest of the iboot
ROM:044 MSR #6, #0xF ; MSR DAIFSET, #0XF
ROM:048 ADRP X30, #loc_AC8@PAGE
ROM:04C ADD X30, X30, #loc_AC8@PAGEOFF
ROM:050 ADRP X10, #loc_1F000@PAGE
ROM:054 ADD X10, X10, #loc_1F000@PAGEOFF
ROM:058 MSR #6, c12, c0, #0, X10 ; MSR VBAR_EL3, X10
~~~
So, the __loading address__ in this example is: __0x83D37B000__.
With this knowledge we can load the iboot to IDA with a proper loading address.
For 32 bits iboot the relocation code works the same, but it's not the first code.
The iboot starts with an exception vector.The first vector (reset) branches to the relocation code and it's the same from there.
Other bootloader: LLB, iBEC, IBSS have the same relocation code and hence the loading address available for grabbing.
### Beyond the loading address
After relocation of the iBoot to the proper running place, the boot continues.
Setting SP pointers, exception tables, etc.
Below is the rest of the first function that runs on boot.
Between the comments and the labels you should have no troubles following the code flow.
~~~ data
......... [ relocation code as shown above ]
ROM:83D07B044
ROM:83D07B044 ; mask exceptions
ROM:83D07B044 MSR #6, #0xF ; MSR DAIFSET, #0XF
ROM:83D07B048 ; set the next function to be executed on return
ROM:83D07B048 ADRP X30, #_start@PAGE
ROM:83D07B04C ADD X30, X30, #_start@PAGEOFF
ROM:83D07B050 ; setup exceptions table base address
ROM:83D07B050 ADRP X10, #exception_table@PAGE
ROM:83D07B054 ADD X10, X10, #exception_table@PAGEOFF
ROM:83D07B058 MSR #6, c12, c0, #0, X10 ; MSR VBAR_EL3, X10
ROM:83D07B05C ; clear 512K of memory
ROM:83D07B05C LDR X10, =base_addr_for_stack_and_stuff
ROM:83D07B060 LDR X11, =0x80000 ; 512K
ROM:83D07B064 ADD X11, X11, X10
ROM:83D07B068 MOV X12, #0
ROM:83D07B06C loop__clear_512K
ROM:83D07B06C STP X12, X12, [X10]
ROM:83D07B070 ADD X10, X10, #0x10
ROM:83D07B074 CMP X10, X11
ROM:83D07B078 B.NE loop__clear_512K
ROM:83D07B07C ; set base address for stack and stuff
ROM:83D07B07C LDR X10, =base_addr_for_stack_and_stuff
ROM:83D07B080 ADD X10, X10, #1,LSL#12 ; (base + 4K)
ROM:83D07B084 ; set EL3 SP to (base + 4K)
ROM:83D07B084 MOV SP, X10
ROM:83D07B088 MSR #5, #0 ; MSR SPSEL, #0
ROM:83D07B08C ADD X10, X10, #2,LSL#12 ; ((base + 4K) + 8K)
ROM:83D07B090 ; set EL0 SP to (base + 12K)
ROM:83D07B090 MOV SP, X10
ROM:83D07B094 ADD X20, X10, #2,LSL#12 ; (((base + 4K) + 8K) + 8K)
ROM:83D07B098 ; zero additional space
ROM:83D07B098 LDR X10, =_iboot_end ; from this addr
ROM:83D07B09C LDR X11, =fb_mbe ; to this addr
ROM:83D07B0A0 MOV X12, #0xF
ROM:83D07B0A4 BIC X12, X11, X12 ; end addr aligned to 16
ROM:83D07B0A8 MOV X13, #0
ROM:83D07B0AC ; clear more space, aligned 16
ROM:83D07B0AC loop__clear_more__aligned
ROM:83D07B0AC STP X13, X13, [X10],#0x10
ROM:83D07B0B0 CMP X10, X12
ROM:83D07B0B4 B.NE loop__clear_more__aligned
ROM:83D07B0B8 CMP X11, X12
ROM:83D07B0BC B.EQ loc_83D07B0CC
ROM:83D07B0C0 ; clear more space, the rest (unaligned)
ROM:83D07B0C0 loop__clear_more__unaligned
ROM:83D07B0C0 STR W13, [X10],#4
ROM:83D07B0C4 CMP X10, X11
ROM:83D07B0C8 B.NE loop__clear_more__unaligned
ROM:83D07B0CC
ROM:83D07B0CC loc_83D07B0CC
ROM:83D07B0CC ; set Exception handlers SP to (base + 20K)
ROM:83D07B0CC ADRP X11, #sp_for_exception_handlers@PAGE
ROM:83D07B0D0 ADD X11, X11, #sp_for_exception_handlers@PAGEOFF
ROM:83D07B0D4 STR X20, [X11]
ROM:83D07B0D8 RET
~~~
Notes:
- MSR DAIFSET, #0XF (mask all exceptions)
This is very early stage and we don't want to be interrupted before we can handle exceptions properly.
- _start
We are running a kind of a 'reset vector' code now and this is the next
function we execute by setting its address in the LR register and running with the RET instruction.
- exception_table
The address that goes into the VBAR_EL3 register is the beginning of the EL3 exception table.
ARMv8 is very different from ARMv7 in how the exception table looks and works.
Some of the differences are:
- Instead of vector of dwords it has 0x80 bytes of code for each exception
- There are multiple entries for the same exception depending on the circumstances of where the exception is taken from

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
iOS PDFs/.DS_Store vendored Normal file

Binary file not shown.

BIN
iOS PDFs/AppendixA.pdf Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

28980
iOS PDFs/iOS Hackers Handbook.pdf Executable file

File diff suppressed because one or more lines are too long

BIN
iOS PDFs/iOS Hacking Guide.pdf Executable file

Binary file not shown.

Binary file not shown.

BIN
iOS PDFs/xkungfoo.pdf Executable file

Binary file not shown.

70
iOS Resources/papers/README.md Executable file
View File

@ -0,0 +1,70 @@
# OS X / iOS Technical Papers
This list includes many technical papers about OS X and iOS exploitation/researching/reversing.
<br>
The papers you see listed here have been published publicly and are free to redistribute.
### Contributing
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.
<br>
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.
# OS X
## Exploitation
| *Document* | *Related Talk* | *Author* | *Year* |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|------------------------------------|--------|
| [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 |
| [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 |
| [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 |
| [Dont 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 |
| [OS X El Capitan sinking the Ship](https://papers.put.as/papers/macosx/2016/syscan360stefanesserosxelcapitansinkingtheship.pdf) | N/A | Stefan Esser | 2016 |
|[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 |
## Technical
| *Document* | *Related Talk* | *Author* | *Year* |
|-----------------------------------------------------------------------------------------------------------|----------------|----------------|--------|
| [DYLIB HIJACKING ON OS X](https://papers.put.as/papers/macosx/2015/vb201503-dylib-hijacking.pdf) | N/A | Patrick Wardle | 2015 |
| [Code Signing Hashed Out](https://papers.put.as/papers/macosx/2015/CodeSigning-RSA.pdf) | N/A | Jonathan Levin | 2015 |
| [The ARMs race to TrustZone](http://technologeeks.com/files/TZ.pdf) | N/A | Jonathan Levin | 2016 |
# iOS
## Exploitation
| *Document* | *Related Talk* | *Author* | *Year* |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|--------|
| [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 |
| [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 |
| [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 |
| [iOS Kernel Heap Armageddon](https://papers.put.as/papers/ios/2012/SyScan2012_StefanEsser_iOS_Kernel_Heap_Armageddon.pdf) | N/A | Stefan Esser | 2012 |
| [iOS 6 Kernel Security: A Hackers 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 |
| [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 |
| [Attacking the iOS Kernel: A Look at evasi0n](https://papers.put.as/papers/ios/2013/NISlecture201303.pdf) | N/A | Tarjei Mandt | 2013 |
| [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 |
| [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 |
| [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 |
| [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 |
| [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 |
| [Hacking from iOS 8 to iOS 9](https://papers.put.as/papers/ios/2015/POC2015_RUXCON2015.pdf) | N/A | Pangu Team | 2015 |
| [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 |
|[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|
## Technical
| *Document* | *Related Talk* | *Author* | *Year* |
|-----------------------------------------------------------------------------------------------------------|----------------|----------------|--------|
| [Security Enclave](http://mista.nu/research/sep-paper.pdf) | N/A | Tarjei Mandt, Mathew Solnik, and David Wang | N/A |
## Exploit Write-ups
| *CVEIDs* | *LINK* |
|-------------|----------------|
|CVE-2016-4655 CVE-2016-4656| <https://jndok.github.io/2016/10/04/pegasus-writeup/> |
|CVE-2016-7644 CVE-2016-7637 CVE-2016-7661|<https://bugs.chromium.org/p/project-zero/issues/detail?id=965> |
|CVE-2017-2370|<https://googleprojectzero.blogspot.co.uk/2017/04/exception-oriented-exploitation-on-ios.html>|
|CVE-2017-2416|<https://blog.flanker017.me/cve-2017-2416-gif-remote-exec/>|
|CVE-2017-2533 CVE-2017-2535 CVE-2017-2534|<https://phoenhex.re/2017-06-09/pwn2own-diskarbitrationd-privesc> <https://phoenhex.re/2017-07-06/pwn2own-sandbox-escape>|
|CVE-2018-4087|https://blog.zimperium.com/cve-2018-4087-poc-escaping-sandbox-misleading-bluetoothd/|
|CVE-2B-DETERMINED|http://bazad.github.io/2018/04/kernel-pointer-crash-log-ios/|
## External Links
Here you can find external list of papers and documents, most of which are not listed here.
* [@osxreverser](https://twitter.com/osxreverser)'s list: https://papers.put.as/
* [@snakeninny](https://twitter.com/snakeninny)'s iOSRE Book for beginners: https://github.com/iosre/iOSAppReverseEngineering

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python
import urllib2
import urllib
import json
headers = { 'User-Agent' : 'Mozilla/5.0' }
req = urllib2.Request('http://hopperapp.com/include/files-api.php?request=releases',None,headers)
print "Loading Hopper URL API"
response = urllib2.urlopen(req)
the_page = response.read()
JSON=json.loads(the_page)
OSXJSON=JSON["OS X"]
url=OSXJSON["filename"]
print "Downloading Hopper Latest With Size:",OSXJSON["file_length"]
urllib.urlretrieve (url, "Hoppper-Latest.zip")

View File

@ -0,0 +1,79 @@
#/bin/bash
echo "Installing Xcode Commandline Tools"
xcode-select --install
if ! type "brew" > /dev/null; then
# install Homebrew
echo "Installing Homebrew"
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
else
echo "Homebrew already installed"
fi
if ! type "dpkg" > /dev/null; then
# install dpkg
echo "Installing dpkg"
brew install dpkg
else
echo "dpkg already installed"
fi
if ! type "ldid" > /dev/null; then
# install ldid
echo "Installing ldid"
brew install ldid
else
echo "ldid already installed"
fi
export THEOS=/opt/theos
if [ ! -d "$THEOS" ]; then
# Theos isn't existe
echo "Installing Theos"
echo "export THEOS=/opt/theos" >>~/.bash_profile
source ~/.bash_profile
sudo git clone --recursive https://github.com/theos/theos.git $THEOS
sudo git clone https://github.com/theos/headers.git $THEOS/Headers
sudo cp -r $THEOS/Headers/ $THEOS/include
sudo rm -rf $THEOS/Headers/
else
# Theos existe
echo "Theos already installed"
fi
if ! type "wget" > /dev/null; then
# install wget
echo "Installing wget"
brew install wget
else
echo "wget already installed"
fi
if [ ! -d "/Applications/Reveal.app" ]; then
# Reveal app isn't existe
echo "Installing Reveal"
wget http://download.revealapp.com/Reveal.app.zip
unzip -XK ./Reveal.app.zip
chmod +x ./Reveal.app/Contents/MacOS/Reveal
mv ./Reveal.app /Applications/Reveal.app
rm -rf ./Reveal.app
rm -rf ./Reveal.app.zip
else
echo "Reveal app already installed"
fi
if [ ! -d "/Applications/Hopper Disassembler v3.app" ]; then
# Hopper app isn't existe
echo "Installing Hopper"
sudo ./Hopper.py
unzip -XK ./Hoppper-Latest.zip
mv './Hopper Disassembler v3.app' '/Applications/Hopper Disassembler v3.app'
else
echo "Hopper app already installed"
fi
sudo ./debugserver.py
git clone https://github.com/nygard/class-dump.git class-dump
xcodebuild -project ./class-dump/class-dump.xcodeproj #Compile classdump
mv ./class-dump/build/Release/class-dump /usr/local/bin
rm -rf ./class-dump

View File

@ -0,0 +1,8 @@
# iOSRETools
>>YOU MUST cd TO THIS FOLDER BEFORE DOING ANYTHING!!!
>>Then Just ./Installer.sh
A collection of commonly used iOSRE Tools
Pull Requests Are Favoured
>>Naville.Zhang

View File

@ -0,0 +1,28 @@
#!/usr/bin/env python
import subprocess
import string
import os
Path = subprocess.check_output(['xcode-select', '-p'])
Path = Path + "/Platforms/iPhoneOS.platform/DeviceSupport"
Path = string.replace(Path, "\n", "")
print "Developer Images Located At:", Path
for Sub in os.listdir(Path):
SubDire = os.path.join(Path, Sub)
if (os.path.isdir(SubDire)):
print "Loading Developer Disk Image At:\n",SubDire
os.system("hdiutil mount "+"\""+SubDire+"\""+"/DeveloperDiskImage.dmg -mountpoint /Volumes/DeveloperDiskImage")
DebugSrvPath=SubDire+"/debugserver"
print DebugSrvPath
print "Current DebugServer Copied To:\n"+DebugSrvPath
os.system("cp /Volumes/DeveloperDiskImage/usr/bin/debugserver "+"\""+SubDire+"\"")
os.system("codesign -s - --entitlements ./debugsrvEntitle.xml -f "+"\""+DebugSrvPath+"\"")
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
print "Version For Current DebugServer:\n"+Version
os.system("cp "+"\""+DebugSrvPath+"\""+" ./DebugServer"+"\""+Version+"\"")
print "Unloading Developer Disk Image At:\n",SubDire
os.system("hdiutil unmount /Volumes/DeveloperDiskImage")
os.remove(DebugSrvPath)

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.springboard.debugapplications</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,51 @@
#!/bin/bash
#######################################################################
#
# Project......: build_xpwn.sh
# Creator......: matteyeux
# Description..: Script to install XPwn tools
#
######################################################################
# Language :
# bash
# Version : 0.3
if [[ "$(whoami)" != "root" ]]; then
echo "Please run this script as root"
exit 1
fi
if [[ $(uname) != 'Linux' ]]; then
echo "This script is only for Linux"
exit 1
fi
apt-get -y install binutils
apt-get -y install p7zip-full
apt-get -y install git
apt-get -y install build-essential
apt-get -y install make
apt-get -y install cmake
apt-get -y install openssl
apt-get -y install libcrypto++-dev:q
apt-get -y install bsdiff
apt-get -y install libbz2-dev
apt-get -y install libpng3
apt-get -y install libusb-1.0.0
apt-get -y install libusb-1.0.0-dev
apt-get -y install libssl-dev
apt-get -y install libcurl3
apt-get -y install python-pip
cd ~
git clone https://github.com/xerub/xpwn.git
mkdir ~/build
cd ~/build
cmake ~/xpwn
make
make package
tar xvjf XPwn-0.5.8-Linux.tar.bz2
cd XPwn-0.5.8-Linux
cp dmg hdutil hfsplus ipsw ticket xpwntool validate /usr/local/bin/
echo "XPwn binaries installed to /usr/local/bin/"

View File

@ -0,0 +1,227 @@
#!/bin/bash
#######################################################################
#
# Project......: libinstaller.sh
# Creator......: matteyeux
# Description..: Script to install libimobiledevice on OS X & Debian Distros
# initials scripts: brew.sh & autobuild.sh by DarkMalloc
# Type.........: Public
#
######################################################################
# Language :
# bash
# Version : 0.2
#
# Change Log
# ==========
#
# ===============================================================
# Date | Who | What
# ---------------------------------------------------------------
# 27/12/15 | Mathieu Hautebas | Script creation
# ---------------------------------------------------------------
# 10/03/16 | HanSheng Zhang | Fix Stack overflow caused by naming issues
# ---------------------------------------------------------------
function apt-get(){
sudo apt-get install -y git
sudo apt-get install -y build-essential
sudo apt-get install -y make
sudo apt-get install -y autoconf
sudo apt-get install -y automake
sudo apt-get install -y libtool
sudo apt-get install -y openssl
sudo apt-get install -y tar
sudo apt-get install -y perl
sudo apt-get install -y binutils
sudo apt-get install -y gcc
sudo apt-get install -y libstdc++6-dev
sudo apt-get install -y libc6-dev
sudo apt-get install -y libssl-dev
sudo apt-get install -y libusb-1.0
sudo apt-get install -y gcc4.2
sudo apt-get install -y g++
sudo apt-get install -y libcurl4-gnutls-dev
sudo apt-get install -y fuse
sudo apt-get install -y libxml2-dev
sudo apt-get install -y libgfortran1
sudo apt-get install -y libgfortran2
sudo apt-get install -y libgfortran
sudo apt-get install -y libgcc1
sudo apt-get install -y libreadline-dev
sudo apt-get install -y libglib2.0-dev
sudo apt-get install -y libzip-dev
sudo apt-get install -y libclutter-1.0-dev
sudo apt-get install -y libgtk2.0-dev
sudo apt-get install -y libclutter-gtk-1.0-dev
sudo apt-get install -y lib32bz2-dev
sudo apt-get install -y libfuse-dev
sudo apt-get install -y subversion
sudo apt-get install -y cython
sudo apt-get install -y python-2.7
sudo apt-get install -y python2.7-numpy
sudo apt-get install -y libncurses4
sudo apt-get install -y libncurses5
sudo apt-get install -y ncurses-base
}
function brewfunc(){
# Install Hombrew.
if ! type "brew" > /dev/null; then
echo "brew Doesn't Exist.Installing"
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
else
echo "Brew Exists. Using"
fi
# Install command-line tools using Homebrew.
# Ask for the administrator password upfront.
sudo -v
# Keep-alive: update existing `sudo` time stamp until the script has finished.
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
echo "Make sure were using the latest Homebrew."
brew update
echo "Upgrade any already-installed formulae."
brew upgrade
echo "Install GNU core utilities (those that come with OS X are outdated)".
echo "Dont forget to add `$(brew --prefix coreutils)/libexec/gnubin` to `$PATH`".
brew install coreutils
sudo ln -s /usr/local/bin/gsha256sum /usr/local/bin/sha256sum
echo " Install some other useful utilities like `sponge`".
brew install moreutils
echo "Install GNU `find`, `locate`, `updatedb`, and `xargs`, `g`-prefixed".
brew install findutils
echo "Install GNU `sed`, overwriting the built-in `sed`".
brew install gnu-sed --with-default-names
echo "Install Development Packages";
brew install libxml2
brew install libzip
brew install libplist
brew install openssl
brew install clutter
brew install cogl
brew install usbmuxd
# Install Software;
brew install automake
brew install cmake
brew install colormake
brew install autoconf
brew install libtool
brew install pkg-config
brew install gcc
brew install libusb
brew install homebrew/fuse/ifuse
brew install glib
# Install Optional;
brew install screenfetch
brew install Caskroom/cask/osxfuse
# Install extras;
brew install bfg
brew install binutils
brew install binwalk
brew install cifer
brew install dex2jar
brew install dns2tcp
brew install fcrackzip
brew install foremost
brew install hashpump
brew install hydra
brew install john
brew install knock
brew install nmap
brew install pngcheck
brew install socat
brew install sqlmap
brew install tcpflow
brew install tcpreplay
brew install tcptrace
brew install ucspi-tcp # `tcpserver` etc.
brew install xz
# Install other useful binaries.
brew install ack
#brew install exiv2
brew install git
#brew install imagemagick --with-webp
brew install lua
brew install lynx
brew install p7zip
brew install pigz
# Install Node.js. Note: this installs `npm` too, using the recommended
# installation method.
brew install node
# Remove outdated versions from the cellar.
brew cleanup
}
function autobuild(){
successlibs=()
failedlibs=()
libs=( "libplist" "libusbmuxd" "libimobiledevice" "usbmuxd" "libirecovery" \
"ideviceinstaller" "libideviceactivation" "idevicerestore" "sbmanager" "ifuse" )
spinner() {
# What On Earth Is This?
local pid=$1
local delay=0.75
local spinstr='|/-\'
echo "$pid" > "/tmp/.spinner.pid"
while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
local temp=${spinstr#?}
printf " [%c] " "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
printf "\b\b\b\b\b\b"
done
printf " \b\b\b\b"
}
buildlibs() {
for i in "${libs[@]}"
do
echo -e "\033[1;32mFetching $i..."
git clone https://github.com/libimobiledevice/${i}.git
cd $i
echo -e "\033[1;32mConfiguring $i..."
./autogen.sh
./configure
echo -e "\033[1;32mBuilding $i..."
make && sudo make install
echo -e "\033[1;32mInstalling $i..."
cd ..
done
echo -e "\033[0m"
}
function buildr {
buildlibs
}
echo -e "\033[1;37mLibimobiledevice library build script - Elrhk 2015"
buildr
}
if [[ $(uname) == 'Linux' ]]; then
apt-get
autobuild
exit 1
elif [[ $(uname) == 'Darwin' ]]; then
brewfunc
autobuild
fi