iOS forensics trick: pulling databases w/o full backup
Previously on Instruments
In the previous post, I wrote about abusing some features in iOS DeveloperImage, including launching an App with custom environment variables on jailed devices.
To be honest my motivation was looking for sandbox logic issues, but failed. But at least I found this trick to abuse some feature to extract SQLite databases, which are common forensics targets, without the pain to make a fresh full backup. This scenario requires screen unlock and trusted USB connection.
To run the experiments you need to grab these tools:
- https://github.com/emonti/afcclient (optional. If you don’t want to code on libimobiledevice by yourself just use this)
The SQLite logging feature
Current built-in SQLite on iOS supports a debug option: if
SQLITE_SQLLOG_DIR environment is set, every database will have a copy in the given directory, with each sql queries in plain text as well.
This file contains experimental code used to record data from live SQLite applications that may be useful for offline…mjtsai.com
** 2012 November 26 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a…www.sqlite.org
Our experiment starts from a jailbroken device. Just start the Gmail app with
SQLITE_SQLLOG_DIR pointing to somewhere it has permission to write:
Modify the script in previous post, add a new key to the environment:
const env = ObjC.classes.NSMutableDictionary.alloc().init();
Here’s what it generates to the directory:
hello:/private/var/mobile/Containers/Data/Application/.../tmp root# ls
WebKit sqllog_05860_00000.sql sqllog_05860_00003.sql sqllog_05860_01.db
sqllog_05860.idx sqllog_05860_00001.sql sqllog_05860_00004.sql sqllog_05860_02.db
sqllog_05860_00.db sqllog_05860_00002.sql sqllog_05860_00005.sql sqllog_05860_03.db
The 05860 in file names is the pid, formatted to fixed 5 digits. The idx file is the mapping index to original databases.
root# cat sqllog_05860.idx
1 /var/mobile/Containers/Data/Application/E89CEF28-30BA-41F8-BDB3-BD05E0598D32/Library/Application Supportfirstname.lastname@example.org/sqlitedb
2 /var/mobile/Containers/Data/Application/E89CEF28-30BA-41F8-BDB3-BD05E0598D32/Library/Application Supportemail@example.com/imapsqlitedb
For example, all queries on
/var/mobile/Containers/Data/Application/E89CEF28–30BA-41F8-BDB3-BD05E0598D32/Library/Application Supportfirstname.lastname@example.org/sqlitedb are logged in
sqllog_05860_00.db is the copy.
Life without jailbreak
Now the problem is, apps on iOS are imprisoned in their containers, which are still unaccessible without a full backup. Every rule has an exception, so does sandbox profile.
Some built-in apps have the privilege to write to
And some apps has
You can read these entitlement via
ideviceinstaller -l -o list_system -o xml.
iOS allows sandboxed file access in
/var/mobile/Media, exposed by AFC. Many third party iPhone management tools allows you directly manipulate this location, even with a nice GUI.
➜ afcclient git:(master) ✗ ./afcclient mkdir Downloads/SQLite
Another place that may be readable is the CrashReporter. You can grab the files with idevicecrashreport.
The bad news is, not all built-in app has these exceptions, no to mention third parties.
During the test, launch the Instruments and use the frida script from previous post, change the bundle id to your target.
There are Safari browser state, bookmarks, history, per site preferences, HTML5 local storage and even caches. Note that typically Cache.db will not be included in backup, and it stores http requests in plain text.
➜ afcclient git:(master) ✗ ./afcclient mkdir iTunes_Control/iTunes/safari
Created directory: iTunes_Control/iTunes/safari
➜ afcclient git:(master) ✗ ./afcclient cat iTunes_Control/iTunes/safari/sqllog_02343.idx
0 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Image Cache/Favicons/Favicons.db
2 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Image Cache/Touch Icons/TouchIconCacheSettings.db
3 /private/var/mobile/Containers/Data/Application/9210B36C-89E2-4728-9831-40CAA961C15E/Library/Image Cache/Password Icons/TouchIconCacheSettings.db
➜ afcclient git:(master) ✗ ./afcclient cat Mail/sqllog_04465.idx
0 /var/mobile/Library/Mail/Envelope Index
1 /var/mobile/Library/Mail/Protected Index
Address Book and call history:
hello:~ root# procexp all fds | grep -i sms.db
IMDPersistenceA 812 FD 4u /private/var/mobile/Library/SMS/sms.db @0x0
IMDPersistenceA 812 FD 5u /private/var/mobile/Library/SMS/sms.db-wal @0x0
IMDPersistenceA 812 FD 6u /private/var/mobile/Library/SMS/sms.db-shm @0x0
hello:~ root# ps aux | grep 812
mobile 812 0.0 0.0 1664672 1296 ?? Ss 22Oct18 0:01.77 /System/Library/PrivateFrameworks/IMDPersistence.framework/XPCServices/IMDPersistenceAgent.xpc/IMDPersistenceAgent
root 6008 0.0 0.1 1593504 1536 s000 S+ 2:50PM 0:00.01 grep 812
➜ afcclient git:(master) ✗ ./afcclient mkdir iTunes_Control/iTunes/Phone
Created directory: iTunes_Control/iTunes/Phone
➜ afcclient git:(master) ✗./afcclient cat iTunes_Control/iTunes/Phone/sqllog_04322.idx
But you will not be able to pull
sms.db, because it’s owned by xpc service
IMDPersistenceAgent. The message app
com.apple.MobileSMS communicates with it via XPC instead of opening the database.