Chris Vance: [Welcome to this] episode of Mobile Unpacked with me, Chris Vance. This time we are covering the meaning of messages. This is a joint Mobile Unpacked and Magnet Virtual Summit presentation. So if you’re just joining us from Magnet Virtual Summit, welcome. This is part of an ongoing series where I like to cover all things that are going on in mobile and unpack all the new stuff and show how we deal with it in the field. So if you are an already scheduled watcher, welcome back for episode two. This one is going to be our first real deep dive into some analysis fun here.
So, this month we are talking about the meaning of messages. And when I say the meaning of messages, we’re talking specifically about iOS messages. But if you are just joining us from the Magnet Virtual Summit, here is a quick rundown on who this guy is and why he is on here talking to you. My name is Christopher Vance and I’m a senior technical forensic specialist with Magnet Forensics where I’ve been for about the last seven years, predominantly earlier in the training department, then moving my way over to R&D because I like to break all the things and try to find the new stuff to help our customers and to help the community get ahead of the cat and mouse game that we constantly play with digital evidence.
I’ve spent the last about 15 years or so in digital forensics starting with the West Virginia State Police Digital Forensics Unit and Marshall University and then working my way through and eventually winding up here at Magnet where now I just get to play around and rip apart all the latest and greatest mobile OSs. And that leads me to our talk today: the meaning of messages.
Now, when we’re talking about messages, we’re talking specifically about the Messages app on iOS this time. A later series part will cover more deeply into the Android message ecosystem, and boy, that’s a doozy. The nice thing about this presentation though is that we get to consolidate down to a singular function because Apple is very controlling on what gets to use the message function and they kind of sandbox or put everything in a nice little package here inside of the Messages.App.
Now, over this presentation, we’re going to cover several different things: we’re going to talk about iMessages; we’re going to talk about SMS and MMS messages; we’re going to talk about location data from the Messages app; we’ll also talk about very important settings and preferences, how to check them, where to check them, and why checking them will let you know how to determine certain factors in your investigation. We’ll also talk about attachments and types, where they live and what they can be. We’ll talk about the new functions of iOS 16, including message deletes, recalls and edits, and how those are going to play in; as well as a nasty one that always gives a lot of folks trouble: cloud and cross-device synchronization.
Again, we’re going to go back to some very important preference files to try to get a deeper dive of this information and find out how it can cause us to have to pivot and go look at new sources of data. We’ll also talk about group threads and replies, how that is mapped out, and why, honestly, there’s a little bit of difference here, even though SMS and MMS messages and iMessages are pushed into the same database, there’s going to be some different functionality between those two. This presentation is pretty much going to cover everything you ever thought you may or may not have wanted to know about the Messages app. And we’re going to try to make sure we answer any questions that anyone has. If you have any questions during any of these broadcasts, please always make sure to put those in the Q&A section and we will get to them as soon as possible.
So let’s cover the iMessage and SMS structure and how it plays into the Messages.App. So Apple is really forcing everybody in the iOS ecosystem to use this specific application. This is our default client. Unlike Android where you can change and say, I want to make Verizon messages plus my default SMS messaging app, or if you really want to, Facebook Messenger, I guess you could? I don’t think I would want to trust that with that data, but you have that option in Android. But in iOS, Apple is that walled garden philosophy. So they’re really locking that down to the Messages.App for all of our SMS, our MMS, and our iMessages within our iOS ecosystem.
And of course we’re going to have that handle our SMS, MMS from our carrier standpoint, but then the very proprietary iMessage format. And that is going to include messaging capabilities for iOS and macOS devices. Users get a lot of customization as far as the settings go. And that little piece right there has caused me more nightmares than I care to mention in digital investigations. Mostly because those settings can control things like how long the data is actually kept and can control things like when that data is going to sync to other devices, whether it be a singular device or across devices and whether or not you’re going to get the full picture of the message. So, knowing that, we’re really going to focus on a couple of these key components because if you want to answer all the questions, you’ve got to know the right places to look.
Now, it is one consolidated database, whether we’re talking about SMS or MMS or iMessage, they put it all together into a single database file, the SMS.db. That being said, not all the preferences are going to live there. In fact, very few of them will live there. So we’ve got to go to a different area of the file system completely. There are also other data points that we have to track down that may only be available if you have a file system level extraction of iOS, but those areas are going to be crucial for recovering deleted or recalled data or finding out exactly which device sent that pesky iMessage.
So let’s talk a little bit about the SMS.db. It is our core storage function for this whole application and its location is going to be in /private/var/mobile/Library/SMS/sms.db. Now, this is included in both your standard backup-style extractions and your file system extractions of AFU or better. Sorry, this is not going to be available in a BFU or a Before First Unlock extraction. But as long as we have that AFU or better file system, or just our standard backup-style image, right? I don’t like to call those logicals.
If you saw episode one, we like to call those our backup-style images. Now, you’re going to get it, but it’s messy. There are lots of different tables to go through, okay? And having all of the records between all of those tables can be a little problematic. Now, this particular file is duplicated exactly pretty much, give or take, inside of the macOS ecosystem, only there it’s called chat.db instead of SMS.db. So it’s going to be a little bit different there, okay?
So tables, tables, tables and more tables. This specific database loves its relational tables. Apple loves to use relational databases across iOS, and this is a prime example of it, because there are seven different tables that you may have to consult just for answering all the information about a single message. And unfortunately, based on the type of message and based on what the content of that message was, it may not be so easily linked. There’s also not a lot of direct correlations between these tables. In fact, using what they call “Join” tables to intermediary link the data together between these bigger tables.
So, there are going to be four “Main” tables and three ”Join” tables that we’re going to have to cover if we really want to know everything about this. I’m not going to go through and bore you with all of the specific details of this, but I am going to hit some of the high points because recovering the full picture of the message data does require a lot of jumping through a lot of different hoops.
So, here’s the key thing when it comes to messages. Now, Apple likes to sync them, they like to sync them to a lot of different types of devices depending upon what settings that you have enabled. But the ROWIDs don’t always match. The ROWID or the primary key of this record database for the messages table isn’t always going to match. In fact, it’s very unlikely that it’ll match because, you know, we have a lot of these different syncing time issues. So, what Apple has done instead is as far as Apple is concerned, the ROWID is just for the local database. What Apple really cares about to track the uniqueness of a message is this GUID value. The GUID, or G-U-I-D, whatever you want to call it, it’s that same 8-4-4-12 structure that Apple likes to use. And every single message is going to be assigned one of these GUID values. This is going to be crucial for tracking our replies to messages, our threaded messages, and for understanding cross-device synchronization, especially when messages in the cloud is enabled.
So please understand that that value, while it looks a little complicated, is truly the unique key as far as Apple is concerned for each of these messages in this structure. And of course, Apple doesn’t make it easy when it comes to date and times, either. The messages table specifically has three dates and time columns, however, there are actually up to seven that could be used. I haven’t seen all seven ever really get used at any given time. Typically you’ll see more happening at about five for a lot of these, but in theory there are seven different timestamp tables, because you’re going to have a date, a date read, and a date delivered, but you’ll also have some additional ones down the line in later versions of iOS.
Now, these three columns: date, date read, and date delivered; there used to be older versions of iOS, a UNIX epoch, okay? They were using a UNIX epoch for that timestamp. Apple has sort of consolidated finally moving towards an Apple Time or Mac Absolute Time, whatever you like to call that, Cocoa WebKit Time, right, if we’re going to get really technical. But it’s using that January 1, 2001 at midnight start point. This particular value, however, is further complicated by the fact that even in the same type of messages, apple will mix using a nanosecond count with using a second count with decimals. So sometimes they use seconds, sometimes they use nanoseconds and sometimes they use seconds with decimal points either two, four or six. It’s annoying, it’s very annoying, but it is something that Apple does when it comes to these different message types.
Now, date and date read could actually mean different things because it matters based on the directionality and it’s going to matter on the service that’s used, what these columns are going to be usually meaning. Now, as far as an outgoing message, right, if it’s an outgoing message, the date is always going to refer to when the local device sent that message, right? It’s always going to refer to when that device sent that message. The date read for outgoing messages is only going to be present in the iMessage service and that is when the other party flagged that message as read. Now, it should be noted, and I do understand that we’re going to have some SMS providers out there through ISPs that will track whether or not it’s read, but Apple doesn’t care. Apple’s not playing nice with that. So if you’re sending a green bubble message, you’re sending out an SMS message, they’re not going to track when the other party has received via delivered or whether it’s read, okay?
And iMessage outgoing messages may not contain read only if that person has read receipts turned on. If the other party doesn’t have read receipts turned on, we won’t get a notification of a timestamp or anything that they have read that message, only that it was delivered to one of their receiving devices. The date delivered column will typically only be present when you actually see an iMessage going out. So right here on this line, you’ll see that we have an arrow pointing here and we have three timestamps being used. The only time that you’re going to see all three is when read receipts are enabled. Delivery is going to mean yeah, it got to the other party. And again, that’s going to be for iMessage only. SMS, it’s throwing it out to the void, it doesn’t know.
But for incoming iMessages and SMS, we’re going to have two different timestamps. For incoming, we’re going to have the date, which is going to be when that message hit our local device or the first receiving device, cause thinking makes this more complicated. And the date read is going to be when the local device actually opened and flagged that message as read, okay? So it’s going to make some differences. Now most of your tools are interpreting these and understanding the logic that goes in behind them, but if you ever just want to take a dive into the messages table, you’ve really got to understand that these date columns have got to have some context behind them.
Now, in later versions of iOS specifically around iOS 16, we have some other date timestamps in play. Now, for audio messages, this one’s been around for a while, but for an audio message sent to the iMessage service, there is actually a date played value, which is going to refer to when the receiver or the local party actually played that message. And that is because audio messages are going to be on a countdown timer for destruction. So that basic information is going to help it decide when it should self-destruct, right?
Then we have these time expressive send played. Now, time expressive send, this is when we have these expressive messages where you’re sending a message, like you say something like “congrats” to somebody and it automatically adds confetti, right? Or my personal favorite, you send somebody “pew pew” and it adds the space lasers effect. That’s an expressive message. And that particular data there is going to be tied to when that effect got triggered. Now, iOS 16 did add two new date columns: we have date retracted and date edited. These are for when messages are going to be recalled or edited. They haven’t actually started using both of them yet, but more on that as we get to that down the road.
Now, what about when you have multipart messages? Let’s say you’re communicating via SMS with an individual and that message is too long to fit into one message. How does iOS understand that it’s a multipart message, or, even just in some iMessages where you’re sending links and things of that, how does it bridge those all together? Well, again, we’re going to go back to that GUID value, that GUID value for each message and then there’s going to be a reply to GUID. This means that whatever message you’re looking at was a reply to this other message and it’s going to work back in a chain. So for example, this message, or five as we’ll call it, was actually a reply to message four, which was actually a reply to message three. Now, you can see here that message three was a reply to something else. That is actually going to be because a lot of times Apple will just put whatever was the last message in the chain if there’s no direct reply.
But we know this is a multi-part message because of this right here associated message GUID. So what this tells me is that this is part of a thread, a multi-piece of this particular message, and both of these track a GUID, which is part of that original source GUID value that’s in there, okay? So message four, message five, we have this associated message GUID that’s going to match the GUID of message number three. Now, as far as threads go, we talk about threads, this is a feature that was added a few versions ago. it’s a really nice feature where you can actually find a message in your conversation log. You can actually reply directly to that message. Now again, replying to that message is going to basically do the same thing.
We’re going to have a GUID and a reply to GUID, but that thread originator GUID is going to get tracked. So you might have a lapse of a day or two. And this is common. I’ll message somebody, someone will say, “Hey, what is the answer to this question?” And I’ll say, “I don’t know the answer to that. I’ll get back to you on it.” but we may continue talking about other stuff. Two days later I may have found an answer. I’ll scroll through the message and use that reply function to say, you know, so I’m not just sending random information out of context and say, okay, this is a reply to your previous message. So Apple will track that visually, we see it with these little lines and the replies here of that top screenshot, but on the bottom we know it’s actually tracked through that thread originator GUID, so it’s going to be linking all together there.
Now as I move on, we also need to talk about message reactions. This is referred to as reactions or tap back. If you are in a macOS ecosystem and you right-click on a message it’s actually called tap back. But a lot of folks just call them reactions. This is where you get to love or heart, like or dislike or laugh or emphasize or question a message, whether it be a singular message, whether it be a picture or you know, some sort of attachment. Now when you react to a message, it will actually treat the reaction as a new message. So if you react to the message of one of those green bubbles, again, what the other user is going to see, they’re not going to see the little heart. They’re actually going to see that name loved this message, and this is going to be something that’s going to let us see that through this data.
Now, what’s interesting about these reactions is that in the database they are treated as individual hits. I’ve actually found where people have deleted the original source message, but thanks to the reaction sticking around, it’s actually told me what the original message content was, so it’s actually really nice there. The issue with some of these is that you can actually remove a reaction and you can actually change a reaction. But when you change your reaction, it’s only going to keep the most recent one. When you remove an action, as you can see down at the bottom screenshot of this page, between messages 93 and 95, there was a message called 94, and that message 94 was the laugh reaction to message 93, but it gets trashed, and then we are left with message 95. And so if you’re tracking this data and looking through all the GUIDs, you’d actually see a missing gap both in row ID and a reply to a GUID that doesn’t exist anymore.
We also have, again, expressive messages and balloons. So this is where I get to send things like loud or echoes and add what they like to refer to as balloons to that data. Now these balloons are going to add some additional information in there and those data points are going to be stored as binary plists, which are saved inside of blobs in the payload data column of the messages table. If you expand that out into a property list viewer, you’ll get a little bit more information of what’s in there. This can be important, especially because there have been times where I can’t really make sense of the message itself until I dive deeper into that. And you can see on our screenshot here, this particular plist was actually hiding an address, right? So this is like sending an address for, or “Hey, join me at dinner at this location” and to actually see all of that information, you can kind of see how Apple is storing it inside of there.
There’s that time expressive send plate again as you see there in the top screenshot relating to that one we talked about earlier. But what about Siri? I’ve gotta be careful there, of course I don’t want to activate it on all my devices, but if I want to send a message with You Know Who, then all I have to do is say, “Send a message to this person” and they’ll say, “What do you want it to say, and then I can send it out.” Anytime that I use that function it’s going to create a record inside of a binary plist embedded inside the message summary info column, and it basically says “com.apple.siri”. Now, if I’m looking at my device, I can see an incoming message will say, “Sent by Siri”, but I can’t see an outgoing message saying that, but the database tracks for both incoming and outgoing regardless of what the UI is showing us. So that is a nice thing.
So if you’re working something like a distracted driving case and they say, “Well, I didn’t send that text message, I used You Know Who, my voice assistant to do that.” we can actually go back and track that and see if it triggered that sent by You Know Who function; that’s to keep all of our Apple watches and devices from activating right now. So this information is a little bit buried. Most of your frenzy tools are going to pull this out for you, but you need to understand how to validate it. That’s that key that they’re looking for that com.apple.siri data inside of that plist.
Now, group threads can get a little bit more complicated. Now, group threads, you’ll actually notice that your outgoing message column will show a handle of zero, but I’ve never really seen a database use row zero for a lot of primary keys. And this is just because it doesn’t use just this one link. Remember I said that iOS loves its relational databases and this is where this really comes into play. There’s no direct link between the message table and the chat table. And in fact, we have to go and use one or two of our joint tables to match up all the different people that were part of a group thread and all of the messages that were sent to that group thread if that handle ID is going to reflect zero.
So to do that, we actually have to find, you’ll see in the top part of our screenshot here, we have a chat ID, a primary key in the chat table. We see in there that this is our, sorry, this is our join table for our chat message join, and our chat ID matches up with our message ID. So what this means, let’s look at the top one for example, message number 11 as identified by chat ID, well it was part of chat 11, but the message was message number 107, okay? And that chat ID 11, it was a standard SMS, we have some information in it and it is actually linked to the handle table by that other join table where chat ID 11 was handle ID 11 and handle ID 11 goes out to our handle table to tell us it’s this person 1299990583, right? The SMS function there.
Lots of pain there when it comes to this. And the reason I really harp on that is that if your tools are carving this data, it’s very likely that you may find a message that you can see the content of the message, you can see the dates and times of the message, but you have no idea who it went to because that handle ID can get destroyed and you’re just left with not having all the pieces of the puzzle, right? So, it’s very common to see that inside of our devices.
Now, attachments also have to be tracked and dealt with kind of in the same way because attachments are not really saved in the way that we always think they are. The database itself doesn’t actually store your attachment. The database only stores information about the attachments, when they were sent and what message they’re related to. But again, there’s no direct correlation between a message and an attachment. There is another join table that’s used to join the messages data and the attachment data and link that back together. Again, very big issue sometimes when that link gets broken of carving all of that data out.
The actual attachments themselves are stored over in private/var/mobile/library/SMS/attachments/, and here’s the key: for MMS messages, it’s got to be a multimedia file. So we’re talking a picture, a video, an audio file, right? I can’t send a PDF through that. But for iMessage there is almost no limitation of file type that you can send via iMessage. If you’re not manually reviewing your attachments folder to see what files are in there, I highly recommend you start doing so, because I have found zip files, I have found torrent files, I have found encrypted files all saved in there. Heck, I have even myself sent myself an EO1 image from one computer to another using the iMessage protocol cause I couldn’t find a thumb drive. So it definitely works. Apple doesn’t put a lot of restrictions on the file types that can be sent via iMessage. Definitely make sure you’re checking a look at that and dig in just a little bit deeper.
Now, the names of these attachments can actually give us a lot of context, right? I love saying context not content on this one, but this is one of those where I can get a lot of context. So files from our camera roll are going to have that typical IMG_name in the database. If you have a file in the attachment and it reflects a totally different numbering scheme than what you’re seeing in the camera of your device, we can tell if it’s an incoming or outgoing, but it might be a good way to say, oh that’s from this device and then we can actually go and match that in another area. If this is an attachment downloaded from online or downloaded from another location, again, it keeps its original name. It only gets renamed when we save that attachment from the actual messages into our camera roll. So if I save that, it’s going to go down a little bit differently.
The other issue to realize is that if I’m taking a picture directly, if I’m taking a file directly from there, it’s going to have a different name than the camera roll. So if I take a picture and then I attach it to a message and I send it, that’s in the camera roll. But if I open up the messages app and I use the built-in camera through the picker function and take a picture and it gets sent, it doesn’t mean it gets added in my camera roll and it can actually have a different name, and again, bring us some context into how that was generated.
Locations. man, oh man, locations are another one that we can share. Now, location sharing is a little bit different here. We can send this in a couple different ways, but really when you share your location, it’s very different than sending your location. If you share your location, you’re actually handing that service off to the find my service and saying, “Find my, go deal with this. I’m not being bothered.” But if you send an individual your location, it takes a one-time drop of that location and it actually sends it to you, the user, where they were at according to GPS at that given moment. It does that by actually sending a .vcf file.
We all often kind of refer to these as V-card files, right? But it sends a .vcf file to that other individual and it’s always named CL.Loc: current location.location, right? So that V-card file is going to store a Maps URL, Apple Maps URL with the latitude and longitude of where it was taken. So if I send that, that’s going to be some good kind of historical location information. And my favorite of this is when someone says like, “Hey, where are you at?” and Apple gives you that nice little like autocomplete fill in, “Oh, I’m right here.” *click*. And I’m like, “Thank you for confirming that you were right outside of our crime scene at that point in time. Appreciate it.” So that information can be really handy in a case. Definitely make sure you’re looking for those.
Now, I talked earlier about preferences and there are a ton of them, a ton of them to look at. Here’s this short list. Now I invite you to screenshot this, but I’m also going to tell you that we’re putting out a blog post that’s going to lay out some of these files and what you can expect to find in them. But I know everyone, some people like to just print off a quick screenshot, so feel free to do so. Now on these me message preference files, there’s a couple of things that we want to track. So, let’s say you want to know if the person has read receipts turned on, then we have to go to this com.apple.madrid.plist in the preferences directory. So, /private/var/mobile/Library/preferences/ and then /com.apple.madrid.plist.
This is going to allow us to track more than just what I’ve listed here, but these are the highlights. Read receipts, if they’re turned on globally or not. Here’s the biggest one: is iMessage in the cloud or messages in the cloud as it’s actually called now, is messages in the cloud turned on or off? That’s a huge one forensically speaking cause it’s really going to change where your data gets stored in a lot of cases. And also list out any other aliases the user may have had like other Apple ID email addresses or even other phone numbers that might be tied to their Apple ID account. Within that same directory, we also have /com.apple.messages pinning .plist. And this is related to a newer feature from a couple of versions ago where I can actually pin a conversation or just a single user to the top of my messages with their little picture and then I can actually just see them and click on them. So really handy for like if you have a chat you always go back to, you can just click on that and jump back into it.
But it’s really good to know because for me it’s kind of like using the favorites and the dialer. It’s like, who do they really care that they’re talking to a lot, they’re going to pin them to the top of their message application. That’s going to give me a lot of context about that. Then if we have the /com.apple.mobileSMS.plist, and this is a doozy, I told you that sometimes they can actually determine how long your data’s kept. And this is one of those files that does that. There is actually a value in /com.apple.mobileSMS.plist, which says keep messages, and this is going to be set for either zero, 30 or 365. However, if you go look in this file and you see nothing in there about keep messages linked and you’re thinking, “What was Vance talking about? That’s not in there.”
No, it’s there, but a lot of times Apple doesn’t populate a plist file with certain default values. I guess to save space they make some assumptions. If that key’s not there, they just know to keep them forever. If the user has ever changed that function, it’ll either be populated with zero, 30 or 365. Now, the two options that you can save in there are 30 days, 365 days. And then of course you can also say just always, keep always. If it’s set as keep always it will reflect zero. But seeing that key means they had changed it to something and then they changed it back to keep forever.
We have /com.apple.sms.plist, different from /mobileSMS. Why do they need five different preference files that refer just to messages in the same directory? I wish I knew half the things that Apple did, to be honest with you. But this particular file is going to track SMS forwarding. Again, another big one if you’re trying to figure out how this message got to this device. This is going to mean that if you’re looking at a cellular device, you can actually look to see if there are other devices that this got sent to, like a MacBook or an iPad that don’t have the same cellular service. And then we have /com.apple.cmfsyncagent.plist. Why is it called cmf? I don’t know. But what its function is it actually is going to hold people that you have blocked. So if a user has blocked an individual, we can actually see that in here.
I’ve seen this in a couple of cases basically saying, you know, I wasn’t getting their messages because I had them blocked. We can actually go in and see that and actually see, yep, they did, they had them blocked, that’s why they weren’t getting the messages. That’s why they appear on one person’s phone, but not both phones, just because they were being sent, they were never being actually received by the other individual cause they had them blocked. So that’s a good way to track that and this, you know, to try to figure out why do we have a difference in two different devices of the same conversation? And, you know, where those messages are. Were they deleted or did they not get sent to the other device really? Cause when you block somebody, it doesn’t really tell you that they’ve blocked you, right? The messages go out into the ether.
Now, I have to make fun of my green bubble friends, my Android friends here for a second because this is where we’re going to dive deeper into the iMessage function of iOS, because blue bubbles get to have more fun than green bubbles. if you are a blue bubble or iMessage user, you get to have a little bit more functionality. Now, some of these functions that we’re going to talk about do not track or SMS or mms. It’s only when the iMessages function is used, do these things actually come into play. So just a little poking fun there at my Android friends. The iMessage messages are going to allow for a lot of different features and they have their own forensic traces to deal with.
So things like actually trying to edit a message, recall a message, those are not going to cross over to the green bubbles. Those are a blue bubble-only area. I can’t send any file type with green bubbles. I can’t, you know, do some of the same location data with a green bubble. It’s a little bit more restrictive, especially when it comes to group conversations. And speaking of group conversations, you will typically find that you have a standard group thread, which is treated as an MMS or you will have an iMessage-only thread. When it is an iMessage-only thread, there are more functions that are available to the end users and more forensic traces for us to find. So if it is a group, you’ll actually see things where if someone tries to change the name of the group, someone tries to change the picture relating to the group, you’ll actually get a text row ID row inside of our message data and the actual content’s going to just be null.
And the handle ID is going to reference who did it, right, who actually made this change, and our item type column in here is going to be for when I rename the group, while our group action type one is going to be for when I change the picture. And there are still some other ones that we’re mapping out, but those are some of the ones that we’ve seen so far. So, for example, in our top screenshot, you can see that group title changes about halfway down, its item type is referred to 2. And that is because whoever handle ID 4 was, they actually changed the name from, you know, nothing to moving company. And then the next record is them actually adding a picture to that. Now, that picture that they add, so if you add a custom picture to this, we can actually recover that and it’s going to be in /private/VAR/mobile/Library/MessagesMetaData/. So, first time outside of just like your attachments, we’re getting outside of that data altogether. So, /private/VAR/mobile/Library/MessagesMetaData/ to actually see what those pictures they saved were and get a little bit more context around those pictures.
How about inviting or leaving a group thread? Because once you have at least, you have to have at least three or more members to a group. If you only have three, you can’t actually leave a group, but if you add a fourth member to the group, then you can leave the group. But once you have these group threads going on, you’ll actually see some UI hits in there. You can see this here in the top and the bottom where a user added other users and then they left the conversation. When a user adds someone to the group, the handle ID is again going to reflect whodunit, as I like to say, and then our item type is going to reference people either being added or people being removed, leaving that group. So, if you are on an iMessage thread with 50 different people and you know, 50 different blue bubble users and you leave, it’s going to leave traces in all those other databases that you left. This is, you know, again, a common thing when someone says, “Oh yeah, so and so added me to that group message thread that was, you know, break into the bank. But I never did it, you know, I left it immediately.” No, you didn’t, you just tried to delete all your messages. So, lots of good context, we can recover there.
You can do this in a one-on-one message, but I see this a lot more when it’s a group message. You can do an @, sort of like Slack or teams or emailing say @suchandsuch and then kind of get their attention. When I do this, it’ll actually put their name, their contact name in there and then that data gets shoved into a binary piece of information inside of a blob called the attributed body column of the messages table. And this is actually going to reference basically the alias that was mentioned in that chat. So in this, if you’re trying to add that, this is where they’re going to store that data and it should give that person that you added with that a little extra notification, you know, that you’re trying to get their attention. Especially for group threads, people might have it, you know, silenced where it only gives them a notification when they are directly mentioned. So this is how Apple’s going to track that.
I mentioned audio messages earlier and this is another iMessage-only function, but audio messages are going to be where you can actually send a clip of your voice back and forth. This is crucial for certain cases and I’ve personally dealt with this, but there’s a big problem with audio messages. Audio messages are said to automatically expire two minutes, two minutes after they have been played. Now, what causes them to get played? You can either hit the play button or raise the phone to your ear and that’s going to cause that to get played. When you do that, it is actually going to start that process and you’ll have a date played, gets added to our database and then eventually when it’s done, it blows up.
Now, you can save these messages, you can actually save a message. However, when you save a message, both parties are going to be alerted that you decided to save that message. So if you’re trying to just save a message and not let the other person know, it’s a little bit harder to do. You can however effectively turn on a setting in your phone under /private/VAR/mobile/Library/Preferences/, this /com.apple.imessage.plist/ see, another different preference file for iMessage and messages that’ll actually track whether or not you have this enabled. You’re actually looking for the key, automatically save audio messages enabled and that basically means that it will permanently save any of these AMR files to your attachments without so many notifications to the other user. So, one investigation I did that was, you know, the way certain individuals were communicating and when we put somebody in that investigation we had to make sure that setting was turned on before they went in so we could get and keep all of those records without alerting everyone and we were actually keeping them. So, definitely make sure if you’re seeing audio messages that are older than that, that’s going to be the reason why.
All right, so what about iOS 16? Cause gave us a lot of new artifacts when it comes to iMessage. It actually added new specific abilities just for iMessage and that’s going to be for our editing or recalling or unsending a message. And both of these went through several different iterations during the beta process. Apple got a lot of pushback, feedback, whatever you want to call it on both of these functions. You know, the editing function was giving some people issues about how you could basically say one thing, someone reacts to it and then you change and say, “Oh, I never said that.” and then of course recalling a message, you know, taking messages out of context, as well. So, how do we know if somebody edited messages, recalled a message? Like, what can we track with that? But then they also added new ways to handle deleting messages, sort of like the photos function. If I delete a message, if I delete an entire thread, if I delete a single message, it actually doesn’t delete anymore, not at first, and it actually makes it a lot easier to recover unless the person knows what they’re doing.
So first off, message recalling. From the UI, they will basically see a tiny message that says, so-and-so unsent a message. And that means that I sent a message out, decided I don’t want that data saved, so I’m pulling it back. Very different from the first versions of iOS 16 in the betas, but in the final release you got two minutes, two minutes just like our audio messages to do this. After two minutes, you will no longer be able to recall that message and you will not be able to pull it back. But if you react within those first two minutes, you can actually recall that message, it sends a notification over to the other person’s device and purges it from their iOS device for macOS device. So, definitely can be a bit of a concern. So, you’ll see that under that sort of long press menu or right-click menu, you’ll actually see an undo send option.
Now, when a message is recalled, the row is actually still present within the database. The content of the message is destroyed from the text column. So, you’ll actually just basically see it blank itself out. And this is both for your source device and your destination device. Both devices, if the recall goes through it gets completely blanked out. You can still see that a message was sent, you can still see some contextual information that you’ll be able to determine that this is a recalled message, but you can’t see the content from here. A little bit of a problem there, right? So, this is going to be an issue if the only thing I have available to me is a backup-style image.
But can we recover that data? Well, yes we can. And this is the really nice part: if you have a file system level extraction of that iOS device, you can recover the original text of a recalled message. There’s actually two different locations you can look. One of them is the KnowledgeC database as part of the App Intents and the other area is part of a BIOME or App Intents or the user notification events. Now, these do keep for only a certain amount of time. So anything over 30 days and you’re really running a risk of not getting that data, very unlikely that you’ll get that data after about 30 days. But the key is that I can still get it if I can get to the device fast enough.
The issue that I noticed in my testing is that I did this multiple times and sometimes the KnowledgeC record was destroyed after I recalled the message, but the BIOME records for App Intents never seemed to get touched. It never seemed to get touched, there was nothing that went back and destroyed that in there. So that was good for us. We were actually able to still recover that data. You can kind of see some examples here on our screen. This is our actual content of a message. You can see the body there of the message and you can know who the sender was, who the recipients were, when it was sent. Lots of good data there. And depending upon where you’re getting it from, there might be more or less data, but one of those recalled messages, well that was that.
Now, interestingly enough, if your recipient actually has a device that is pre-iOS 16 or a Mac device, pre-macOS 13, they’ll see something very different. It won’t do anything. It won’t purchase the record at all from their device. There’s no functionality built into those older versions. So, you’re not going to see this as much with iOS 15. I know there are some holdouts there, 15.7 for folks, but, you know, iOS devices do tend to be on a faster upgrade cycle. Mac devices, however, if people are out there running pretty much anything, unless it is macOS 13, Ventura they’ll actually see the still content to the message in that database. Nothing will actually get redacted or recalled at all. Now, the sender of that who tries to recall the message will get a little pop-up notification in the message. The person may still see it if it hasn’t been updated, okay? So a little bit of fun stuff there makes those older devices that may be hanging around on the account even more important for getting that recalled information.
Now, message editing was another one that went through a couple of different changes, but we got to the bottom of it. Like the recalling, it is time-based and you get 15 minutes for editing, you only get 15 minutes versus two minutes. So it’s a lot more. But the nice thing here is that in that 15 minutes when I edit a message, it actually tracks every single message that I send. So if I edit that message 10 times, it’s going to hold all 10 of them in there. It can be edited basically pretty much as many times as you want, as long as you’re within that 15-minute window and each edit is tracked individually and saved. You can’t completely blank it out, either. I’ve done it where I’ve blanked it out and put a few spaces, but then I can just type, you know, the other button and see all of the other edits, so you’re still going to be able to see everything. And the database itself, the text column appears to be destroyed and you’re like, “Oh no, we can’t recover it.” Well, we can, because the latest message gets stored in that attributed body column similar to our @ mentions.
But every single message as part of that edit structure gets stored over in a binary plist. And that same one, that message summary info that we found are sent by Siri data. It’s just under a different key and it gets a timestamp of when that edit took place. And you’re going to see all of that information. So here’s an example here. As you browse through that, you’ll eventually get to this little plist file embedded inside of a database and then inside of that is another blog record, which will actually track that data. You’ll have a date and time recorded and actual content to the message. So, really nice way to track that data back and, you know, recover that info.
Now, when I delete a message in iOS 16, no, you didn’t. Because when you delete a message in iOS 16, really it just starts a 30-day timer. It actually hides this message from the user but still makes itself available if you go and know where to find it. The database itself is unchanged for that 30 days. What happens is a new table has been created and that new table effectively references and says, “Okay, these messages were flagged for deletion on this date” and 30 days later, then they’ll actually purge themself from the database. So it’s really handy for folks who, you know, if they’re maybe not the most savvy, they’re going to delete a bunch of messages before they go in to talk to somebody. But, unless they do it twice, the date is still there, right?
This new table in the record database is going to basically just show us, it’s going to keep a good track of what was recently deleted. It’s really nice to have. But the best part about this is how Apple’s made it a little bit hard to find. In order to actually see these deleted messages, I have to first go to my message main home screen, I have to hit the edit button, then go down and say show recently deleted, then select my messages and permanently delete them. I like that it says 30 days, but even Apple says, “Hey, it might take up to 40 days.” And it’s just their way of saying, “Yeah, we’ll get to it when we get to it.” This is one of those times I’m totally okay with it because more time for us to potentially recover that information.
So, where else? I know I’ve covered a ton about messages and we’ve talked a lot about the database itself, but where else can we look? And we mentioned this earlier with our message recalls, but where else can I go if the message is not in the wall file, it’s not in the main database? Where do I go to try to recover these, you know, the guy was smart, double-deleted the messages? The KnowledgeC database actually keeps a track of a lot of messages on your device. Not because Apple is keylogging it so to speak, but they are tracking what they refer to as an application intent.
And this application intent is very important to us forensically because it actually stores copies of the message, dates and times and the participants inside of it. But it’s not as simple as just opening a database and looking at it. Within a single table. you have to find this Z_DKINTENTMETADATAKEY_ SERIALIZEDINTERACTION mouthful. And you’ll see that it is a binary plist file. Inside of that binary plist file, there is another embedded binary Plist file. Inside of that layered binary plist file, there is a Protobuf inside of that Protobuf, there is a message content. So all of that has to be done to recover that data. So if your tool’s doing this for you, fantastic, great love to see it. If not, and you want to dig down to try to find these records, you’re going to have to go through all of these chains. Now all of that is totally possible just using something like Cyberchef and SQLite Database Explorer, but you’re really going to have to know where to go to find all that.
So, here’s an example of that. This is that second layer plist taken. And so this is basically we’ve gotten to the step of found the blob, extracted the plist, extracted the plist inside of that. And you see some basic 64 encoded data, which is actually just a base 64 encoded Protobuf. Running that Protobuf through good old Cyberchef shows me that we can actually see the content of the DA of the message, the service, the number that was used in even the dates and times in there too. So lots of good information for us to see, as long as you know what you’re doing and how to parse it all out. Now, KnowledgeC is good, but what we found is that KnowledgeC would sometimes get retracted. When I deleted messages, when I recalled messages in some of my testing, Apple was like, “Okay, we’ll reach into KnowledgeC and get rid of those.”
They didn’t always use to do that. But it seems that more lately they’re trying to do a better job of removing those records from KnowledgeC. Where I found that they didn’t really do this was the BIOME data. Now, Apple’s BIOME folder is still a bit of a mystery. It seems to be tied to certain suggestions like Siri Kit. There are a number of functions here that the BIOMEs are tracking. And if you join us next month in March, we’ll be episode three of Mobile Unpacked, we’re actually going to explore all of these BIOME structures and files even deeper. So hopefully you’ll come back and see us for that. But I want to give you kind of a quick rundown of some of the key ones that are going to play into your messages here.
Now, these BIOME files, they are, we’ve kind of come up collectively in the forensic community and call them a segB file, it’s because it’s a header they use. But that binary file, that segB file, stores a bunch of Protobufs. And inside of those Protobufs you’ll find a binary plist. And inside of that plist, you’ll find another binary plist. And inside of that binary plist, you’ll find another Protobuf. And then you finally get down to your actual message content. So, really having to dive multiple layers deeply, or you really want a tool looking can automate this process for you. But this is going to give us the ability to recover potentially deleted messages. Messages that just, you know, were recalled and are not there anymore. But I’m super excited to say that this is going to give us even more context now.
So, how do we know who did it? A question that vexed me for many years of doing forensics and doing digital investigations was, which device actually sent the iMessage, or for that matter, the SMS message, right? Because the GUIDs are going to be the same across the devices. And every time I thought I had it figured out, like, oh, well the timestamps are a little bit off, or you can tell because their IDs are in a different order, something would change and, you know, it would be harder to determine. And it was easier when you would have these chunks of messages sent. But if you had something where someone’s sitting on a Mac and then they’ll be replying from the Mac one second using their phone another second, and then going back to the Mac and then going to the iPad, it became a mess and you couldn’t really track it. So how do we actually make these determinations? How can we actually figure out, was the message coming from inside the house or the phone in this case?
So, first off, we have to figure out what messages sync, because if the messages can’t sync then we know a little bit more about them, right? So first, got to understand that all iMessages are going to sync across any iOS device or macOS device as long as they’re signed in with the same Apple ID. But it can also be as part of the cloud as well with that message and the cloud feature. SMS MMS messages can sync from a cellular device to a non-cellular device under two settings. One, they have call forwarding enabled. Now, that’s not going to be every message ever, right? They do need to typically be in a close proximity for that to work, and then you actually will have just the messages in the cloud function. If messages in the cloud is turned on, all messages are going and actually getting backed up once they’re sent and received by the cellular device to the cloud, who then distributes those messages a little bit deeper.
So, I like to kind of use a flow chart. First question I ask myself, am I looking at an SMS message or I’m looking at an MMS message or an iMessage, right? If it’s SMS or MMS, I have to think, well, was call forwarding enabled? If no, then it’s only going to be present on the cellular device, right? If SMS forwarding is enabled, well then we’re going to kind of have that same path as you see below it. So, is it an iMessage? I always ask myself the same question: is messages in the cloud on? And honestly you could put a line from is SMS forwarding enabled down to is messages in the cloud enabled? Because both of those are going to come and fall into the same category. If that forwarding is on, you’re going to have copies of that saved over on the other devices, in theory, they’re not maybe always going to be there, especially for like offline devices.
But if iMessages in the cloud is on, then pretty much all your messages are going to be sent across all your devices. And if it’s off, well then they still may get synced, like, iMessages are always going to sync, but it’s going to be very asynchronous, meaning that the message might get synced, but if I delete it off one device, it may not automatically delete it from another.
So, how do we know the message was coming from that device? SMS only on non-cellular devices if forwarding or messages in the cloud are enabled, okay? iMessages are going to sync as long as they’re signed up with the same Apple ID. But here’s the key, here’s the one that’s kept me up at night that really kind of answers the question. It’s the BIOMEs and the KnowledgeC that are going to give me that information, because the data, if it’s a synced message, what we found in our testing, what I’ve ripped apart, phone after phone after phone, the data doesn’t end up in the BIOMEs. Only the data that I send from the device ends up in the BIOMEs for that device. And if it does end up over in the BIOME area, maybe not in the same area that I normally look, we can track that it’s coming from a remote device as well.
So here’s an example of this. This is a conversation where the user started on their MacBook, all the messages flagged in gray, where then sending them from their MacBook and then all of a sudden they jumped over and the last message was actually sent from the iPhone. Now, both of these were taken from the actual iPhone, okay? Taken from the iPhone. And what you notice is that there’s a gap. So if you look at the second screenshot, which is coming from one of those BIOME segB files, you see that it kind of jumps from yeah and then, but those NFC keys were a pain to, ooh, there’s some missing data there. Now, the database has that because you know, it says my new toy might be a good answer for you. The flipper’s 0.1. You know, there were three little messages that were sent there that are not present in our BIOME and that’s because they were sent from a different device.
Only the messages that I send from my device are going to show up in the BIOME. Now, received messages still get populated into the BIOME, right? Received messages, it’s still going to be difficult, they’re still going to get synced. But those messages that I’ve outlined in an arrow in blue, those are the ones that are sent from the local device. So that, plus it works for RFID 2, was actually sent from our local device, the phone, not the MacBook in our case. So that’s how we’re going to do it. We’re going to actually check and compare records recovered from the SMS database to compare those over to that BIOME area from App Intents or our KnowledgeC data as well for App Intents, right? Really we’re looking for App Intents. That seems to be the greatest place to look for that. It’s really, really handy to actually pinpoint which device is responsible for it.
And inside the BIOMEs, Apple really is using these a lot with iOS 16, they’re heavily utilizing these. Certain BIOME folders are now putting a separation between local and remote. Local are going to be basically events that took place on our local device, but then they’re also tracking things that are getting synced from other devices but categorizing those as remote and each device is assigned its own separate good value. So, if we do eventually see some of that data get synced over through the BIOMEs, thanks to the remote folder, we’ll be able to track where it actually originated from. Did it get generated on our device? Did it simply get synced over on our device? And this is going to be true for a lot of our BIOME data, which is going to be super handy across multiple new artifacts that we have coming out that focus on this BIOME subdirectory. Cause boy, it’s a great, great place to look for data nowadays especially with iOS 16.
So, who did it? Step one: check for your forwarding, check for your message in the cloud settings to understand what could or could not be synced. Step two: compare your data recovered from the database with the BIOME or KnowledgeC. Again, KnowledgeC is going to be more heavily used pre-iOS 16, but BIOME is going to be a lot more heavily used iOS 16 and higher. Local messages will appear there, synced messages will not. Meaning that if it’s in the biome, it was sent from that local device to all of our testing that we’ve done. And a great way to find that and kind of help your cases out with that one answer those weird questions that we often get asked.
So that was a lot when it comes to our message data. A ton of information to cover and just a little bit of a time to do it. So, I’m sure there are probably going to be a lot of questions. If you have any of those, please feel free to drop those as always in the Q&A box here on our platform and we will get those answers back to you as soon as possible. Covering a lot of different time zones, so it may take us a day or so to get through those and get them received and get them back to you. But we want to see them, we want to respond to them, we want to answer them. We are hoping to get a blog post out or at least a little cheat sheet, which gives you a better way of seeing some of those preference files very soon.
So keep a watch on the Magnet website for that. Feel free to reach out to me directly at any point in time and I really hope that we’re going to see you back here for the March presentation of Mobile Unpacked because that is where we are going to deepen our knowledge of the BIOME data. We’re going to break down those segB files and we’re going to really explore how they’re being stored, structured and what goodies we can get inside of them. Until then, and all of my MVS viewers, thank you for joining us. Hopefully we’ll see you back too. But until then, see you next time. Thanks.