Dyld shared cache: Difference between revisions

From iPhone Development Wiki
(rewrite-ish intro for clarity)
m (Formatting.)
Line 1: Line 1:
{{DISPLAYTITLE:dyld_shared_cache}}
{{DISPLAYTITLE:dyld_shared_cache}}
Since iPhone OS 3.1, all system (private and public) libraries have been combined into a big cache file to improve performance. The original files are redundant and thus eliminated from the system.
Since iPhone OS 3.1, all system (private and public) libraries have been combined into a big cache file to improve performance. The original files are redundant and thus eliminated from the system.


Line 6: Line 7:
OS X also uses a shared cache. Unlike iOS, OS X ships with the source binaries still on-disk, particularly so it can be updated with [https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/update_dyld_shared_cache.1.html update_dyld_shared_cache]. The cache is only vaguely documented in dyld man pages.
OS X also uses a shared cache. Unlike iOS, OS X ships with the source binaries still on-disk, particularly so it can be updated with [https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/update_dyld_shared_cache.1.html update_dyld_shared_cache]. The cache is only vaguely documented in dyld man pages.


== Cache location ==
= Cache location =


The cache is located in <tt>/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX</tt>, where X can be:
The cache is located in <tt>/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX</tt>, where X can be:
Line 29: Line 30:
|}
|}


== Cache extraction ==
= Cache extraction =
 
It used to be possible to compile and link from an iOS device without an SDK, but the introduction of dyld_shared_cache has made using an SDK a necessity. Alternatively, one may need to extract the appropriate dylibs from the dyld_shared_cache, if it's not available in the SDK.
It used to be possible to compile and link from an iOS device without an SDK, but the introduction of dyld_shared_cache has made using an SDK a necessity. Alternatively, one may need to extract the appropriate dylibs from the dyld_shared_cache, if it's not available in the SDK.


Line 42: Line 44:
* [http://www.newosxbook.com/index.php?page=downloads jtool] is another option if other tools fail (which seems to be common starting with iOS 8).  
* [http://www.newosxbook.com/index.php?page=downloads jtool] is another option if other tools fail (which seems to be common starting with iOS 8).  


== Example usage for decache ==


=== Example usage for decache ===
This will extract the binary of the private framework SpringBoardServices
This will extract the binary of the private framework SpringBoardServices
<source lang=bash>decache -c path/to/dyld_shared_cache -x /System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices -o SpringBoardServices</source>
 
<source lang=bash>
decache -c path/to/dyld_shared_cache -x /System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices -o SpringBoardServices
</source>


If you get a message about an unsupported load command, ignore it. decache does not support some newer mach-o load commands, so the binary won't be able to run probably in the most cases. But for linking or reverse-engineering purposes it is still usable.
If you get a message about an unsupported load command, ignore it. decache does not support some newer mach-o load commands, so the binary won't be able to run probably in the most cases. But for linking or reverse-engineering purposes it is still usable.


=== Example usage for jtool ===
== Example usage for jtool ==


To extract a specific binary from the cache ("UIKit" can be replaced with a different framework or library):
To extract a specific binary from the cache ("UIKit" can be replaced with a different framework or library):
Line 57: Line 62:
An example of one way to dump all the binaries at once (be careful with this, it creates huge files):
An example of one way to dump all the binaries at once (be careful with this, it creates huge files):


<source lang=bash>jtool -lv cache_armv7 | cut -c 24- | tail +5 | while read line ; do jtool -extract $line cache_armv7 ; done</source>
<source lang=bash>
jtool -lv cache_armv7 | cut -c 24- | tail +5 | while read line ; do jtool -extract $line cache_armv7 ; done
</source>


====Problems with jtool====
=== Problems with jtool ===


Please be aware that decache produces currently (16.04.15) better and more usable results then jtool, as jtool fails to resolve and fix the "uniqued" objectiv c selectors correctly.
Please be aware that decache produces currently (16.04.15) better and more usable results then jtool, as jtool fails to resolve and fix the "uniqued" objectiv c selectors correctly.
Line 65: Line 72:
Apple "uniques" objectiv c selectors, such as "alloc" (alloc is used almost everywhere), which are used in more then one place, into a single one. When extracting an image from the cache, the address of such a shared selector will most likely not be in the extracted image anymore, so this needs to fixed, which jtool apparently fails to do. (For more information: http://opensource.apple.com/source/dyld/dyld-132.13/launch-cache/update_dyld_shared_cache.cpp, look at the class ObjCSelectorUniquer)
Apple "uniques" objectiv c selectors, such as "alloc" (alloc is used almost everywhere), which are used in more then one place, into a single one. When extracting an image from the cache, the address of such a shared selector will most likely not be in the extracted image anymore, so this needs to fixed, which jtool apparently fails to do. (For more information: http://opensource.apple.com/source/dyld/dyld-132.13/launch-cache/update_dyld_shared_cache.cpp, look at the class ObjCSelectorUniquer)


== Cache retrieval ==
= Cache retrieval =


Since ASLR was implemented in iOS, trivial ways to pull the cache off the device have provided a "broken" cache, which can't be processed correctly by the aforementioned tools. This is because when read by processes in which ASLR is enabled, some offsetting is applied to the cache too. In order to circumvent this issue and pull a "valid" shared cache off the device, there are different options:
Since ASLR was implemented in iOS, trivial ways to pull the cache off the device have provided a "broken" cache, which can't be processed correctly by the aforementioned tools. This is because when read by processes in which ASLR is enabled, some offsetting is applied to the cache too. In order to circumvent this issue and pull a "valid" shared cache off the device, there are different options:
Line 76: Line 83:
Alternatively, [https://github.com/npupyshev/dt.fetchsymbols dt.fetchsymbols] can be used to extract the cache from an iOS device. This tool doesn't require file system access (jailbreak) or app installation.
Alternatively, [https://github.com/npupyshev/dt.fetchsymbols dt.fetchsymbols] can be used to extract the cache from an iOS device. This tool doesn't require file system access (jailbreak) or app installation.


== Class dumping ==
= Class dumping =


See [[Reverse_Engineering_Tools#class-dump.2C_class_dump_z.2C_classdump-dyld|this section of Reverse Engineering Tools]].
See [[Reverse_Engineering_Tools#class-dump.2C_class_dump_z.2C_classdump-dyld|this section of Reverse Engineering Tools]].
   
   
== External Links ==
= External Links =


* [http://blog.howett.net/?p=75 Cache or Check?] — an analysis of the dyld_shared_cache system by D. Howett.
* [http://blog.howett.net/?p=75 Cache or Check?] — an analysis of the dyld_shared_cache system by D. Howett.

Revision as of 04:24, 26 December 2015


Since iPhone OS 3.1, all system (private and public) libraries have been combined into a big cache file to improve performance. The original files are redundant and thus eliminated from the system.

If you're looking for binaries or libraries inside of /System/Library/Frameworks or /System/Library/PrivateFrameworks (or other directories) and can't, this is why.

OS X also uses a shared cache. Unlike iOS, OS X ships with the source binaries still on-disk, particularly so it can be updated with update_dyld_shared_cache. The cache is only vaguely documented in dyld man pages.

Cache location

The cache is located in /System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX, where X can be:

X Device ARM Architecture
v6 ARMv6
v7 ARMv7
v7s
v7k
64 ARMv8

Cache extraction

It used to be possible to compile and link from an iOS device without an SDK, but the introduction of dyld_shared_cache has made using an SDK a necessity. Alternatively, one may need to extract the appropriate dylibs from the dyld_shared_cache, if it's not available in the SDK.

Starting with iOS 8, the framework binaries shipped with the iOS SDK only contain the symbols, not the compiled code anymore. Binaries extracted from the dyld_shared_cache contain all compiled code and are therefore useful for reverse-engineering purposes.

Options:

  • You could use dyld_decache by KennyTM~ to extract these dylibs.
  • Alternatively, you could use DySlim by comex to mount the whole cache file on Mac OS X.
  • decache by phoenixdev also works quite well. Out of the tools presented here, it currently produces the most usable results.
  • dsc_extractor (source code). More info here.
  • jtool is another option if other tools fail (which seems to be common starting with iOS 8).

Example usage for decache

This will extract the binary of the private framework SpringBoardServices

decache -c path/to/dyld_shared_cache -x /System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices -o SpringBoardServices

If you get a message about an unsupported load command, ignore it. decache does not support some newer mach-o load commands, so the binary won't be able to run probably in the most cases. But for linking or reverse-engineering purposes it is still usable.

Example usage for jtool

To extract a specific binary from the cache ("UIKit" can be replaced with a different framework or library):

jtool -extract UIKit path/to/dyld_shared_cache

An example of one way to dump all the binaries at once (be careful with this, it creates huge files):

jtool -lv cache_armv7 | cut -c 24- | tail +5 | while read line ; do jtool -extract $line cache_armv7 ; done

Problems with jtool

Please be aware that decache produces currently (16.04.15) better and more usable results then jtool, as jtool fails to resolve and fix the "uniqued" objectiv c selectors correctly.

Apple "uniques" objectiv c selectors, such as "alloc" (alloc is used almost everywhere), which are used in more then one place, into a single one. When extracting an image from the cache, the address of such a shared selector will most likely not be in the extracted image anymore, so this needs to fixed, which jtool apparently fails to do. (For more information: http://opensource.apple.com/source/dyld/dyld-132.13/launch-cache/update_dyld_shared_cache.cpp, look at the class ObjCSelectorUniquer)

Cache retrieval

Since ASLR was implemented in iOS, trivial ways to pull the cache off the device have provided a "broken" cache, which can't be processed correctly by the aforementioned tools. This is because when read by processes in which ASLR is enabled, some offsetting is applied to the cache too. In order to circumvent this issue and pull a "valid" shared cache off the device, there are different options:

  • Copy the cache off the device using a program on which ASLR has been explicitly disabled, using the -mdynamic-no-pic compile flag.
  • Read the cache explicitly from the filesystem by setting the F_NOCACHE flag on the cache's file descriptor.
  • Copy the cache through AFC (filesystem browsers which use an AFC connection are fine) - on iOS 7 and 8, you'll want to install the package Apple File Conduit "2", hosted/maintained by saurik.
  • Pull the cache off a decrypted root filesystem DMG which you can find inside the IPSW.

Alternatively, dt.fetchsymbols can be used to extract the cache from an iOS device. This tool doesn't require file system access (jailbreak) or app installation.

Class dumping

See this section of Reverse Engineering Tools.

External Links

  • Cache or Check? — an analysis of the dyld_shared_cache system by D. Howett.