Skip to content

Instantly share code, notes, and snippets.

@NSExceptional
Last active January 21, 2024 14:17
Show Gist options
  • Save NSExceptional/85527151eeec4b0640187a0a165da1cd to your computer and use it in GitHub Desktop.
Save NSExceptional/85527151eeec4b0640187a0a165da1cd to your computer and use it in GitHub Desktop.

iOS Shared Cache Extraction

Having fallen off the iOS-exploration train due to completing my Masters and other commitments, I have finally climbed back aboard in pursuit of understanding the telephony stack.

Like most things in iOS that are used frequently, the vast majority of the frameworks and libraries used in the telephony stack reside in the DYLD shared cache located at /System/Library/Caches/com.apple.dyld/dyld_shared_cache_armv7.

In this post I am going to explain how to go about extracting this cache file so that you can then work with each library individually.

Get The Cache

The first step in all of this is to copy the cache over to your local machine. I did this using a program called iExplorer, but you can just as easily do it over SSH. As a side note, you can connect to your iDevice using SSH over USB if you install a tool called iProxy.

Building dsc_extractor

The easiest way I found to extract the cache is to use a program provided by Apple called dsc_extractor. You can get the source for dsc_extractor by downloading the dyld package from Apples open source page at: http://opensource.apple.com/.

After downloading the package, unarchive it then go to the launch-cache subdirectory.

$ tar -xvzf dyld-210.2.3.tar.gz
$ cd dyld-210.2.3/launch-cache/

At this point we need to apply a patch to the dsc_extractor code so that it can be compiled and function properly. The patch to be applied is available on GitHub at https://gist.github.com/lightbulbone/6092321

The patch can be applied using the patch command; once patched dsc_extractor can then be compiled.

$ patch < dsc_extractor.patch
$ clang++ -o dsc_extractor dsc_extractor.cpp dsc_iterator.cpp

You should now have a working copy of dsc_extractor.

Extracting The Cache The last step is pretty simple. All you need to do is run dsc_extractor.

$ dsc_extractor dyld_shared_cache_armv7 armv7/

If you then look inside the armv7/ folder you’ll find all the extracted libraries used on iOS.

As a quick side note, you can also open the cache file directly in IDA Pro. I found this be a bit cumbersome although you may have better luck.

Until next time, happy hacking!

@watbulb
Copy link

watbulb commented Apr 15, 2021

😆 ... you don't even need to patch or use the dsc_extractor.cpp or dsc_iterator files at all, just copy the content between the #if block in the original dsc_extractor.cpp to some foobar.c file. compile it, done. you don't need any of this nonsense.

If you notice the prototype for the trigger is an external export linkage, dlsym imports the symbol, assigns it to the external linkage prototype, done. No external code needed whatsoever. Literally all you need to do this on any system is this snippet, compile it, run it, done. dsc_extractor is not required at any point. Bundle is already on-disk with the dsc-extractor code ...

#include <stdio.h>
#include <stddef.h>
#include <dlfcn.h>

typedef int (*extractor_proc)(const char* shared_cache_file_path, const char* extraction_root_path,
													void (^progress)(unsigned current, unsigned total));
int main(int argc, const char* argv[])
{
	if ( argc != 3 ) {
		fprintf(stderr, "usage: dsc_extractor <path-to-cache-file> <path-to-device-dir>\n");
		return 1;
	}
	
	//void* handle = dlopen("/Volumes/my/src/dyld/build/Debug/dsc_extractor.bundle", RTLD_LAZY);
	void* handle = dlopen("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle", RTLD_LAZY);
	if ( handle == NULL ) {
		fprintf(stderr, "dsc_extractor.bundle could not be loaded\n");
		return 1;
	}
	
	extractor_proc proc = (extractor_proc)dlsym(handle, "dyld_shared_cache_extract_dylibs_progress");
	if ( proc == NULL ) {
		fprintf(stderr, "dsc_extractor.bundle did not have dyld_shared_cache_extract_dylibs_progress symbol\n");
		return 1;
	}
	
	int result = (*proc)(argv[1], argv[2], ^(unsigned c, unsigned total) { printf("%d/%d\n", c, total); } );
	fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n", result);
	return 0;
}
#endif

@Macmee
Copy link

Macmee commented Aug 21, 2022

dyld gives errno=22 if you try and actually load any of the extracted libraries. Is something else perhaps needed for these extracted libraries to be usable?

@NSExceptional
Copy link
Author

I have never seen a tool that can extract libraries that can be loaded and run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment