jsharkey13 / iphone_backup_decrypt

Decrypt an encrypted iOS backup created by iTunes on Windows or MacOS
Other
247 stars 41 forks source link

Add extraction of (locally stored) iCloud Photos #13

Closed john-corcoran closed 4 months ago

john-corcoran commented 4 months ago

Thanks for this fantastic script, it works great!

I noticed when browsing the output for a few devices that only a subset of photos from the devices' camera rolls were being provided. All these devices use iCloud Photos, and it looks like photos are split between Media/DCIM/ and Media/PhotoData/CPLAssets/ when this is the case.

I've added ICLOUD_PHOTOS to RelativePathsLike and MatchFiles in this PR, with example usage in the README - during testing I was seeing combined file counts across the camera_roll and icloud_photos output folders being higher than the media counts reported by the devices in their Photos apps - so there's likely media duplication within the data extracted from the DCIM and CPLAssets folders, but probably better to over provide and let the user de-duplicate as required?

jsharkey13 commented 4 months ago

Hello, thanks for the feedback and for suggesting this!

The counts mismatch seems familiar; I remember having to craft the relativePath quite carefully for the on-device camera roll to avoid the (many!) thumbnail variants iOS seems to store for each image. E.g. I have an image with a relativePath of Media/DCIM/114APPLE/IMG_4700.JPG, and there are several related files derived from this original image:

Media/PhotoData/Mutations/DCIM/114APPLE/IMG_4700/Adjustments/FullSizeRender.jpg
Media/PhotoData/Thumbnails/V2/DCIM/114APPLE/IMG_4700.JPG
Media/PhotoData/Thumbnails/V2/DCIM/114APPLE/IMG_4700.JPG/5005.JPG

I wonder if the same thing is happening for iCloud photos? I don't use iCloud for photos, so I can't test this easily right now, but I wouldn't be surprised if the relative path you suggest is just a bit too broad (the % wildcard in LIKE matches is just too wild).

You could probably investigate this using the Manifest SQLite database, to see what the matched files were before being output:

backup = EncryptedBackup(.....)
backup.test_decryption()  # Trick the code into opening the Manifest file
cur = backup._temp_manifest_db_conn.cursor()  # Use the internal connection object
cur.execute("SELECT fileID, domain, relativePath FROM Files WHERE relativePath LIKE 'Media/PhotoData/CPLAssets/group%/%.%' AND domain LIKE 'CameraRollDomain' ORDER BY relativePath;")
cur.fetchall()

(Or use backup.save_manifest_file(...) and open the SQLite file in a nicer app to query it). It may be the case, looking at that output, you can see the problematic cases in the relative paths right away. You might be able to narrow down the matching that way? Don't post the output here, it will likely be much too long.

If you don't have time to do this, or it is not obvious, maybe merging it and letting the user clean it up isn't that bad!

jsharkey13 commented 4 months ago

This makes the iCloud storage sound very complicated, since many of the images will not have the originals stored on the device, but only various smaller versions: https://theforensicscooter.com/2022/12/05/do-you-have-a-full-sized-assetor-just-a-thumbnail-did-optimized-iphone-storage-process-occur/

Maybe it's simplest to stick with this as-is!