Mo’ SIMs, Mo’ Problems. Examining Phones with Dual SIMs.

This is the second time this song has appeared on the blog. 🙂

I love getting questions from people. There are many times when I am not completely sure of the answer and other times when I have no idea. Regardless, getting questions will always cause me to go dig for the answer. I was recently asked a question that was a result of someone taking FOR585: what was the last number used on an iOS device? That question could be interpreted in a couple of different ways; however, my mind went to a phone with dual SIMs because my personal phone has a physical SIM and an active embedded SIM (eSIM). So I started digging into my iPhone backups and some new Android 13 data that was available.

eSIMs have been around commercially since 2016 when the Samsung Gear S2 smart watch was released. AppleWatch Series 3 and the Google Pixel 2 followed in 2017. Fast forward five years and many Android and iOS devices are dual-SIM capable by way of one physical SIM and an eSIM.

eSIMs are easy and make it trivial to add a second number to a phone. Simply sign up for service on a website of a cellular provider by providing a bit of information about the phone, and the eSIM downloads directly to the device. A few more button pushes and the phone has cellular service. No traveling to a store to pick up a SIM card, and no waiting for a SIM to arrive by mail. There are several cellular providers that offer their services via eSIM: Google Fi, Visible (part of Verzion), Mint Mobile, Boost Mobile, and more. There are several providers outside of the U.S. that do the same. With the ease of use of eSIMs and more people working remotely, I anticipate the amount of phones examiners encounter with dual phone numbers will increase over time.

While this post will be shorter than most I write, it will cover both iOS and Android. For the latter, I used the recently-completed (but not-quite-done-with-documentation) Android 13 public image, and, for the former, an encrypted backup of my personal iPhone 12 Pro (running iOS 16.1.2). The Android had Google Fi as its primary number/physical SIM and Visible (part of Verizon) as its secondary number/eSIM, and the iPhone had AT&T as its primary number/physical SIM and Google Fi as its secondary number/eSIM.

iOS

iPhones have had dual-SIM capabilities by way of an eSIM since 2018 when the XS and its larger sibling were introduced and iOS 12.1 came around. iPhone has had dual-SIMs since so most iPhones examiners are going to encounter are capable of having two phone numbers.

iOS is very subtle about how it handles documenting which phone number received/made phone calls, and it took me a bit of digging to find the pertinent data. The first place to look is at the call log itself, CallHistory.storedata, which is found in private/var/mobile/Library/CallHistoryDB/. This file is available in a full-file system and in an encrypted backup. The file is a SQLite database, and the table containing the call logs is ZCALLRECORD. The column of interest is ZLOCALPARTICIPANTUUID. Figure 1 shows the call log from the iPhone 12 Pro. The last used number (Google Fi) is highlighted in red, while the last call is highlighted in blue. Note that the offset for my current location is EST (UTC -0500). Figure 2 shows the call’s entry highlighted in the blue box, along with the column ZLOCALPARTICIPANTUUID highlighted in red. See Figures 1 & 2.

Figure 1. Sample Google Fi call from the Call Log.
Figure 2. Same call in CallHistory.storedata.

The important part of Figure 2 is the BLOB data which is in the right pane in Figure 2. This 16-byte value was consistent across all of my historical calls that were made/received by the Google Fi number. Calls made and received on the AT&T number had a different 16-byte value. Figures 3 and 4 show an example of a call on the AT&T number along with the relevant portion of the call log.

Figure 3. Sample AT&T call from the Call Log.
Figure 3. Same call from Figure 3, different 16-byte value.

As with the Google Fi number calls made/received on the AT&T number consistently had the same 16-byte value. So what does this 16-byte value represent and where does it come from? After scouring through my backup up a few times and a fresh set of eyes courtesy of Ian Whiffin, the answer presented itself. See Figure 5.

Figure 5. Those are not 16-byte values! No idea on those time stamps, though.

The file com.apple.commcenter.data.plist has the answers. It is available in an encrypted backup and is located in private/var/wireless/Library/Preferences/. As it turns out the 16-byte values are actually the UUIDs for the SIMs (red boxes). The UUIDs seen in Figures 2 and 4 (in the red boxes in Figure 5) are associated to the correct phone numbers (“mdn” values – redacted by the purple boxes in Figure 5) and ICCID numbers (redacted by the green boxes in Figure 5). Also note that the type of SIM is also described in this file (blue boxes in Figure 5). Again, my Google Fi number is an eSIM whereas my AT&T number is a physical SIM, so the data here makes sense. As a side note, Google Fi is a Mobile Virtual Network Operator (MVNO) and one of the networks it leverages belongs to T-Mobile.

The rest of what we know about call logs in iOS remain true. Messages, as it turns out, are easier, and more explicit, since the number of the account used to send/receive messages is all in the same database, sms.db, the same table, message, and same column, destination_caller_id. See Figures 6, 7, and 8.

Figure 6. The chat. Clippy makes an appearance.
Figure 7. Excerpt from sms.db.
Figure 8. Second excerpt from sms.db with accounts used (destination_caller_id).

Figure 6 shows the chat in the Messages UI. The conversation initially started on the AT&T line and changed to the Google Fi line with the message “Are you there?” I then changed back to the AT&T line with the message “Here is the message for AT&T.” Figure 7 show the same text with the areas in the red boxes representing the messages on the AT&T line and the area in the blue boxes representing the messages on the Google Fi line. Figure 8 is the money-maker as it has the same rows highlighted along with the column destination_caller_id highlighted in green, and contains the respective phone numbers used to send/receive messages.

Android

Android, for once, is slightly easier than iOS when it comes to determining which phone number was used to make/receive a call. Again, I am working off of the recently-released Android 13 public image. The device had Google Fi for its physical SIM and Visible (part of Verizon) for the eSIM. I will skip the Android call log UI, and get right to calllog.db, which is found in USERDATA/data/com.android.providers.contacts/databases/. The table of interest is calls. See Figure 9.

Figure 9. Excerpt from calllog.db.

In Figure 9 there are two columns of interest: subscription_id (purple arrow) and phone_account_address (green arrow). The latter is self-explanatory. It is the phone number used to make/receive the phone call. The red boxes represent calls made /received on the Visible phone number and the blue box represents calls made/received on the Google Fi number. The column, subscription_id, is not quite as clear. The values are actually stored in a different database: telephony.db. See Figures 10 and 11.

Figure 10. telephony.db (Part 1).
Figure 11. telephony.db (Part 2).

In the Android 13 image telephony.db is found in USERDATA/user_de/%USER_NUMBER%/com.android.providers.telephony/databases/. The column _id represents the values seen in the subscription_id column found in calllog.db. Figure 10 highlights the respective carrier names (Google Fi in blue, Visible in red) along with the SIM ICCID (redacted by purple box), and Figure 11 highlights the phone numbers associated with the carriers (same color coding).

Messages on Android also utilize the _id column in telephony.db to determine which number sent/received which message. The column sub_id in mmssms.db found in USERDATA/data/com.android.providers.telephony/databases/ is the column that corresponds to _id in telephony.db. See Figure 12.

Figure 12. Excerpt from mmssms.db.

Again, the messages sent/received on the Google Fi number are in the blue boxes, the messages sent/received on the Visible number are in the red box, and the column sub_id highlighted by the purple arrow, which correspond to the _id values in telephony.db.

With Android there can be differences among the many different OEM implementations, so mileage may vary. Examiners should take care to diligently examine these databases.

Ejecting the SIM

This is probably the shortest blog post I have written. While this was a short exercise, it is still important. With most modern phones capable of handling more than one SIM it is important that examiners be able to differentiate activity between multiple numbers. Knowing where to look can help examiners determine which phone number was in use for which phone call or SMS/MMS.

As usual, Alexis Brignoni has already tool’d iLEAPP to parse com.apple.commcenter.data.plist. Head over to his GitHub repo to download the latest copy.

2 thoughts on “Mo’ SIMs, Mo’ Problems. Examining Phones with Dual SIMs.

  1. How very apt in light of the most recent Cellebrite PA issue of incorrectly parsing data from iOS devices with multiple SIM cards!

Leave a Reply