*This writeup is also readable on my [GitHub repository](https://github.com/shawnduong/zero-to-hero-hacking/blob/master/writeups/closed/2021-uiuctf.md) and [personal website](https://shawnd.xyz/blog/2021-08-05/Performing-Digital-Forensics-on-an-Apple-Tablet-to-Recover-Evidence).*
## forensics/Tablet 2
*Challenge written by WhiteHoodHacker.*
> Wait... there are TWO impostors?! Red must have been in contact with the other impostor. See if you can find out what they are plotting.
Files: [`tablet.tar.gz`](https://shawnd.xyz/blog/uploads/2021-08-05/tablet.tar.gz)
Checksum (SHA-1):
```27dfb3448130b5e4f0f73a51d2a41b32fd81b284  tablet.tar.gz```
Looks like this is a development to our initial investigation! Based on this description, let's get our situation oriented:
- There's another impostor that Red's been in contact with.- Our objective is to find out what they're plotting.
Immediately, my mind jumps to SMS text messages. Let's find out where SMS text messages are located on the tablet:
```sh[skat@anubis:~/work/UIUCTF/private/var] $ find . -name "SMS"./mobile/Library/SMS[skat@anubis:~/work/UIUCTF/private/var] $ cd mobile/Library/SMS/[skat@anubis:~/work/UIUCTF/private/var/mobile/Library/SMS] $ lsCloudKitMetaData  PluginMetaDataCache  transferInfo                               prewarm.db      prewarm.db-wal  sms.db-shmDrafts            StickerCache         com.apple.messages.geometrycache_v5.plist  prewarm.db-shm  sms.db          sms.db-wal```
`sms.db` looks interesting. Let's access and dump that database, just like we dumped an application's database in **forensics/Tablet 1** earlier:
```sh[skat@anubis:~/work/UIUCTF/private/var/mobile/Library/SMS] $ sqlite3 sms.db```
```sqlSQLite version 3.36.0 2021-06-18 18:36:39Enter ".help" for usage hints.qlite> .dumpearlieAGMA foreign_keys=OFF;BEGIN TRANSACTION;CREATE TABLE _SqliteDatabaseProperties (key TEXT, value TEXT, UNIQUE(key));INSERT INTO _SqliteDatabaseProperties VALUES('counter_in_all','0');INSERT INTO _SqliteDatabaseProperties VALUES('counter_out_all','0');INSERT INTO _SqliteDatabaseProperties VALUES('counter_in_lifetime','0');INSERT INTO _SqliteDatabaseProperties VALUES('counter_out_lifetime','0');INSERT INTO _SqliteDatabaseProperties VALUES('counter_last_reset','0');INSERT INTO _SqliteDatabaseProperties VALUES('_ClientVersion','14006');INSERT INTO _SqliteDatabaseProperties VALUES('__CSDBRecordSequenceNumber','175');CREATE TABLE deleted_messages (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, guid TEXT NOT NULL);CREATE TABLE chat_handle_join (chat_id INTEGER REFERENCES chat (ROWID) ON DELETE CASCADE, handle_id INTEGER REFERENCES handle (ROWID) ON DELETE CASCADE, UNIQUE(chat_id, handle_id));INSERT INTO chat_handle_join VALUES(2,2);CREATE TABLE sync_deleted_messages (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, guid TEXT NOT NULL, recordID TEXT );INSERT INTO sync_deleted_messages VALUES(1,'91ED3477-EDA9-48BF-8E87-873B37D804A8','');INSERT INTO sync_deleted_messages VALUES(2,'D06D2D50-7C12-4114-B849-1A1D2146D306',NULL);INSERT INTO sync_deleted_messages VALUES(3,'1EE3DB69-8FD1-478F-A7A7-D0C3D8716133',NULL);INSERT INTO sync_deleted_messages VALUES(4,'096B56BF-5A85-4194-A5CA-4A9195AE0183',NULL);INSERT INTO sync_deleted_messages VALUES(5,'D4A09E09-A6FE-40D6-B79C-B68A878B0568','');INSERT INTO sync_deleted_messages VALUES(6,'0C78643A-0A67-4022-A3F2-301A9496F2AD','');CREATE TABLE message_processing_task (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, guid TEXT NOT NULL, task_flags INTEGER NOT NULL );CREATE TABLE handle (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, id TEXT NOT NULL, country TEXT, service TEXT NOT NULL, uncanonicalized_id TEXT, person_centric_id TEXT, UNIQUE (id, service) );INSERT INTO handle VALUES(2,'[email protected]','us','iMessage',NULL,NULL);CREATE TABLE sync_deleted_chats (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, guid TEXT NOT NULL, recordID TEXT,timestamp INTEGER);CREATE TABLE message_attachment_join (message_id INTEGER REFERENCES message (ROWID) ON DELETE CASCADE, attachment_id INTEGER REFERENCES attachment (ROWID) ON DELETE CASCADE, UNIQUE(message_id, attachment_id));CREATE TABLE sync_deleted_attachments (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, guid TEXT NOT NULL, recordID TEXT );INSERT INTO sync_deleted_attachments VALUES(1,'F0DA17FE-0A7B-4B8D-BAA0-0CB898315AA4',NULL);CREATE TABLE kvtable (ROWID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, key TEXT UNIQUE NOT NULL, value BLOB NOT NULL);CREATE TABLE chat_message_join (chat_id INTEGER REFERENCES chat (ROWID) ON DELETE CASCADE, message_id INTEGER REFERENCES message (ROWID) ON DELETE CASCADE, message_date INTEGER DEFAULT 0, PRIMARY KEY (chat_id, message_id));INSERT INTO chat_message_join VALUES(2,7,648927160045514368);INSERT INTO chat_message_join VALUES(2,8,648927174089999872);-- snip --```
Alright, that's a lot of data to take in! Let's find out what tables are created and prepare our filters from there.
```sqlsqlite> .tables_SqliteDatabaseProperties  kvtableattachment                 messagechat                       message_attachment_joinchat_handle_join           message_processing_taskchat_message_join          sync_deleted_attachmentsdeleted_messages           sync_deleted_chatshandle                     sync_deleted_messages```
The table "message" looks interesting. Let's have a look at that.
```sqlsqlite> .dump messagePRAGMA foreign_keys=OFF;BEGIN TRANSACTION;CREATE TABLE message (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, guid TEXT UNIQUE NOT NULL, text TEXT, replace INTEGER DEFAULT 0, service_center TEXT, handle_id INTEGER DEFAULT 0, subject TEXT, country TEXT, attributedBody BLOB, version INTEGER DEFAULT 0, type INTEGER DEFAULT 0, service TEXT, account TEXT, account_guid TEXT, error INTEGER DEFAULT 0, date INTEGER, date_read INTEGER, date_delivered INTEGER, is_delivered INTEGER DEFAULT 0, is_finished INTEGER DEFAULT 0, is_emote INTEGER DEFAULT 0, is_from_me INTEGER DEFAULT 0, is_empty INTEGER DEFAULT 0, is_delayedINTEGER DEFAULT 0, is_auto_reply INTEGER DEFAULT 0, is_prepared INTEGER DEFAULT 0, is_read INTEGER DEFAULT 0, is_system_message INTEGER DEFAULT 0, is_sent INTEGER DEFAULT 0, has_dd_resultsINTEGER DEFAULT 0, is_service_message INTEGER DEFAULT 0, is_forward INTEGER DEFAULT 0, was_downgraded INTEGER DEFAULT 0, is_archive INTEGER DEFAULT 0, cache_has_attachments INTEGER DEFAULT0, cache_roomnames TEXT, was_data_detected INTEGER DEFAULT 0, was_deduplicated INTEGER DEFAULT 0, is_audio_message INTEGER DEFAULT 0, is_played INTEGER DEFAULT 0, date_played INTEGER, item_type INTEGER DEFAULT 0, other_handle INTEGER DEFAULT 0, group_title TEXT, group_action_type INTEGER DEFAULT 0, share_status INTEGER DEFAULT 0, share_direction INTEGER DEFAULT 0, is_expirable INTEGER DEFAULT 0, expire_state INTEGER DEFAULT 0, message_action_type INTEGER DEFAULT 0, message_source INTEGER DEFAULT 0, associated_message_guid TEXT, associated_message_type INTEGER DEFAULT 0, balloon_bundle_id TEXT, payload_data BLOB, expressive_send_style_id TEXT, associated_message_range_location INTEGER DEFAULT 0, associated_message_range_length INTEGER DEFAULT 0, time_expressive_send_played INTEGER, message_summary_info BLOB, ck_sync_state INTEGER DEFAULT 0, ck_record_id TEXT, ck_record_change_tag TEXT, destination_caller_id TEXT, sr_ck_sync_state INTEGER DEFAULT 0, sr_ck_record_id TEXT, sr_ck_record_change_tag TEXT, is_corrupt INTEGER DEFAULT 0, reply_to_guid TEXT, sort_id INTEGER, is_spam INTEGER DEFAULT 0, has_unseen_mention INTEGER DEFAULT 0, thread_originator_guid TEXT, thread_originator_part TEXT);INSERT INTO message VALUES(7,'336CCB7F-3CB8-477A-AEED-8A4418EE7FFF','Hey what’s your Discord tag',0,NULL,2,NULL,NULL,X'040b73747265616d747970656481e803840140848484124e5341747472696275746564537472696e67008484084e534f626a656374008592848484084e53537472696e67019484012b1d4865792077686174e280997320796f757220446973636f7264207461678684026949011b928484840c4e5344696374696f6e617279009484016901928496961d5f5f6b494d4d657373616765506172744174747269627574654e616d658692848484084e534e756d626572008484074e5356616c7565009484012a84999900868686',10,0,'iMessage','E:[email protected]','73890C71-600D-4961-B1A7-687F2FAD3566',0,648927160045514368,648927163675579008,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,NULL,1,0,0,0,0,0,0,NULL,0,0,0,0,0,0,0,NULL,0,NULL,NULL,NULL,0,0,0,X'62706c6973743030d20102030453616d6353757374100009080d1115170000000000000101000000000000000500000000000000000000000000000018',0,NULL,NULL,'[email protected]',0,NULL,NULL,0,NULL,0,0,0,NULL,NULL);INSERT INTO message VALUES(8,'0D123DA5-AB98-49EF-821A-5B9BC672E461','RedAmogus#8715',0,NULL,2,NULL,NULL,X'040b73747265616d747970656481e803840140848484194e534d757461626c6541747472696275746564537472696e67008484124e5341747472696275746564537472696e67008484084e534f626a6563740085928484840f4e534d757461626c65537472696e67018484084e53537472696e67019584012b0e526564416d6f67757323383731358684026949010e928484840c4e5344696374696f6e617279009584016901928498981d5f5f6b494d4d657373616765506172744174747269627574654e616d658692848484084e534e756d626572008484074e5356616c7565009584012a849b9b00868686',10,0,'iMessage','E:[email protected]','73890C71-600D-4961-B1A7-687F2FAD3566',0,648927174089999872,648927174257075840,648927174238451968,1,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,NULL,1,0,0,0,0,0,0,NULL,0,0,0,0,0,0,0,NULL,0,NULL,NULL,NULL,0,0,0,X'62706c6973743030d101025375737409080b0f0000000000000101000000000000000300000000000000000000000000000010',0,'','','[email protected]',0,'','',0,'336CCB7F-3CB8-477A-AEED-8A4418EE7FFF',0,0,0,NULL,NULL);INSERT INTO message VALUES(9,'8F42373C-2567-4CCE-8D2A-6EBB95E5FD1D','Ok I sent you a friend request',0,NULL,2,NULL,NULL,X'040b73747265616d747970656481e803840140848484124e5341747472696275746564537472696e67008484084e534f626a656374008592848484084e53537472696e67019484012b1e4f6b20492073656e7420796f75206120667269656e6420726571756573748684026949011e928484840c4e5344696374696f6e617279009484016901928496961d5f5f6b494d4d657373616765506172744174747269627574654e616d658692848484084e534e756d626572008484074e5356616c7565009484012a84999900868686',10,0,'iMessage','E:[email protected]','73890C71-600D-4961-B1A7-687F2FAD3566',0,648927183589449856,648927183862630016,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,NULL,1,0,0,0,0,0,0,NULL,0,0,0,0,0,0,0,NULL,0,NULL,NULL,NULL,0,0,0,X'62706c6973743030d20102030453616d6353757374100009080d1115170000000000000101000000000000000500000000000000000000000000000018',0,NULL,NULL,'[email protected]',0,NULL,NULL,0,'0D123DA5-AB98-49EF-821A-5B9BC672E461',0,0,0,NULL,NULL);INSERT INTO message VALUES(10,'55C30F22-0A25-4391-BC0B-FD706018D307','We should communicate on there instead of iMessage',0,NULL,2,NULL,NULL,X'040b73747265616d747970656481e803840140848484124e5341747472696275746564537472696e67008484084e534f626a656374008592848484084e53537472696e67019484012b3257652073686f756c6420636f6d6d756e6963617465206f6e20746865726520696e7374656164206f6620694d65737361676586840269490132928484840c4e5344696374696f6e617279009484016901928496961d5f5f6b494d4d657373616765506172744174747269627574654e616d658692848484084e534e756d626572008484074e5356616c7565009484012a84999900868686',10,0,'iMessage','E:[email protected]','73890C71-600D-4961-B1A7-687F2FAD3566',0,648927208709548672,648927208949269120,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,NULL,1,0,0,0,0,0,0,NULL,0,0,0,0,0,0,0,NULL,0,NULL,NULL,NULL,0,0,0,X'62706c6973743030d20102030453616d6353757374100009080d1115170000000000000101000000000000000500000000000000000000000000000018',0,NULL,NULL,'[email protected]',0,NULL,NULL,0,'8F42373C-2567-4CCE-8D2A-6EBB95E5FD1D',0,0,0,NULL,NULL);INSERT INTO message VALUES(11,'A5BE983C-196B-48DC-B412-CE69A8B115FE','?',0,NULL,2,NULL,NULL,X'040b73747265616d747970656481e803840140848484124e5341747472696275746564537472696e67008484084e534f626a656374008592848484084e53537472696e67019484012b04f09fa4a286840269490102928484840c4e5344696374696f6e617279009484016901928496961d5f5f6b494d4d657373616765506172744174747269627574654e616d658692848484084e534e756d626572008484074e5356616c7565009484012a84999900868686',10,0,'iMessage','E:[email protected]','73890C71-600D-4961-B1A7-687F2FAD3566',0,648927219266664448,648927219586212096,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,NULL,1,0,0,0,0,0,0,NULL,0,0,0,0,0,0,0,NULL,0,NULL,NULL,NULL,0,0,0,X'62706c6973743030d20102030453616d6353757374100009080d1115170000000000000101000000000000000500000000000000000000000000000018',0,NULL,NULL,'[email protected]',0,NULL,NULL,0,'55C30F22-0A25-4391-BC0B-FD706018D307',0,0,0,NULL,NULL);COMMIT;```
That's still a lot to take in! It may be valuable to understand how this table is constructed:
```sqlCREATE TABLE message (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, guid TEXT UNIQUE NOT NULL, text TEXT, replace INTEGER DEFAULT 0, service_center TEXT, handle_id INTEGER DEFAULT 0, subject TEXT, country TEXT, attributedBody BLOB, version INTEGER DEFAULT 0, type INTEGER DEFAULT 0, service TEXT, account TEXT, account_guid TEXT, error INTEGER DEFAULT 0, date INTEGER, date_read INTEGER, date_delivered INTEGER, is_delivered INTEGER DEFAULT 0, is_finished INTEGER DEFAULT 0, is_emote INTEGER DEFAULT 0, is_from_me INTEGER DEFAULT 0, is_empty INTEGER DEFAULT 0, is_delayed```
Based on this, we can prepare a SQL query to only return data from the column "text" in the table "message."
```sqlsqlite> SELECT text FROM message;Hey what’s your Discord tagRedAmogus#8715Ok I sent you a friend requestWe should communicate on there instead of iMessage?```
Just as a quick aside, I found this to be really funny while I was doing the challenge:
```sqlsqlite> SELECT account FROM message;E:[email protected]E:[email protected]E:[email protected]E:[email protected]E:[email protected]```
[poggers.university](https://poggers.university/) just redirects to [illinois.edu](https://illinois.edu/). That gave me a good laugh.
Back to the challenge, it looks like our next target is Discord. If you recall from earlier in **forensics/Tablet 1**, we found that Discord was one of the apps on the tablet:
```sh[skat@anubis:~/.../Containers] $ find . -name "com.*" | awk -F '/' '{print $NF}' | sort | uniq -u | grep -v "com.apple"com.crashlyticscom.crashlytics.datacom.firebase.FIRInstallations.plistcom.google.gmp.measurement.monitor.plistcom.google.gmp.measurement.plistcom.hackemist.SDImageCachecom.hammerandchisel.discord - {DEFAULT GROUP}com.hammerandchisel.discord.plistcom.hammerandchisel.discord.savedStatecom.innersloth.amongus - {DEFAULT GROUP}com.innersloth.amongus.plistcom.innersloth.amongus.savedStatecom.itimeteo.webssh - {DEFAULT GROUP}com.itimeteo.webssh.plistcom.itimeteo.webssh.savedStatecom.plausiblelabs.crashreporter.data```
Let's go ahead and see what kind of data we can recover from the saved Discord application data on this tablet using the same method we used earlier for the SSH client:
```sh[skat@anubis:~/work/UIUCTF/private/var] $ find . -name "com.hammerandchisel.discord - {DEFAULT GROUP}"./mobile/Containers/Data/Application/0CE5D539-F72A-4C22-BADF-A02CE5A50D2E/Library/SplashBoard/Snapshots/com.hammerandchisel.discord - {DEFAULT GROUP}[skat@anubis:~/work/UIUCTF/private/var] $ cd ./mobile/Containers/Data/Application/0CE5D539-F72A-4C22-BADF-A02CE5A50D2E/[skat@anubis:~/.../0CE5D539-F72A-4C22-BADF-A02CE5A50D2E] $ tree.├── Documents│   ├── mmkv│   │   ├── mmkv.default│   │   └── mmkv.default.crc│   └── RCTAsyncLocalStorage_V1├── Library│   ├── Application Support│   │   ├── Adjust│   │   │   ├── AdjustIoActivityState│   │   │   ├── AdjustIoAttribution│   │   │   └── AdjustIoPackageQueue│   │   ├── com.crashlytics│   │   │   └── CLSUserDefaults.plist│   │   └── Google│   │       ├── FIRApp│   │       │   ├── FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE│   │       │   └── HEARTBEAT_INFO_STORAGE│   │       └── Measurement│   │           ├── google-app-measurement.sql│   │           └── google_experimentation_database.sql│   ├── Caches│   │   ├── assets│   │   │   ├── components_ios│   │   │   │   └── add_friend│   │   │   │       └── images│   │   │   │           ├── [email protected]│   │   │   │           └── [email protected]│   │   │   ├── data│   │   │   │   ├── country-codes.json│   │   │   │   ├── emoji-shortcuts.json│   │   │   │   └── emojis.json│   │   │   ├── i18n│   │   │   │   ├── languages.json│   │   │   │   └── messages│   │   │   │       ├── bg.json│   │   │   │       ├── cs.json│   │   │   │       ├── da.json│   │   │   │       ├── de.json-- snip --```
1,843 lines of output, and we don't really care about most of these files! Just like before when we found what we were looking for in the application's database file, let's apply the same idea here and see if we can find what we're looking for in the Discord app's database file(s):
```sh[skat@anubis:~/.../0CE5D539-F72A-4C22-BADF-A02CE5A50D2E] $ find . -name "*.db"./Library/Caches/com.hammerandchisel.discord/Cache.db./Library/WebKit/WebsiteData/ResourceLoadStatistics/observations.db```
`Cache.db` probably has some really interesting information valuable to us! Perhaps we can find cached messages or contacts. Let's load up the database and dig around:
```sh[skat@anubis:~/.../0CE5D539-F72A-4C22-BADF-A02CE5A50D2E] $ cd ./Library/Caches/com.hammerandchisel.discord/[skat@anubis:~/.../com.hammerandchisel.discord] $ sqlite3 Cache.db```
```sqlSQLite version 3.36.0 2021-06-18 18:36:39Enter ".help" for usage hints.sqlite> .dumpPRAGMA foreign_keys=OFF;BEGIN TRANSACTION;CREATE TABLE cfurl_cache_response(entry_ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,     version INTEGER, hash_value INTEGER, storage_policy INTEGER, request_key TEXT UNIQUE,   time_stamp NOT NULL DEFAULT CURRENT_TIMESTAMP, partition TEXT);INSERT INTO cfurl_cache_response VALUES(1,0,1139453470654270506,0,'https://discord.com/ios/83.0/manifest.json','2021-07-25 18:56:41',NULL);INSERT INTO cfurl_cache_response VALUES(2,0,-1441044142,0,'https://discord.com/api/v9/gateway','2021-07-25 18:56:42',NULL);INSERT INTO cfurl_cache_response VALUES(3,0,2017693604,0,'https://discord.com/api/v9/channels/868908952434384926/messages?limit=25','2021-07-25 18:56:43',NULL);INSERT INTO cfurl_cache_response VALUES(4,0,-1637691448,0,'https://latency.discord.media/rtc','2021-07-25 18:57:06',NULL);CREATE TABLE cfurl_cache_blob_data(entry_ID INTEGER PRIMARY KEY, response_object BLOB, request_object BLOB,               proto_props BLOB, user_info BLOB);INSERT INTO cfurl_cache_blob_data VALUES(1,X'62706c6973743030d2010203045756657273696f6e5541727261791001a7050a0b0c0d3839d2060708095f10105f434655524c537472696e67547970655c5f434655524c537472696e67100f5f102a68747470733a2f2f646973636f72642e636f6d2f696f732f38332e302f6d616e69666573742e6a736f6e2341c356f5b49c4a27100010c8df10150e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536375f1010436f6e74656e742d456e636f64696e675a782d6275696c642d69645663662d726179565365727665725d43616368652d436f6e74726f6c5f10195374726963742d5472616e73706f72742d5365637572697479585f5f686861615f5f5f10127065726d697373696f6e732d706f6c69637957416c742d537663597265706f72742d746f5f1010782d7873732d70726f74656374696f6e544461746554566172795f100f782d6672616d652d6f7074696f6e73536e656c596578706563742d63745c436f6e74656e742d5479706554457461675f100f63662d63616368652d7374617475735d4c6173742d4d6f6469666965645f1016782d636f6e74656e742d747970652d6f7074696f6e7354677a697057616534663662645f1014363734373963313133653630326137652d4f52445a636c6f7564666c617265586e6f2d63616368655f102c6d61782d6167653d33313533363030303b20696e636c756465537562446f6d61696e733b207072656c6f61645f11069c0d0a0d0a596e427361584e304d4444664542514241674d454251594843416b4b4377774e446738514552495446425558475273644879456a4a5363704b7930764d544d314e7a6b3758784151513239756447567564433146626d4e765a476c755a3170344c574a316157786b4c576c6b58557868633351745457396b61575a705a57525755325679646d567958554e685932686c4c554e76626e52796232786645426c5464484a705933517456484a68626e4e7762334a304c564e6c5933567961585235587841536347567962576c7a63326c76626e4d746347397361574e355630467364433154646d4e5a636d567762334a304c585276587841516543313463334d7463484a766447566a64476c76626c52455958526c56465a68636e6c66454139344c575a795957316c4c57397764476c76626e4e54626d5673575756346347566a6443316a64467844623235305a5735304c56523563475655525852685a31385144324e6d4c574e685932686c4c584e305958523163313851466e67745932397564475675644331306558426c4c57397764476c76626e4e5759325974636d46356f525a555a337070634b45595632466c4e475932596d5368476c38514856646c5a4377674d6a4567536e5673494449774d6a45674d5467364d5451364d544967523031556f527861593278766457526d624746795a614565574735764c574e685932686c6f53426645437874595867745957646c50544d784e544d324d4441774f794270626d4e736457526c553356695247397459576c75637a736763484a6c624739685a4b456958784153615735305a584a6c633351745932396f62334a30505367706f5352664546746f4d7930794e7a30694f6a51304d79493749473168505467324e4441774c43426f4d7930794f4430694f6a51304d79493749473168505467324e4441774c43426f4d7930794f5430694f6a51304d79493749473168505467324e4441774c43426f4d7a30694f6a51304d79493749473168505467324e4441776f535a66454f7437496d56755a48427661573530637949365733736964584a73496a6f696148523063484d36584339634c324575626d56734c6d4e736233566b5a6d7868636d557559323974584339795a584276636e52634c33597a50334d394f58566a52336c5661335a776348593261474e786258457862334e764a544a475448676c4d6b5a46636e685853323552556d78305a444d786358593554555a7455327733546c4931546e46745532706d534452764e6a6b6c4d6b4a6e56336c7653585a69596e4e685232566c51556f784e577333576b784552474e53576b566963304e3264335a524d4855784d554532636d704a613064505932684f544851306145394864466853626c553165534a39585377695a334a76645841694f694a6a5a6931755a5777694c434a74595868665957646c496a6f324d4451344d4442396f5368644d5473676257396b5a5431696247396a6136457158784164553356754c4341794e53424b645777674d6a41794d5341784f446f314e6a6f304d534248545653684c4638514430466a5932567764433146626d4e765a476c755a36457556455246546c6d684d4638514a337369636d567762334a3058335276496a6f6959325974626d567349697769625746345832466e5a5349364e6a41304f4441776661457958784258625746344c57466e5a5430324d4451344d44417349484a6c6347397964433131636d6b39496d68306448427a4f693876636d567762334a304c5856796153356a624739315a475a7359584a6c4c6d4e766253396a5a473474593264704c324a6c59574e766269396c6548426c59335174593351696f545266454242686348427361574e6864476c7662693971633239756f545a66454352584c7949774e3249314d6d466b4d4463305a446c6c4e5467314f4452694f5759784e6a4d304d4451354f575a6a5a434b684f464e49535653684f6c647562334e7561575a6d6f547866454251324e7a51334f574d784d544e6c4e6a41795954646c4c5539535241414941444d4152674252414638415a674230414a414170514374414c634179674450414e5141356744714150514241514547415267424d51453441546f425077464241556b4253774672415730426541463641594d4268514730416259427977484e416973434c514d62417830444b774d744130304454774e6841324d4461414e71413551446c675077412f494542515148424334454d4151304244594550675241414141414141414141674541414141414141414150514141414141414141414141414141414141414246633d5f1012696e7465726573742d636f686f72743d28295f105b68332d32373d223a343433223b206d613d38363430302c2068332d32383d223a343433223b206d613d38363430302c2068332d32393d223a343433223b206d613d38363430302c2068333d223a343433223b206d613d38363430305f10eb7b22656e64706f696e7473223a5b7b2275726c223a2268747470733a5c2f5c2f612e6e656c2e636c6f7564666c6172652e636f6d5c2f7265706f72745c2f76333f733d3975634779556b76707076366863716d71316f736f2532464c78253246457278574b6e51526c746433317176394d466d536c374e52354e716d536a6648346f36392532426757796f497662627361476565414a31356b375a4c444463525a4562734376777651307531314136726a496b474f63684e4c7434684f477458526e553579227d5d2c2267726f7570223a2263662d6e656c222c226d61785f616765223a3630343830307d5d313b206d6f64653d626c6f636b5f101d53756e2c203235204a756c20323032312031383a35363a343120474d545f100f4163636570742d456e636f64696e675444454e595f10277b227265706f72745f746f223a2263662d6e656c222c226d61785f616765223a3630343830307d5f10576d61782d6167653d3630343830302c207265706f72742d7572693d2268747470733a2f2f7265706f72742d7572692e636c6f7564666c6172652e636f6d2f63646e2d6367692f626561636f6e2f6578706563742d6374225f10106170706c69636174696f6e2f6a736f6e5f1024572f22303762353261643037346439653538353834623966313633343034393966636422534849545f101d5765642c203231204a756c20323032312031383a31343a313220474d54576e6f736e6966661200023b6e5f10106170706c69636174696f6e2f6a736f6e0008000d0015001b001d0025002a003d004a004c007900820084008600b300c600d100d800df00ed010901120127012f0139014c015101560168016c017601830188019a01a801c101c601ce01e501f001f9022808c808dd093b0a290a370a570a690a6e0a980af20b050b2c0b300b500b580b5d0000000000000201000000000000003a00000000000000000000000000000b70',X'62706c6973743030d2010203045756657273696f6e5541727261791009af101605060b0c0d0e0f0d0d0e0512131312140d1516170d0d08d20708090a5f10105f434655524c537472696e67547970655c5f434655524c537472696e67100f5f102a68747470733a2f2f646973636f72642e636f6d2f696f732f38332e302f6d616e69666573742e6a736f6e23404e00000000000010015f101f5f5f434655524c526571756573744e756c6c546f6b656e537472696e675f5f0910840908100023000000000000000013ffffffffffffffff100253474554d618191a1b1c1d1e1f202122235a557365722d4167656e745f100f4163636570742d4c616e6775616765564163636570745d49662d4e6f6e652d4d617463685f100f4163636570742d456e636f64696e67585f5f68686-- snip --```
There's a lot of data, so let's pipe everything to `grep` and find out how the tables are created:
```sh[skat@anubis:~/.../com.hammerandchisel.discord] $ sqlite3 Cache.db ".dump" | grep "CREATE TABLE"```
```sqlCREATE TABLE cfurl_cache_response(entry_ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,     version INTEGER, hash_value INTEGER, storage_policy INTEGER, request_key TEXT UNIQUE,   time_stamp NOT NULL DEFAULT CURRENT_TIMESTAMP, partition TEXT);CREATE TABLE cfurl_cache_blob_data(entry_ID INTEGER PRIMARY KEY, response_object BLOB, request_object BLOB,               proto_props BLOB, user_info BLOB);CREATE TABLE cfurl_cache_receiver_data(entry_ID INTEGER PRIMARY KEY, isDataOnFS INTEGER, receiver_data BLOB);```
Given that most of what is presumably our mother lode data are data blobs, let's dump those blobs and see what they say. It takes a bit of trial and error until we find what we're looking for in the `receiver_data` blob column of the table `cfurl_cache_receiver_data`:
```sh[skat@anubis:~/.../com.hammerandchisel.discord] $ sqlite3 Cache.db "SELECT receiver_data FROM cfurl_cache_receiver_data"7EE02011-9C66-45A1-BFE4-CB18F2251F24{"url": "wss://gateway.discord.gg"}[{"id": "868914084370866187", "type": 0, "content": "", "channel_id": "868908952434384926", "author": {"id": "868302522304053248", "username": "RedAmogus", "avatar": "f15b13e77a7fe5ef2d4b4d13be65d1dd", "discriminator": "8715", "public_flags": 0}, "attachments": [{"id": "868914084639293490", "filename": "image0.jpg", "size": 13859, "url": "https://cdn.discordapp.com/attachments/868908952434384926/868914084639293490/image0.jpg", "proxy_url": "https://media.discordapp.net/attachments/868908952434384926/868914084639293490/image0.jpg", "width": 421, "height": 421, "content_type": "image/jpeg"}], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:54:21.357000+00:00","edited_timestamp": null, "flags": 0, "components": []}, {"id": "868913936542597140", "type": 0, "content": "Ok", "channel_id": "868908952434384926", "author": {"id": "868302522304053248","username": "RedAmogus", "avatar": "f15b13e77a7fe5ef2d4b4d13be65d1dd", "discriminator": "8715", "public_flags": 0}, "attachments": [], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:53:46.112000+00:00", "edited_timestamp": null, "flags": 0, "components": []}, {"id": "868913804002607114", "type": 0, "content": "The password is ||su5Syb@k4||", "channel_id": "868908952434384926", "author": {"id": "868907394569207858", "username": "BlueAmogus", "avatar": "92f083abd028e406866677d86f4ca3d4", "discriminator": "8346", "public_flags": 0}, "attachments": [], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:53:14.512000+00:00", "edited_timestamp": null, "flags": 0, "components": []}, {"id": "868913676176994324", "type": 0, "content": "I sent you an encrypted note with all the details", "channel_id": "868908952434384926", "author": {"id": "868907394569207858", "username": "BlueAmogus", "avatar": "92f083abd028e406866677d86f4ca3d4", "discriminator": "8346", "public_flags": 0}, "attachments": [], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:52:44.036000+00:00", "edited_timestamp": null, "flags": 0, "components": []}, {"id": "868913627615363103", "type": 0, "content": "I'll deal with them, you just make sure this next sabotage goes to plan", "channel_id": "868908952434384926", "author": {"id": "868907394569207858", "username": "BlueAmogus", "avatar": "92f083abd028e406866677d86f4ca3d4", "discriminator": "8346", "public_flags": 0}, "attachments": [], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:52:32.458000+00:00", "edited_timestamp": null, "flags": 0, "components": []}, {"id": "868913576629403659", "type": 0, "content": "White is onto me\u2026 they kept calling me out last meeting", "channel_id": "868908952434384926", "author": {"id": "868302522304053248", "username": "RedAmogus", "avatar": "f15b13e77a7fe5ef2d4b4d13be65d1dd", "discriminator": "8715", "public_flags": 0}, "attachments": [], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:52:20.302000+00:00", "edited_timestamp": null, "flags": 0, "components": []}, {"id": "868913513463181332", "type": 0, "content": "Yo", "channel_id": "868908952434384926", "author": {"id": "868302522304053248", "username": "RedAmogus", "avatar": "f15b13e77a7fe5ef2d4b4d13be65d1dd", "discriminator": "8715", "public_flags": 0}, "attachments": [], "embeds": [], "mentions": [], "mention_roles": [], "pinned": false, "mention_everyone": false, "tts": false, "timestamp": "2021-07-25T17:52:05.242000+00:00", "edited_timestamp": null, "flags": 0, "components": []}][{"region":"us-central","ips":["138.128.141.109","138.128.143.75","138.128.142.25","138.128.143.90","138.128.143.9"]},{"region":"us-east","ips":["162.244.55.137","35.212.111.96","35.212.103.235","35.212.77.192","35.212.111.72"]},{"region":"atlanta","ips":["31.204.134.61","31.204.134.50","31.204.133.74","31.204.134.36","31.204.133.27"]},{"region":"newark","ips":["109.200.210.38","109.200.210.45","109.200.210.27","109.200.210.51","109.200.210.42"]},{"region":"us-south","ips":["138.128.139.7","138.128.137.12","138.128.139.16","138.128.137.190","138.128.138.244"]}]```
Great, some data! Let's toss this into a code prettifier for easier reading:
```json[  {    "id": "868914084370866187",    "type": 0,    "content": "",    "channel_id": "868908952434384926",    "author": {      "id": "868302522304053248",      "username": "RedAmogus",      "avatar": "f15b13e77a7fe5ef2d4b4d13be65d1dd",      "discriminator": "8715",      "public_flags": 0    },    "attachments": [      {        "id": "868914084639293490",        "filename": "image0.jpg",        "size": 13859,        "url": "https://cdn.discordapp.com/attachments/868908952434384926/868914084639293490/image0.jpg",        "proxy_url": "https://media.discordapp.net/attachments/868908952434384926/868914084639293490/image0.jpg",        "width": 421,        "height": 421,        "content_type": "image/jpeg"      }    ],    "embeds": [],    "mentions": [],    "mention_roles": [],    "pinned": false,    "mention_everyone": false,    "tts": false,    "timestamp": "2021-07-25T17:54:21.357000+00:00",    "edited_timestamp": null,    "flags": 0,    "components": []  },  {    "id": "868913936542597140",    "type": 0,    "content": "Ok",    "channel_id": "868908952434384926",    "author": {      "id": "868302522304053248",      "username": "RedAmogus",      "avatar": "f15b13e77a7fe5ef2d4b4d13be65d1dd",      "discriminator": "8715",      "public_flags": 0    },    "attachments": [],    "embeds": [],    "mentions": [],    "mention_roles": [],    "pinned": false,    "mention_everyone": false,    "tts": false,    "timestamp": "2021-07-25T17:53:46.112000+00:00",    "edited_timestamp": null,    "flags": 0,    "components": []  },-- snip --```
Based on this little snippet, it looks like messages are stored in a field called "content." We can throw the prettified code into a file and then `grep` it to quickly give us only the messages themselves without all the other data that comes along with them:
```sh[skat@anubis:~/dl] $ grep "\"content\":" codebeautify.json    "content": "",    "content": "Ok",    "content": "The password is ||su5Syb@k4||",    "content": "I sent you an encrypted note with all the details",    "content": "I'll deal with them, you just make sure this next sabotage goes to plan",    "content": "White is onto me… they kept calling me out last meeting",    "content": "Yo",```
Just like that, we have the messages from Red's conversation with... with whom? Let's try to get the usernames as well so that we can better understand the situation:
```sh[skat@anubis:~/dl] $ grep "\"content\":\|\"username\":" codebeautify.json    "content": "",      "username": "RedAmogus",    "content": "Ok",      "username": "RedAmogus",    "content": "The password is ||su5Syb@k4||",      "username": "BlueAmogus",    "content": "I sent you an encrypted note with all the details",      "username": "BlueAmogus",    "content": "I'll deal with them, you just make sure this next sabotage goes to plan",      "username": "BlueAmogus",    "content": "White is onto me… they kept calling me out last meeting",      "username": "RedAmogus",    "content": "Yo",      "username": "RedAmogus",```
It looks like Red is in contact with Blue, and Blue sent Red a note encrypted with the password `su5Syb@k4`. Given that Red is running an Apple system, it would be logical to entertain the hunch that this must be an Apple note. Let's try finding where these files are located on the iPad:
```sh[skat@anubis:~/work/UIUCTF/private/var] $ find . -name "Note"[skat@anubis:~/work/UIUCTF/private/var] $ find . -name "Note*"./mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NotesIndexerState-Modern./mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NotesIndexerState-Legacy./mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NoteStore.sqlite-shm./mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NoteStore.sqlite-wal./mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NoteStore.sqlite./mobile/Library/Assistant/CustomVocabulary/com.apple.reminders/0000000000000000000000000000000000000000/NotebookItemTitleType./mobile/Library/Notes```
Great, more databases! We should be familiar with the process by now, but there's an added catch: Blue mentioned that the note is encrypted. If we try accessing the database as it currently is, then it's pretty useless to us. We need some kind of parser, such as [apple_cloud_notes_parser](https://github.com/threeplanetssoftware/apple_cloud_notes_parser), in order to decrypt the note using the `NoteStore.sqlite` file:
```sh[skat@anubis:~/dl/apple_cloud_notes_parser] $ echo "su5Syb@k4" > password.txt[skat@anubis:~/dl/apple_cloud_notes_parser] $ ruby notes_cloud_ripper.rb -f ~/work/UIUCTF/private/var/mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NoteStore.sqlite -w password.txt
Starting Apple Notes Parser at Wed Aug  4 13:27:05 2021Storing the results in ./output/2021_08_04-13_27_05
Created a new AppleBackup from single file: /home/skat/work/UIUCTF/private/var/mobile/Containers/Shared/AppGroup/4DCEB2C7-5420-4446-9111-4091A929B4AC/NoteStore.sqliteGuessed Notes Version: 14Added 1 passwords to the AppleDecrypter from password.txtUpdated AppleNoteStore object with 1 AppleNotes in 2 folders belonging to 1 accounts.Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds
Successfully finished at Wed Aug  4 13:27:05 2021```
Great, it looks like we were able to successfully decrypt the note! Let's check out the data:
```sh[skat@anubis:~/dl/apple_cloud_notes_parser] $ cd output/2021_08_04-13_27_05/[skat@anubis:~/dl/apple_cloud_notes_parser/output/2021_08_04-13_27_05] $ lscsv  html  debug_log.txt  NoteStore.sqlite[skat@anubis:~/dl/apple_cloud_notes_parser/output/2021_08_04-13_27_05] $ tree.├── csv│   ├── note_store_accounts_1.csv│   ├── note_store_cloudkit_participants_1.csv│   ├── note_store_embedded_objects_1.csv│   ├── note_store_folders_1.csv│   └── note_store_notes_1.csv├── debug_log.txt├── html│   └── all_notes_1.html├── NoteStore.sqlite└── output.dat
2 directories, 9 files```
It looks like `NoteStore.sqlite` is the original encrypted note store, and `csv` and `html` are directories containing the decrypted output. Let's have a look at `all_notes_1.html` by opening it up in a web browser:
![](https://irissec.xyz/uploads/2021-08-07/all_notes_1.png)
We've successfully uncovered what Red and Blue are plotting and in the process, we captured the flag!
### Debriefing
We were initially given new information and told that Red had been communicating with another impostor; our objective was to find out who Red and this other impostor were plotting. Looking through Red's SMS text messages on the iPad device, we learned that they agreed with this new party to communicate via Discord. Looking through the cached application data from the Discord app present on Red's device, we discover that the other impostor is Blue and they sent Red an encrypted note with the password given in the Discord chat. Upon locating and decrypting the encrypted note from the device's note store, we uncover what Red and Blue were plotting.
This was great and absolutely something that I can see mirroring a real-life scenario! I can say for a fact that I've asked people before to switch from SMS to another service such as Discord since it's easier for me to type from a keyboard. I can also say for a fact that I've discovered a mother lode of data in saved application data and cached application data, and that's something you can expect from real-life scenarios as well! By understanding our situation well and by orienting ourselves at every step, we were able to much more precisely and intently execute our investigation.