|
| 1 | +# Shared Cache |
| 2 | + |
| 3 | +Shared Cache support in Binary Ninja provides you with tools to selectively load specific images, search for |
| 4 | +specific symbols, and follow analysis references between any loaded images in one view. |
| 5 | + |
| 6 | +## Support Matrix |
| 7 | + |
| 8 | +List of supported features for the given shared cache targets. |
| 9 | + |
| 10 | +| Platform | Arch | Versions | Features | |
| 11 | +|----------|--------|----------|-----------------------------| |
| 12 | +| iOS | arm64 | 11 - 18 | Core, Objective-C, Workflow | |
| 13 | +| macOS | x86_64 | 11 - 15 | Core, Objective-C, Workflow | |
| 14 | +| macOS | arm64 | 11 - 15 | Core, Objective-C, Workflow | |
| 15 | + |
| 16 | +- **Core**: Core functionality, such as loading, navigating, and analyzing shared cache files. |
| 17 | +- **Objective-C**: Support for analyzing Objective-C information and symbols within the shared cache. |
| 18 | +- **Workflow**: Shared cache workflow that improves on the base Binary Ninja analysis with shared cache specific analysis. |
| 19 | + |
| 20 | +## Obtaining a Shared Cache |
| 21 | + |
| 22 | +The shared cache is one or more files that contain all the shared libraries used by macOS and iOS. These can be obtained |
| 23 | +directly from apple, or with the help of a tool such as `blacktop/ipsw`. |
| 24 | + |
| 25 | +### With blacktop/ipsw tool |
| 26 | + |
| 27 | +The recommended way to retrieve iOS shared caches is using blacktop's wonderful ipsw tool. |
| 28 | + |
| 29 | +1. [Install blacktop/ipsw](https://github.com/blacktop/ipsw?tab=readme-ov-file#install) |
| 30 | +2. Run `ipsw download ipsw --version [target iOS version] --device [target device model (e.g. iPhone10,3)]` |
| 31 | +3. Run `ipsw extract --dyld [filename]` |
| 32 | + |
| 33 | +### With Local macOS install |
| 34 | + |
| 35 | +The local shared cache on macOS is located at `/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/`. |
| 36 | + |
| 37 | +## Opening a Shared Cache |
| 38 | + |
| 39 | +Binary Ninja currently supports shared cache files extracted into a flat directory only, so you will need to extract the IPSW (if there is one) first. |
| 40 | + |
| 41 | +- `your_directory` |
| 42 | + - `dyld_shared_cache_arm64` (**Primary**) |
| 43 | + - `dyld_shared_cache_arm64.01` (Secondary, optional) |
| 44 | + - `dyld_shared_cache_arm64.02` (Secondary, optional) |
| 45 | + - `dyld_shared_cache_arm64.symbols` (Symbols, optional) |
| 46 | + |
| 47 | +To access the entire shared cache, open the **Primary** file in Binary Ninja, for the example above this would be `dyld_shared_cache_arm64`. |
| 48 | +Opening any other file (e.g. `dyld_shared_cache_arm64.01`) will result in a partial shared cache, with only the information present |
| 49 | +in the file you opened. |
| 50 | + |
| 51 | +### Project Support |
| 52 | + |
| 53 | +Shared caches are supported for Binary Ninja projects, however due to the nature of the project files not having a mappable path, |
| 54 | +saving shared cache databases (`.bndb`) in a seperate directory will require you to select the primary shared cache file on |
| 55 | +every open of the database. It is advised to keep your shared cache databases next to your shared cache files (in the same folder). |
| 56 | + |
| 57 | +- `your_project_folder` |
| 58 | + - `dyld_shared_cache_arm64` (**Primary**) |
| 59 | + - `dyld_shared_cache_arm64.01` (Secondary, optional) |
| 60 | + - `dyld_shared_cache_arm64.02` (Secondary, optional) |
| 61 | + - `dyld_shared_cache_arm64.symbols` (Symbols, optional) |
| 62 | + - `your_database.bndb` (This is recommended) |
| 63 | + |
| 64 | +## Interacting with a Shared Cache |
| 65 | + |
| 66 | +After opening a shared cache you will be provided a supercharged binary view, one which has information not only from |
| 67 | +the opened primary file, but all the associated files (ex. `dyld_shared_cache_arm64.02`). Because of the large size of these |
| 68 | +caches we cannot load all the information into the binary view, instead we do so selectively. |
| 69 | + |
| 70 | +### Shared Cache Triage (DSCTriage) |
| 71 | + |
| 72 | +The main way to interact with the shared cache information is through the triage view. This is the first thing you see when |
| 73 | +opening a shared cache and is how you add images to the actual binary view. |
| 74 | + |
| 75 | +=== "Images" |
| 76 | + Shows a list of all images within the shared cache and their virtual addresses. |
| 77 | + |
| 78 | + - Double click on an image to load |
| 79 | + - Select image(s) and click button "Load Selected" to load multiple images at once |
| 80 | + - Select image(s) and right click if you want more options for loading images |
| 81 | + |
| 82 | +  |
| 83 | + |
| 84 | +=== "Symbols" |
| 85 | + Shows a list of all exported symbols within the shared cache and their virtual addresses. |
| 86 | + |
| 87 | + - Double click on a symbol to load the associated image, or use the "Load Image" button |
| 88 | + |
| 89 | +  |
| 90 | + |
| 91 | +=== "Mappings & Regions" |
| 92 | + Shows information about the entry mappings and the cache regions. |
| 93 | + |
| 94 | +  |
| 95 | + |
| 96 | +### Scripting |
| 97 | + |
| 98 | +Another way to interact with the shared cache information is through the provided python API, available in the `binaryninja.sharedcache` module. |
| 99 | + |
| 100 | +Additionally, the `dsc` magic variable is available in the scripting console whenever a Shared Cache is opened. |
| 101 | + |
| 102 | +```python |
| 103 | +# Load all dependency images for the current loaded images |
| 104 | +from binaryninja import sharedcache |
| 105 | +for image in dsc.loaded_images: |
| 106 | + dependencies = dsc.get_image_dependencies(image) |
| 107 | + for dependency in dependencies: |
| 108 | + dep_image = dsc.get_image_with_name(dependency) |
| 109 | + if dep_image is None: |
| 110 | + continue |
| 111 | + dsc.apply_image(bv, dep_image) |
| 112 | +``` |
| 113 | + |
| 114 | +## Glossary |
| 115 | + |
| 116 | +### CacheEntry |
| 117 | + |
| 118 | +A **CacheEntry** is a single file in the shared cache. It contains images, symbols, and regions that collectively |
| 119 | +represent a portion of the shared cache's contents. |
| 120 | + |
| 121 | +### CacheRegion |
| 122 | + |
| 123 | +A **CacheRegion** is the logical segment of the shared cache for which the memory is mapped into the `BinaryView`. It |
| 124 | +represents distinct sections of the cache, no region should be overlapping. |
| 125 | + |
| 126 | +### CacheImage |
| 127 | + |
| 128 | +A **CacheImage** is a single shared library within the shared cache. It consists of sections (located within cache |
| 129 | +regions) that include both code and data. This is analogous to a single mach-o file. |
| 130 | + |
| 131 | +### CacheSymbol |
| 132 | + |
| 133 | +A **CacheSymbol** represents a symbol within the shared cache, such as a function or data variable. It is **not** a view |
| 134 | +symbol and is **not** directly available from the `BinaryView`. Instead, it is specifically associated with the shared |
| 135 | +cache data, otherwise we would be putting millions of symbols into the view and slowing down the core unnecessarily. |
0 commit comments